Support another type of jmptbl for x86-64 ##anal

This commit is contained in:
radare 2019-02-27 03:30:29 +01:00 committed by GitHub
parent fa0b39896c
commit a404c77063
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -439,9 +439,11 @@ static int walkthrough_arm_jmptbl_style(RAnal *anal, RAnalFunction *fcn, int dep
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f switch.0x%08"PFMT64x" 1 @ 0x%08"PFMT64x"\n",
ip, ip);
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f case.default.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n",
default_case, default_case);
if (default_case != 0 && default_case != UT64_MAX) {
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f case.default.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n",
default_case, default_case);
}
}
return ret;
@ -499,7 +501,7 @@ static int try_walkthrough_jmptbl(RAnal *anal, RAnalFunction *fcn, int depth, ut
break;
}
}
queue_case (anal, ip, jmpptr, offs/sz, jmptbl_loc + offs);
queue_case (anal, ip, jmpptr, offs / sz, jmptbl_loc + offs);
recurseAt (jmpptr);
}
@ -511,10 +513,11 @@ static int try_walkthrough_jmptbl(RAnal *anal, RAnalFunction *fcn, int depth, ut
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f switch.0x%08"PFMT64x" 1 @ 0x%08"PFMT64x"\n",
ip, ip);
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f case.default.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n",
default_case, default_case);
if (default_case != 0 && default_case != UT64_MAX) {
anal->cmdtail = r_str_appendf (anal->cmdtail,
"f case.default.0x%"PFMT64x " 1 @ 0x%08"PFMT64x "\n",
default_case, default_case);
}
}
free (jmptbl);
@ -873,8 +876,8 @@ static bool purity_checked(HtUP *ht, RAnalFunction *fcn)
/*
* Checks whether a given function is pure and sets its 'is_pure' field.
* This function marks fcn 'not pure' if fcn, or any function called by fcn, accesses data
* from outside, even if it only READS it.
* Probably worth changing it in the future, so that it marks fcn 'impure' only when it
* from outside, even if it only READS it.
* Probably worth changing it in the future, so that it marks fcn 'impure' only when it
* (or any function called by fcn) MODIFIES external data.
*/
static void check_purity(HtUP *ht, RAnal *anal, RAnalFunction *fcn) {
@ -971,6 +974,7 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut6
VERBOSE_ANAL eprintf ("Append bb at 0x%08"PFMT64x" (fcn 0x%08"PFMT64x ")\n", addr, fcn->addr);
ut64 leaddr = UT64_MAX;
bool last_is_push = false;
bool last_is_mov_lr_pc = false;
ut64 last_push_addr = UT64_MAX;
@ -1126,7 +1130,7 @@ repeat:
last_is_mov_lr_pc = true;
}
}
// skip mov reg,reg
// skip mov reg, reg
if (anal->opt.jmptbl) {
if (op.scale && op.ireg) {
movptr = op.ptr;
@ -1144,6 +1148,14 @@ repeat:
}
break;
case R_ANAL_OP_TYPE_LEA:
// if first byte in op.ptr is 0xff, then set leaddr assuming its a jumptable
{
ut8 buf[4];
anal->iob.read_at (anal->iob.io, op.ptr, &buf, sizeof (buf));
if (buf[2] == 0xff && buf[3] == 0xff) {
leaddr = op.ptr; // XXX movptr is dupped but seems to be trashed sometimes, better track leaddr separately
}
}
// skip lea reg,[reg]
if (anal->opt.hpskip && regs_exist (op.src[0], op.dst)
&& !strcmp (op.src[0]->reg->name, op.dst->reg->name)) {
@ -1182,7 +1194,7 @@ repeat:
op.type = R_ANAL_OP_TYPE_RET;
gotoBeach (R_ANAL_RET_END);
}
}
}
break;
case R_ANAL_OP_TYPE_ILL:
if (anal->opt.nopskip && len > 3 && !memcmp (buf, "\x00\x00\x00\x00", 4)) {
@ -1298,8 +1310,16 @@ repeat:
gotoBeachRet ();
#endif
break;
case R_ANAL_OP_TYPE_SUB:
if (op.val != UT64_MAX && op.val > 0) {
// if register is not stack
cmpval = op.val;
}
break;
case R_ANAL_OP_TYPE_CMP:
cmpval = op.ptr;
if (op.ptr) {
cmpval = op.ptr;
}
break;
case R_ANAL_OP_TYPE_CJMP:
case R_ANAL_OP_TYPE_MCJMP:
@ -1448,6 +1468,10 @@ repeat:
if (try_get_jmptbl_info (anal, fcn, op.addr, bb, &table_size, &default_case)) {
ret = try_walkthrough_jmptbl (anal, fcn, depth, op.addr, op.ptr, op.ptr, anal->bits >> 3, table_size, default_case, ret);
}
} else if (movptr == 0) {
ut64 jmptbl_base = leaddr;
ut64 table_size = cmpval + 1;
ret = try_walkthrough_jmptbl (anal, fcn, depth, op.addr, jmptbl_base, jmptbl_base, 4, table_size, -1, ret);
} else if (movptr != UT64_MAX) {
ut64 table_size, default_case;