parent
e0ec191f97
commit
8fcf3e736b
5 changed files with 202 additions and 0 deletions
|
|
@ -319,6 +319,7 @@ static char *ds_esc_str(RzDisasmState *ds, const char *str, int len, const char
|
|||
static void ds_print_ptr(RzDisasmState *ds, int len, int idx);
|
||||
static void ds_print_str(RzDisasmState *ds, const char *str, int len, ut64 refaddr);
|
||||
static void ds_opstr_sub_jumps(RzDisasmState *ds);
|
||||
static void ds_opstr_resolve_aav_symbols(RzDisasmState *ds);
|
||||
static void ds_start_line_highlight(RzDisasmState *ds);
|
||||
static void ds_end_line_highlight(RzDisasmState *ds);
|
||||
static bool line_highlighted(RzDisasmState *ds);
|
||||
|
|
@ -876,6 +877,54 @@ static void __replaceImports(RzDisasmState *ds) {
|
|||
}
|
||||
}
|
||||
|
||||
static void ds_opstr_resolve_aav_symbols(RzDisasmState *ds) {
|
||||
if (!ds->opstr || !ds->core || !ds->core->flags || !ds->core->io || !ds->analysis_op.refptr) {
|
||||
return;
|
||||
}
|
||||
RzCore *core = ds->core;
|
||||
const char *pattern = "aav.aav.";
|
||||
char *pos = strstr(ds->opstr, pattern);
|
||||
if (!pos) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *addr_start = pos + strlen(pattern);
|
||||
char *addr_end = addr_start;
|
||||
while (*addr_end == 'x' || IS_HEXCHAR(*addr_end)) {
|
||||
addr_end++;
|
||||
}
|
||||
if (addr_end == addr_start) {
|
||||
return;
|
||||
}
|
||||
|
||||
char addr_str[32] = { 0 };
|
||||
const size_t addr_len = RZ_MIN((size_t)(addr_end - addr_start), sizeof(addr_str) - 1);
|
||||
memcpy(addr_str, addr_start, addr_len);
|
||||
ut64 aav_addr = rz_num_get(NULL, addr_str);
|
||||
if (!aav_addr || aav_addr < ds->min_ref_addr) {
|
||||
return;
|
||||
}
|
||||
|
||||
RzFlagItem *f1 = rz_flag_get_preferred_item(core->flags, aav_addr);
|
||||
if (!f1 || !rz_str_startswith(f1->name, "aav.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
ut8 hop_buf[sizeof(ut64)] = { 0 };
|
||||
if (!rz_io_read_at_mapped(core->io, aav_addr, hop_buf, ds->analysis_op.refptr)) {
|
||||
return;
|
||||
}
|
||||
ut64 dereferenced = rz_read_ble(hop_buf, core->print->big_endian, ds->analysis_op.refptr * 8);
|
||||
RzFlagItem *f2 = rz_flag_get_preferred_item(core->flags, dereferenced);
|
||||
if (!f2 || rz_str_startswith(f2->name, "aav.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
char pattern_to_replace[64] = { 0 };
|
||||
rz_strf(pattern_to_replace, "aav.aav.%s", addr_str);
|
||||
ds->opstr = rz_str_replace(ds->opstr, pattern_to_replace, f2->name, 1);
|
||||
}
|
||||
|
||||
static void ds_opstr_try_colorize(RzDisasmState *ds, bool print_color) {
|
||||
bool colorize_asm = print_color && ds->show_color && ds->colorop;
|
||||
if (!colorize_asm) {
|
||||
|
|
@ -1054,6 +1103,7 @@ static void ds_build_op_str(RzDisasmState *ds, bool print_color) {
|
|||
core->parser->flagspace = ofs;
|
||||
free(ds->opstr);
|
||||
ds->opstr = rz_str_dup(ds->str);
|
||||
ds_opstr_resolve_aav_symbols(ds);
|
||||
} else {
|
||||
ds_opstr_try_colorize(ds, print_color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,6 +436,47 @@ beach:
|
|||
return ret ? evalFlag(f, ret) : NULL;
|
||||
}
|
||||
|
||||
static bool is_auto_aav_flag(const RzFlagItem *flag) {
|
||||
return flag && !RZ_STR_ISEMPTY(flag->name) && rz_str_startswith(flag->name, "aav.");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the preferred flag item at an offset.
|
||||
*
|
||||
* The preferred item follows the standard space priority and avoids returning
|
||||
* auto-generated `aav.*` entries when a non-`aav.*` fallback exists at the
|
||||
* same offset.
|
||||
*
|
||||
* \param f The flag instance.
|
||||
* \param off The offset to query.
|
||||
*
|
||||
* \return The preferred flag item, or NULL if none exists.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzFlagItem *rz_flag_get_preferred_item(RZ_NONNULL RzFlag *f, ut64 off) {
|
||||
rz_return_val_if_fail(f, NULL);
|
||||
|
||||
RzFlagItem *preferred = rz_flag_get_by_spaces(f, off,
|
||||
"symbols",
|
||||
"imports",
|
||||
"relocs",
|
||||
"symbols.sections",
|
||||
"functions",
|
||||
"globals",
|
||||
"strings",
|
||||
"resources",
|
||||
"sections",
|
||||
"segments",
|
||||
NULL);
|
||||
if (!preferred || !is_auto_aav_flag(preferred)) {
|
||||
return preferred;
|
||||
}
|
||||
RzFlagItem *fallback = rz_flag_get_i(f, off);
|
||||
if (fallback && !is_auto_aav_flag(fallback)) {
|
||||
return fallback;
|
||||
}
|
||||
return preferred;
|
||||
}
|
||||
|
||||
static bool isFunctionFlag(const char *n) {
|
||||
return (!strncmp(n, "sym.func.", 9) || !strncmp(n, "method.", 7) || !strncmp(n, "sym.", 4) || !strncmp(n, "func.", 5) || !strncmp(n, "fcn.0", 5));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ RZ_API bool rz_flag_exist_at(RzFlag *f, const char *flag_prefix, ut16 fp_size, u
|
|||
RZ_API RzFlagItem *rz_flag_get(RzFlag *f, const char *name);
|
||||
RZ_API RzFlagItem *rz_flag_get_i(RzFlag *f, ut64 off);
|
||||
RZ_API RzFlagItem *rz_flag_get_by_spaces(RzFlag *f, ut64 off, ...);
|
||||
RZ_API RZ_BORROW RzFlagItem *rz_flag_get_preferred_item(RZ_NONNULL RzFlag *f, ut64 off);
|
||||
RZ_API RzFlagItem *rz_flag_get_at(RzFlag *f, ut64 off, bool closest);
|
||||
RZ_API RZ_BORROW RzFlagItem *rz_flag_get_at_by_spaces(RZ_NONNULL RzFlag *f, bool closest, ut64 off, ...);
|
||||
RZ_API RzList /*<RzFlagItem *>*/ *rz_flag_all_list(RzFlag *f, bool by_space);
|
||||
|
|
|
|||
|
|
@ -180,10 +180,63 @@ bool test_rz_core_print_disasm() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_core_print_disasm_resolve_aav_symbols() {
|
||||
RzCore *core = rz_core_new();
|
||||
mu_assert_notnull(core, "rz_core_new failed");
|
||||
RzIODesc *io_desc = rz_io_open_at(core->io, "malloc://0x200000", RZ_PERM_RWX, 0644, 0, NULL);
|
||||
mu_assert_notnull(io_desc, "io open failed");
|
||||
bool arch_configured = rz_core_arch_configure(core, "x86", 32, NULL, NULL, NULL);
|
||||
mu_assert_true(arch_configured, "rz_core_arch_configure failed");
|
||||
bool analysis_arch_set = rz_analysis_use(core->analysis, "x86");
|
||||
mu_assert_true(analysis_arch_set, "rz_analysis_use failed");
|
||||
bool analysis_bits_set = rz_analysis_set_bits(core->analysis, 32);
|
||||
mu_assert_true(analysis_bits_set, "rz_analysis_set_bits failed");
|
||||
rz_config_set_i(core->config, "scr.color", 0);
|
||||
rz_config_set_b(core->config, "asm.sub.names", true);
|
||||
rz_config_set_b(core->config, "asm.sub.rel", true);
|
||||
rz_config_set_i(core->config, "asm.sub.varmin", 0);
|
||||
|
||||
ut8 code[] = { 0xa1, 0x20, 0x00, 0x10, 0x00 }; // mov eax, dword [0x100020]
|
||||
ut8 ptr[] = { 0x40, 0x00, 0x10, 0x00 }; // *(0x100020) = 0x100040
|
||||
rz_io_write_at(core->io, 0x100020, ptr, sizeof(ptr));
|
||||
|
||||
rz_flag_space_set(core->flags, "symbols");
|
||||
rz_flag_set(core->flags, "aav.0x00100020", 0x100020, 4);
|
||||
rz_flag_set(core->flags, "obj.__stack_chk_guard", 0x100040, 4);
|
||||
|
||||
RzPVector *vec = rz_pvector_new((RzPVectorFree)rz_analysis_disasm_text_free);
|
||||
mu_assert_notnull(vec, "rz_core_print_disasm vec not null");
|
||||
RzCoreDisasmOptions options = {
|
||||
.vec = vec,
|
||||
.cbytes = 1,
|
||||
};
|
||||
rz_core_print_disasm(core, 0, code, sizeof(code), sizeof(code), NULL, &options);
|
||||
|
||||
size_t line_count = rz_pvector_len(vec);
|
||||
mu_assert_true(line_count >= 1, "rz_core_print_disasm should produce at least one line");
|
||||
RzAnalysisDisasmText *t = rz_pvector_at(vec, 0);
|
||||
mu_assert_notnull(t, "first disasm line");
|
||||
char *insn = rz_str_dup(t->text);
|
||||
mu_assert_notnull(insn, "instruction line copy");
|
||||
char *comment = strchr(insn, ';');
|
||||
if (comment) {
|
||||
*comment = '\0';
|
||||
}
|
||||
mu_assert_strcontains(insn, "obj.__stack_chk_guard", "aav.aav symbol should be resolved to preferred symbol");
|
||||
char *aav_symbol = strstr(insn, "aav.aav.");
|
||||
mu_assert_null(aav_symbol, "aav.aav symbol should not be present in instruction operand");
|
||||
free(insn);
|
||||
|
||||
rz_core_free(core);
|
||||
rz_pvector_free(vec);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int all_tests() {
|
||||
mu_run_test(test_rz_analysis_op_val);
|
||||
mu_run_test(test_rz_core_analysis_bytes);
|
||||
mu_run_test(test_rz_core_print_disasm);
|
||||
mu_run_test(test_rz_core_print_disasm_resolve_aav_symbols);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -169,11 +169,68 @@ bool test_rz_flag_set_next() {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_flag_get_preferred_item() {
|
||||
RzFlag *flags = rz_flag_new();
|
||||
mu_assert_notnull(flags, "rz_flag_new() failed");
|
||||
|
||||
ut64 off = 0x1337;
|
||||
rz_flag_space_set(flags, "symbols");
|
||||
rz_flag_set(flags, "sym.real_name", off, 0);
|
||||
rz_flag_space_set(flags, "custom");
|
||||
rz_flag_set(flags, "custom.name", off, 0);
|
||||
|
||||
RzFlagItem *fi = rz_flag_get_preferred_item(flags, off);
|
||||
mu_assert_notnull(fi, "preferred flag should exist");
|
||||
mu_assert_streq(fi->name, "sym.real_name", "must prefer symbol space item");
|
||||
|
||||
rz_flag_free(flags);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_flag_get_preferred_item_fallback_non_aav() {
|
||||
RzFlag *flags = rz_flag_new();
|
||||
mu_assert_notnull(flags, "rz_flag_new() failed");
|
||||
|
||||
ut64 off = 0x4242;
|
||||
rz_flag_space_set(flags, "symbols");
|
||||
rz_flag_set(flags, "aav.0x00004242", off, 0);
|
||||
rz_flag_space_set(flags, "custom");
|
||||
rz_flag_set(flags, "obj.__stack_chk_guard", off, 0);
|
||||
|
||||
RzFlagItem *fi = rz_flag_get_preferred_item(flags, off);
|
||||
mu_assert_notnull(fi, "preferred flag should exist");
|
||||
mu_assert_streq(fi->name, "obj.__stack_chk_guard", "must fallback to non-aav item");
|
||||
|
||||
rz_flag_free(flags);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_flag_get_preferred_item_keep_aav_when_only_aav() {
|
||||
RzFlag *flags = rz_flag_new();
|
||||
mu_assert_notnull(flags, "rz_flag_new() failed");
|
||||
|
||||
ut64 off = 0x5151;
|
||||
rz_flag_space_set(flags, "symbols");
|
||||
rz_flag_set(flags, "aav.0x00005151", off, 0);
|
||||
rz_flag_space_set(flags, "custom");
|
||||
rz_flag_set(flags, "aav.0x0000beef", off, 0);
|
||||
|
||||
RzFlagItem *fi = rz_flag_get_preferred_item(flags, off);
|
||||
mu_assert_notnull(fi, "preferred flag should exist");
|
||||
mu_assert_streq(fi->name, "aav.0x00005151", "must keep preferred aav when no non-aav fallback exists");
|
||||
|
||||
rz_flag_free(flags);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int all_tests(void) {
|
||||
mu_run_test(test_rz_flag_get_set);
|
||||
mu_run_test(test_rz_flag_by_spaces);
|
||||
mu_run_test(test_rz_flag_get_at);
|
||||
mu_run_test(test_rz_flag_set_next);
|
||||
mu_run_test(test_rz_flag_get_preferred_item);
|
||||
mu_run_test(test_rz_flag_get_preferred_item_fallback_non_aav);
|
||||
mu_run_test(test_rz_flag_get_preferred_item_keep_aav_when_only_aav);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue