mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-03 04:05:06 +00:00
Add aar
command to search xrefs in code
- Ignore references to sections with vaddr=0 - Skip overlapping instructions in xref search - Improve debugger mode support of `axa` - Remove unused cmd variable
This commit is contained in:
parent
8ff870be8e
commit
9d92712cea
138
libr/core/anal.c
138
libr/core/anal.c
@ -1568,6 +1568,144 @@ R_API int r_core_anal_search(RCore *core, ut64 from, ut64 to, ut64 ref) {
|
||||
return count;
|
||||
}
|
||||
|
||||
R_API int r_core_anal_search_xrefs(RCore *core, ut64 from, ut64 to, int rad) {
|
||||
ut8 *buf;
|
||||
ut64 at;
|
||||
int count = 0;
|
||||
RAnalOp op = {0};
|
||||
|
||||
if (from >= to) {
|
||||
eprintf ("Invalid range (from >= to)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (core->blocksize <= OPSZ) {
|
||||
eprintf ("Error: block size too small\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = (ut8 *)malloc (core->blocksize);
|
||||
if (!buf) {
|
||||
eprintf ("Error: cannot allocate a block\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rad == 'j')
|
||||
r_cons_printf ("{");
|
||||
|
||||
r_io_use_desc (core->io, core->file->desc);
|
||||
r_cons_break (NULL, NULL);
|
||||
at = from;
|
||||
while (at < to && !r_cons_singleton ()->breaked) {
|
||||
int i, ret;
|
||||
|
||||
ret = r_io_read_at (core->io, at, buf, core->blocksize);
|
||||
if (ret != core->blocksize && at+ret-OPSZ < to)
|
||||
break;
|
||||
|
||||
i = 0;
|
||||
while (at+i < to && i < ret-OPSZ) {
|
||||
RAnalRefType type;
|
||||
ut64 xref_from, xref_to;
|
||||
|
||||
xref_from = at+i;
|
||||
r_anal_op_fini (&op);
|
||||
ret = r_anal_op (core->anal, &op, at+i, buf+i, core->blocksize-i);
|
||||
i += (ret > 0) ? ret : 1;
|
||||
if (ret <= 0 || at+i > to)
|
||||
continue;
|
||||
|
||||
// Get reference type and target address
|
||||
type = R_ANAL_REF_TYPE_NULL;
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
type = R_ANAL_REF_TYPE_CODE;
|
||||
xref_to = op.jump;
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
case R_ANAL_OP_TYPE_CCALL:
|
||||
type = R_ANAL_REF_TYPE_CALL;
|
||||
xref_to = op.jump;
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
case R_ANAL_OP_TYPE_UCJMP:
|
||||
type = R_ANAL_REF_TYPE_CODE;
|
||||
xref_to = op.ptr;
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_UCALL:
|
||||
case R_ANAL_OP_TYPE_UCCALL:
|
||||
type = R_ANAL_REF_TYPE_CALL;
|
||||
xref_to = op.ptr;
|
||||
break;
|
||||
default:
|
||||
if (op.ptr != -1) {
|
||||
type = R_ANAL_REF_TYPE_DATA;
|
||||
xref_to = op.ptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Validate the reference. If virtual addressing is enabled, we
|
||||
// allow only references to virtual addresses in order to reduce
|
||||
// the number of false positives. In debugger mode, the reference
|
||||
// must point to a mapped memory region.
|
||||
if (type == R_ANAL_REF_TYPE_NULL)
|
||||
continue;
|
||||
if (!r_core_is_valid_offset (core, xref_to))
|
||||
continue;
|
||||
if (r_config_get_i (core->config, "cfg.debug")) {
|
||||
if (!r_debug_map_get (core->dbg, xref_to))
|
||||
continue;
|
||||
} else if (core->io->va) {
|
||||
RListIter *iter;
|
||||
RIOSection *s;
|
||||
r_list_foreach (core->io->sections, iter, s) {
|
||||
if (xref_to >= s->vaddr && xref_to < s->vaddr + s->vsize) {
|
||||
if (s->vaddr != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!iter)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rad) {
|
||||
// Add to SDB
|
||||
r_anal_xrefs_set (core->anal, type, xref_from, xref_to);
|
||||
} else if (rad == 'j') {
|
||||
// Output JSON
|
||||
if (count > 0) r_cons_printf (",");
|
||||
r_cons_printf ("%"PFMT64d":%"PFMT64d, xref_to, xref_from);
|
||||
} else {
|
||||
// Display in radare commands format
|
||||
char *cmd;
|
||||
switch (type) {
|
||||
case R_ANAL_REF_TYPE_CODE: cmd = "axc"; break;
|
||||
case R_ANAL_REF_TYPE_CALL: cmd = "axC"; break;
|
||||
case R_ANAL_REF_TYPE_DATA: cmd = "axd"; break;
|
||||
default: cmd = "ax"; break;
|
||||
}
|
||||
|
||||
r_cons_printf ("%s 0x%08"PFMT64x" 0x%08"PFMT64x"\n",
|
||||
cmd, xref_to, xref_from);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
at += i;
|
||||
}
|
||||
r_cons_break_end ();
|
||||
free (buf);
|
||||
r_anal_op_fini (&op);
|
||||
|
||||
if (rad == 'j')
|
||||
r_cons_printf ("}\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
R_API int r_core_anal_ref_list(RCore *core, int rad) {
|
||||
r_anal_xrefs_list (core->anal, rad);
|
||||
return 0;
|
||||
|
@ -2610,6 +2610,7 @@ static int cmd_anal(void *data, const char *input) {
|
||||
"aa*", "", "analyze all flags starting with sym. (af @@ sym.*)",
|
||||
"aaa", "", "autoname functions after aa (see afna)",
|
||||
"aac", " [len]", "analyze function calls (af @@ `pi len~call[1]`)",
|
||||
"aar", " [len]", "analyze len bytes of instructions for references",
|
||||
"aas", " [len]", "analyze symbols (af @@= `isq~[0]`)",
|
||||
"aap", "", "find and analyze function preludes",
|
||||
NULL};
|
||||
@ -2706,6 +2707,71 @@ static int cmd_anal(void *data, const char *input) {
|
||||
if (input[1] == 'a') // "aaa"
|
||||
r_core_cmd0 (core, ".afna @@ fcn.*"); break; // "aaa"
|
||||
break;
|
||||
case 'r':
|
||||
{
|
||||
ut64 from, to;
|
||||
char *ptr;
|
||||
int rad, n;
|
||||
const char* help_msg_aar[] = {
|
||||
"Usage:", "aar", "[j*] [sz] # search and analyze xrefs",
|
||||
"aar", " [sz]", "analyze xrefs in current section or sz bytes of code",
|
||||
"aarj", " [sz]", "list found xrefs in JSON format",
|
||||
"aar*", " [sz]", "list found xrefs in radare commands format",
|
||||
NULL};
|
||||
|
||||
if (input[2] == '?') {
|
||||
r_core_cmd_help (core, help_msg_aar);
|
||||
break;
|
||||
}
|
||||
|
||||
if (input[2] == 'j' || input[2] == '*') {
|
||||
rad = input[2];
|
||||
input++;
|
||||
} else rad = 0;
|
||||
|
||||
from = to = 0;
|
||||
ptr = strdup (r_str_trim_head ((char*)input+2));
|
||||
n = r_str_word_set0 (ptr);
|
||||
if (n == 0) {
|
||||
int rwx = R_IO_EXEC;
|
||||
// get boundaries of current memory map, section or io map
|
||||
if (r_config_get_i (core->config, "cfg.debug")) {
|
||||
RDebugMap *map = r_debug_map_get (core->dbg, core->offset);
|
||||
if (map) {
|
||||
from = map->addr;
|
||||
to = map->addr_end;
|
||||
rwx = map->perm;
|
||||
}
|
||||
} else if (core->io->va) {
|
||||
RIOSection *section = r_io_section_vget (core->io, core->offset);
|
||||
if (section) {
|
||||
from = section->vaddr;
|
||||
to = section->vaddr + section->vsize;
|
||||
rwx = section->rwx;
|
||||
}
|
||||
} else {
|
||||
RIOMap *map = r_io_map_get (core->io, core->offset);
|
||||
from = core->offset;
|
||||
to = r_io_size (core->io) + (map? map->to:0);
|
||||
}
|
||||
if (from == 0 && to == 0)
|
||||
eprintf ("Cannot determine xref search boundaries\n");
|
||||
else if (!(rwx & R_IO_EXEC))
|
||||
eprintf ("Warning: Searching xrefs in non-executable region\n");
|
||||
} else if (n == 1) {
|
||||
from = core->offset;
|
||||
to = core->offset + r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
||||
} else {
|
||||
eprintf ("Invalid number of arguments\n");
|
||||
}
|
||||
free (ptr);
|
||||
|
||||
if (from == 0 && to == 0)
|
||||
return R_FALSE;
|
||||
|
||||
r_core_anal_search_xrefs (core, from, to, rad);
|
||||
}
|
||||
break;
|
||||
default: r_core_cmd_help (core, help_msg_aa); break;
|
||||
}
|
||||
break;
|
||||
|
@ -1936,7 +1936,7 @@ static void agraph_init(RAGraph *g) {
|
||||
g->graph = r_graph_new ();
|
||||
g->nodes = sdb_new0 ();
|
||||
g->zoom = ZOOM_DEFAULT;
|
||||
g->movspeed = r_config_get_i (g->core->config, "graph.scroll");
|
||||
g->movspeed = DEFAULT_SPEED; //r_config_get_i (g->core->config, "graph.scroll");
|
||||
}
|
||||
|
||||
R_API void r_agraph_print (RAGraph *g) {
|
||||
|
@ -295,6 +295,7 @@ R_API ut64 r_core_anal_address (RCore *core, ut64 addr);
|
||||
R_API void r_core_anal_undefine (RCore *core, ut64 off);
|
||||
R_API void r_core_anal_hint_list (RAnal *a, int mode);
|
||||
R_API int r_core_anal_search(RCore *core, ut64 from, ut64 to, ut64 ref);
|
||||
R_API int r_core_anal_search_xrefs(RCore *core, ut64 from, ut64 to, int rad);
|
||||
R_API int r_core_anal_data (RCore *core, ut64 addr, int count, int depth);
|
||||
R_API void r_core_anal_refs(RCore *core, ut64 addr, int gv);
|
||||
R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head);
|
||||
|
Loading…
x
Reference in New Issue
Block a user