Fix aav.aav.* naming #2205 (#6079)

This commit is contained in:
loki 2026-03-29 10:49:04 +01:00 committed by GitHub
parent e0ec191f97
commit 8fcf3e736b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 202 additions and 0 deletions

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}