mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
Initial support for 'an' aka no-return analysis points
This commit is contained in:
parent
c0da7a1c9e
commit
d91df64286
@ -75,6 +75,7 @@ R_API RAnal *r_anal_new() {
|
||||
RAnal *anal = R_NEW0 (RAnal);
|
||||
if (!anal) return NULL;
|
||||
anal->os = strdup (R_SYS_OS);
|
||||
anal->noreturn = r_list_newf ((RListFree)&r_anal_noreturn_free);
|
||||
anal->reflines = anal->reflines2 = NULL;
|
||||
anal->esil_goto_limit = R_ANAL_ESIL_GOTO_LIMIT;
|
||||
anal->limit = NULL;
|
||||
@ -132,6 +133,7 @@ R_API RAnal *r_anal_free(RAnal *a) {
|
||||
/* TODO: Free anals here */
|
||||
R_FREE (a->cpu);
|
||||
r_list_free (a->plugins);
|
||||
r_list_free (a->noreturn);
|
||||
a->fcns->free = r_anal_fcn_free;
|
||||
r_list_free (a->fcns);
|
||||
r_space_fini (&a->meta_spaces);
|
||||
@ -404,3 +406,93 @@ R_API int r_anal_archinfo(RAnal *anal, int query) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
R_API void r_anal_noreturn_free(RAnalNoreturn *nr) {
|
||||
free (nr->name);
|
||||
free (nr);
|
||||
}
|
||||
|
||||
R_API void r_anal_noreturn_list(RAnal *anal, int mode) {
|
||||
RListIter *iter;
|
||||
RAnalNoreturn *nr;
|
||||
r_list_foreach (anal->noreturn, iter, nr) {
|
||||
switch (mode) {
|
||||
case 1:
|
||||
case '*':
|
||||
case 'r':
|
||||
if (nr->name) anal->cb_printf ("ann %s\n", nr->name);
|
||||
else anal->cb_printf ("0x%08"PFMT64x"\n", nr->addr);
|
||||
break;
|
||||
default:
|
||||
if (nr->name) anal->cb_printf ("%s\n", nr->name);
|
||||
else anal->cb_printf ("0x%08"PFMT64x"\n", nr->addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_API bool r_anal_noreturn_add(RAnal *anal, const char *name, ut64 addr) {
|
||||
RAnalNoreturn *nr = R_NEW0(RAnalNoreturn);
|
||||
if (!nr) return false;
|
||||
if (name && *name) nr->name = strdup (name);
|
||||
nr->addr = addr;
|
||||
if (!nr->name && !nr->addr) {
|
||||
free (nr);
|
||||
return false;
|
||||
}
|
||||
r_list_append (anal->noreturn, nr);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_anal_noreturn_drop(RAnal *anal, const char *expr) {
|
||||
bool ret = false;
|
||||
if (!strcmp (expr, "*")) {
|
||||
if (!r_list_empty (anal->noreturn)) {
|
||||
r_list_free (anal->noreturn);
|
||||
anal->noreturn = r_list_newf ((RListFree)&r_anal_noreturn_free);
|
||||
ret = true;
|
||||
}
|
||||
} else {
|
||||
RListIter *iter, *iter2;
|
||||
RAnalNoreturn *nr;
|
||||
if (!strncmp (expr, "0x", 2)) {
|
||||
ut64 n = r_num_math (NULL, expr);
|
||||
r_list_foreach_safe (anal->noreturn, iter, iter2, nr) {
|
||||
if (nr->addr == n) {
|
||||
r_list_delete (anal->noreturn, iter);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r_list_foreach_safe (anal->noreturn, iter, iter2, nr) {
|
||||
if (r_str_glob (nr->name, expr)) {
|
||||
r_list_delete (anal->noreturn, iter);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API bool r_anal_noreturn_at(RAnal *anal, ut64 addr) {
|
||||
RListIter *iter;
|
||||
RAnalNoreturn *nr;
|
||||
RAnalFunction *f = r_anal_get_fcn_at (anal, addr, 0);
|
||||
RFlagItem *fi = anal->flb.get_at (anal->flb.f, addr);
|
||||
r_list_foreach (anal->noreturn, iter, nr) {
|
||||
if (nr->name) {
|
||||
RFlagItem *fi2 = anal->flb.get (anal->flb.f, nr->name);
|
||||
if (fi2 && fi2->offset == addr)
|
||||
return true;
|
||||
if (f && !strcmp (f->name, nr->name))
|
||||
return true;
|
||||
if (fi && fi->name && !strcmp (fi->name, nr->name))
|
||||
return true;
|
||||
} else {
|
||||
if (addr == nr->addr)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -448,6 +448,11 @@ repeat:
|
||||
}
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
if (r_anal_noreturn_at (anal, op.jump)) {
|
||||
FITFCNSZ ();
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_END;
|
||||
}
|
||||
if (anal->opt.eobjmp) {
|
||||
FITFCNSZ();
|
||||
op.jump = UT64_MAX;
|
||||
@ -583,6 +588,11 @@ repeat:
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_CCALL:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
if (r_anal_noreturn_at (anal, op.jump)) {
|
||||
FITFCNSZ ();
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_END;
|
||||
}
|
||||
(void)r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CALL);
|
||||
#if CALL_IS_EOB
|
||||
recurseAt (op.jump);
|
||||
|
@ -1991,6 +1991,52 @@ static void cmd_anal_esil(RCore *core, const char *input) {
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_anal_noreturn(RCore *core, const char *input) {
|
||||
const char* help_msg[] = {
|
||||
"Usage:", "an [-][0xaddr|symname]", " manage no-return marks",
|
||||
"an[a]", " 0x3000", "stop function analysis if call/jmp to this address",
|
||||
"an[n]", " sym.imp.exit", "same as above but for flag/fcn names",
|
||||
"an", "-*", "remove all no-return references",
|
||||
"an", "", "list them all",
|
||||
"ao*", "", "display opcode in r commands",
|
||||
NULL};
|
||||
switch (input[0]) {
|
||||
case '-':
|
||||
r_anal_noreturn_drop (core->anal, input+1);
|
||||
break;
|
||||
case ' ':
|
||||
if (input[1] == '0' && input[2] == 'x') {
|
||||
r_anal_noreturn_add (core->anal, NULL,
|
||||
r_num_math (core->num, input+1));
|
||||
} else {
|
||||
r_anal_noreturn_add (core->anal, input+1,
|
||||
r_num_math (core->num, input+1));
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
if (input[1] == ' ') {
|
||||
r_anal_noreturn_add (core->anal, NULL,
|
||||
r_num_math (core->num, input+1));
|
||||
} else r_core_cmd_help (core, help_msg);
|
||||
break;
|
||||
case 'n':
|
||||
if (input[1] == ' ') {
|
||||
} else r_core_cmd_help (core, help_msg);
|
||||
break;
|
||||
case '*':
|
||||
case 'r':
|
||||
r_anal_noreturn_list (core->anal, 1);
|
||||
break;
|
||||
case 0:
|
||||
r_anal_noreturn_list (core->anal, 0);
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
r_core_cmd_help (core, help_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_anal_opcode(RCore *core, const char *input) {
|
||||
int l, len = core->blocksize;
|
||||
ut32 tbs = core->blocksize;
|
||||
@ -3099,6 +3145,7 @@ static int cmd_anal(void *data, const char *input) {
|
||||
"ah", "[?lba-]", "analysis hints (force opcode size, ...)",
|
||||
"ai", " [addr]", "address information (show perms, stack, heap, ...)",
|
||||
"ao", "[e?] [len]", "analyze Opcodes (or emulate it)",
|
||||
"an", "[an-] [...]", "manage no-return addresses/symbols/functions",
|
||||
"ar", "", "like 'dr' but for the esil vm. (registers)",
|
||||
"ax", "[?ld-*]", "manage refs/xrefs (see also afx?)",
|
||||
"as", " [num]", "analyze syscall using dbg.reg",
|
||||
@ -3123,6 +3170,7 @@ static int cmd_anal(void *data, const char *input) {
|
||||
case 'r': cmd_anal_reg (core, input+1); break; // "ar"
|
||||
case 'e': cmd_anal_esil (core, input+1); break; // "ae"
|
||||
case 'o': cmd_anal_opcode (core, input+1); break;
|
||||
case 'n': cmd_anal_noreturn (core, input+1); break; // "an"
|
||||
case 'F':
|
||||
r_core_anal_fcn (core, core->offset, UT64_MAX, R_ANAL_REF_TYPE_NULL, 1);
|
||||
break;
|
||||
|
@ -622,6 +622,7 @@ R_API const char *r_flag_color(RFlag *f, RFlagItem *it, const char *color) {
|
||||
R_API int r_flag_bind (RFlag *f, RFlagBind *fb) {
|
||||
fb->f = f;
|
||||
fb->get = r_flag_get;
|
||||
fb->get_at = r_flag_get_at;
|
||||
fb->set = r_flag_set;
|
||||
fb->set_fs = r_flag_space_set;
|
||||
return 0;
|
||||
|
@ -634,6 +634,7 @@ typedef struct r_anal_t {
|
||||
RAnalOptions opt;
|
||||
RList *reflines;
|
||||
RList *reflines2;
|
||||
RList *noreturn;
|
||||
} RAnal;
|
||||
|
||||
typedef struct r_anal_hint_t {
|
||||
@ -927,7 +928,13 @@ typedef struct r_anal_reil {
|
||||
char pc[8];
|
||||
} RAnalReil;
|
||||
|
||||
#define ESIL_INTERNAL_PREFIX '$' //must be a char
|
||||
typedef struct r_anal_noreturn_t {
|
||||
char *name;
|
||||
ut64 addr;
|
||||
} RAnalNoreturn;
|
||||
|
||||
// must be a char
|
||||
#define ESIL_INTERNAL_PREFIX '$'
|
||||
#define ESIL struct r_anal_esil_t
|
||||
|
||||
typedef struct r_anal_esil_callbacks_t {
|
||||
@ -1476,6 +1483,12 @@ R_API void r_anal_unset_limits(RAnal *anal);
|
||||
/* ESIL to REIL */
|
||||
R_API int r_anal_esil_to_reil_setup (RAnalEsil *esil, RAnal *anal, int romem, int stats);
|
||||
|
||||
/* no-return stuff */
|
||||
R_API void r_anal_noreturn_list(RAnal *anal, int mode);
|
||||
R_API void r_anal_noreturn_free(RAnalNoreturn *nr);
|
||||
R_API bool r_anal_noreturn_add(RAnal *anal, const char *name, ut64 addr);
|
||||
R_API int r_anal_noreturn_drop(RAnal *anal, const char *expr);
|
||||
|
||||
/* plugin pointers */
|
||||
extern RAnalPlugin r_anal_plugin_null;
|
||||
extern RAnalPlugin r_anal_plugin_csr;
|
||||
|
@ -60,6 +60,7 @@ typedef struct r_flag_t {
|
||||
|
||||
#include <r_flags.h> // compile time line, no linkage needed
|
||||
typedef RFlagItem* (*RFlagGet)(RFlag *f, const char *name);
|
||||
typedef RFlagItem* (*RFlagGetAt)(RFlag *f, ut64 addr);
|
||||
typedef RFlagItem* (*RFlagSet)(RFlag *f, const char *name, ut64 addr, ut32 size, int dup);
|
||||
typedef int (*RFlagSetSpace)(RFlag *f, const char *name);
|
||||
|
||||
@ -67,6 +68,7 @@ typedef struct r_flag_bind_t {
|
||||
int init;
|
||||
RFlag *f;
|
||||
RFlagGet get;
|
||||
RFlagGetAt get_at;
|
||||
RFlagSet set;
|
||||
RFlagSetSpace set_fs;
|
||||
} RFlagBind;
|
||||
|
Loading…
Reference in New Issue
Block a user