mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-30 08:30:53 +00:00
Add and use the new Indirect Code XREF type to improve code coverage ##analysis
This commit is contained in:
parent
114096b8c4
commit
c8d18b8123
@ -354,6 +354,7 @@ static void check_purity(HtUP *ht, RAnalFunction *fcn) {
|
||||
switch (rt) {
|
||||
case R_ANAL_REF_TYPE_CALL:
|
||||
case R_ANAL_REF_TYPE_CODE:
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
{
|
||||
RAnalFunction *called_fcn = r_anal_get_fcn_in (fcn->anal, ref->addr, 0);
|
||||
if (!called_fcn) {
|
||||
@ -1059,25 +1060,31 @@ repeat:
|
||||
}
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_LOAD:
|
||||
// R2R db/anal/arm db/esil/apple
|
||||
if (anal->iob.is_valid_offset (anal->iob.io, op->ptr, 0)) {
|
||||
// TODO: what about the qword loads!??!?
|
||||
ut8 dd[4] = {0};
|
||||
(void)anal->iob.read_at (anal->iob.io, op->ptr, (ut8 *) dd, sizeof (dd));
|
||||
// if page have exec perms
|
||||
ut64 da = (ut64)r_read_ble32 (dd, R_ARCH_CONFIG_IS_BIG_ENDIAN (anal->config));
|
||||
if (da != UT32_MAX && anal->iob.is_valid_offset (anal->iob.io, da, 0)) {
|
||||
if (da != UT32_MAX && da != UT64_MAX && anal->iob.is_valid_offset (anal->iob.io, da, 0)) {
|
||||
/// R2_590 - this must be CODE | READ , not CODE|DATA, but raises 10 fails
|
||||
r_anal_xrefs_set (anal, op->addr, da, R_ANAL_REF_TYPE_CODE | R_ANAL_REF_TYPE_DATA);
|
||||
// r_anal_xrefs_set (anal, op->addr, da, R_ANAL_REF_TYPE_CODE | R_ANAL_REF_TYPE_DATA);
|
||||
r_anal_xrefs_set (anal, op->addr, da, R_ANAL_REF_TYPE_ICOD | R_ANAL_REF_TYPE_EXEC);
|
||||
} else {
|
||||
R_LOG_DEBUG ("Invalid refs 0x%08"PFMT64x" .. 0x%08"PFMT64x" .. 0x%08"PFMT64x" not adding", op->addr, op->ptr, da);
|
||||
/// XXX this breaks the db/esil/apple tests
|
||||
// r_meta_set (anal, R_META_TYPE_DATA, op->ptr, 4, "");
|
||||
}
|
||||
r_anal_xrefs_set (anal, op->addr, op->ptr, R_ANAL_REF_TYPE_DATA);
|
||||
// maybe optional or in the else
|
||||
// r_anal_xrefs_set (anal, op->addr, op->ptr, R_ANAL_REF_TYPE_DATA);
|
||||
if (anal->opt.loads) {
|
||||
// set this address as data if destination is not code
|
||||
if (anal->iob.is_valid_offset (anal->iob.io, op->ptr, 0)) {
|
||||
r_meta_set (anal, R_META_TYPE_DATA, op->ptr, 4, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
// Case of valid but unused "add [rax], al"
|
||||
case R_ANAL_OP_TYPE_ADD:
|
||||
if (is_arm && anal->config->bits == 32) {
|
||||
|
@ -364,8 +364,8 @@ R_API const char *r_anal_ref_type_tostring(RAnalRefType type) {
|
||||
case ' ':
|
||||
case R_ANAL_REF_TYPE_NULL:
|
||||
return "NULL";
|
||||
case R_ANAL_REF_TYPE_CODE | R_ANAL_REF_TYPE_DATA:
|
||||
return "ICOD"; // indirect code reference
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
return "ICOD";
|
||||
case R_ANAL_REF_TYPE_CODE:
|
||||
return "CODE";
|
||||
case R_ANAL_REF_TYPE_CALL:
|
||||
@ -374,9 +374,10 @@ R_API const char *r_anal_ref_type_tostring(RAnalRefType type) {
|
||||
return "JUMP";
|
||||
case R_ANAL_REF_TYPE_DATA:
|
||||
return "DATA";
|
||||
case R_ANAL_REF_TYPE_STRING:
|
||||
case R_ANAL_REF_TYPE_STRN:
|
||||
return "STRN";
|
||||
default:
|
||||
// R_LOG_ERROR("Invalid unknown ref type %c", R_ANAL_REF_TYPE_MASK (type));
|
||||
return "UNKN";
|
||||
}
|
||||
}
|
||||
@ -414,12 +415,16 @@ R_API int r_anal_ref_typemask(int x) {
|
||||
const int maskedType = x & 0xff;
|
||||
switch (maskedType) {
|
||||
case R_ANAL_REF_TYPE_NULL:
|
||||
case R_ANAL_REF_TYPE_CODE | R_ANAL_REF_TYPE_DATA: // 'g' // XXX R2_590 - this is a conflictive type
|
||||
case R_ANAL_REF_TYPE_CODE: // 'c' // code ref
|
||||
case R_ANAL_REF_TYPE_CALL: // 'C' // code ref (call)
|
||||
case R_ANAL_REF_TYPE_JUMP: // 'j' // code ref (call)
|
||||
case R_ANAL_REF_TYPE_DATA: // 'd' // mem ref
|
||||
case R_ANAL_REF_TYPE_STRN: // 's' // string ref
|
||||
case R_ANAL_REF_TYPE_STRN: // 's' // string ref
|
||||
case R_ANAL_REF_TYPE_ICOD: // 'i' // indirect cod reference
|
||||
return maskedType;
|
||||
case ' ':
|
||||
return R_ANAL_REF_TYPE_NULL;
|
||||
}
|
||||
R_LOG_ERROR ("Invalid reftype mask '%c' (0x%02x)", x, x);
|
||||
// SHOULD NEVER HAPPEN MAYBE WARN HERE
|
||||
@ -433,6 +438,7 @@ R_API RAnalRefType r_anal_xrefs_type(char ch) {
|
||||
case R_ANAL_REF_TYPE_CALL:
|
||||
case R_ANAL_REF_TYPE_DATA:
|
||||
case R_ANAL_REF_TYPE_STRN:
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
case R_ANAL_REF_TYPE_NULL:
|
||||
return (RAnalRefType)ch;
|
||||
default:
|
||||
|
@ -658,18 +658,35 @@ static void r_anal_analyze_fcn_refs(RCore *core, RAnalFunction *fcn, int depth)
|
||||
continue;
|
||||
}
|
||||
int rt = R_ANAL_REF_TYPE_MASK (ref->type);
|
||||
if (rt == R_ANAL_REF_TYPE_DATA) {
|
||||
switch (rt) {
|
||||
case R_ANAL_REF_TYPE_DATA:
|
||||
if (core->anal->opt.followdatarefs) {
|
||||
r_anal_try_get_fcn (core, ref, depth, 2);
|
||||
}
|
||||
} else if (rt == R_ANAL_REF_TYPE_CODE || rt == R_ANAL_REF_TYPE_CALL) {
|
||||
break;
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
// check if its used as data or code.. or at least check what's in the destination
|
||||
{
|
||||
const int t = r_anal_data_type (core->anal, ref->addr);
|
||||
switch (R_ANAL_REF_TYPE_MASK (t)) {
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
case R_ANAL_REF_TYPE_CODE:
|
||||
r_core_anal_fcn (core, ref->addr, ref->at, ref->type, depth - 1);
|
||||
break;
|
||||
case R_ANAL_REF_TYPE_DATA:
|
||||
// TODO: maybe check if the contents of dst is a pointer to code
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case R_ANAL_REF_TYPE_CODE:
|
||||
case R_ANAL_REF_TYPE_CALL:
|
||||
r_core_anal_fcn (core, ref->addr, ref->at, ref->type, depth - 1);
|
||||
break;
|
||||
}
|
||||
// TODO: fix memleak here, fcn not freed even though it is
|
||||
// added in core->anal->fcns which is freed in r_anal_free ()
|
||||
}
|
||||
r_list_free (refs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void function_rename(RFlag *flags, RAnalFunction *fcn) {
|
||||
@ -1995,9 +2012,8 @@ R_API bool r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
||||
// 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
|
||||
int rt = R_ANAL_REF_TYPE_MASK (reftype);
|
||||
int ft = R_ANAL_REF_TYPE_MASK (fcn->type);
|
||||
if (rt == R_ANAL_REF_TYPE_CALL && ft == R_ANAL_FCN_TYPE_LOC) {
|
||||
const int rt = R_ANAL_REF_TYPE_MASK (reftype);
|
||||
if (rt == R_ANAL_REF_TYPE_CALL && fcn->type == R_ANAL_FCN_TYPE_LOC) {
|
||||
function_rename (core->flags, fcn);
|
||||
}
|
||||
return 0; // already analyzed function
|
||||
@ -2986,7 +3002,7 @@ static int fcn_print_json(RCore *core, RAnalFunction *fcn, bool dorefs, PJ *pj)
|
||||
pj_a (pj);
|
||||
r_list_foreach (xrefs, iter, refi) {
|
||||
int rt = R_ANAL_REF_TYPE_MASK (refi->type);
|
||||
if (rt == R_ANAL_REF_TYPE_CODE || rt == R_ANAL_REF_TYPE_CALL) {
|
||||
if (rt == R_ANAL_REF_TYPE_CODE || rt == R_ANAL_REF_TYPE_CALL || rt == R_ANAL_REF_TYPE_ICOD) {
|
||||
indegree++;
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "addr", refi->addr);
|
||||
@ -3147,6 +3163,8 @@ static int fcn_print_detail(RCore *core, RAnalFunction *fcn) {
|
||||
r_cons_printf ("axC 0x%"PFMT64x" 0x%"PFMT64x"\n", refi->addr, refi->at);
|
||||
} else if (t == R_ANAL_REF_TYPE_DATA) {
|
||||
r_cons_printf ("axd 0x%"PFMT64x" 0x%"PFMT64x"\n", refi->addr, refi->at);
|
||||
} else if (t == R_ANAL_REF_TYPE_ICOD) {
|
||||
r_cons_printf ("axi 0x%"PFMT64x" 0x%"PFMT64x"\n", refi->addr, refi->at);
|
||||
} else if (t == R_ANAL_REF_TYPE_CODE) {
|
||||
r_cons_printf ("axc 0x%"PFMT64x" 0x%"PFMT64x"\n", refi->addr, refi->at);
|
||||
} else if (t == R_ANAL_REF_TYPE_STRING) {
|
||||
@ -3244,7 +3262,8 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn, bool dorefs) {
|
||||
r_cons_printf ("\ncode-xrefs:");
|
||||
r_list_foreach (xrefs, iter, refi) {
|
||||
int rt = R_ANAL_REF_TYPE_MASK (refi->type);
|
||||
if (rt == R_ANAL_REF_TYPE_CODE || rt == R_ANAL_REF_TYPE_CALL) {
|
||||
// TODO: just check for the exec perm
|
||||
if (rt == R_ANAL_REF_TYPE_CODE || rt == R_ANAL_REF_TYPE_CALL || rt == R_ANAL_REF_TYPE_ICOD) {
|
||||
indegree++;
|
||||
r_cons_printf (" 0x%08"PFMT64x" %c", refi->addr,
|
||||
rt == R_ANAL_REF_TYPE_CALL? 'C': 'J');
|
||||
@ -4227,6 +4246,7 @@ static bool found_xref(RCore *core, ut64 at, ut64 xref_to, RAnalRefType type, PJ
|
||||
// Display in radare commands format
|
||||
char *cmd;
|
||||
switch (type) {
|
||||
case R_ANAL_REF_TYPE_ICOD: cmd = "axi"; break;
|
||||
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;
|
||||
|
@ -1016,6 +1016,7 @@ static RCoreHelpMessage help_msg_ax = {
|
||||
"axg", " [addr]", "show xrefs graph to reach current function",
|
||||
"axg*", " [addr]", "show xrefs graph to given address, use .axg*;aggv",
|
||||
"axgj", " [addr]", "show xrefs graph to reach current function in json format",
|
||||
"axi", " addr [at]", "add indirect code reference (see ax?)",
|
||||
"axj", "", "add jmp reference", // list refs in json format",
|
||||
"axl", "[jcq]", "list xrefs (axlc = count, axlq = quiet, axlj = json)",
|
||||
"axm", " addr [at]", "copy data/code references pointing to addr to also point to curseek (or at)",
|
||||
@ -5284,6 +5285,7 @@ static int cmd_af(RCore *core, const char *input) {
|
||||
r_cons_printf ("0x%08" PFMT64x " ", ref->addr);
|
||||
break;
|
||||
case R_ANAL_REF_TYPE_CODE:
|
||||
case R_ANAL_REF_TYPE_ICOD:
|
||||
case R_ANAL_REF_TYPE_JUMP:
|
||||
case R_ANAL_REF_TYPE_CALL:
|
||||
case R_ANAL_REF_TYPE_DATA:
|
||||
@ -9672,31 +9674,36 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
|
||||
break;
|
||||
case 'C': // "axC"
|
||||
case 'c': // "axc"
|
||||
case 'i': // "axi"
|
||||
case 'r': // "axr"
|
||||
case 'w': // "axw"
|
||||
case 'j': // "axj"
|
||||
case 'd': // "axd"
|
||||
case 's': // "axs"
|
||||
case ' ': // "ax "
|
||||
{
|
||||
char *ptr = strdup (r_str_trim_head_ro ((char *)input + 1));
|
||||
int n = r_str_word_set0 (ptr);
|
||||
ut64 at = core->offset;
|
||||
ut64 addr = UT64_MAX;
|
||||
RAnalRefType reftype = r_anal_xrefs_type (input[0]);
|
||||
switch (n) {
|
||||
case 2: // get at
|
||||
at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
||||
/* fall through */
|
||||
case 1: // get addr
|
||||
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
||||
break;
|
||||
default:
|
||||
if (input[1] == '?') {
|
||||
char *s = r_str_newf ("ax%c", input[0]);
|
||||
r_core_cmd_help_match (core, help_msg_ax, s, true);
|
||||
free (s);
|
||||
} else {
|
||||
char *ptr = strdup (r_str_trim_head_ro ((char *)input + 1));
|
||||
int n = r_str_word_set0 (ptr);
|
||||
ut64 at = core->offset;
|
||||
ut64 addr = UT64_MAX;
|
||||
RAnalRefType reftype = r_anal_xrefs_type (input[0]);
|
||||
switch (n) {
|
||||
case 2: // get at
|
||||
at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
||||
/* fall through */
|
||||
case 1: // get addr
|
||||
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
||||
break;
|
||||
default:
|
||||
free (ptr);
|
||||
return false;
|
||||
}
|
||||
r_anal_xrefs_set (core->anal, at, addr, reftype);
|
||||
free (ptr);
|
||||
return false;
|
||||
}
|
||||
r_anal_xrefs_set (core->anal, at, addr, reftype);
|
||||
free (ptr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -659,8 +659,9 @@ typedef enum {
|
||||
R_ANAL_REF_TYPE_CALL = 'C', // code ref (call) -- maybe use 'k' for kall?
|
||||
R_ANAL_REF_TYPE_JUMP = 'j', // code ref (call)
|
||||
R_ANAL_REF_TYPE_DATA = 'd', // mem ref
|
||||
R_ANAL_REF_TYPE_STRING = 's', // string ref // R_DEPRECATE
|
||||
R_ANAL_REF_TYPE_STRN = 's', // string ref
|
||||
R_ANAL_REF_TYPE_ICOD = 'i', // indirect code reference
|
||||
R_ANAL_REF_TYPE_STRING = 's', // string ref // R_DEPRECATE
|
||||
R_ANAL_REF_TYPE_STRN = 's', // string ref
|
||||
// perm / direction
|
||||
R_ANAL_REF_TYPE_READ = 4 << 8,
|
||||
R_ANAL_REF_TYPE_WRITE = 2 << 8,
|
||||
|
Loading…
Reference in New Issue
Block a user