anal/op: add var field to RAnalOp to store the local used by op

anal: save writes/reades of vars/args and fix x86 stackop analysis
This commit is contained in:
Riccardo Schirone 2016-02-15 17:49:17 +01:00 committed by pancake
parent c2f5b72c80
commit e72f5ed0ae
5 changed files with 61 additions and 30 deletions

View File

@ -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;

View File

@ -4,6 +4,14 @@
#include <r_util.h>
#include <r_list.h>
#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))) {

View File

@ -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 {

View File

@ -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

View File

@ -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