Add jumptable support for main() in bins/elf/ls.odd (#15233) ##anal

This commit is contained in:
Khairul Azhar Kasmiran 2019-10-13 08:17:56 +08:00 committed by radare
parent f6265e131f
commit dc59b5e7dc

View File

@ -741,7 +741,8 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int
return R_ANAL_RET_ERROR; // MUST BE NOT DUP
}
ut64 leaddr = UT64_MAX;
static ut64 leaddr = UT64_MAX;
static ut64 lea_jmptbl_ip = UT64_MAX;
char *last_reg_mov_lea_name = NULL;
ut64 last_reg_mov_lea_val = UT64_MAX;
bool last_is_reg_mov_lea = false;
@ -997,7 +998,7 @@ repeat:
{
ut8 buf[4];
anal->iob.read_at (anal->iob.io, op.ptr, buf, sizeof (buf));
if (buf[2] == 0xff && buf[3] == 0xff) {
if ((buf[2] == 0xff || buf[2] == 0xfe) && buf[3] == 0xff) {
leaddr = op.ptr; // XXX movdisp is dupped but seems to be trashed sometimes(?), better track leaddr separately
}
if (op.dst && op.dst->reg && op.dst->reg->name && op.ptr > 0 && op.ptr != UT64_MAX) {
@ -1033,6 +1034,9 @@ repeat:
if (try_get_jmptbl_info (anal, fcn, jmp_aop.addr, bb, &table_size, &default_case)
|| try_get_delta_jmptbl_info (anal, fcn, jmp_aop.addr, op.addr, &table_size, &default_case)) {
ret = try_walkthrough_jmptbl (anal, fcn, depth, jmp_aop.addr, jmptbl_addr, op.ptr, 4, table_size, default_case, 4);
if (ret) {
lea_jmptbl_ip = jmp_aop.addr;
}
}
}
r_anal_op_fini (&jmp_aop);
@ -1123,7 +1127,7 @@ repeat:
}
break;
case R_ANAL_OP_TYPE_CMP: {
ut64 val = is_x86 ? op.disp : op.ptr;
ut64 val = is_x86 ? op.val : op.ptr;
if (val) {
cmpval = val;
bb->cmpval = cmpval;
@ -1264,7 +1268,7 @@ repeat:
gotoBeach (R_ANAL_RET_END);
}
// switch statement
if (anal->opt.jmptbl) {
if (anal->opt.jmptbl && lea_jmptbl_ip != op.addr) {
// op.ireg since rip relative addressing produces way too many false positives otherwise
// op.ireg is 0 for rip relative, "rax", etc otherwise
if (op.ptr != UT64_MAX && op.ireg) { // direct jump
@ -1281,6 +1285,8 @@ repeat:
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);
leaddr = UT64_MAX;
cmpval = UT64_MAX;
} else if (movdisp != UT64_MAX) {
ut64 table_size, default_case;
@ -1318,6 +1324,9 @@ repeat:
}
}
}
if (lea_jmptbl_ip == op.addr) {
lea_jmptbl_ip = UT64_MAX;
}
if (anal->opt.ijmp) {
if (continue_after_jump) {
r_anal_fcn_bb (anal, fcn, op.jump, depth);