Code cleanup for some var analysis code

This commit is contained in:
pancake 2017-08-09 19:21:53 +02:00 committed by radare
parent 53fb6d668d
commit a62b33e939
6 changed files with 132 additions and 159 deletions

View File

@ -4,6 +4,9 @@
#include <r_util.h>
#include <r_list.h>
#define VARPREFIX "local"
#define ARGPREFIX "arg"
#define USE_SDB_CACHE 0
#define SDB_KEY_BB "bb.0x%"PFMT64x ".0x%"PFMT64x
// XXX must be configurable by the user
@ -264,8 +267,7 @@ static RAnalBlock *appendBasicBlock(RAnal *anal, RAnalFunction *fcn, ut64 addr)
r_anal_fcn_set_size (fcn, 0);\
return R_ANAL_RET_ERROR; }
#define VARPREFIX "local"
#define ARGPREFIX "arg"
// ETOOSLOW
static char *get_varname(RAnal *a, RAnalFunction *fcn, char type, const char *pfx, int idx) {
char *varname = r_str_newf ("%s_%xh", pfx, idx);
int i = 2;
@ -284,8 +286,8 @@ static char *get_varname(RAnal *a, RAnalFunction *fcn, char type, const char *pf
r_anal_var_free (v);
break;
}
free (varname);
r_anal_var_free (v);
free (varname);
varname = r_str_newf ("%s_%xh_%d", pfx, idx, i);
i++;
}
@ -369,70 +371,69 @@ static ut64 search_reg_val(RAnal *anal, ut8 *buf, ut64 len, ut64 addr, char *reg
#define gotoBeachRet() goto beach;
static void extract_arg(RAnal *anal, RAnalFunction *fcn, RAnalOp *op, const char *reg, const char *sign, char type) {
char *varname, *esil_buf, *ptr_end, *addr, *op_esil;
char sigstr[16] = {0};
st64 ptr;
char *sig = r_str_newf (",%s,%s", reg, sign);
if (!sig || !anal) {
free (sig);
char *addr;
if (!anal || !fcn || !op) {
return;
}
op_esil = r_strbuf_get (&op->esil);
// snprintf (sigstr, sizeof (sigstr), ",%s,%s", reg, sign);
snprintf (sigstr, sizeof (sigstr), ",%s,%s", reg, sign);
const char *op_esil = r_strbuf_get (&op->esil);
if (!op_esil) {
free (sig);
return;
}
esil_buf = strdup (op_esil);
char *esil_buf = strdup (op_esil);
if (!esil_buf) {
free (sig);
free (op_esil);
return;
}
ptr_end = strstr (esil_buf, sig);
char *ptr_end = strstr (esil_buf, sigstr);
if (!ptr_end) {
free (sig);
free (esil_buf);
return;
}
#if 1
*ptr_end = 0;
addr = ptr_end;
while ((addr[0] != '0' || addr[1] != 'x') &&
addr >= esil_buf + 1 && *addr != ',') {
while ((addr[0] != '0' || addr[1] != 'x') && addr >= esil_buf + 1 && *addr != ',') {
addr--;
}
if (strncmp (addr, "0x", 2)) {
free (sig);
free (esil_buf);
return;
}
ptr = (st64) r_num_get (NULL, addr);
#else
ptr = -op->ptr;
if (ptr%4) {
free (esil_buf);
return;
}
#endif
if (*sign == '+') {
if (ptr < fcn->maxstack && type == 's') {
varname = get_varname (anal, fcn, type, VARPREFIX, R_ABS (ptr));
} else {
varname = get_varname (anal, fcn, type, ARGPREFIX, R_ABS (ptr));
}
const char *pfx = (ptr < fcn->maxstack && type == 's')? VARPREFIX: ARGPREFIX;
char *varname = get_varname (anal, fcn, type, pfx, R_ABS (ptr));
r_anal_var_add (anal, fcn->addr, 1, ptr, type, NULL, anal->bits / 8, varname);
r_anal_var_access (anal, fcn->addr, type, 1, ptr, 0, op->addr);
free (varname);
} else {
varname = get_varname (anal, fcn, type, VARPREFIX, R_ABS (ptr));
char *varname = get_varname (anal, fcn, type, VARPREFIX, R_ABS (ptr));
r_anal_var_add (anal, fcn->addr, 1, -ptr, type, NULL, anal->bits / 8, varname);
r_anal_var_access (anal, fcn->addr, type, 1, -ptr, 1, op->addr);
free (varname);
}
free (varname);
free (sig);
free (esil_buf);
}
R_API void fill_args(RAnal *anal, RAnalFunction *fcn, RAnalOp *op) {
if (anal && anal->reg) {
extract_arg (anal, fcn, op, anal->reg->name[R_REG_NAME_BP], "+", 'b');
extract_arg (anal, fcn, op, anal->reg->name[R_REG_NAME_BP], "-", 'b');
extract_arg (anal, fcn, op, anal->reg->name[R_REG_NAME_SP], "+", 's');
R_API void r_anal_fcn_fill_args(RAnal *anal, RAnalFunction *fcn, RAnalOp *op) {
if (!anal || !fcn || !op) {
return;
}
extract_arg (anal, fcn, op, "bp", "+", 'b');
extract_arg (anal, fcn, op, "bp", "-", 'b');
extract_arg (anal, fcn, op, "sp", "+", 's');
const char *BP = anal->reg->name[R_REG_NAME_BP];
const char *SP = anal->reg->name[R_REG_NAME_SP];
extract_arg (anal, fcn, op, BP, "+", 'b');
extract_arg (anal, fcn, op, BP, "-", 'b');
extract_arg (anal, fcn, op, SP, "+", 's');
}
static bool isInvalidMemory(const ut8 *buf, int len) {

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2016 - pancake, nibble */
/* radare - LGPL - Copyright 2010-2017 - pancake, nibble */
#include <r_anal.h>
#include <r_util.h>
@ -27,10 +27,9 @@ R_API RAnalOp *r_anal_op_new () {
R_API RList *r_anal_op_list_new() {
RList *list = r_list_new ();
if (!list) {
return NULL;
if (list) {
list->free = &r_anal_op_free;
}
list->free = &r_anal_op_free;
return list;
}
@ -68,19 +67,16 @@ static RAnalVar *get_used_var(RAnal *anal, RAnalOp *op) {
char *inst_key = sdb_fmt (0, "inst.0x%"PFMT64x".vars", op->addr);
const char *var_def = sdb_const_get (anal->sdb_fcns, inst_key, 0);
struct VarUsedType vut;
RAnalVar *res;
if (sdb_fmt_tobin (var_def, SDB_VARUSED_FMT, &vut) != 4) {
return NULL;
}
res = r_anal_var_get (anal, vut.fcn_addr, vut.type[0], vut.scope, vut.delta);
RAnalVar *res = r_anal_var_get (anal, vut.fcn_addr, vut.type[0], vut.scope, vut.delta);
sdb_fmt_free (&vut, SDB_VARUSED_FMT);
return res;
}
R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
int ret = 0;
RAnalVar *tmp;
//len will end up in memcmp so check for negative
if (!anal || len < 0) {
return -1;
@ -101,31 +97,29 @@ R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
if (anal && anal->coreb.archbits) {
anal->coreb.archbits (anal->coreb.core, addr);
}
ret = anal->cur->op (anal, op, addr, data, len);
int ret = anal->cur->op (anal, op, addr, data, len);
if (ret < 1) {
op->type = R_ANAL_OP_TYPE_ILL;
}
op->addr = addr;
/* consider at least 1 byte to be part of the opcode */
if (op->nopcode < 1) {
op->nopcode = 1;
}
//free the previous var in op->var
tmp = get_used_var (anal, op);
RAnalVar *tmp = get_used_var (anal, op);
if (tmp) {
r_anal_var_free (op->var);
op->var = tmp;
}
if (ret < 1) {
op->type = R_ANAL_OP_TYPE_ILL;
}
} else {
if (!memcmp (data, "\xff\xff\xff\xff", R_MIN (4, len))) {
op->type = R_ANAL_OP_TYPE_ILL;
ret = R_MIN (2, len); // HACK
} else {
op->type = R_ANAL_OP_TYPE_MOV;
ret = R_MIN (2, len); // HACK
}
return ret;
}
return ret;
if (!memcmp (data, "\xff\xff\xff\xff", R_MIN (4, len))) {
op->type = R_ANAL_OP_TYPE_ILL;
return R_MIN (2, len); // HACK
}
op->type = R_ANAL_OP_TYPE_MOV;
return R_MIN (2, len); // HACK
}
R_API RAnalOp *r_anal_op_copy(RAnalOp *op) {
@ -291,8 +285,7 @@ R_API const char *r_anal_op_to_esil_string(RAnal *anal, RAnalOp *op) {
R_API char *r_anal_op_to_string(RAnal *anal, RAnalOp *op) {
RAnalBlock *bb;
RAnalFunction *f;
char ret[128];
char *cstr;
char *cstr, ret[128];
char *r0 = r_anal_value_to_string (op->dst);
char *a0 = r_anal_value_to_string (op->src[0]);
char *a1 = r_anal_value_to_string (op->src[1]);
@ -337,8 +330,11 @@ R_API char *r_anal_op_to_string(RAnal *anal, RAnalOp *op) {
break;
case R_ANAL_OP_TYPE_CALL:
f = r_anal_get_fcn_in (anal, op->jump, R_ANAL_FCN_TYPE_NULL);
if (f) snprintf (ret, sizeof (ret), "%s()", f->name);
else snprintf (ret, sizeof (ret), "0x%"PFMT64x"()", op->jump);
if (f) {
snprintf (ret, sizeof (ret), "%s()", f->name);
} else {
snprintf (ret, sizeof (ret), "0x%"PFMT64x"()", op->jump);
}
break;
case R_ANAL_OP_TYPE_CCALL:
f = r_anal_get_fcn_in (anal, op->jump, R_ANAL_FCN_TYPE_NULL);

View File

@ -2820,7 +2820,7 @@ static char *get_reg_profile(RAnal *anal) {
p = \
"=PC r15\n"
"=LR r14\n"
"=SP r13\n"
"=SP sp\n"
"=BP fp\n"
"=A0 r0\n"
"=A1 r1\n"

View File

@ -51,8 +51,10 @@ R_API bool r_anal_var_display(RAnal *anal, int delta, char kind, const char *typ
return true;
}
R_API int r_anal_var_add(RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name) {
char *var_def;
R_API bool r_anal_var_add(RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name) {
if (!a) {
return false;
}
if (!kind) {
kind = R_ANAL_VAR_KIND_BPV;
}
@ -68,29 +70,29 @@ R_API int r_anal_var_add(RAnal *a, ut64 addr, int scope, int delta, char kind, c
eprintf ("Invalid var kind '%c'\n", kind);
return false;
}
var_def = sdb_fmt (0, "%c,%s,%d,%s", kind, type, size, name);
const char *var_def = sdb_fmt (0, "%c,%s,%d,%s", kind, type, size, name);
if (scope > 0) {
char *sign = "";
const char *sign = "";
if (delta < 0) {
delta = -delta;
sign = "_";
}
/* local variable */
char *fcn_key = sdb_fmt (1, "fcn.0x%"PFMT64x ".%c", addr, kind);
char *var_key = sdb_fmt (2, "var.0x%"PFMT64x ".%c.%d.%s%d", addr, kind, scope, sign, delta);
char *name_key = sdb_fmt (3, "var.0x%"PFMT64x ".%d.%s", addr, scope, name);
char *shortvar = sdb_fmt (4, "%d.%s%d", scope, sign, delta);
const char *fcn_key = sdb_fmt (1, "fcn.0x%"PFMT64x ".%c", addr, kind);
const char *var_key = sdb_fmt (2, "var.0x%"PFMT64x ".%c.%d.%s%d", addr, kind, scope, sign, delta);
const char *name_key = sdb_fmt (3, "var.0x%"PFMT64x ".%d.%s", addr, scope, name);
const char *shortvar = sdb_fmt (4, "%d.%s%d", scope, sign, delta);
sdb_array_add (DB, fcn_key, shortvar, 0);
sdb_set (DB, var_key, var_def, 0);
if (*sign) {
delta = -delta;
}
char *name_val = sdb_fmt (5, "%c,%d", kind, delta);
const char *name_val = sdb_fmt (5, "%c,%d", kind, delta);
sdb_set (DB, name_key, name_val, 0);
} else {
/* global variable */
char *var_global = sdb_fmt (1, "var.0x%"PFMT64x, addr);
char *var_def = sdb_fmt (2, "%c.%s,%d,%s", kind, type, size, name);
const char *var_global = sdb_fmt (1, "var.0x%"PFMT64x, addr);
const char *var_def = sdb_fmt (2, "%c.%s,%d,%s", kind, type, size, name);
sdb_array_add (DB, var_global, var_def, 0);
}
// ls_sort (DB->ht->list, mystrcmp);
@ -117,12 +119,10 @@ R_API int r_anal_var_retype(RAnal *a, ut64 addr, int scope, int delta, char kind
RListIter *iter;
RAnalVar *var;
r_list_foreach (list, iter, var) {
if (delta == -1) {
if (!strcmp (var->name, name)) {
delta = var->delta;
size = var->size;
break;
}
if (delta == -1 && !strcmp (var->name, name)) {
delta = var->delta;
size = var->size;
break;
}
}
r_list_free (list);
@ -136,7 +136,7 @@ R_API int r_anal_var_retype(RAnal *a, ut64 addr, int scope, int delta, char kind
eprintf ("Invalid var kind '%c'\n", kind);
return false;
}
char *var_def = sdb_fmt (0, "%c,%s,%d,%s", kind, type, size, name);
const char *var_def = sdb_fmt (0, "%c,%s,%d,%s", kind, type, size, name);
if (scope > 0) {
char *sign = delta> 0? "": "_";
/* local variable */
@ -176,8 +176,7 @@ R_API int r_anal_var_retype(RAnal *a, ut64 addr, int scope, int delta, char kind
}
R_API int r_anal_var_delete_all(RAnal *a, ut64 addr, const char kind) {
RAnalFunction *fcn;
fcn = r_anal_get_fcn_in (a, addr, 0);
RAnalFunction *fcn = r_anal_get_fcn_in (a, addr, 0);
if (fcn) {
RAnalVar *v;
RListIter *iter;
@ -186,6 +185,7 @@ R_API int r_anal_var_delete_all(RAnal *a, ut64 addr, const char kind) {
// r_anal_var_delete (a, addr, kind, v->scope, v->delta);
r_anal_var_delete (a, addr, kind, 1, v->delta);
}
// XXX: i dont think we want to alocate and free by hand. r_anal_var_delete should be the list->free already
r_list_free (list);
}
return 0;
@ -348,29 +348,10 @@ R_API void r_anal_var_free(RAnalVar *av) {
#define R_ANAL_VAR_SDB_SIZE 2 /* number */
#define R_ANAL_VAR_SDB_NAME 3 /* string */
R_API int r_anal_var_check_name(const char *name) {
// restrict length
// name is not base64'd . because no specials can be contained
// TODO: check that new_name is valid. this is a hack
if (*name == '0' || atoi (name) > 0) {
return 0;
}
if (strchr (name, '.')) {
return 0;
}
if (strchr (name, ',')) {
return 0;
}
if (strchr (name, ' ')) {
return 0;
}
if (strchr (name, '=')) {
return 0;
}
if (strchr (name, '/')) {
return 0;
}
return 1;
#define IS_NUMBER(x) ((x) >= '0' && (x) <= '9')
R_API bool r_anal_var_check_name(const char *name) {
return !IS_NUMBER (*name) && strtok (name, "., =/");
}
// afvn local_48 counter
@ -539,63 +520,60 @@ static void var_add_structure_fields_to_list(RAnal *a, RAnalVar *av, const char
}
static RList *var_generate_list(RAnal *a, RAnalFunction *fcn, int kind, bool dynamicVars) {
char *varlist;
RList *list = NULL;
if (!a || !fcn) {
return NULL;
}
list = r_list_newf ((RListFree) r_anal_var_free);
RList *list = r_list_newf ((RListFree) r_anal_var_free);
if (kind < 1) {
kind = R_ANAL_VAR_KIND_BPV; // by default show vars
}
varlist = sdb_get (DB, sdb_fmt (0, "fcn.0x%"PFMT64x ".%c", fcn->addr, kind), 0);
if (varlist) {
char *varlist = sdb_get (DB, sdb_fmt (0, "fcn.0x%"PFMT64x ".%c", fcn->addr, kind), 0);
if (varlist && *varlist) {
char *next, *ptr = varlist;
if (varlist && *varlist) {
do {
struct VarType vt = {
0
};
char *word = sdb_anext (ptr, &next);
const char *vardef = sdb_const_get (DB, sdb_fmt (1,
"var.0x%"PFMT64x ".%c.%s",
fcn->addr, kind, word), 0);
if (word[2] == '_') {
word[2] = '-';
do {
char *word = sdb_anext (ptr, &next);
if (r_str_nlen (word, 3) < 3) {
return NULL;
}
const char *vardef = sdb_const_get (DB, sdb_fmt (1,
"var.0x%"PFMT64x ".%c.%s",
fcn->addr, kind, word), 0);
if (word[2] == '_') {
word[2] = '-';
}
int delta = atoi (word + 2);
if (vardef) {
struct VarType vt = { 0 };
sdb_fmt_init (&vt, SDB_VARTYPE_FMT);
sdb_fmt_tobin (vardef, SDB_VARTYPE_FMT, &vt);
RAnalVar *av = R_NEW0 (RAnalVar);
if (!av) {
free (varlist);
r_list_free (list);
return NULL;
}
int delta = atoi (word + 2);
if (vardef) {
sdb_fmt_init (&vt, SDB_VARTYPE_FMT);
sdb_fmt_tobin (vardef, SDB_VARTYPE_FMT, &vt);
RAnalVar *av = R_NEW0 (RAnalVar);
if (!av) {
free (varlist);
r_list_free (list);
return NULL;
}
if (!vt.name || !vt.type) {
// This should be properly fixed
eprintf ("Warning null var in fcn.0x%"PFMT64x ".%c.%s\n",
fcn->addr, kind, word);
free (av);
continue;
}
av->delta = delta;
av->kind = kind;
av->name = strdup (vt.name);
av->size = vt.size;
av->type = strdup (vt.type);
r_list_append (list, av);
if (dynamicVars) { // make dynamic variables like structure fields
var_add_structure_fields_to_list (a, av, vt.name, delta, list);
}
sdb_fmt_free (&vt, SDB_VARTYPE_FMT);
} else {
eprintf ("Cannot find var definition for '%s'\n", word);
if (!vt.name || !vt.type) {
// This should be properly fixed
eprintf ("Warning null var in fcn.0x%"PFMT64x ".%c.%s\n",
fcn->addr, kind, word);
free (av);
continue;
}
ptr = next;
} while (next);
}
av->delta = delta;
av->kind = kind;
av->name = strdup (vt.name);
av->size = vt.size;
av->type = strdup (vt.type);
r_list_append (list, av);
if (dynamicVars) { // make dynamic variables like structure fields
var_add_structure_fields_to_list (a, av, vt.name, delta, list);
}
sdb_fmt_free (&vt, SDB_VARTYPE_FMT);
} else {
eprintf ("Cannot find var definition for '%s'\n", word);
}
ptr = next;
} while (next);
}
free (varlist);
return list;
@ -603,7 +581,7 @@ static RList *var_generate_list(RAnal *a, RAnalFunction *fcn, int kind, bool dyn
R_API RList *r_anal_var_all_list(RAnal *anal, RAnalFunction *fcn) {
// r_anal_var_list if there are not vars with that kind returns a list with
// zero element
// zero element.. which is an unnecessary loss of cpu time
RList *list = r_anal_var_list (anal, fcn, R_ANAL_VAR_KIND_ARG);
if (!list) {
return NULL;
@ -650,7 +628,6 @@ R_API void r_anal_var_list_show(RAnal *anal, RAnalFunction *fcn, int kind, int m
}
anal->cb_printf ("afv%c %s %s %s @ 0x%"PFMT64x "\n",
kind, i->name, var->name, var->type, fcn->addr);
} else {
anal->cb_printf ("afv%c %d %s %s @ 0x%"PFMT64x "\n",
kind, var->delta, var->name, var->type,
@ -726,10 +703,9 @@ R_API void r_anal_var_list_show(RAnal *anal, RAnalFunction *fcn, int kind, int m
eprintf ("Register not found");
break;
}
anal->cb_printf ("reg %s %s @ %s\n",
var->type, var->name, i->name);
}
}
break;
case R_ANAL_VAR_KIND_SPV:
if (var->delta < fcn->maxstack) {

View File

@ -2316,7 +2316,7 @@ R_API void fcn_callconv(RCore *core, RAnalFunction *fcn) {
// eprintf ("Cannot get op\n");
break;
}
fill_args (core->anal, fcn, op);
r_anal_fcn_fill_args (core->anal, fcn, op);
int opsize = op->size;
r_anal_op_free (op);
if (opsize < 1) {

View File

@ -1308,7 +1308,7 @@ R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name);
R_API RList *r_anal_fcn_list_new(void);
R_API int r_anal_fcn_insert(RAnal *anal, RAnalFunction *fcn);
R_API void r_anal_fcn_free(void *fcn);
R_API void fill_args (RAnal *anal, RAnalFunction *fcn, RAnalOp *op);
R_API void r_anal_fcn_fill_args (RAnal *anal, RAnalFunction *fcn, RAnalOp *op);
R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr,
ut8 *buf, ut64 len, int reftype);
R_API int r_anal_fcn_add(RAnal *anal, ut64 addr, ut64 size,
@ -1412,7 +1412,7 @@ R_API void r_anal_var_access_free(void *access);
R_API int r_anal_var_delete_all (RAnal *a, ut64 addr, const char kind);
R_API int r_anal_var_delete (RAnal *a, ut64 var_addr, const char kind, int scope, int delta);
R_API bool r_anal_var_delete_byname (RAnal *a, RAnalFunction *fcn, int type, const char *name);
R_API int r_anal_var_add (RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name);
R_API bool r_anal_var_add (RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name);
R_API int r_anal_var_del(RAnal *anal, RAnalFunction *fcn, int delta, int scope);
R_API RAnalVar *r_anal_var_get (RAnal *a, ut64 addr, char kind, int scope, int index);
R_API const char *r_anal_var_scope_to_str(RAnal *anal, int scope);