mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-23 22:36:27 +00:00
Intial work on type propgation on variable equality
This commit is contained in:
parent
2d4678a430
commit
506144d797
@ -1069,6 +1069,7 @@ repeat:
|
||||
ret = try_walkthrough_jmptbl (anal, fcn, depth, jmp_aop.addr, jmptbl_addr, op.ptr, 4, table_size, default_case, 4);
|
||||
}
|
||||
}
|
||||
r_anal_op_fini (&jmp_aop);
|
||||
}
|
||||
break;
|
||||
// Case of valid but unused "add [rax], al"
|
||||
|
@ -84,15 +84,21 @@ static void var_retype (RAnal *anal, RAnalVar *var, const char *vname, char *typ
|
||||
if (!type || !var) {
|
||||
return;
|
||||
}
|
||||
if (!*type) {
|
||||
char *trim = r_str_trim (type);
|
||||
if (!*trim) {
|
||||
return;
|
||||
}
|
||||
if (!strncmp (type, "int", 3)) {
|
||||
if (!strncmp (trim, "int", 3)) {
|
||||
return;
|
||||
}
|
||||
const char *tmp = strstr (var->type, "int");
|
||||
bool is_default = tmp? true: false;
|
||||
if (strncmp (var->type, "void", 4) && !is_default) {
|
||||
bool is_ptr = (vname && *vname == '*')? true: false;
|
||||
bool is_void = !strncmp (var->type, "void", 4)? true: false;
|
||||
if (!is_void && !is_default) {
|
||||
return;
|
||||
}
|
||||
if (is_void && !is_ptr && !r_str_endswith (var->type, "*")) {
|
||||
return;
|
||||
}
|
||||
char ntype[256];
|
||||
@ -104,7 +110,7 @@ static void var_retype (RAnal *anal, RAnalVar *var, const char *vname, char *typ
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
strncpy (ntype, r_str_trim (type), len);
|
||||
strncpy (ntype, trim, len);
|
||||
}
|
||||
if (!strncmp (ntype, "const ", 6)) {
|
||||
// Droping const from type
|
||||
@ -122,30 +128,30 @@ static void var_retype (RAnal *anal, RAnalVar *var, const char *vname, char *typ
|
||||
r_anal_var_retype (anal, addr, 1, var->delta, var->kind, ntype, var->size, var->isarg, var->name);
|
||||
}
|
||||
|
||||
static char *get_src_regname (RCore *core, ut64 addr) {
|
||||
static void get_src_regname (RCore *core, ut64 addr, char *regname, int size) {
|
||||
RAnal *anal = core->anal;
|
||||
RAnalOp *op = r_core_anal_op (core, addr, R_ANAL_OP_MASK_ESIL);
|
||||
char *regname = strdup (r_strbuf_get (&op->esil));
|
||||
char *tmp = strchr (regname, ',');
|
||||
char *op_esil = strdup (r_strbuf_get (&op->esil));
|
||||
char *tmp = strchr (op_esil, ',');
|
||||
if (tmp) {
|
||||
*tmp = '\0';
|
||||
}
|
||||
RRegItem *ri = r_reg_get (anal->reg, regname, -1);
|
||||
memset (regname, 0, size);
|
||||
RRegItem *ri = r_reg_get (anal->reg, op_esil, -1);
|
||||
if (ri) {
|
||||
if ((anal->bits == 64) && (ri->size == 32)) {
|
||||
char *foo = strdup (r_reg_32_to_64 (anal->reg, regname));
|
||||
free (regname);
|
||||
regname = foo;
|
||||
char *foo = strdup (r_reg_32_to_64 (anal->reg, op_esil));
|
||||
free (op_esil);
|
||||
op_esil = foo;
|
||||
}
|
||||
} else {
|
||||
regname = NULL;
|
||||
strncpy (regname, op_esil, size - 1);
|
||||
}
|
||||
free (op_esil);
|
||||
r_anal_op_free (op);
|
||||
return regname;
|
||||
}
|
||||
|
||||
static ut64 get_addr (Sdb *trace, const char *regname, int idx) {
|
||||
if (!regname) {
|
||||
if (!regname || !*regname) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
const char *query = sdb_fmt ("%d.reg.read.%s", idx, regname);
|
||||
@ -189,7 +195,7 @@ static void type_match(RCore *core, ut64 addr, char *fcn_name, ut64 faddr, const
|
||||
if (!in_stack) {
|
||||
place = r_anal_cc_arg (anal, cc, arg_num + 1);
|
||||
}
|
||||
char *regname = NULL;
|
||||
char regname[10] = {0};
|
||||
ut64 xaddr = UT64_MAX;
|
||||
bool memref = false;
|
||||
bool cmt_set = false;
|
||||
@ -234,12 +240,12 @@ static void type_match(RCore *core, ut64 addr, char *fcn_name, ut64 faddr, const
|
||||
}
|
||||
res = true;
|
||||
} else {
|
||||
regname = get_src_regname (core, instr_addr);
|
||||
get_src_regname (core, instr_addr, regname, sizeof (regname));
|
||||
xaddr = get_addr (trace, regname, j);
|
||||
}
|
||||
}
|
||||
// Type propagate by following source reg
|
||||
if (!res && regname && SDB_CONTAINS (j, regname)) {
|
||||
if (!res && *regname && SDB_CONTAINS (j, regname)) {
|
||||
if (var) {
|
||||
if (!userfnc) {
|
||||
var_retype (anal, var, name, type, addr, memref, false);
|
||||
@ -252,28 +258,26 @@ static void type_match(RCore *core, ut64 addr, char *fcn_name, ut64 faddr, const
|
||||
switch (op->type) {
|
||||
case R_ANAL_OP_TYPE_MOV:
|
||||
case R_ANAL_OP_TYPE_PUSH:
|
||||
free (regname);
|
||||
regname = get_src_regname (core, instr_addr);
|
||||
get_src_regname (core, instr_addr, regname, sizeof (regname));
|
||||
break;
|
||||
case R_ANAL_OP_TYPE_LEA:
|
||||
case R_ANAL_OP_TYPE_LOAD:
|
||||
case R_ANAL_OP_TYPE_STORE:
|
||||
R_FREE (regname);
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (var && res && (xaddr != UT64_MAX)) { // Type progation using value
|
||||
char *reg = get_src_regname (core, instr_addr);
|
||||
ut64 ptr = get_addr (trace, reg, j);
|
||||
char tmp[10] = {0};
|
||||
get_src_regname (core, instr_addr, tmp, sizeof (tmp));
|
||||
ut64 ptr = get_addr (trace, tmp, j);
|
||||
if (ptr == xaddr) {
|
||||
var_retype (anal, var, name, type, addr, memref, false);
|
||||
}
|
||||
free (reg);
|
||||
}
|
||||
r_anal_op_free (op);
|
||||
}
|
||||
size += anal->bits / 8;
|
||||
free (regname);
|
||||
free (type);
|
||||
}
|
||||
beach:
|
||||
@ -315,6 +319,8 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
|
||||
char *fcn_name = NULL;
|
||||
char *ret_type = NULL;
|
||||
bool str_flag = false;
|
||||
bool prop = false;
|
||||
char prev_type[256] = {0};
|
||||
const char *prev_dest = NULL;
|
||||
const char *ret_reg = NULL;
|
||||
const char *pc = r_reg_get_name (core->dbg->reg, R_REG_NAME_PC);
|
||||
@ -389,15 +395,15 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
|
||||
bool sign = false;
|
||||
// Forward propgation of function return type
|
||||
if (!resolved && ret_type && ret_reg) {
|
||||
char *reg = get_src_regname (core, aop.addr);
|
||||
if (reg && !strcmp (reg, ret_reg) && var) {
|
||||
char tmp[10] = {0};
|
||||
get_src_regname (core, aop.addr, tmp, sizeof (tmp));
|
||||
if ((type == R_ANAL_OP_TYPE_MOV) && *tmp && !strcmp (tmp, ret_reg) && var) {
|
||||
var_retype (anal, var, NULL, ret_type, addr, false, false);
|
||||
resolved = true;
|
||||
}
|
||||
if (SDB_CONTAINS (cur_idx, ret_reg)) {
|
||||
resolved = true;
|
||||
}
|
||||
free (reg);
|
||||
}
|
||||
// Type Propgation using intruction access pattern
|
||||
if ((type == R_ANAL_OP_TYPE_CMP) && next_op) {
|
||||
@ -413,21 +419,39 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
|
||||
var_retype (anal, var, NULL, "signed", addr, false, true);
|
||||
}
|
||||
// lea rax , str.hello ; mov [local_ch], rax;
|
||||
if (str_flag && (type == R_ANAL_OP_TYPE_MOV)) {
|
||||
const char *q = sdb_fmt ("%d.reg.read", cur_idx);
|
||||
if (sdb_array_contains (trace, q, prev_dest, 0)) {
|
||||
var_retype (anal, var, NULL, "const char *", addr, false, true);
|
||||
if (prop && (type == R_ANAL_OP_TYPE_MOV)) {
|
||||
char *vtype = str_flag ? "const char *": prev_type;
|
||||
char reg[10] = {0};
|
||||
bool match = false;
|
||||
get_src_regname (core, addr, reg, sizeof (reg));
|
||||
char *tmp = strchr (reg , ',');
|
||||
if (tmp) {
|
||||
if (!strcmp (tmp + 1, prev_dest)) {
|
||||
match = true;
|
||||
}
|
||||
*tmp = '\0';
|
||||
}
|
||||
if (*reg && prev_dest && !strcmp (reg, prev_dest)) {
|
||||
match = true;
|
||||
}
|
||||
if ((vtype && *vtype) && match) {
|
||||
var_retype (anal, var, NULL, vtype, addr, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
str_flag = false;
|
||||
prop = false;
|
||||
prev_dest = NULL;
|
||||
}
|
||||
if (type == R_ANAL_OP_TYPE_LEA) {
|
||||
if ((type == R_ANAL_OP_TYPE_LEA) || (type == R_ANAL_OP_TYPE_MOV)) {
|
||||
if (r_flag_exist_at (core->flags, "str", 3, aop.ptr)) {
|
||||
str_flag = true;
|
||||
}
|
||||
const char *query = sdb_fmt ("%d.reg.write", cur_idx);
|
||||
prev_dest = sdb_const_get (trace, query, 0);
|
||||
if (var) {
|
||||
strncpy (prev_type, var->type, sizeof (prev_type) - 1);
|
||||
}
|
||||
prop = true;
|
||||
}
|
||||
i += ret;
|
||||
addr += ret;
|
||||
|
@ -6801,6 +6801,7 @@ static int cmd_anal_all(RCore *core, const char *input) {
|
||||
}
|
||||
//extract only reg based var here
|
||||
r_core_recover_vars (core, fcni, true);
|
||||
r_list_free (list);
|
||||
}
|
||||
}
|
||||
if (sdb_count (core->anal->sdb_zigns) > 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user