336 lines
10 KiB
C
336 lines
10 KiB
C
// SPDX-FileCopyrightText: 2009-2025 PremadeS <emadsohail001@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <stddef.h>
|
|
#include <rz_cons.h>
|
|
#include <rz_core.h>
|
|
#include <../core_private.h>
|
|
#include <rz_mark.h>
|
|
#include <rz_cmd.h>
|
|
#include <rz_flag.h>
|
|
#include <rz_util/rz_log.h>
|
|
|
|
static bool mark_set_comment(RzMarkItem *item, const char *comment) {
|
|
if (!strncmp(comment, "base64:", 7)) {
|
|
const char *b64str = comment + 7;
|
|
char *dec = (char *)rz_base64_decode_dyn(b64str, -1);
|
|
if (!dec) {
|
|
RZ_LOG_ERROR("Failed to decode base64-encoded string: \"%s\"\n", b64str);
|
|
return false;
|
|
}
|
|
rz_mark_item_set_comment(item, dec);
|
|
free(dec);
|
|
} else {
|
|
rz_mark_item_set_comment(item, comment);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
struct mark_to_mark_t {
|
|
ut64 next;
|
|
ut64 offset;
|
|
};
|
|
|
|
static bool mark_to_mark_foreach(RzMarkItem *bi, void *user) {
|
|
struct mark_to_mark_t *u = (struct mark_to_mark_t *)user;
|
|
if (bi->from < u->next && bi->from > u->offset) {
|
|
u->next = bi->from;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int mark_to_mark(RzCore *core, const char *glob) {
|
|
rz_return_val_if_fail(core, 0);
|
|
rz_return_val_if_fail(glob, 0);
|
|
glob = rz_str_trim_head_ro(glob);
|
|
struct mark_to_mark_t u = { .next = UT64_MAX, .offset = core->offset };
|
|
rz_mark_foreach_regex(core->marks, glob, mark_to_mark_foreach, &u);
|
|
if (u.next != UT64_MAX && u.next > core->offset) {
|
|
return u.next - core->offset;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void mark_add_flag(RzFlag *f, RzMarkItem *bi) {
|
|
if (!f || !bi) {
|
|
return;
|
|
}
|
|
RzSpace *prev_space = rz_flag_space_cur(f);
|
|
RzSpace *mark_space = rz_flag_space_get(f, "marks");
|
|
if (!mark_space) {
|
|
mark_space = rz_flag_space_set(f, "marks");
|
|
} else {
|
|
rz_flag_space_set(f, "marks");
|
|
}
|
|
|
|
rz_flag_set(f, bi->name, bi->from, (ut32)(bi->to - bi->from));
|
|
if (prev_space) {
|
|
rz_flag_space_set(f, prev_space->name);
|
|
}
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_add_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *item;
|
|
bool addMark = true;
|
|
ut64 end = rz_num_math(core->num, argv[2]);
|
|
if ((item = rz_mark_get_at(core->marks, core->offset))) {
|
|
RZ_LOG_ERROR("Cannot create mark \"%s\" from 0x%" PFMT64x " to 0x%" PFMT64x " because there is already \"%s\" mark\n", argv[1], core->offset, end, item->name);
|
|
addMark = false;
|
|
}
|
|
|
|
if (end < core->offset) {
|
|
RZ_LOG_ERROR("Ending offset (0x%" PFMT64x ") must be greater than or equal to starting offset (0x%" PFMT64x ")\n",
|
|
end, core->offset);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
|
|
if (addMark) {
|
|
item = rz_mark_set(core->marks, argv[1], core->offset, end);
|
|
if (item) {
|
|
mark_add_flag(core->flags, item);
|
|
}
|
|
}
|
|
if (!item) {
|
|
RZ_LOG_ERROR(
|
|
"Cannot create mark \"%s\" from 0x%" PFMT64x " to 0x%" PFMT64x "\n", argv[1], core->offset, end);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
if (argc > 3) {
|
|
return bool2status(mark_set_comment(item, argv[3]));
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_append_handler(RzCore *core, int argc, const char **argv) {
|
|
ut64 end = rz_num_math(core->num, argv[2]);
|
|
RzMarkItem *item = rz_mark_set(core->marks, argv[1], core->offset, end);
|
|
if (!item) {
|
|
RZ_LOG_ERROR(
|
|
"Cannot create mark \"%s\" from 0x%" PFMT64x " to 0x%" PFMT64x "\n", argv[1], core->offset, end);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
mark_add_flag(core->flags, item);
|
|
if (argc > 3) {
|
|
return bool2status(mark_set_comment(item, argv[3]));
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_remove_handler(RzCore *core, int argc, const char **argv) {
|
|
if (argc < 2) {
|
|
RzList *list = rz_mark_get_all_off(core->marks, core->offset);
|
|
RzListIter *it;
|
|
RzMarkItem *bi;
|
|
rz_list_foreach (list, it, bi) {
|
|
RzFlagItem *fi = rz_flag_get(core->flags, bi->name);
|
|
rz_flag_unset(core->flags, fi);
|
|
}
|
|
rz_mark_unset_all_off(core->marks, core->offset);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
if (rz_mark_unset_glob(core->marks, argv[1]) < 0) {
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
RzFlagItem *fi = rz_flag_get(core->flags, argv[1]);
|
|
if (fi) {
|
|
rz_flag_unset(core->flags, fi);
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_list_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
|
rz_core_mark_print(core->marks, state);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_remove_all_handler(RzCore *core, int argc, const char **argv) {
|
|
RzList *list = rz_mark_all_list(core->marks);
|
|
RzListIter *it;
|
|
RzMarkItem *bi;
|
|
rz_list_foreach (list, it, bi) {
|
|
RzFlagItem *fi = rz_flag_get(core->flags, bi->name);
|
|
if (fi) {
|
|
rz_flag_unset(core->flags, fi);
|
|
}
|
|
}
|
|
rz_list_free(list);
|
|
rz_mark_unset_all(core->marks);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_color_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *bi = rz_mark_get(core->marks, argv[1]);
|
|
if (!bi) {
|
|
RZ_LOG_ERROR("Cannot find the mark '%s'\n", argv[1]);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
if (argc < 3) {
|
|
if (bi->color) {
|
|
rz_cons_println(bi->color);
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
const char *ret = rz_mark_item_set_color(bi, argv[2]);
|
|
if (ret) {
|
|
rz_cons_println(ret);
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_list_at_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
|
rz_core_mark_range_print(core->marks, state, core->offset, core->offset + 1);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_comment_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *item;
|
|
if (argc > 2) {
|
|
item = rz_mark_get(core->marks, argv[1]);
|
|
if (!item) {
|
|
RZ_LOG_ERROR("Cannot find mark with name '%s'\n", argv[1]);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
return bool2status(mark_set_comment(item, argv[2]));
|
|
} else {
|
|
item = rz_mark_get(core->marks, argv[1]);
|
|
if (!item) {
|
|
RZ_LOG_ERROR("Cannot find mark\n");
|
|
return RZ_CMD_STATUS_ERROR;
|
|
} else if (item->comment) {
|
|
rz_cons_println(item->comment);
|
|
}
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_rename_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *item = rz_mark_get(core->marks, argv[1]);
|
|
if (!item) {
|
|
RZ_LOG_ERROR("Cannot find matching mark\n");
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
if (!rz_mark_rename(core->marks, item, argv[2])) {
|
|
RZ_LOG_ERROR("Invalid new mark name\n");
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
RzFlagItem *fi = rz_flag_get(core->flags, argv[1]);
|
|
rz_flag_rename(core->flags, fi, argv[2]);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_realname_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *item = rz_mark_get(core->marks, argv[1]);
|
|
if (!item) {
|
|
RZ_LOG_ERROR("Cannot find mark\n");
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
if (argc < 3) {
|
|
rz_cons_printf("%s\n", item->realname);
|
|
} else {
|
|
rz_mark_item_set_realname(item, argv[2]);
|
|
RzFlagItem *fi = rz_flag_get(core->flags, item->name);
|
|
rz_flag_item_set_realname(fi, argv[2]);
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_move_handler(RzCore *core, int argc, const char **argv) {
|
|
RzMarkItem *item = rz_mark_get(core->marks, argv[1]);
|
|
if (!item) {
|
|
RZ_LOG_ERROR("Cannot find matching mark\n");
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
ut64 new_start = rz_num_math(core->num, argv[2]);
|
|
ut64 new_end = rz_num_math(core->num, argv[3]);
|
|
RzMarkItem *new_item = rz_mark_set(core->marks, item->name, new_start, new_end);
|
|
if (!new_item) {
|
|
RZ_LOG_ERROR(
|
|
"Cannot move mark \"%s\" to 0x%" PFMT64x " - 0x%" PFMT64x "\n", argv[1], new_start, new_end);
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
rz_flag_set(core->flags, item->name, new_start, (ut32)(new_end - new_start));
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_distance_handler(RzCore *core, int argc, const char **argv) {
|
|
rz_cons_printf("%d\n", mark_to_mark(core, argv[1]));
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_core_mark_describe(RzCore *core, ut64 addr, RzMarkItem *b, RzCmdStateOutput *state) {
|
|
ut64 size = (b->to >= b->from) ? (b->to - b->from) : 0;
|
|
PJ *pj = state->d.pj;
|
|
rz_cmd_state_output_set_columnsf(state, "ssXXds", "name", "realname",
|
|
"from", "to", "size", "comment");
|
|
switch (state->mode) {
|
|
case RZ_OUTPUT_MODE_JSON:
|
|
pj_o(pj);
|
|
pj_ks(pj, "name", b->name);
|
|
pj_kn(pj, "from", b->from);
|
|
pj_kn(pj, "to", b->to);
|
|
pj_kn(pj, "size", size);
|
|
if (b->comment) {
|
|
pj_ks(pj, "comment", b->comment);
|
|
}
|
|
if (b->realname) {
|
|
pj_ks(pj, "realname", b->realname);
|
|
}
|
|
pj_end(pj);
|
|
break;
|
|
|
|
case RZ_OUTPUT_MODE_TABLE: {
|
|
ut64 size = (b->to >= b->from) ? (b->to - b->from) : 0;
|
|
const char *name = b->realname ? b->realname : b->name;
|
|
if (addr >= b->from && addr <= b->to) {
|
|
rz_table_add_rowf(state->d.t, "ssXXds", b->name, name, b->from, b->to, size, b->comment);
|
|
} else if (addr < b->from) {
|
|
const char *descr_name = rz_str_newf("%s - %d", name, (int)(b->from - addr));
|
|
rz_table_add_rowf(state->d.t, "ssXXds", b->name, descr_name, b->from, b->to, size, b->comment);
|
|
} else {
|
|
const char *descr_name = rz_str_newf("%s + %d", name, (int)(addr - b->to));
|
|
rz_table_add_rowf(state->d.t, "ssXXds", b->name, descr_name, b->from, b->to, size, b->comment);
|
|
}
|
|
break;
|
|
}
|
|
case RZ_OUTPUT_MODE_STANDARD: {
|
|
const char *name = b->realname ? b->realname : b->name;
|
|
if (addr >= b->from && addr <= b->to) {
|
|
rz_cons_printf("[0x%08" PFMT64x " - 0x%08" PFMT64x "] %s\n", b->from, b->to, name);
|
|
} else if (addr < b->from) {
|
|
rz_cons_printf("[0x%08" PFMT64x " - 0x%08" PFMT64x "] %s - %d\n", b->from, b->to, name, (int)(b->from - addr));
|
|
} else {
|
|
rz_cons_printf("[0x%08" PFMT64x " - 0x%08" PFMT64x "] %s + %d\n", b->from, b->to, name, (int)(addr - b->to));
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
rz_warn_if_reached();
|
|
break;
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_describe_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
|
RzMarkItem *b;
|
|
if (argc > 1) {
|
|
b = rz_mark_get(core->marks, argv[1]);
|
|
} else {
|
|
b = rz_mark_get_at(core->marks, core->offset);
|
|
}
|
|
if (!b) {
|
|
RZ_LOG_ERROR("Cannot find mark\n");
|
|
return RZ_CMD_STATUS_ERROR;
|
|
}
|
|
rz_core_mark_describe(core, core->offset, b, state);
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_mark_range_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
|
|
if (argc > 1) {
|
|
ut64 size = rz_num_math(core->num, argv[1]);
|
|
rz_core_mark_range_print(core->marks, state, core->offset, core->offset + size);
|
|
} else {
|
|
rz_core_mark_range_print(core->marks, state, core->offset, core->offset + core->blocksize);
|
|
}
|
|
return RZ_CMD_STATUS_OK;
|
|
}
|