Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 47 additions & 14 deletions librz/core/canalysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -4004,11 +4004,6 @@ static bool addr_in_exec_section(RzBinObject *bo, ut64 addr) {
return sec && (sec->perm & RZ_PERM_X);
}

static bool addr_in_exec_segment(RzBinObject *bo, ut64 addr) {
RzBinSection *seg = rz_bin_get_segment_at(bo, addr, true);
return seg && (seg->perm & RZ_PERM_X);
}

/** \brief How a DATA xref's instruction relates to its target address. */
typedef enum {
XREF_REF_OTHER = 0, ///< address computation, control flow, etc. — handled as before
Expand Down Expand Up @@ -4050,6 +4045,12 @@ static void analysis_mark_xrefs_as_data(RzCore *core) {
return;
}

RzBinObject *bo = rz_bin_cur_object(core->bin);
if (!bo) {
rz_list_free(all_xrefs);
return;
}

// collect every target address that has at least one CODE/CALL xref
RzSetU *code_call_targets = rz_set_u_new();
if (!code_call_targets) {
Expand Down Expand Up @@ -4102,15 +4103,9 @@ static void analysis_mark_xrefs_as_data(RzCore *core) {
// ; DATA XREF from dbg.sched_run @ 0x490
// ;-- data.000004e0:
// 0x000004e0 .dword 0x1fff0274 ; runqueue_bitcache ; section..bss ; sym..bss ; obj.runqueue_bitcache ; loc._sbss ; loc._szero ; loc._erelocate ; sched.c:135
RzBinObject *bo = rz_bin_cur_object(core->bin);
if (!bo) {
continue;
}
// Only executable-region targets need classifying: reject constants that merely
// equal a code address (e.g. `sub sp, sp, 0x810`), while skipping the decode for
// the common data-section case.
bool in_exec_segment = addr_in_exec_segment(bo, target);
XrefRefKind ref_kind = in_exec_segment ? xref_ref_kind(core, xref->from, target) : XREF_REF_OTHER;

// reject constants that merely equal a code address (e.g. `sub sp, sp, 0x810`)
XrefRefKind ref_kind = xref_ref_kind(core, xref->from, target);
if (ref_kind == XREF_REF_COINCIDENTAL_IMM) {
continue;
}
Expand Down Expand Up @@ -4202,6 +4197,44 @@ static void analysis_mark_xrefs_as_data(RzCore *core) {
}
}
ut64 upper = RZ_MIN(next_data, next_fcn);
// cap upper to curr section boundary or map
RzBinSection *sec = rz_bin_get_section_at(bo, target, true);
if (sec) {
ut64 sec_end = sec->vaddr + sec->vsize;
if (upper > sec_end)
upper = sec_end;

} else {
// target is in a section gap or we are in a binary w/o metadata
ut64 next_sec_start = UT64_MAX;

RzBinSection *s;
void **iter;
rz_pvector_foreach (bo->sections, iter) {
s = *iter;
if (s->is_segment) {
continue;
}
ut64 vaddr = rz_bin_object_addr_with_base(bo, s->vaddr);
if (vaddr > target && vaddr < next_sec_start) {
next_sec_start = vaddr;
}
}
Comment on lines +4209 to +4222

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering if we should create api fxn for rz_bin_get_next_section or not


// cap upper to next section start if exists
if (next_sec_start != UT64_MAX && upper > next_sec_start) {
upper = next_sec_start;
}
// last fallback, cap upper to map_end
// also if target was in last section before unmapped region
RzIOMap *map = rz_io_map_get(core->io, target);
if (map) {
ut64 map_end = rz_io_map_get_to(map) + 1;
if (upper > map_end) {
upper = map_end;
}
}
}
ut64 size;
if (upper != UT64_MAX) {
size = rz_set_u_contains(exec_targets, target)
Expand Down
63 changes: 63 additions & 0 deletions test/db/analysis/x86_64
Original file line number Diff line number Diff line change
Expand Up @@ -4521,3 +4521,66 @@ EXPECT=<<EOF
\ 0x1400010ae ret
EOF
RUN

NAME=do not mark coincidental imm in non-exec segment as data
FILE=bins/elf/hello-freebsd-x64
CMDS=<<EOF
e io.cache=true
s 0x002015ae
wa "and dword [rbp-8], 0x0020001f"
aaa
Cdl~0x0020001f
EOF
EXPECT=<<EOF
EOF
RUN

NAME=data block should not bleed across section or map boundary
FILE=bins/elf/hello-freebsd-x64
CMDS=<<EOF
aaa
# map at 0x200000 ends at 0x0020059b = 1435 bytes
oml~0x00200000
# should not be 5536 bytes (upto next fxn at 0x002015a0), cap at next section
Cdl~0x00200000
echo "===not bleed across section==="
e io.cache=true
s 0x002015ae
wa "add dword [0x00200546], 1"
aaa
# 0x00200546 is in section gap
# should be caped at next section, 2 bytes ahead
# should not be 4186 bytes (upto next fxn at 0x002015a0)
Cdl~0x00200546
echo "===handle section gap==="
wa "add dword [0x00200544], 1"
aaa
# 0x00200544 is in .rodata
s 0x00200544
iS.
# should be caped to curr section end, 2 bytes ahead
# should not be 4188 bytes (upto next fxn at 0x002015a0)
Cdl~0x00200544
echo "===cap at map end==="
s 0x002015ae
wa "add dword [0x00200562], 1"
aaa
# 0x00200562 is last section before unmapped
# so data block should cap at curr map end 0x0020059b = 57 bytes,
# should not be 4158 bytes (upto next fxn at 0x002015a0)
Cdl~0x00200562
EOF
EXPECT=<<EOF
2 fd: 3 +0x00000000 0x00200000 - 0x0020059b r-- fmap.LOAD0
0x00200000 data Cd 680
===not bleed across section===
0x00200546 data Cd 2
===handle section gap===
paddr size vaddr vsize align perm name type flags
---------------------------------------------------------------------------------
0x00000538 0xe 0x00200538 0xe 0x0 -r-- .rodata PROGBITS alloc,merge,strings
0x00200544 data Cd 2
===cap at map end===
0x00200562 data Cd 58
EOF
RUN
Loading