Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add jumptable support for main() in bins/elf/analysis/ls-alxchk #15266

Merged
merged 1 commit into from
Oct 13, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 40 additions & 4 deletions libr/anal/fcn.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,11 @@ static void check_purity(HtUP *ht, RAnal *anal, RAnalFunction *fcn) {
r_list_free (refs);
}

typedef struct {
ut64 op_addr;
ut64 leaddr;
} leaddr_pair;

static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int depth) {
const int continue_after_jump = anal->opt.afterjmp;
const int addrbytes = anal->iob.io ? anal->iob.io->addrbytes : 1;
Expand Down Expand Up @@ -741,7 +746,14 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int
return R_ANAL_RET_ERROR; // MUST BE NOT DUP
}

static ut64 leaddr = UT64_MAX;
static RList *leaddrs = NULL;
if (!leaddrs) {
leaddrs = r_list_new (); // TODO: leaks
if (!leaddrs) {
eprintf ("Cannot create leaddr list\n");
return R_ANAL_RET_ERROR;
}
}
static ut64 lea_jmptbl_ip = UT64_MAX;
char *last_reg_mov_lea_name = NULL;
ut64 last_reg_mov_lea_val = UT64_MAX;
Expand Down Expand Up @@ -999,7 +1011,14 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int
ut8 buf[4];
anal->iob.read_at (anal->iob.io, op.ptr, buf, sizeof (buf));
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
leaddr_pair *pair = R_NEW (leaddr_pair);
if (!pair) {
eprintf ("Cannot create leaddr_pair\n");
gotoBeach (R_ANAL_RET_ERROR);
}
pair->op_addr = op.addr;
pair->leaddr = op.ptr; // XXX movdisp is dupped but seems to be trashed sometimes(?), better track leaddr separately
r_list_append (leaddrs, pair);
}
if (op.dst && op.dst->reg && op.dst->reg->name && op.ptr > 0 && op.ptr != UT64_MAX) {
free (last_reg_mov_lea_name);
Expand Down Expand Up @@ -1282,10 +1301,27 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int
ret = try_walkthrough_jmptbl (anal, fcn, depth, op.addr, op.ptr, op.ptr, anal->bits >> 3, table_size, default_case, ret);
}
} else if (movdisp == 0) {
ut64 jmptbl_base = leaddr;
ut64 jmptbl_base = UT64_MAX;
ut64 lea_op_off = UT64_MAX;
RListIter *lea_op_iter = NULL;
RListIter *iter;
leaddr_pair *pair;
// find nearest candidate leaddr before op.addr
r_list_foreach (leaddrs, iter, pair) {
if (pair->op_addr >= op.addr) {
continue;
}
if (lea_op_off == UT64_MAX || lea_op_off > op.addr - pair->op_addr) {
lea_op_off = op.addr - pair->op_addr;
jmptbl_base = pair->leaddr;
lea_op_iter = iter;
}
}
if (lea_op_iter) {
r_list_delete (leaddrs, lea_op_iter);
}
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;
Expand Down