rizinorg/rizin

`aac` doesn't add inner functions.

Opened this issue · 0 comments

Work environment

Questions Answers
OS/arch/bits (mandatory) Fedora 40
File format of the file you reverse (mandatory) ELF
Architecture/bits of the file (mandatory) x86/32
rizin -v full output, not truncated (mandatory) rizin a420733 - Date: Sat May 4 09:31:02 2024

Expected behavior

Running aac should create a function at every code xref off a call analyzed.
Even if a newly discovered function lies within a block of another function.

rizin tests/bins/elf/vim
> aac
> s 0x001b8420
> axt
sym.syntax_start 0x1b9f10 [CALL] call sym.syn_start_line
sym.syntax_start 0x1b9fca [CODE] jmp sym.syn_start_line
sym.syntax_start 0x1ba458 [CALL] call sym.syn_start_line
> fl.
0x001b8420 71 sym.syn_start_line
> afl.
0x001b9b30 sym.syntax_start
# It misses sym.syn_start_line here

For reference the function in question:

:> pd 14 @ 0x001b8420
│           ; CALL XREFS from sym.syntax_start @ 0x1b9f10, 0x1b9fca, 0x1ba458
│           ;-- syn_start_line:
│           0x001b8420      sub   rsp, 8
│           0x001b8424      mov   eax, dword [0x004b3d90]              ; [0x4b3d90:4]=0
│           0x001b842a      mov   dword [0x004b3da8], 0                ; [0x4b3da8:4]=0
│           0x001b8434      mov   dword [0x004b3db0], 0                ; [0x4b3db0:4]=0
│           0x001b843e      test  eax, eax
│       ┌─< 0x001b8440      jle   0x1b8451
│       │   0x001b8442      mov   edi, 1
│       │   0x001b8447      call  sym.syn_update_ends                  ; sym.syn_update_ends
│       │   0x001b844c      call  sym.check_state_ends                 ; sym.check_state_ends
│       └─> 0x001b8451      mov   dword [0x004b3e18], 0xffffffff       ; [0x4b3e18:4]=0
│           0x001b845b      add   dword [0x004b3d74], 1                ; [0x4b3d74:4]=0
│           0x001b8462      add   rsp, 8
│           0x001b8466      ret
            0x001b8467      nop   word [rax + rax]

Actual behavior

It doesn't add the function sym.syn_start_line.

The bug happens likely when it attempts to analyze the function due to these lines:

rizin/librz/core/canalysis.c

Lines 1538 to 1564 in 2b4aa53

fcn = rz_analysis_get_fcn_in(core->analysis, at, 0);
if (fcn) {
if (fcn->addr == at) {
// if the function was already analyzed as a "loc.",
// convert it to function and rename it to "fcn.",
// because we found a call to this address
if (reftype == RZ_ANALYSIS_XREF_TYPE_CALL && fcn->type == RZ_ANALYSIS_FCN_TYPE_LOC) {
function_rename(core->flags, fcn);
}
return 0; // already analyzed function
}
if (rz_analysis_function_contains(fcn, from)) { // inner function
RzList *l = rz_analysis_xrefs_get_to(core->analysis, from);
if (l && !rz_list_empty(l)) {
rz_list_free(l);
return true;
}
rz_list_free(l);
// we should analyze and add code ref otherwise aaa != aac
if (from != UT64_MAX) {
rz_analysis_xrefs_set(core->analysis, from, at, reftype);
}
return true;
}
}

It enters those lines because at 0x001b8420 a function already exists.
In line 1550 it enters the if statement, because the call comes from within sym.syntax_start.
So it doesn't add a new function.

Steps to reproduce the behavior

See above.