mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-27 08:12:44 +00:00
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:
parent
c2f5b72c80
commit
e72f5ed0ae
@ -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;
|
||||
|
@ -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))) {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user