* More work in var analysis

* Put RAnalVar->type and RAnalVar->dir together
This commit is contained in:
Nibble 2010-12-03 13:52:11 +01:00
parent b955a66459
commit fc11acc128
4 changed files with 60 additions and 52 deletions

View File

@ -63,7 +63,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFcn *fcn, ut64 addr, ut8 *buf, ut64 len,
fcn->ninstr++;
idx += oplen;
fcn->size += oplen;
/* TODO: Parse fastargs (R_ANAL_VAR_ARGREG), check negative ref meaning */
/* TODO: Parse fastargs (R_ANAL_VAR_ARGREG) */
switch (aop.stackop) {
case R_ANAL_STACK_INCSTACK:
fcn->stack += aop.value;
@ -71,24 +71,24 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFcn *fcn, ut64 addr, ut8 *buf, ut64 len,
case R_ANAL_STACK_SET:
if (aop.ref > 0) {
varname = r_str_dup_printf ("arg_%x", aop.ref);
r_anal_var_add (anal, fcn, aop.addr, aop.ref, R_ANAL_VAR_TYPE_ARG,
R_ANAL_VAR_DIR_IN, NULL, varname, 1);
r_anal_var_add (anal, fcn, aop.addr, aop.ref,
R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN, NULL, varname, 1);
} else {
varname = r_str_dup_printf ("local_%x", -aop.ref);
r_anal_var_add (anal, fcn, aop.addr, -aop.ref, R_ANAL_VAR_TYPE_LOCAL,
R_ANAL_VAR_DIR_NONE, NULL, varname, 1);
r_anal_var_add (anal, fcn, aop.addr, -aop.ref,
R_ANAL_VAR_TYPE_LOCAL|R_ANAL_VAR_DIR_NONE, NULL, varname, 1);
}
free (varname);
break;
case R_ANAL_STACK_GET:
if (aop.ref > 0) {
varname = r_str_dup_printf ("arg_%x", aop.ref);
r_anal_var_add (anal, fcn, aop.addr, aop.ref, R_ANAL_VAR_TYPE_ARG,
R_ANAL_VAR_DIR_IN, NULL, varname, 0);
r_anal_var_add (anal, fcn, aop.addr, aop.ref,
R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN, NULL, varname, 0);
} else {
varname = r_str_dup_printf ("local_%x", -aop.ref);
r_anal_var_add (anal, fcn, aop.addr, -aop.ref, R_ANAL_VAR_TYPE_LOCAL,
R_ANAL_VAR_DIR_NONE, NULL, varname, 0);
r_anal_var_add (anal, fcn, aop.addr, -aop.ref,
R_ANAL_VAR_TYPE_LOCAL|R_ANAL_VAR_DIR_NONE, NULL, varname, 0);
}
free (varname);
break;
@ -176,13 +176,13 @@ R_API RAnalFcn *r_anal_fcn_find(RAnal *anal, ut64 addr, int type) {
return ret;
}
R_API RAnalVar *r_anal_fcn_get_var(RAnalFcn *fs, int num, int dir) {
R_API RAnalVar *r_anal_fcn_get_var(RAnalFcn *fs, int num, int type) {
RAnalVar *var;
RListIter *iter;
int count = 0;
// vars are sorted by delta in r_anal_var_add()
r_list_foreach (fs->vars, iter, var) {
if (dir & var->dir)
if (type & var->type)
if (count++ == num)
return var;
}
@ -194,27 +194,29 @@ R_API char *r_anal_fcn_to_string(RAnal *a, RAnalFcn* fs) {
char *sign;
if (fs->type != R_ANAL_FCN_TYPE_FCN)
return NULL;
RAnalVar *arg, *ret = r_anal_fcn_get_var (fs, 0, R_ANAL_VAR_DIR_OUT);
RAnalVar *arg, *ret = r_anal_fcn_get_var (fs, 0, R_ANAL_VAR_TYPE_RET);
if (ret) sign = r_str_newf ("%s %s (", ret->name, fs->name);
else sign = r_str_newf ("void %s (", fs->name);
for (i=0;;i++) {
if (!(arg = r_anal_fcn_get_var (fs, i, R_ANAL_VAR_DIR_IN)))
if (!(arg = r_anal_fcn_get_var (fs, i,
R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_TYPE_ARGREG)))
break;
if (arg->array>1) {
if (i) sign = r_str_concatf (sign, ", %s %s[%d]", arg->vartype, arg->name, arg->array);
else sign = r_str_concatf (sign, "%s %s[%d]", arg->vartype, arg->name, arg->array);
if (i) sign = r_str_concatf (sign, ", %s %s:%02x[%d]", arg->vartype, arg->name, arg->delta, arg->array);
else sign = r_str_concatf (sign, "%s %s:%02x[%d]", arg->vartype, arg->name, arg->delta, arg->array);
} else {
if (i) sign = r_str_concatf (sign, ", %s %s", arg->vartype, arg->name);
else sign = r_str_concatf (sign, "%s %s", arg->vartype, arg->name);
if (i) sign = r_str_concatf (sign, ", %s %s:%02x", arg->vartype, arg->name, arg->delta);
else sign = r_str_concatf (sign, "%s %s:%02x", arg->vartype, arg->name, arg->delta);
}
}
return (sign = r_str_concatf (sign, ");"));
}
R_API int r_anal_fcn_from_string(RAnal *a, RAnalFcn *f, const char *_str) {
RAnalVar *var;
char *str = strdup (_str);
char *p, *q, *r;
int arg;
int i, arg;
// TODO: This function is not fully implemented
if (!a || !f) {
eprintf ("r_anal_fcn_from_string: No function received\n");
@ -238,11 +240,11 @@ R_API int r_anal_fcn_from_string(RAnal *a, RAnalFcn *f, const char *_str) {
f->name = strdup (q+1);
/* set return value */
// TODO: simplify this complex api usage
r_anal_var_add (a, f, 0LL, 0, R_ANAL_VAR_TYPE_RET,
R_ANAL_VAR_DIR_OUT, str, "ret", 1);
r_anal_var_add (a, f, 0LL, 0,
R_ANAL_VAR_TYPE_RET|R_ANAL_VAR_DIR_OUT, str, "ret", 1);
/* parse arguments */
for (arg=0,p++;;) {
for (i=arg=0,p++;;p=q+1,i++) {
q = strchr (p, ',');
if (!q) {
q = strchr (p, ')');
@ -256,10 +258,11 @@ R_API int r_anal_fcn_from_string(RAnal *a, RAnalFcn *f, const char *_str) {
r = r_str_chop (r+1);
printf ("VAR %d=(%s)(%s)\n", arg, p, r);
// TODO : increment arg by var size
r_anal_var_add (a, f, 0LL, arg, R_ANAL_VAR_TYPE_ARG,
R_ANAL_VAR_DIR_IN, p, r, 1);
if ((var = r_anal_fcn_get_var (f, i, R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_TYPE_ARGREG))) {
free (var->name); var->name = strdup (r);
free (var->vartype); var->vartype = strdup (p);
} else r_anal_var_add (a, f, 0LL, arg, R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN, p, r, 0);
arg++;
p=q+1;
}
// r_anal_fcn_set_var (fs, 0, R_ANAL_VAR_DIR_OUT, );
free (str);

View File

@ -111,7 +111,7 @@ static int cmpdelta(RAnalVar *a, RAnalVar *b) {
return (a->delta - b->delta);
}
R_API int r_anal_var_add(RAnal *anal, RAnalFcn *fcn, ut64 from, int delta, int type, int dir, const char *vartype, const char *name, int set) {
R_API int r_anal_var_add(RAnal *anal, RAnalFcn *fcn, ut64 from, int delta, int type, const char *vartype, const char *name, int set) {
RAnalVar *var, *vari;
RListIter *iter;
if (from != 0LL)
@ -125,7 +125,8 @@ R_API int r_anal_var_add(RAnal *anal, RAnalFcn *fcn, ut64 from, int delta, int t
if (vartype)
var->vartype = strdup (vartype);
var->type = type;
var->dir = dir;
if ((type & R_ANAL_VAR_TYPE_ARG) || (type & R_ANAL_VAR_TYPE_ARGREG))
fcn->nargs++;
var->delta = delta;
if (from != 0LL)
r_anal_var_access_add (anal, var, from, set);
@ -155,12 +156,16 @@ R_API RAnalVar *r_anal_var_get(RAnal *anal, RAnalFcn *fcn, int delta, int type)
// XXX: rename function type? i think this is 'scope'
R_API const char *r_anal_var_type_to_str (RAnal *anal, int type) {
switch(type) {
case R_ANAL_VAR_TYPE_GLOBAL: return "global";
case R_ANAL_VAR_TYPE_LOCAL: return "local";
case R_ANAL_VAR_TYPE_ARG: return "arg";
case R_ANAL_VAR_TYPE_ARGREG: return "fastarg";
}
if (type & R_ANAL_VAR_TYPE_GLOBAL)
return "global";
else if (type & R_ANAL_VAR_TYPE_LOCAL)
return "local";
else if (type & R_ANAL_VAR_TYPE_ARG)
return "arg";
else if (type & R_ANAL_VAR_TYPE_ARGREG)
return "fastarg";
else if (type & R_ANAL_VAR_TYPE_RET)
return "ret";
return "(?)";
}

View File

@ -436,6 +436,7 @@ static void r_print_disasm(RPrint *p, RCore *core, ut64 addr, ut8 *buf, int len,
r_cons_printf("\n ");
if(fcn&&fcn->name) r_cons_printf ("; %s(", fcn->name);
else r_cons_printf ("; 0x%08"PFMT64x"(", analop.jump);
if(fcn) nargs = (fcn->nargs>nargs?nargs:fcn->nargs);
for(i=0;i<nargs;i++) {
if (args[i]>1024) r_cons_printf("%d", args[nargs-i]);
else r_cons_printf("0x%x", args[nargs-i]);
@ -1786,7 +1787,7 @@ static void var_help() {
static int var_cmd(RCore *core, const char *str) {
RAnalFcn *fcn = r_anal_fcn_find (core->anal, core->offset, R_ANAL_FCN_TYPE_FCN);
char *p,*p2,*p3;
int type, dir, delta, len = strlen(str)+1;
int type, delta, len = strlen(str)+1;
p = alloca(len);
memcpy(p, str, len);
@ -1803,9 +1804,9 @@ static int var_cmd(RCore *core, const char *str) {
case 'A': // fastcall arg
// XXX nested dup
switch (*str) {
case 'v': type = R_ANAL_VAR_TYPE_LOCAL; dir = R_ANAL_VAR_DIR_NONE; break;
case 'a': type = R_ANAL_VAR_TYPE_ARG; dir = R_ANAL_VAR_DIR_IN; break;
case 'A': type = R_ANAL_VAR_TYPE_ARGREG; dir = R_ANAL_VAR_DIR_IN; break;
case 'v': type = R_ANAL_VAR_TYPE_LOCAL|R_ANAL_VAR_DIR_NONE; break;
case 'a': type = R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN; break;
case 'A': type = R_ANAL_VAR_TYPE_ARGREG|R_ANAL_VAR_DIR_IN; break;
default:
eprintf ("Unknown type\n");
return 0;
@ -1841,7 +1842,7 @@ static int var_cmd(RCore *core, const char *str) {
p3[0]='\0';
p3=p3+1;
}
r_anal_var_add (core->anal, fcn, core->offset, delta, type, dir, p, p2, p3?atoi(p3):0);
r_anal_var_add (core->anal, fcn, core->offset, delta, type, p, p2, p3?atoi(p3):0);
} else var_help();
break;
default:

View File

@ -74,13 +74,18 @@ enum {
};
enum {
R_ANAL_VAR_TYPE_NULL = 0,
R_ANAL_VAR_TYPE_GLOBAL,
R_ANAL_VAR_TYPE_LOCAL,
R_ANAL_VAR_TYPE_ARG,
R_ANAL_VAR_TYPE_ARGREG,
R_ANAL_VAR_TYPE_RET,
R_ANAL_VAR_TYPE_NULL = 0,
R_ANAL_VAR_TYPE_GLOBAL = 0x01,
R_ANAL_VAR_TYPE_LOCAL = 0x02,
R_ANAL_VAR_TYPE_ARG = 0x04,
R_ANAL_VAR_TYPE_ARGREG = 0x08,
R_ANAL_VAR_TYPE_RET = 0x10,
};
typedef enum {
R_ANAL_VAR_DIR_NONE = 0,
R_ANAL_VAR_DIR_IN = 0x100,
R_ANAL_VAR_DIR_OUT = 0x200
} _RAnalVarDir;
typedef enum {
R_ANAL_DATA_NULL = 0,
@ -221,6 +226,7 @@ typedef struct r_anal_fcn_t {
int stack;
int diff;
int ninstr;
int nargs;
RNumBig *fingerprint;
RList *vars;
RList *refs;
@ -232,19 +238,12 @@ typedef struct r_anal_var_access_t {
int set;
} RAnalVarAccess;
typedef enum {
R_ANAL_VAR_DIR_NONE = 0,
R_ANAL_VAR_DIR_IN = 1,
R_ANAL_VAR_DIR_OUT = 2
} _RAnalVarDir;
typedef struct r_anal_var_t {
char *name; /* name of the variable */
ut64 addr; // not used correctly?
ut64 eaddr; // not used correctly?
int delta; /* delta offset inside stack frame */
int dir; /* direction (in, out) */
int type; /* global, local... */
int type; /* global, local... | in, out... */
int array; /* array size */
char *vartype; /* float, int... */
/* probably dupped or so */
@ -360,7 +359,7 @@ R_API int r_anal_var_type_add(RAnal *anal, const char *name, int size, const cha
R_API int r_anal_var_type_del(RAnal *anal, const char *name);
R_API RAnalVarType *r_anal_var_type_get(RAnal *anal, const char *name);
R_API int r_anal_var_add(RAnal *anal, RAnalFcn *fcn, ut64 from, int delta, int type,
int dir, const char *vartype, const char *name, int set);
const char *vartype, const char *name, int set);
R_API int r_anal_var_del(RAnal *anal, RAnalFcn *fcn, int delta, int type);
R_API RAnalVar *r_anal_var_get(RAnal *anal, RAnalFcn *fcn, int delta, int type);
R_API const char *r_anal_var_type_to_str (RAnal *anal, int type);