diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index caeeda9334..72b0459bcd 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -426,11 +426,13 @@ repeat: varname = get_varname (anal, ARGPREFIX, R_ABS(op.ptr)); r_anal_var_add (anal, fcn->addr, 1, op.ptr, 'a', NULL, anal->bits/8, varname); + r_anal_var_access (anal, fcn->addr, 'a', 1, op.ptr, 1, op.addr); // TODO: DIR_IN? } else { varname = get_varname (anal, VARPREFIX, R_ABS(op.ptr)); r_anal_var_add (anal, fcn->addr, 1, -op.ptr, 'v', NULL, anal->bits/8, varname); + r_anal_var_access (anal, fcn->addr, 'v', 1, -op.ptr, 1, op.addr); } free (varname); break; @@ -439,11 +441,11 @@ repeat: if (((int)op.ptr) > 0) { varname = get_varname (anal, ARGPREFIX, R_ABS(op.ptr)); r_anal_var_add (anal, fcn->addr, 1, op.ptr, 'a', NULL, anal->bits/8, varname); - r_anal_var_access (anal, fcn->addr, 'a', 0, op.ptr, 0, op.addr); + r_anal_var_access (anal, fcn->addr, 'a', 1, op.ptr, 0, op.addr); } else { varname = get_varname (anal, VARPREFIX, R_ABS(op.ptr)); r_anal_var_add (anal, fcn->addr, 1, -op.ptr, 'v', NULL, anal->bits/8, varname); - r_anal_var_access (anal, fcn->addr, 'v', 0, -op.ptr, 0, -op.addr); + r_anal_var_access (anal, fcn->addr, 'v', 1, -op.ptr, 0, op.addr); } free (varname); break; diff --git a/libr/anal/op.c b/libr/anal/op.c index d431dd239b..2a26b6e929 100644 --- a/libr/anal/op.c +++ b/libr/anal/op.c @@ -4,6 +4,14 @@ #include #include +#define SDB_VARUSED_FMT "qzdq" +struct VarUsedType { + ut64 fcn_addr; + char *type; + ut32 scope; + st64 delta; +}; + R_API RAnalOp *r_anal_op_new () { RAnalOp *op = R_NEW0 (RAnalOp); if (!op) return NULL; @@ -32,6 +40,7 @@ R_API void r_anal_op_fini(RAnalOp *op) { if (((ut64)(size_t)op->mnemonic) == UT64_MAX) { return; } + r_anal_var_free (op->var); r_anal_value_free (op->src[0]); r_anal_value_free (op->src[1]); r_anal_value_free (op->src[2]); @@ -47,6 +56,19 @@ R_API void r_anal_op_free(void *_op) { free (_op); } +static RAnalVar *get_used_var(RAnal *anal, RAnalOp *op) { + char *inst_key = sdb_fmt (0, "inst.0x%"PFMT64x".vars", op->addr); + char *var_def = sdb_get (anal->sdb_fcns, inst_key, 0); + struct VarUsedType vut; + RAnalVar *res; + + if (!var_def) return NULL; + sdb_fmt_tobin (var_def, SDB_VARUSED_FMT, &vut); + 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; @@ -64,6 +86,7 @@ R_API int r_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le anal->cur && anal->cur->op && strcmp (anal->cur->name, "null")) { ret = anal->cur->op (anal, op, addr, data, len); op->addr = addr; + op->var = get_used_var (anal, op); if (ret < 1) op->type = R_ANAL_OP_TYPE_ILL; } else { if (!memcmp (data, "\xff\xff\xff\xff", R_MIN(4, len))) { diff --git a/libr/anal/p/anal_x86_cs.c b/libr/anal/p/anal_x86_cs.c index c0e3e5a391..da3155843c 100644 --- a/libr/anal/p/anal_x86_cs.c +++ b/libr/anal/p/anal_x86_cs.c @@ -517,7 +517,6 @@ SETL/SETNGE if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { - op->ptr = UT64_MAX; op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } else { diff --git a/libr/anal/var.c b/libr/anal/var.c index 3b9bd8b890..11da42d272 100644 --- a/libr/anal/var.c +++ b/libr/anal/var.c @@ -233,9 +233,11 @@ R_API RAnalVar *r_anal_var_get (RAnal *a, ut64 addr, char kind, int scope, int d } R_API void r_anal_var_free (RAnalVar *av) { - free (av->name); - free (av->type); - free (av); + if (av) { + free (av->name); + free (av->type); + free (av); + } } /* (columns) elements in the array value */ @@ -323,6 +325,10 @@ R_API int r_anal_var_access (RAnal *a, ut64 var_addr, char kind, int scope, int if (scope>0) { // local char *var_local = sdb_fmt (0, "var.0x%"PFMT64x".%d.%d.%s", var_addr, scope, delta, xs_type_str); + char *inst_key = sdb_fmt (1, "inst.0x%"PFMT64x".vars", xs_addr); + char *var_def = sdb_fmt(2, "0x%"PFMT64x",%c,0x%x,0x%x", var_addr, + kind, scope, delta); + sdb_set (DB, inst_key, var_def, 0); return sdb_array_add_num (DB, var_local, xs_addr, 0); } // global diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 0ec808da61..f94a78adcf 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -660,6 +660,30 @@ typedef struct r_anal_hint_t { int immbase; } RAnalHint; +typedef struct r_anal_var_access_t { + ut64 addr; + int set; +} RAnalVarAccess; + +#define R_ANAL_VAR_KIND_ARG 'a' +#define R_ANAL_VAR_KIND_VAR 'v' +#define R_ANAL_VAR_KIND_REG 'r' + +// generic for args and locals +typedef struct r_anal_var_t { + char *name; /* name of the variable */ + char *type; // cparse type of the variable + char kind; // 'a'rg, 'v'ar .. + ut64 addr; // not used correctly? + ut64 eaddr; // not used correctly? + int size; + int delta; /* delta offset inside stack frame */ + int scope; /* global, local... | in, out... */ + /* probably dupped or so */ + RList/*RAnalVarAccess*/ *accesses; /* list of accesses for this var */ + RList/*RAnalValue*/ *stores; /* where this */ +} RAnalVar; + // mul*value+regbase+regidx+delta typedef struct r_anal_value_t { int absolute; // if true, unsigned cast is used @@ -698,6 +722,7 @@ typedef struct r_anal_op_t { int ptrsize; /* f.ex: zero extends for 8, 16 or 32 bits only */ st64 stackptr; /* stack pointer */ int refptr; /* if (0) ptr = "reference" else ptr = "load memory of refptr bytes" */ + RAnalVar *var; /* local var/arg used by this instruction */ RAnalValue *src[3]; RAnalValue *dst; struct r_anal_op_t *next; // XXX deprecate @@ -751,30 +776,6 @@ typedef struct r_anal_bb_t { RList /*struct r_anal_bb_t*/ *cases; } RAnalBlock; -typedef struct r_anal_var_access_t { - ut64 addr; - int set; -} RAnalVarAccess; - -#define R_ANAL_VAR_KIND_ARG 'a' -#define R_ANAL_VAR_KIND_VAR 'v' -#define R_ANAL_VAR_KIND_REG 'r' - -// generic for args and locals -typedef struct r_anal_var_t { - char *name; /* name of the variable */ - char *type; // cparse type of the variable - char kind; // 'a'rg, 'v'ar .. - ut64 addr; // not used correctly? - ut64 eaddr; // not used correctly? - int size; - int delta; /* delta offset inside stack frame */ - int scope; /* global, local... | in, out... */ - /* probably dupped or so */ - RList/*RAnalVarAccess*/ *accesses; /* list of accesses for this var */ - RList/*RAnalValue*/ *stores; /* where this */ -} RAnalVar; - typedef enum { R_ANAL_REF_TYPE_NULL = 0, R_ANAL_REF_TYPE_CODE = 'c', // code ref