Reduce analysis recursion (#1284)
* Reduce recursion when analyzing function control-flow * Jump table refactoring * Use rz_ prefix for the API * Use struct instead of long parameter list * Add `analysis.jmp.tblmax` to configure maximun amount of cases to analyze * Remove recursion
This commit is contained in:
parent
f340b90fd7
commit
146d3b5d4f
16 changed files with 478 additions and 297 deletions
|
|
@ -11,7 +11,6 @@
|
|||
#define READ_AHEAD 1
|
||||
#define SDB_KEY_BB "bb.0x%" PFMT64x ".0x%" PFMT64x
|
||||
// XXX must be configurable by the user
|
||||
#define JMPTBLSZ 512
|
||||
#define JMPTBL_LEA_SEARCH_SZ 64
|
||||
#define JMPTBL_MAXFCNSIZE 4096
|
||||
#define BB_ALIGN 0x10
|
||||
|
|
@ -521,12 +520,31 @@ static inline bool does_arch_destroys_dst(const char *arch) {
|
|||
return arch && (!strncmp(arch, "arm", 3) || !strcmp(arch, "riscv") || !strcmp(arch, "ppc"));
|
||||
}
|
||||
|
||||
static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, ut64 len, int depth) {
|
||||
static int analyze_function_locally(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 address) {
|
||||
rz_return_val_if_fail(analysis && fcn, RZ_ANALYSIS_RET_ERROR);
|
||||
RzVector tasks;
|
||||
rz_vector_init(&tasks, sizeof(RzAnalysisTaskItem), NULL, NULL);
|
||||
RzAnalysisTaskItem item = { fcn, NULL, fcn->stack, address };
|
||||
rz_vector_push(&tasks, &item);
|
||||
int saved_stack = fcn->stack; // TODO: DO NOT use fcn->stack to keep track of stack during analysis
|
||||
int ret = rz_analysis_run_tasks(&tasks);
|
||||
rz_vector_fini(&tasks);
|
||||
fcn->stack = saved_stack;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_basic_block_analysis(RzAnalysisTaskItem *item, RzVector *tasks) {
|
||||
rz_return_val_if_fail(item && tasks, RZ_ANALYSIS_RET_ERROR);
|
||||
RzAnalysis *analysis = item->fcn->analysis;
|
||||
RzAnalysisFunction *fcn = item->fcn;
|
||||
fcn->stack = item->stack;
|
||||
ut64 addr = item->start_address;
|
||||
ut64 len = analysis->opt.bb_max_size;
|
||||
const int continue_after_jump = analysis->opt.afterjmp;
|
||||
const int addrbytes = analysis->iob.io ? analysis->iob.io->addrbytes : 1;
|
||||
char *last_reg_mov_lea_name = NULL;
|
||||
char *movbasereg = NULL;
|
||||
RzAnalysisBlock *bb = NULL;
|
||||
RzAnalysisBlock *bb = item->block;
|
||||
RzAnalysisBlock *bbg = NULL;
|
||||
int ret = RZ_ANALYSIS_RET_END, skip_ret = 0;
|
||||
bool overlapped = false;
|
||||
|
|
@ -558,19 +576,13 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
bool has_variadic_reg = !!variadic_reg;
|
||||
|
||||
if (rz_cons_is_breaked()) {
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, bb, addr);
|
||||
return RZ_ANALYSIS_RET_END;
|
||||
}
|
||||
if (analysis->sleep) {
|
||||
rz_sys_usleep(analysis->sleep);
|
||||
}
|
||||
|
||||
if (depth < 1) {
|
||||
if (analysis->verbose) {
|
||||
eprintf("Analysis went too deep at address 0x%" PFMT64x ".\n", addr);
|
||||
}
|
||||
return RZ_ANALYSIS_RET_ERROR; // MUST BE TOO DEEP
|
||||
}
|
||||
|
||||
// check if address is readable //:
|
||||
if (!analysis->iob.is_valid_offset(analysis->iob.io, addr, 0)) {
|
||||
if (addr != UT64_MAX && !analysis->iob.io->va) {
|
||||
|
|
@ -586,31 +598,33 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
return RZ_ANALYSIS_RET_ERROR; // MUST BE NOT FOUND
|
||||
}
|
||||
|
||||
RzAnalysisBlock *existing_bb = bbget(analysis, addr, analysis->opt.jmpmid && is_x86);
|
||||
if (existing_bb) {
|
||||
bool existing_in_fcn = rz_list_contains(existing_bb->fcns, fcn);
|
||||
existing_bb = rz_analysis_block_split(existing_bb, addr);
|
||||
if (!existing_in_fcn && existing_bb) {
|
||||
if (existing_bb->addr == fcn->addr) {
|
||||
// our function starts directly there, so we steal what is ours!
|
||||
fcn_takeover_block_recursive(fcn, existing_bb);
|
||||
}
|
||||
}
|
||||
if (!bb) {
|
||||
RzAnalysisBlock *existing_bb = bbget(analysis, addr, analysis->opt.jmpmid && is_x86);
|
||||
if (existing_bb) {
|
||||
rz_analysis_block_unref(existing_bb);
|
||||
bool existing_in_fcn = rz_list_contains(existing_bb->fcns, fcn);
|
||||
existing_bb = rz_analysis_block_split(existing_bb, addr);
|
||||
if (!existing_in_fcn && existing_bb) {
|
||||
if (existing_bb->addr == fcn->addr) {
|
||||
// our function starts directly there, so we steal what is ours!
|
||||
fcn_takeover_block_recursive(fcn, existing_bb);
|
||||
}
|
||||
}
|
||||
if (existing_bb) {
|
||||
rz_analysis_block_unref(existing_bb);
|
||||
}
|
||||
if (analysis->opt.recont) {
|
||||
return RZ_ANALYSIS_RET_END;
|
||||
}
|
||||
if (analysis->verbose) {
|
||||
eprintf("rz_analysis_fcn_bb() fails at 0x%" PFMT64x ".\n", addr);
|
||||
}
|
||||
return RZ_ANALYSIS_RET_ERROR; // MUST BE NOT DUP
|
||||
}
|
||||
if (analysis->opt.recont) {
|
||||
return RZ_ANALYSIS_RET_END;
|
||||
}
|
||||
if (analysis->verbose) {
|
||||
eprintf("rz_analysis_fcn_bb() fails at 0x%" PFMT64x ".\n", addr);
|
||||
}
|
||||
return RZ_ANALYSIS_RET_ERROR; // MUST BE NOT DUP
|
||||
}
|
||||
|
||||
bb = fcn_append_basic_block(analysis, fcn, addr);
|
||||
// we checked before whether there is a bb at addr, so the create should have succeeded
|
||||
rz_return_val_if_fail(bb, RZ_ANALYSIS_RET_ERROR);
|
||||
item->block = bb = fcn_append_basic_block(analysis, fcn, addr);
|
||||
// we checked before whether there is a bb at addr, so the create should have succeeded
|
||||
rz_return_val_if_fail(bb, RZ_ANALYSIS_RET_ERROR);
|
||||
}
|
||||
|
||||
if (!analysis->leaddrs) {
|
||||
analysis->leaddrs = rz_list_newf(free_leaddr_pair);
|
||||
|
|
@ -662,6 +676,8 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
|
||||
while (addrbytes * idx < maxlen) {
|
||||
ut32 at_delta;
|
||||
ut64 at;
|
||||
if (!last_is_reg_mov_lea) {
|
||||
free(last_reg_mov_lea_name);
|
||||
last_reg_mov_lea_name = NULL;
|
||||
|
|
@ -670,11 +686,12 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
break;
|
||||
}
|
||||
repeat:
|
||||
at_delta = addrbytes * idx;
|
||||
at = addr + at_delta;
|
||||
if (rz_cons_is_breaked()) {
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, bb, at);
|
||||
break;
|
||||
}
|
||||
ut32 at_delta = addrbytes * idx;
|
||||
ut64 at = addr + at_delta;
|
||||
ut64 bytes_read = RZ_MIN(len - at_delta, sizeof(buf));
|
||||
ret = read_ahead(analysis, at, buf, bytes_read);
|
||||
|
||||
|
|
@ -764,7 +781,7 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
bb->jump = at + oplen;
|
||||
if (from_addr != bb->addr) {
|
||||
bb->fail = handle_addr;
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, handle_addr, depth);
|
||||
ret = analyze_function_locally(analysis, fcn, handle_addr);
|
||||
eprintf("(%s) 0x%08" PFMT64x "\n", handle, handle_addr);
|
||||
if (bb->size == 0) {
|
||||
rz_analysis_function_remove_block(fcn, bb);
|
||||
|
|
@ -941,18 +958,24 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
ut64 jmptbl_addr = op.ptr;
|
||||
ut64 casetbl_addr = op.ptr;
|
||||
if (is_delta_pointer_table(analysis, fcn, op.addr, op.ptr, &jmptbl_addr, &casetbl_addr, &jmp_aop)) {
|
||||
ut64 table_size, default_case = 0;
|
||||
st64 case_shift;
|
||||
// we require both checks here since try_get_jmptbl_info uses
|
||||
// we require both checks here since rz_analysis_get_jmptbl_info uses
|
||||
// BB info of the final jmptbl jump, which is no present with
|
||||
// is_delta_pointer_table just scanning ahead
|
||||
// try_get_delta_jmptbl_info doesn't work at times where the
|
||||
// rz_analysis_get_delta_jmptbl_info doesn't work at times where the
|
||||
// lea comes after the cmp/default case cjmp, which can be
|
||||
// handled with try_get_jmptbl_info
|
||||
if (try_get_jmptbl_info(analysis, fcn, jmp_aop.addr, bb, &table_size, &default_case, &case_shift) || try_get_delta_jmptbl_info(analysis, fcn, jmp_aop.addr, op.addr, &table_size, &default_case, &case_shift)) {
|
||||
// handled with rz_analysis_get_jmptbl_info
|
||||
RzAnalysisJmpTableParams params = {
|
||||
.jmp_address = jmp_aop.addr,
|
||||
.jmptbl_loc = jmptbl_addr,
|
||||
.casetbl_loc = casetbl_addr,
|
||||
.entry_size = 4,
|
||||
.jmptbl_off = op.ptr,
|
||||
.tasks = tasks
|
||||
};
|
||||
if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, jmp_aop.addr, ¶ms) || rz_analysis_get_delta_jmptbl_info(analysis, fcn, jmp_aop.addr, op.addr, ¶ms)) {
|
||||
ret = casetbl_addr == op.ptr
|
||||
? try_walkthrough_jmptbl(analysis, fcn, bb, depth, jmp_aop.addr, case_shift, jmptbl_addr, op.ptr, 4, table_size, default_case, 4)
|
||||
: try_walkthrough_casetbl(analysis, fcn, bb, depth, jmp_aop.addr, case_shift, jmptbl_addr, casetbl_addr, op.ptr, 4, table_size, default_case, 4);
|
||||
? rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms)
|
||||
: rz_analysis_walkthrough_casetbl(analysis, fcn, bb, ¶ms);
|
||||
if (ret) {
|
||||
lea_jmptbl_ip = jmp_aop.addr;
|
||||
}
|
||||
|
|
@ -1028,7 +1051,7 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
bb->jump = op.jump;
|
||||
bb->fail = UT64_MAX;
|
||||
}
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, op.jump, depth);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
int tc = analysis->opt.tailcall;
|
||||
if (tc) {
|
||||
// eprintf ("TAIL CALL AT 0x%llx\n", op.addr);
|
||||
|
|
@ -1037,11 +1060,11 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
ut8 buf[32];
|
||||
(void)analysis->iob.read_at(analysis->iob.io, op.jump, (ut8 *)buf, sizeof(buf));
|
||||
if (rz_analysis_is_prelude(analysis, buf, sizeof(buf))) {
|
||||
fcn_recurse(analysis, fcn, op.jump, analysis->opt.bb_max_size, depth - 1);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
}
|
||||
} else if (RZ_ABS(diff) > tc) {
|
||||
(void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_REF_TYPE_CALL);
|
||||
fcn_recurse(analysis, fcn, op.jump, analysis->opt.bb_max_size, depth - 1);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
gotoBeach(RZ_ANALYSIS_RET_END);
|
||||
}
|
||||
}
|
||||
|
|
@ -1080,14 +1103,22 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
if (analysis->opt.jmptbl) {
|
||||
if (op.ptr != UT64_MAX) {
|
||||
ut64 table_size, default_case;
|
||||
table_size = cmpval + 1;
|
||||
default_case = op.fail; // is this really default case?
|
||||
if (cmpval != UT64_MAX && default_case != UT64_MAX && (op.reg || op.ireg)) {
|
||||
if (cmpval != UT64_MAX && op.fail != UT64_MAX && (op.reg || op.ireg)) {
|
||||
RzAnalysisJmpTableParams params = {
|
||||
.jmp_address = op.addr,
|
||||
.case_shift = 0,
|
||||
.jmptbl_loc = op.ptr,
|
||||
.casetbl_loc = UT64_MAX,
|
||||
.entry_size = analysis->bits >> 3,
|
||||
.table_count = cmpval + 1,
|
||||
.jmptbl_off = op.ptr,
|
||||
.default_case = op.fail,
|
||||
.tasks = tasks
|
||||
};
|
||||
if (op.ireg) {
|
||||
try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, 0, op.ptr, op.ptr, analysis->bits >> 3, table_size, default_case, ret);
|
||||
rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
} else { // op.reg
|
||||
walkthrough_arm_jmptbl_style(analysis, fcn, bb, depth, op.addr, op.ptr, analysis->bits >> 3, table_size, default_case, ret);
|
||||
rz_analysis_walkthrough_arm_jmptbl_style(analysis, fcn, bb, ¶ms);
|
||||
}
|
||||
// check if op.jump and op.fail contain jump table location
|
||||
// clear jump address, because it's jump table location
|
||||
|
|
@ -1100,17 +1131,9 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
}
|
||||
}
|
||||
int saved_stack = fcn->stack;
|
||||
if (continue_after_jump) {
|
||||
rz_analysis_fcn_bb(analysis, fcn, op.jump, depth);
|
||||
fcn->stack = saved_stack;
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, op.fail, depth);
|
||||
fcn->stack = saved_stack;
|
||||
} else {
|
||||
rz_analysis_fcn_bb(analysis, fcn, op.jump, depth);
|
||||
fcn->stack = saved_stack;
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, op.fail, depth);
|
||||
fcn->stack = saved_stack;
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.fail);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
if (!continue_after_jump) {
|
||||
if (op.jump < fcn->addr) {
|
||||
if (!overlapped) {
|
||||
bb->jump = op.jump;
|
||||
|
|
@ -1172,12 +1195,17 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
// switch statement
|
||||
if (analysis->opt.jmptbl && lea_jmptbl_ip != op.addr) {
|
||||
RzAnalysisJmpTableParams params = {
|
||||
.jmp_address = op.addr,
|
||||
.entry_size = analysis->bits >> 3,
|
||||
.jmptbl_loc = op.ptr,
|
||||
.jmptbl_off = op.ptr,
|
||||
.tasks = tasks
|
||||
};
|
||||
// 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
|
||||
ut64 table_size, default_case;
|
||||
st64 case_shift;
|
||||
if (try_get_jmptbl_info(analysis, fcn, op.addr, bb, &table_size, &default_case, &case_shift)) {
|
||||
if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, ¶ms)) {
|
||||
bool case_table = false;
|
||||
RzAnalysisOp prev_op;
|
||||
analysis->iob.read_at(analysis->iob.io, op.addr - op.size, buf, sizeof(buf));
|
||||
|
|
@ -1188,30 +1216,26 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
if (prev_op.type == RZ_ANALYSIS_OP_TYPE_MOV && prev_op.disp && prev_op.disp != UT64_MAX && same_reg) {
|
||||
// movzx reg, byte [reg + case_table]
|
||||
// jmp dword [reg*4 + jump_table]
|
||||
if (try_walkthrough_casetbl(analysis, fcn, bb, depth, op.addr, case_shift, op.ptr, prev_op.disp, op.ptr, analysis->bits >> 3, table_size, default_case, ret)) {
|
||||
params.casetbl_loc = prev_op.disp;
|
||||
if (rz_analysis_walkthrough_casetbl(analysis, fcn, bb, ¶ms)) {
|
||||
ret = case_table = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
rz_analysis_op_fini(&prev_op);
|
||||
if (!case_table) {
|
||||
ret = try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, case_shift, op.ptr, op.ptr, analysis->bits >> 3, table_size, default_case, ret);
|
||||
ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
}
|
||||
}
|
||||
} else if (op.ptr != UT64_MAX && op.reg) { // direct jump
|
||||
ut64 table_size, default_case;
|
||||
st64 case_shift;
|
||||
if (try_get_jmptbl_info(analysis, fcn, op.addr, bb, &table_size, &default_case, &case_shift)) {
|
||||
ret = try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, case_shift, op.ptr, op.ptr, analysis->bits >> 3, table_size, default_case, ret);
|
||||
if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, ¶ms)) {
|
||||
ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
}
|
||||
} else if (movdisp != UT64_MAX) {
|
||||
ut64 table_size;
|
||||
ut64 default_case;
|
||||
ut64 jmptbl_base = 0;
|
||||
ut64 lea_op_off = UT64_MAX;
|
||||
st64 case_shift;
|
||||
RzListIter *iter;
|
||||
leaddr_pair *pair;
|
||||
params.jmptbl_off = 0;
|
||||
if (movbasereg) {
|
||||
// find nearest candidate leaddr before op.addr
|
||||
rz_list_foreach_prev(analysis->leaddrs, iter, pair) {
|
||||
|
|
@ -1220,42 +1244,46 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
if ((lea_op_off == UT64_MAX || lea_op_off > op.addr - pair->op_addr) && pair->reg && !strcmp(movbasereg, pair->reg)) {
|
||||
lea_op_off = op.addr - pair->op_addr;
|
||||
jmptbl_base = pair->leaddr;
|
||||
params.jmptbl_off = pair->leaddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!try_get_jmptbl_info(analysis, fcn, op.addr, bb, &table_size, &default_case, &case_shift)) {
|
||||
table_size = cmpval + 1;
|
||||
default_case = -1;
|
||||
if (!rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, ¶ms)) {
|
||||
params.table_count = cmpval + 1;
|
||||
params.default_case = -1;
|
||||
}
|
||||
ret = try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, case_shift, jmptbl_base + movdisp, jmptbl_base, movscale, table_size, default_case, ret);
|
||||
params.jmptbl_loc = params.jmptbl_off + movdisp;
|
||||
params.entry_size = movscale;
|
||||
ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
cmpval = UT64_MAX;
|
||||
} else if (is_arm) {
|
||||
params.jmptbl_loc = op.addr + op.size;
|
||||
params.jmptbl_off = op.addr + 4;
|
||||
params.default_case = UT64_MAX;
|
||||
if (op.ptrsize == 1) { // TBB
|
||||
ut64 pred_cmpval = try_get_cmpval_from_parents(analysis, fcn, bb, op.ireg);
|
||||
ut64 table_size = 0;
|
||||
params.table_count = 0;
|
||||
if (pred_cmpval != UT64_MAX) {
|
||||
table_size += pred_cmpval;
|
||||
params.table_count += pred_cmpval;
|
||||
} else {
|
||||
table_size += cmpval;
|
||||
params.table_count += cmpval;
|
||||
}
|
||||
ret = try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, 0, op.addr + op.size,
|
||||
op.addr + 4, 1, table_size, UT64_MAX, ret);
|
||||
params.entry_size = 1;
|
||||
ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
// skip inlined jumptable
|
||||
idx += table_size;
|
||||
}
|
||||
if (op.ptrsize == 2) { // LDRH on thumb/arm
|
||||
idx += params.table_count;
|
||||
} else if (op.ptrsize == 2) { // LDRH on thumb/arm
|
||||
ut64 pred_cmpval = try_get_cmpval_from_parents(analysis, fcn, bb, op.ireg);
|
||||
int tablesize = 1;
|
||||
params.table_count = 1;
|
||||
if (pred_cmpval != UT64_MAX) {
|
||||
tablesize += pred_cmpval;
|
||||
params.table_count += pred_cmpval;
|
||||
} else {
|
||||
tablesize += cmpval;
|
||||
params.table_count += cmpval;
|
||||
}
|
||||
ret = try_walkthrough_jmptbl(analysis, fcn, bb, depth, op.addr, 0, op.addr + op.size,
|
||||
op.addr + 4, 2, tablesize, UT64_MAX, ret);
|
||||
params.entry_size = 2;
|
||||
ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, ¶ms);
|
||||
// skip inlined jumptable
|
||||
idx += (tablesize * 2);
|
||||
idx += (params.table_count * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1264,8 +1292,8 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
if (analysis->opt.ijmp) {
|
||||
if (continue_after_jump) {
|
||||
rz_analysis_fcn_bb(analysis, fcn, op.jump, depth);
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, op.fail, depth);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.fail);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
if (overlapped) {
|
||||
goto analopfinish;
|
||||
}
|
||||
|
|
@ -1282,7 +1310,6 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
}
|
||||
break;
|
||||
/* fallthru */
|
||||
case RZ_ANALYSIS_OP_TYPE_PUSH:
|
||||
last_is_push = true;
|
||||
last_push_addr = op.val;
|
||||
|
|
@ -1307,7 +1334,7 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
op.type = RZ_ANALYSIS_OP_TYPE_JMP;
|
||||
op.jump = last_push_addr;
|
||||
bb->jump = op.jump;
|
||||
ret = rz_analysis_fcn_bb(analysis, fcn, op.jump, depth);
|
||||
rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
|
||||
goto beach;
|
||||
}
|
||||
if (!op.cond) {
|
||||
|
|
@ -1358,10 +1385,6 @@ static int fcn_recurse(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr,
|
|||
}
|
||||
}
|
||||
beach:
|
||||
while (lea_cnt > 0) {
|
||||
rz_list_delete(analysis->leaddrs, rz_list_tail(analysis->leaddrs));
|
||||
lea_cnt--;
|
||||
}
|
||||
rz_analysis_op_fini(&op);
|
||||
RZ_FREE(last_reg_mov_lea_name);
|
||||
if (bb && bb->size == 0) {
|
||||
|
|
@ -1373,8 +1396,65 @@ beach:
|
|||
return ret;
|
||||
}
|
||||
|
||||
RZ_API int rz_analysis_fcn_bb(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, int depth) {
|
||||
return fcn_recurse(analysis, fcn, addr, analysis->opt.bb_max_size, depth - 1);
|
||||
/**
|
||||
* \brief Adds a new task item to the `tasks` parameter.
|
||||
*
|
||||
* Used to create a new item to the `tasks` parameter
|
||||
* that can be worked on later by the `rz_analysis_run_tasks` function.
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance.
|
||||
* \param tasks Pointer to RzVector to add a new RzAnalysisTaskItem to.
|
||||
* \param fcn Pointer to RzAnalysisFunction in which analysis will be performed on.
|
||||
* \param block Pointer to RzAnalysisBlock in which analysis will be performed on. If null, analysis will take care of block creation.
|
||||
* \param address Address where analysis will start from
|
||||
*/
|
||||
RZ_API bool rz_analysis_task_item_new(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzVector *tasks, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE RzAnalysisBlock *block, ut64 address) {
|
||||
rz_return_val_if_fail(analysis && tasks && fcn, false);
|
||||
RzAnalysisTaskItem item = { fcn, block, fcn->stack, address };
|
||||
RzAnalysisTaskItem *it;
|
||||
rz_vector_foreach(tasks, it) {
|
||||
if (item.start_address == it->start_address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return rz_vector_push(tasks, &item);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Runs analysis on the task items.
|
||||
*
|
||||
* Runs control-flow and variable usage analysis on each of the task items until tasks vector becomes empty.
|
||||
* Items are removed from the tasks vector as they are processed.
|
||||
* Items are added to the tasks vector as new basic blocks are found to be analyzed.
|
||||
*
|
||||
* \param tasks Pointer to RzVector of RzAnalysisTaskItem to be performed analysis on.
|
||||
*/
|
||||
RZ_API int rz_analysis_run_tasks(RZ_NONNULL RzVector *tasks) {
|
||||
rz_return_val_if_fail(tasks, RZ_ANALYSIS_RET_ERROR);
|
||||
int ret = RZ_ANALYSIS_RET_ERROR;
|
||||
while (!rz_vector_empty(tasks)) {
|
||||
RzAnalysisTaskItem item;
|
||||
rz_vector_pop(tasks, &item);
|
||||
int r = run_basic_block_analysis(&item, tasks);
|
||||
switch (r) {
|
||||
case RZ_ANALYSIS_RET_NOP:
|
||||
case RZ_ANALYSIS_RET_ERROR:
|
||||
case RZ_ANALYSIS_RET_DUP:
|
||||
case RZ_ANALYSIS_RET_NEW:
|
||||
if (ret != RZ_ANALYSIS_RET_END) {
|
||||
ret = r;
|
||||
}
|
||||
break;
|
||||
case RZ_ANALYSIS_RET_END:
|
||||
default:
|
||||
ret = r;
|
||||
break;
|
||||
}
|
||||
if (rz_cons_is_breaked()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RZ_API bool rz_analysis_check_fcn(RzAnalysis *analysis, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high) {
|
||||
|
|
@ -1487,12 +1567,11 @@ RZ_API int rz_analysis_fcn(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 a
|
|||
const int shadow_store = 0x28; // First 4 args + retaddr
|
||||
fcn->stack = fcn->maxstack = fcn->reg_save_area = shadow_store;
|
||||
}
|
||||
int ret = rz_analysis_fcn_bb(analysis, fcn, addr, analysis->opt.depth);
|
||||
if (ret < 0) {
|
||||
if (analysis->verbose) {
|
||||
eprintf("Failed to analyze basic block at 0x%" PFMT64x "\n", addr);
|
||||
}
|
||||
}
|
||||
RzVector tasks;
|
||||
rz_vector_init(&tasks, sizeof(RzAnalysisTaskItem), NULL, NULL);
|
||||
rz_analysis_task_item_new(analysis, &tasks, fcn, NULL, addr);
|
||||
int ret = rz_analysis_run_tasks(&tasks);
|
||||
rz_vector_fini(&tasks);
|
||||
if (analysis->opt.endsize && ret == RZ_ANALYSIS_RET_END && rz_analysis_function_realsize(fcn)) { // cfg analysis completed
|
||||
RzListIter *iter;
|
||||
RzAnalysisBlock *bb;
|
||||
|
|
@ -2033,7 +2112,7 @@ static bool analize_addr_cb(ut64 addr, void *user) {
|
|||
RzAnalysisBlock *existing_bb = rz_analysis_get_block_at(analysis, addr);
|
||||
if (!existing_bb || !rz_list_contains(ctx->fcn->bbs, existing_bb)) {
|
||||
int old_len = rz_list_length(ctx->fcn->bbs);
|
||||
rz_analysis_fcn_bb(ctx->fcn->analysis, ctx->fcn, addr, analysis->opt.depth);
|
||||
analyze_function_locally(ctx->fcn->analysis, ctx->fcn, addr);
|
||||
if (old_len != rz_list_length(ctx->fcn->bbs)) {
|
||||
rz_analysis_block_recurse(rz_analysis_get_block_at(analysis, addr), mark_as_visited, user);
|
||||
}
|
||||
|
|
@ -2118,7 +2197,7 @@ static void update_analysis(RzAnalysis *analysis, RzList *fcns, HtUP *reachable)
|
|||
// analyze edges that don't have a block
|
||||
RzAnalysisBlock *bb = rz_analysis_get_block_at(analysis, fcn->addr);
|
||||
if (!bb) {
|
||||
rz_analysis_fcn_bb(analysis, fcn, fcn->addr, analysis->opt.depth);
|
||||
analyze_function_locally(analysis, fcn, fcn->addr);
|
||||
bb = rz_analysis_get_block_at(analysis, fcn->addr);
|
||||
if (!bb) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
if (analysis->verbose) \
|
||||
eprintf(format, __VA_ARGS__)
|
||||
|
||||
#define JMPTBL_MAXSZ 512
|
||||
|
||||
static void apply_case(RzAnalysis *analysis, RzAnalysisBlock *block, ut64 switch_addr, ut64 offset_sz, ut64 case_addr, ut64 id, ut64 case_addr_loc) {
|
||||
// eprintf ("** apply_case: 0x%"PFMT64x " from 0x%"PFMT64x "\n", case_addr, case_addr_loc);
|
||||
rz_meta_set_data_at(analysis, case_addr_loc, offset_sz);
|
||||
|
|
@ -46,64 +44,69 @@ static void apply_switch(RzAnalysis *analysis, ut64 switch_addr, ut64 jmptbl_add
|
|||
|
||||
// analyze a jmptablle inside a function // maybe rename to rz_analysis_fcn_jmptbl() ?
|
||||
RZ_API bool rz_analysis_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, ut64 jmpaddr, ut64 table, ut64 tablesize, ut64 default_addr) {
|
||||
const int depth = 50;
|
||||
return try_walkthrough_jmptbl(analysis, fcn, block, depth, jmpaddr, 0, table, table, tablesize, tablesize, default_addr, false);
|
||||
RzAnalysisJmpTableParams params = {
|
||||
.jmp_address = jmpaddr,
|
||||
.case_shift = 0,
|
||||
.jmptbl_loc = table,
|
||||
.casetbl_loc = UT64_MAX,
|
||||
.jmptbl_off = table,
|
||||
.entry_size = tablesize,
|
||||
.table_count = tablesize,
|
||||
.default_case = default_addr,
|
||||
};
|
||||
return rz_analysis_walkthrough_jmptbl(analysis, fcn, block, ¶ms);
|
||||
}
|
||||
|
||||
static inline void analyze_new_case(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, ut64 ip, ut64 jmpptr, int depth) {
|
||||
const ut64 block_size = block->size;
|
||||
(void)rz_analysis_fcn_bb(analysis, fcn, jmpptr, depth - 1);
|
||||
if (block->size != block_size) {
|
||||
// block was be split during analysis and does not contain the
|
||||
// jmp instruction anymore, so we need to search for it and get it again
|
||||
RzAnalysisSwitchOp *sop = block->switch_op;
|
||||
block = rz_analysis_find_most_relevant_block_in(analysis, ip);
|
||||
if (!block) {
|
||||
rz_warn_if_reached();
|
||||
return;
|
||||
}
|
||||
block->switch_op = sop;
|
||||
/**
|
||||
* \brief Marks for analysis jump table cases with a space optimization for multiple cases corresponding to the same address
|
||||
*
|
||||
* This function works similarly to `rz_analysis_walkthrough_jmptbl`,
|
||||
* with the difference that jump targets are hidden behind a indirection in the case table
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance
|
||||
* \param fcn Pointer to RzAnalysisFunction to add the new cases
|
||||
* \param block Pointer to RzAnalysisBlock that originates the switch table
|
||||
* \param params Pointer to RzAnalysisJmpTableParams necessary to analyze the jump table
|
||||
*/
|
||||
RZ_API bool rz_analysis_walkthrough_casetbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params) {
|
||||
rz_return_val_if_fail(analysis && fcn && block && params, false);
|
||||
bool ret = true;
|
||||
if (params->table_count == 0) {
|
||||
params->table_count = analysis->opt.jmptbl_maxcount;
|
||||
}
|
||||
}
|
||||
|
||||
RZ_API bool try_walkthrough_casetbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, st64 start_casenum_shift, ut64 jmptbl_loc, ut64 casetbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, bool ret0) {
|
||||
bool ret = ret0;
|
||||
if (jmptbl_size == 0) {
|
||||
jmptbl_size = JMPTBL_MAXSZ;
|
||||
}
|
||||
if (jmptbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable location 0x%08" PFMT64x "\n", jmptbl_loc);
|
||||
if (params->jmptbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable location 0x%08" PFMT64x "\n", params->jmptbl_loc);
|
||||
return false;
|
||||
}
|
||||
if (casetbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid CaseTable location 0x%08" PFMT64x "\n", jmptbl_loc);
|
||||
if (params->casetbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid CaseTable location 0x%08" PFMT64x "\n", params->jmptbl_loc);
|
||||
return false;
|
||||
}
|
||||
if (jmptbl_size < 1 || jmptbl_size > ST32_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable size at 0x%08" PFMT64x "\n", ip);
|
||||
if (params->table_count < 1 || params->table_count > ST32_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable size at 0x%08" PFMT64x "\n", params->jmp_address);
|
||||
return false;
|
||||
}
|
||||
ut64 jmpptr, case_idx, jmpptr_idx;
|
||||
ut8 *jmptbl = calloc(jmptbl_size, sz);
|
||||
if (!jmptbl || !analysis->iob.read_at(analysis->iob.io, jmptbl_loc, jmptbl, jmptbl_size * sz)) {
|
||||
ut8 *jmptbl = calloc(params->table_count, params->entry_size);
|
||||
if (!jmptbl || !analysis->iob.read_at(analysis->iob.io, params->jmptbl_loc, jmptbl, params->table_count * params->entry_size)) {
|
||||
free(jmptbl);
|
||||
return false;
|
||||
}
|
||||
ut8 *casetbl = calloc(jmptbl_size, sizeof(ut8));
|
||||
if (!casetbl || !analysis->iob.read_at(analysis->iob.io, casetbl_loc, casetbl, jmptbl_size)) {
|
||||
ut8 *casetbl = calloc(params->table_count, sizeof(ut8));
|
||||
if (!casetbl || !analysis->iob.read_at(analysis->iob.io, params->casetbl_loc, casetbl, params->table_count)) {
|
||||
free(jmptbl);
|
||||
free(casetbl);
|
||||
return false;
|
||||
}
|
||||
for (case_idx = 0; case_idx < jmptbl_size; case_idx++) {
|
||||
for (case_idx = 0; case_idx < params->table_count; case_idx++) {
|
||||
jmpptr_idx = casetbl[case_idx];
|
||||
|
||||
if (jmpptr_idx >= jmptbl_size) {
|
||||
if (jmpptr_idx >= params->table_count) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sz) {
|
||||
switch (params->entry_size) {
|
||||
case 1:
|
||||
jmpptr = rz_read_le8(jmptbl + jmpptr_idx);
|
||||
break;
|
||||
|
|
@ -123,7 +126,7 @@ RZ_API bool try_walkthrough_casetbl(RzAnalysis *analysis, RzAnalysisFunction *fc
|
|||
if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
|
||||
st32 jmpdelta = (st32)jmpptr;
|
||||
// jump tables where sign extended movs are used
|
||||
jmpptr = jmptbl_off + jmpdelta;
|
||||
jmpptr = params->jmptbl_off + jmpdelta;
|
||||
if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -134,19 +137,19 @@ RZ_API bool try_walkthrough_casetbl(RzAnalysis *analysis, RzAnalysisFunction *fc
|
|||
}
|
||||
}
|
||||
|
||||
const ut64 jmpptr_idx_off = casetbl_loc + case_idx;
|
||||
const ut64 jmpptr_idx_off = params->casetbl_loc + case_idx;
|
||||
rz_meta_set_data_at(analysis, jmpptr_idx_off, 1);
|
||||
rz_analysis_hint_set_immbase(analysis, jmpptr_idx_off, 10);
|
||||
|
||||
apply_case(analysis, block, ip, sz, jmpptr, case_idx + start_casenum_shift, jmptbl_loc + jmpptr_idx * sz);
|
||||
analyze_new_case(analysis, fcn, block, ip, jmpptr, depth);
|
||||
apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, case_idx + params->case_shift, params->jmptbl_loc + jmpptr_idx * params->entry_size);
|
||||
rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
|
||||
}
|
||||
|
||||
if (case_idx > 0) {
|
||||
if (default_case == 0) {
|
||||
default_case = UT64_MAX;
|
||||
if (params->default_case == 0) {
|
||||
params->default_case = UT64_MAX;
|
||||
}
|
||||
apply_switch(analysis, ip, jmptbl_loc, case_idx, default_case);
|
||||
apply_switch(analysis, params->jmp_address, params->jmptbl_loc, case_idx, params->default_case);
|
||||
}
|
||||
|
||||
free(jmptbl);
|
||||
|
|
@ -154,30 +157,41 @@ RZ_API bool try_walkthrough_casetbl(RzAnalysis *analysis, RzAnalysisFunction *fc
|
|||
return ret;
|
||||
}
|
||||
|
||||
RZ_API bool try_walkthrough_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, st64 start_casenum_shift, ut64 jmptbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, bool ret0) {
|
||||
bool ret = ret0;
|
||||
// jmptbl_size can not always be determined
|
||||
if (jmptbl_size == 0) {
|
||||
jmptbl_size = JMPTBL_MAXSZ;
|
||||
/**
|
||||
* \brief Marks the jump table cases for analysis
|
||||
*
|
||||
* Goes through each case on the jump table, adds necessary flags/metadata and
|
||||
* a new RzAnalysisTaskItem to `params->tasks` to be analyzed later.
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance
|
||||
* \param fcn Pointer to RzAnalysisFunction to add the new cases
|
||||
* \param block Pointer to RzAnalysisBlock that originates the switch table
|
||||
* \param params Pointer to RzAnalysisJmpTableParams necessary to analyze the jump table
|
||||
*/
|
||||
RZ_API bool rz_analysis_walkthrough_jmptbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params) {
|
||||
rz_return_val_if_fail(analysis && fcn && block && params, false);
|
||||
// table_count can not always be determined
|
||||
if (params->table_count == 0) {
|
||||
params->table_count = analysis->opt.jmptbl_maxcount;
|
||||
}
|
||||
if (jmptbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable location 0x%08" PFMT64x "\n", jmptbl_loc);
|
||||
if (params->jmptbl_loc == UT64_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable location 0x%08" PFMT64x "\n", params->jmptbl_loc);
|
||||
return false;
|
||||
}
|
||||
if (jmptbl_size < 1 || jmptbl_size > ST32_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable size at 0x%08" PFMT64x "\n", ip);
|
||||
if (params->table_count < 1 || params->table_count > ST32_MAX) {
|
||||
aprintf("Warning: Invalid JumpTable size at 0x%08" PFMT64x "\n", params->jmp_address);
|
||||
return false;
|
||||
}
|
||||
ut64 jmpptr, offs;
|
||||
ut8 *jmptbl = calloc(jmptbl_size, sz);
|
||||
ut8 *jmptbl = calloc(params->table_count, params->entry_size);
|
||||
if (!jmptbl) {
|
||||
return false;
|
||||
}
|
||||
bool is_arm = analysis->cur->arch && !strncmp(analysis->cur->arch, "arm", 3);
|
||||
// eprintf ("JMPTBL AT 0x%"PFMT64x"\n", jmptbl_loc);
|
||||
analysis->iob.read_at(analysis->iob.io, jmptbl_loc, jmptbl, jmptbl_size * sz);
|
||||
for (offs = 0; offs + sz - 1 < jmptbl_size * sz; offs += sz) {
|
||||
switch (sz) {
|
||||
analysis->iob.read_at(analysis->iob.io, params->jmptbl_loc, jmptbl, params->table_count * params->entry_size);
|
||||
for (offs = 0; offs + params->entry_size - 1 < params->table_count * params->entry_size; offs += params->entry_size) {
|
||||
switch (params->entry_size) {
|
||||
case 1:
|
||||
jmpptr = (ut64)(ut8)rz_read_le8(jmptbl + offs);
|
||||
break;
|
||||
|
|
@ -201,14 +215,14 @@ RZ_API bool try_walkthrough_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn
|
|||
if (jmpptr == 0 || jmpptr == UT32_MAX || jmpptr == UT64_MAX) {
|
||||
break;
|
||||
}
|
||||
if (sz == 2 && is_arm) {
|
||||
jmpptr = ip + 4 + (jmpptr * 2); // tbh [pc, r2, lsl 1] // assume lsl 1
|
||||
} else if (sz == 1 && is_arm) {
|
||||
jmpptr = ip + 4 + (jmpptr * 2); // lbb [pc, r2] // assume lsl 1
|
||||
if (params->entry_size == 2 && is_arm) {
|
||||
jmpptr = params->jmp_address + 4 + (jmpptr * 2); // tbh [pc, r2, lsl 1] // assume lsl 1
|
||||
} else if (params->entry_size == 1 && is_arm) {
|
||||
jmpptr = params->jmp_address + 4 + (jmpptr * 2); // lbb [pc, r2] // assume lsl 1
|
||||
} else if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
|
||||
st32 jmpdelta = (st32)jmpptr;
|
||||
// jump tables where sign extended movs are used
|
||||
jmpptr = jmptbl_off + jmpdelta;
|
||||
jmpptr = params->jmptbl_off + jmpdelta;
|
||||
if (!analysis->iob.is_valid_offset(analysis->iob.io, jmpptr, 0)) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -218,19 +232,19 @@ RZ_API bool try_walkthrough_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn
|
|||
break;
|
||||
}
|
||||
}
|
||||
apply_case(analysis, block, ip, sz, jmpptr, (offs / sz) + start_casenum_shift, jmptbl_loc + offs);
|
||||
analyze_new_case(analysis, fcn, block, ip, jmpptr, depth);
|
||||
apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, (offs / params->entry_size) + params->case_shift, params->jmptbl_loc + offs);
|
||||
rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
|
||||
}
|
||||
|
||||
if (offs > 0) {
|
||||
if (default_case == 0) {
|
||||
default_case = UT64_MAX;
|
||||
if (params->default_case == 0) {
|
||||
params->default_case = UT64_MAX;
|
||||
}
|
||||
apply_switch(analysis, ip, jmptbl_loc, offs / sz, default_case);
|
||||
apply_switch(analysis, params->jmp_address, params->jmptbl_loc, offs / params->entry_size, params->default_case);
|
||||
}
|
||||
|
||||
free(jmptbl);
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool detect_casenum_shift(RzAnalysisOp *op, RzRegItem **cmp_reg, st64 *start_casenum_shift) {
|
||||
|
|
@ -255,29 +269,43 @@ static bool detect_casenum_shift(RzAnalysisOp *op, RzRegItem **cmp_reg, st64 *st
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: RENAME
|
||||
RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 jmp_addr, ut64 lea_addr, ut64 *table_size, ut64 *default_case, st64 *start_casenum_shift) {
|
||||
/**
|
||||
* \brief Gets some necessary information about a jump table to perform analysis on
|
||||
*
|
||||
* Gets amount of cases inside a jump table, the default case address and the case shift amount
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance
|
||||
* \param fcn Pointer to RzAnalysisFunction where jump table ocurred
|
||||
* \param jmp_address Address of jump intruction that uses the table
|
||||
* \param lea_addr Address of lea instruction that loads the address of the jump table base
|
||||
* \param params Pointer to RzAnalysisJmpTableParams where the results of the function are stored
|
||||
*/
|
||||
RZ_API bool rz_analysis_get_delta_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, ut64 jmp_address, ut64 lea_address, RZ_NONNULL RzAnalysisJmpTableParams *params) {
|
||||
rz_return_val_if_fail(analysis && fcn && params, false);
|
||||
bool isValid = false;
|
||||
bool foundCmp = false;
|
||||
int i;
|
||||
|
||||
RzAnalysisOp tmp_aop = { 0 };
|
||||
if (lea_addr > jmp_addr) {
|
||||
if (lea_address > jmp_address) {
|
||||
return false;
|
||||
}
|
||||
int search_sz = jmp_addr - lea_addr;
|
||||
|
||||
params->jmp_address = jmp_address;
|
||||
|
||||
int search_sz = jmp_address - lea_address;
|
||||
ut8 *buf = malloc(search_sz);
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
// search for a cmp register with a reasonable size
|
||||
analysis->iob.read_at(analysis->iob.io, lea_addr, (ut8 *)buf, search_sz);
|
||||
analysis->iob.read_at(analysis->iob.io, lea_address, (ut8 *)buf, search_sz);
|
||||
RzVector v;
|
||||
rz_vector_init(&v, sizeof(ut64), NULL, NULL);
|
||||
int len = 0;
|
||||
RzRegItem *cmp_reg = NULL;
|
||||
for (i = 0; i + 8 < search_sz; i += len) {
|
||||
len = rz_analysis_op(analysis, &tmp_aop, lea_addr + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_BASIC);
|
||||
len = rz_analysis_op(analysis, &tmp_aop, lea_address + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_BASIC);
|
||||
if (len < 1) {
|
||||
len = 1;
|
||||
}
|
||||
|
|
@ -287,7 +315,7 @@ RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *
|
|||
continue;
|
||||
}
|
||||
|
||||
*default_case = tmp_aop.jump == tmp_aop.jump + len ? tmp_aop.fail : tmp_aop.jump;
|
||||
params->default_case = tmp_aop.jump == tmp_aop.jump + len ? tmp_aop.fail : tmp_aop.jump;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -303,16 +331,16 @@ RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *
|
|||
// might not actually have a value, let the next step figure out the size then
|
||||
if (tmp_aop.val == UT64_MAX && tmp_aop.refptr == 0) {
|
||||
isValid = true;
|
||||
*table_size = 0;
|
||||
params->table_count = 0;
|
||||
} else if (tmp_aop.refptr == 0) {
|
||||
isValid = tmp_aop.val < 0x200;
|
||||
*table_size = tmp_aop.val + 1;
|
||||
params->table_count = tmp_aop.val + 1;
|
||||
} else {
|
||||
isValid = tmp_aop.refptr < 0x200;
|
||||
*table_size = tmp_aop.refptr + 1;
|
||||
params->table_count = tmp_aop.refptr + 1;
|
||||
}
|
||||
rz_vector_push(&v, &i);
|
||||
rz_analysis_op(analysis, &tmp_aop, lea_addr + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_VAL);
|
||||
rz_analysis_op(analysis, &tmp_aop, lea_address + i, buf + i, search_sz - i, RZ_ANALYSIS_OP_MASK_VAL);
|
||||
if (tmp_aop.dst && tmp_aop.dst->reg) {
|
||||
cmp_reg = tmp_aop.dst->reg;
|
||||
} else if (tmp_aop.reg) {
|
||||
|
|
@ -325,15 +353,15 @@ RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *
|
|||
foundCmp = true;
|
||||
}
|
||||
if (isValid) {
|
||||
*start_casenum_shift = 0;
|
||||
params->case_shift = 0;
|
||||
void **it;
|
||||
rz_vector_foreach_prev(&v, it) {
|
||||
const ut64 op_off = *(ut64 *)it;
|
||||
ut64 op_addr = lea_addr + op_off;
|
||||
ut64 op_addr = lea_address + op_off;
|
||||
rz_analysis_op(analysis, &tmp_aop, op_addr,
|
||||
buf + op_off, search_sz - op_off,
|
||||
RZ_ANALYSIS_OP_MASK_VAL);
|
||||
if (detect_casenum_shift(&tmp_aop, &cmp_reg, start_casenum_shift)) {
|
||||
if (detect_casenum_shift(&tmp_aop, &cmp_reg, ¶ms->case_shift)) {
|
||||
rz_analysis_op_fini(&tmp_aop);
|
||||
break;
|
||||
}
|
||||
|
|
@ -345,8 +373,17 @@ RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *
|
|||
return isValid;
|
||||
}
|
||||
|
||||
// TODO: find a better function name
|
||||
RZ_API int walkthrough_arm_jmptbl_style(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, ut64 jmptbl_loc, ut64 sz, ut64 jmptbl_size, ut64 default_case, int ret0) {
|
||||
/**
|
||||
* \brief Marks for analysis ARM specific jump table cases
|
||||
*
|
||||
* This function works similarly to `rz_analysis_walkthrough_jmptbl`, but is specific to ARM
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance
|
||||
* \param fcn Pointer to RzAnalysisFunction to add the new cases
|
||||
* \param block Pointer to RzAnalysisBlock that originates the switch table
|
||||
* \param params Pointer to RzAnalysisJmpTableParams necessary to analyze the jump table
|
||||
*/
|
||||
RZ_API bool rz_analysis_walkthrough_arm_jmptbl_style(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params) {
|
||||
/*
|
||||
* Example about arm jump table
|
||||
*
|
||||
|
|
@ -365,30 +402,41 @@ RZ_API int walkthrough_arm_jmptbl_style(RzAnalysis *analysis, RzAnalysisFunction
|
|||
* ; CODE XREF from loc._a_7 (+0x18)
|
||||
* 0x000105e8 bbffffea b sym.input_3
|
||||
*/
|
||||
|
||||
rz_return_val_if_fail(analysis && fcn && block && params, false);
|
||||
ut64 offs, jmpptr;
|
||||
int ret = ret0;
|
||||
|
||||
if (jmptbl_size == 0) {
|
||||
jmptbl_size = JMPTBL_MAXSZ;
|
||||
if (params->table_count == 0) {
|
||||
params->table_count = analysis->opt.jmptbl_maxcount;
|
||||
}
|
||||
|
||||
for (offs = 0; offs + sz - 1 < jmptbl_size * sz; offs += sz) {
|
||||
jmpptr = jmptbl_loc + offs;
|
||||
apply_case(analysis, block, ip, sz, jmpptr, offs / sz, jmptbl_loc + offs);
|
||||
analyze_new_case(analysis, fcn, block, ip, jmpptr, depth);
|
||||
for (offs = 0; offs + params->entry_size - 1 < params->table_count * params->entry_size; offs += params->entry_size) {
|
||||
jmpptr = params->jmptbl_loc + offs;
|
||||
apply_case(analysis, block, params->jmp_address, params->entry_size, jmpptr, offs / params->entry_size, params->jmptbl_loc + offs);
|
||||
rz_analysis_task_item_new(analysis, params->tasks, fcn, NULL, jmpptr);
|
||||
}
|
||||
|
||||
if (offs > 0) {
|
||||
if (default_case == 0 || default_case == UT32_MAX) {
|
||||
default_case = UT64_MAX;
|
||||
if (params->default_case == 0 || params->default_case == UT32_MAX) {
|
||||
params->default_case = UT64_MAX;
|
||||
}
|
||||
apply_switch(analysis, ip, jmptbl_loc, offs / sz, default_case);
|
||||
apply_switch(analysis, params->jmp_address, params->jmptbl_loc, offs / params->entry_size, params->default_case);
|
||||
}
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, RzAnalysisBlock *my_bb, ut64 *table_size, ut64 *default_case, st64 *start_casenum_shift) {
|
||||
/**
|
||||
* \brief Gets some necessary information about a jump table to perform analysis on
|
||||
*
|
||||
* Gets amount of cases inside a jump table, the default case address and the case shift amount
|
||||
*
|
||||
* \param analysis Pointer to RzAnalysis instance
|
||||
* \param fcn Pointer to RzAnalysisFunction where jump table ocurred
|
||||
* \param block Pointer to RzAnalysisBlock where the jump instruction related to the jump table ocurred
|
||||
* \param jmp_address Address of jump intruction that uses the table
|
||||
* \param params Pointer to RzAnalysisJmpTableParams where the results of the function are stored
|
||||
*/
|
||||
RZ_API bool rz_analysis_get_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, ut64 jmp_address, RZ_NONNULL RzAnalysisJmpTableParams *params) {
|
||||
rz_return_val_if_fail(analysis && fcn && params && block, false);
|
||||
bool isValid = false;
|
||||
int i;
|
||||
RzListIter *iter;
|
||||
|
|
@ -398,8 +446,10 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
return false;
|
||||
}
|
||||
|
||||
params->jmp_address = jmp_address;
|
||||
|
||||
/* if UJMP is in .plt section just skip it */
|
||||
RzBinSection *s = analysis->binb.get_vsect_at(analysis->binb.bin, addr);
|
||||
RzBinSection *s = analysis->binb.get_vsect_at(analysis->binb.bin, jmp_address);
|
||||
if (s && s->name[0]) {
|
||||
bool in_plt = strstr(s->name, ".plt") != NULL;
|
||||
if (!in_plt && strstr(s->name, "_stubs") != NULL) {
|
||||
|
|
@ -413,19 +463,19 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
|
||||
// search for the predecessor bb
|
||||
rz_list_foreach (fcn->bbs, iter, tmp_bb) {
|
||||
if (tmp_bb->jump == my_bb->addr || tmp_bb->fail == my_bb->addr) {
|
||||
if (tmp_bb->jump == block->addr || tmp_bb->fail == block->addr) {
|
||||
prev_bb = tmp_bb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// predecessor must be a conditional jump
|
||||
if (!prev_bb || !prev_bb->jump || !prev_bb->fail) {
|
||||
aprintf("Warning: [analysis.jmp.tbl] Missing predecesessor cjmp bb at 0x%08" PFMT64x "\n", addr);
|
||||
aprintf("Warning: [analysis.jmp.tbl] Missing predecesessor cjmp bb at 0x%08" PFMT64x "\n", jmp_address);
|
||||
return false;
|
||||
}
|
||||
|
||||
// default case is the jump target of the unconditional jump
|
||||
*default_case = prev_bb->jump == my_bb->addr ? prev_bb->fail : prev_bb->jump;
|
||||
params->default_case = prev_bb->jump == block->addr ? prev_bb->fail : prev_bb->jump;
|
||||
|
||||
RzAnalysisOp tmp_aop = { 0 };
|
||||
ut8 *bb_buf = calloc(1, prev_bb->size);
|
||||
|
|
@ -436,12 +486,12 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
analysis->iob.read_at(analysis->iob.io, prev_bb->addr, (ut8 *)bb_buf, prev_bb->size);
|
||||
isValid = false;
|
||||
|
||||
RzAnalysisHint *hint = rz_analysis_hint_get(analysis, addr);
|
||||
RzAnalysisHint *hint = rz_analysis_hint_get(analysis, jmp_address);
|
||||
if (hint) {
|
||||
ut64 val = hint->val;
|
||||
rz_analysis_hint_free(hint);
|
||||
if (val != UT64_MAX) {
|
||||
*table_size = val;
|
||||
params->table_count = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -470,13 +520,13 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
// might not actually have a value, let the next step figure out the size then
|
||||
if (tmp_aop.val == UT64_MAX && tmp_aop.refptr == 0) {
|
||||
isValid = true;
|
||||
*table_size = 0;
|
||||
params->table_count = 0;
|
||||
} else if (tmp_aop.refptr == 0 || tmp_aop.val != UT64_MAX) {
|
||||
isValid = tmp_aop.val < 0x200;
|
||||
*table_size = tmp_aop.val + 1;
|
||||
params->table_count = tmp_aop.val + 1;
|
||||
} else {
|
||||
isValid = tmp_aop.refptr < 0x200;
|
||||
*table_size = tmp_aop.refptr + 1;
|
||||
params->table_count = tmp_aop.refptr + 1;
|
||||
}
|
||||
if (isValid) {
|
||||
rz_analysis_op_fini(&tmp_aop);
|
||||
|
|
@ -496,7 +546,7 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
break;
|
||||
}
|
||||
if (isValid) {
|
||||
*start_casenum_shift = 0;
|
||||
params->case_shift = 0;
|
||||
for (i--; i >= 0; i--) {
|
||||
const ut64 prev_pos = rz_analysis_block_get_op_offset(prev_bb, i);
|
||||
const ut64 op_addr = rz_analysis_block_get_op_addr(prev_bb, i);
|
||||
|
|
@ -507,7 +557,7 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
rz_analysis_op(analysis, &tmp_aop, op_addr,
|
||||
bb_buf + prev_pos, buflen,
|
||||
RZ_ANALYSIS_OP_MASK_VAL);
|
||||
if (detect_casenum_shift(&tmp_aop, &cmp_reg, start_casenum_shift)) {
|
||||
if (detect_casenum_shift(&tmp_aop, &cmp_reg, ¶ms->case_shift)) {
|
||||
rz_analysis_op_fini(&tmp_aop);
|
||||
break;
|
||||
}
|
||||
|
|
@ -516,9 +566,5 @@ RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, u
|
|||
}
|
||||
}
|
||||
free(bb_buf);
|
||||
// eprintf ("switch at 0x%" PFMT64x "\n\tdefault case 0x%" PFMT64x "\n\t#cases: %d\n",
|
||||
// addr,
|
||||
// *default_case,
|
||||
// *table_size);
|
||||
return isValid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2593,6 +2593,13 @@ static bool cb_analysis_jmptbl(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_analysis_jmptblmax(void *user, void *data) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
core->analysis->opt.jmptbl_maxcount = node->i_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_analysis_cjmpref(void *user, void *data) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
|
|
@ -2874,6 +2881,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETICB("asm.lines.maxref", 0, &cb_analysis_maxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
|
||||
|
||||
SETCB("analysis.jmp.tbl", "true", &cb_analysis_jmptbl, "Analyze jump tables in switch statements");
|
||||
SETICB("analysis.jmp.tblmax", 512, &cb_analysis_jmptblmax, "Maximum amount of entries to analyze in jump tables");
|
||||
|
||||
SETCB("analysis.jmp.cref", "false", &cb_analysis_cjmpref, "Create references for conditional jumps");
|
||||
SETCB("analysis.jmp.ref", "true", &cb_analysis_jmpref, "Create references for unconditional jumps");
|
||||
|
|
|
|||
|
|
@ -542,6 +542,7 @@ typedef struct rz_analysis_options_t {
|
|||
int nopskip; // skip nops at the beginning of functions
|
||||
int hpskip; // skip `mov reg,reg` and `lea reg,[reg]`
|
||||
int jmptbl; // analyze jump tables
|
||||
int jmptbl_maxcount; // maximum amount of entries to analyse in a jump table
|
||||
int nonull;
|
||||
bool pushret; // analyze push+ret as jmp
|
||||
bool armthumb; //
|
||||
|
|
@ -887,6 +888,13 @@ typedef struct rz_analysis_bb_t {
|
|||
#undef RzAnalysisBlock
|
||||
} RzAnalysisBlock;
|
||||
|
||||
typedef struct rz_analysis_task_item {
|
||||
RzAnalysisFunction *fcn; // current function
|
||||
RzAnalysisBlock *block; // block being analyzed
|
||||
st64 stack; // stack pointer value for variable analysis
|
||||
ut64 start_address; // if block = NULL, creates block at address, else continues analysis from here
|
||||
} RzAnalysisTaskItem;
|
||||
|
||||
typedef enum {
|
||||
RZ_ANALYSIS_REF_TYPE_NULL = 0,
|
||||
RZ_ANALYSIS_REF_TYPE_CODE = 'c', // code ref
|
||||
|
|
@ -1426,7 +1434,6 @@ RZ_API int rz_analysis_set_big_endian(RzAnalysis *analysis, int boolean);
|
|||
RZ_API ut8 *rz_analysis_mask(RzAnalysis *analysis, int size, const ut8 *data, ut64 at);
|
||||
RZ_API void rz_analysis_trace_bb(RzAnalysis *analysis, ut64 addr);
|
||||
RZ_API const char *rz_analysis_fcntype_tostring(int type);
|
||||
RZ_API int rz_analysis_fcn_bb(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, int depth);
|
||||
RZ_API void rz_analysis_bind(RzAnalysis *b, RzAnalysisBind *bnd);
|
||||
RZ_API bool rz_analysis_set_triplet(RzAnalysis *analysis, const char *os, const char *arch, int bits);
|
||||
RZ_API void rz_analysis_add_import(RzAnalysis *analysis, const char *imp);
|
||||
|
|
@ -1520,6 +1527,9 @@ RZ_API void rz_analysis_function_check_bp_use(RzAnalysisFunction *fcn);
|
|||
RZ_API void rz_analysis_update_analysis_range(RzAnalysis *analysis, ut64 addr, int size);
|
||||
RZ_API void rz_analysis_function_update_analysis(RzAnalysisFunction *fcn);
|
||||
|
||||
RZ_API bool rz_analysis_task_item_new(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzVector *tasks, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE RzAnalysisBlock *block, ut64 address);
|
||||
RZ_API int rz_analysis_run_tasks(RZ_NONNULL RzVector *tasks);
|
||||
|
||||
#define RZ_ANALYSIS_FCN_VARKIND_LOCAL 'v'
|
||||
|
||||
RZ_API int rz_analysis_fcn_var_del_byindex(RzAnalysis *a, ut64 fna, const char kind, int scope, ut32 idx);
|
||||
|
|
@ -1652,12 +1662,23 @@ RZ_API const char *rz_analysis_cond_tostring(int cc);
|
|||
/* jmptbl */
|
||||
RZ_API bool rz_analysis_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, ut64 jmpaddr, ut64 table, ut64 tablesize, ut64 default_addr);
|
||||
|
||||
// TODO: should be renamed
|
||||
RZ_API bool try_get_delta_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 jmp_addr, ut64 lea_addr, ut64 *table_size, ut64 *default_case, st64 *start_casenum_shift);
|
||||
RZ_API bool try_walkthrough_jmptbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, st64 start_casenum_shift, ut64 jmptbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, bool ret0);
|
||||
RZ_API bool try_walkthrough_casetbl(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, st64 start_casenum_shift, ut64 jmptbl_loc, ut64 casetbl_loc, ut64 jmptbl_off, ut64 sz, ut64 jmptbl_size, ut64 default_case, bool ret0);
|
||||
RZ_API bool try_get_jmptbl_info(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, RzAnalysisBlock *my_bb, ut64 *table_size, ut64 *default_case, st64 *start_casenum_shift);
|
||||
RZ_API int walkthrough_arm_jmptbl_style(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *block, int depth, ut64 ip, ut64 jmptbl_loc, ut64 sz, ut64 jmptbl_size, ut64 default_case, int ret0);
|
||||
typedef struct rz_jmptable_params_t {
|
||||
ut64 jmp_address; /// Address of the jump instruction
|
||||
st64 case_shift; /// Shift that is added to get the real number of the case.
|
||||
ut64 jmptbl_loc; /// Address of the jump table
|
||||
ut64 casetbl_loc; /// Address of the indirect case table
|
||||
ut64 jmptbl_off; /// Base of the jump table
|
||||
ut64 entry_size; /// Size in bytes of each case entry inside the jump table
|
||||
ut64 table_count; /// Count of cases inside the jump table
|
||||
ut64 default_case; /// Code address of the default case of the switch
|
||||
RzVector *tasks; /// RzVector of RzAnalysisTaskItem to add new tasks to
|
||||
} RzAnalysisJmpTableParams;
|
||||
|
||||
RZ_API bool rz_analysis_get_delta_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, ut64 jmp_address, ut64 lea_address, RZ_NONNULL RzAnalysisJmpTableParams *params);
|
||||
RZ_API bool rz_analysis_get_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, ut64 jmp_address, RZ_NONNULL RzAnalysisJmpTableParams *params);
|
||||
RZ_API bool rz_analysis_walkthrough_jmptbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params);
|
||||
RZ_API bool rz_analysis_walkthrough_casetbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params);
|
||||
RZ_API bool rz_analysis_walkthrough_arm_jmptbl_style(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params);
|
||||
|
||||
/* reflines.c */
|
||||
RZ_API RzList * /*<RzAnalysisRefline>*/ rz_analysis_reflines_get(RzAnalysis *analysis,
|
||||
|
|
|
|||
|
|
@ -847,7 +847,7 @@ EXPECT=<<EOF
|
|||
0x00002818 78 fcn.00002818
|
||||
0x00002a54 770 fcn.00002a54
|
||||
0x00002d56 286 fcn.00002d56
|
||||
0x00002ec8 1682 fcn.00002ec8
|
||||
0x00002ec8 16 fcn.00002ec8
|
||||
0x00002ed8 16 fcn.00002ed8
|
||||
0x00002ee8 16 fcn.00002ee8
|
||||
0x00002ef8 18 fcn.00002ef8
|
||||
|
|
@ -885,6 +885,7 @@ EXPECT=<<EOF
|
|||
0x00003486 4 fcn.00003486
|
||||
0x0000349e 174 fcn.0000349e
|
||||
0x0000354c 8 fcn.0000354c
|
||||
0x00003554 6 loc.00003554
|
||||
0x0000357a 68 fcn.0000357a
|
||||
0x000035be 22 fcn.000035be
|
||||
0x000035d4 8 fcn.000035d4
|
||||
|
|
|
|||
|
|
@ -262,7 +262,6 @@ fcn.1000ef70:
|
|||
sym.imp.__assert_fail
|
||||
sym.imp.elf_getdata
|
||||
sym.imp.error
|
||||
sym.imp.elf_flagscn
|
||||
|
||||
fcn.10004120:
|
||||
sym.imp.__assert_fail
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ afi~complex[1]
|
|||
afbi@main
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
165
|
||||
167
|
||||
0x0002bca0 0x0002bccc 00:0000 44 j 0x0002c534 f 0x0002bccc
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -163,7 +163,7 @@ af
|
|||
afl
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00018c08 350 8388 -> 7132 main
|
||||
0x00018c08 357 8388 -> 7340 main
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ af
|
|||
afb
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x0002bca0 0x0002bccc 00:0000 44 f 0x0002bccc
|
||||
0x0002bca0 0x0002bccc 00:0000 44 j 0x0002c534 f 0x0002bccc
|
||||
0x0002bccc 0x0002bcec 00:0000 32 j 0x0002bd04 f 0x0002bcec
|
||||
0x0002bcec 0x0002bd04 00:0000 24 j 0x0002bcec f 0x0002bd04
|
||||
0x0002bd04 0x0002bd2c 00:0000 40 j 0x0002bd90 f 0x0002bd2c
|
||||
|
|
@ -187,55 +187,55 @@ EXPECT=<<EOF
|
|||
0x0002bd64 0x0002bd74 00:0000 16 j 0x0002bd80 f 0x0002bd74
|
||||
0x0002bd74 0x0002bd80 00:0000 12 j 0x0002bd80
|
||||
0x0002bd80 0x0002bd90 00:0000 16 j 0x0002bd90
|
||||
0x0002bd90 0x0002bdc8 00:0000 56 f 0x0002bdc8
|
||||
0x0002bd90 0x0002bdc8 00:0000 56 j 0x0002c5dc f 0x0002bdc8
|
||||
0x0002bdc8 0x0002bde8 00:0000 32 f 0x0002bde8
|
||||
0x0002bde8 0x0002bdec 00:0000 4 j 0x0002bdec
|
||||
0x0002bdec 0x0002bdf8 00:0000 12 j 0x0002bdf8
|
||||
0x0002bdf8 0x0002be10 00:0000 24 j 0x0002be40 f 0x0002be10
|
||||
0x0002be10 0x0002be40 00:0000 48 j 0x0002be40
|
||||
0x0002be40 0x0002be60 00:0000 32 j 0x0002be60 f 0x0002be60
|
||||
0x0002be60 0x0002bebc 00:0000 92 f 0x0002bebc
|
||||
0x0002bebc 0x0002bed4 00:0000 24 f 0x0002bed4
|
||||
0x0002be60 0x0002bebc 00:0000 92 j 0x0002c53c f 0x0002bebc
|
||||
0x0002bebc 0x0002bed4 00:0000 24 j 0x0002c564 f 0x0002bed4
|
||||
0x0002bed4 0x0002bed8 00:0000 4 j 0x0002bed8
|
||||
0x0002bed8 0x0002bfdc 00:0000 260 f 0x0002bfdc
|
||||
0x0002bed8 0x0002bfdc 00:0000 260 j 0x0002c534 f 0x0002bfdc
|
||||
0x0002bfdc 0x0002bff4 00:0000 24 f 0x0002bff4
|
||||
0x0002bff4 0x0002c014 00:0000 32 f 0x0002c014
|
||||
0x0002bff4 0x0002c014 00:0000 32 j 0x0002c644 f 0x0002c014
|
||||
0x0002c014 0x0002c024 00:0000 16 f 0x0002c024
|
||||
0x0002c024 0x0002c028 00:0000 4 j 0x0002c028
|
||||
0x0002c028 0x0002c030 00:0000 8 f 0x0002c030
|
||||
0x0002c030 0x0002c048 00:0000 24 j 0x0002c054 f 0x0002c048
|
||||
0x0002c048 0x0002c054 00:0000 12 j 0x0002c054
|
||||
0x0002c054 0x0002c084 00:0000 48 j 0x0002c094 f 0x0002c084
|
||||
0x0002c084 0x0002c094 00:0000 16 f 0x0002c094
|
||||
0x0002c084 0x0002c094 00:0000 16 j 0x0002c614 f 0x0002c094
|
||||
0x0002c094 0x0002c098 00:0000 4 j 0x0002c098
|
||||
0x0002c098 0x0002c0a4 00:0000 12 j 0x0002c0a4
|
||||
0x0002c0a4 0x0002c0c4 00:0000 32 f 0x0002c0c4
|
||||
0x0002c0c4 0x0002c0dc 00:0000 24 j 0x0002c200 f 0x0002c0dc
|
||||
0x0002c0dc 0x0002c0ec 00:0000 16 j 0x0002c200 f 0x0002c0ec
|
||||
0x0002c0ec 0x0002c108 00:0000 28 j 0x0002c108
|
||||
0x0002c108 0x0002c118 00:0000 16 f 0x0002c118
|
||||
0x0002c118 0x0002c128 00:0000 16 f 0x0002c128
|
||||
0x0002c108 0x0002c118 00:0000 16 j 0x0002c570 f 0x0002c118
|
||||
0x0002c118 0x0002c128 00:0000 16 j 0x0002c58c f 0x0002c128
|
||||
0x0002c128 0x0002c12c 00:0000 4 j 0x0002c12c
|
||||
0x0002c12c 0x0002c13c 00:0000 16 j 0x0002c14c
|
||||
0x0002c13c 0x0002c14c 00:0000 16 f 0x0002c14c
|
||||
0x0002c13c 0x0002c14c 00:0000 16 j 0x0002c58c f 0x0002c14c
|
||||
0x0002c14c 0x0002c15c 00:0000 16 j 0x0002c13c f 0x0002c15c
|
||||
0x0002c15c 0x0002c174 00:0000 24 j 0x0002c13c f 0x0002c174
|
||||
0x0002c174 0x0002c18c 00:0000 24 f 0x0002c18c
|
||||
0x0002c174 0x0002c18c 00:0000 24 j 0x0002c5c4 f 0x0002c18c
|
||||
0x0002c18c 0x0002c1a4 00:0000 24 f 0x0002c1a4
|
||||
0x0002c1a4 0x0002c1b8 00:0000 20 j 0x0002c1b8
|
||||
0x0002c1b8 0x0002c1cc 00:0000 20 f 0x0002c1cc
|
||||
0x0002c1b8 0x0002c1cc 00:0000 20 j 0x0002c58c f 0x0002c1cc
|
||||
0x0002c1cc 0x0002c1dc 00:0000 16 f 0x0002c1dc
|
||||
0x0002c1dc 0x0002c1f0 00:0000 20 j 0x0002c200 f 0x0002c1f0
|
||||
0x0002c1f0 0x0002c200 00:0000 16 j 0x0002c108 f 0x0002c200
|
||||
0x0002c200 0x0002c218 00:0000 24 f 0x0002c218
|
||||
0x0002c218 0x0002c228 00:0000 16 f 0x0002c228
|
||||
0x0002c218 0x0002c228 00:0000 16 j 0x0002c634 f 0x0002c228
|
||||
0x0002c228 0x0002c244 00:0000 28 f 0x0002c244
|
||||
0x0002c244 0x0002c25c 00:0000 24 j 0x0002c384 f 0x0002c25c
|
||||
0x0002c25c 0x0002c284 00:0000 40 j 0x0002c380 f 0x0002c284
|
||||
0x0002c284 0x0002c2b8 00:0000 52 j 0x0002c340
|
||||
0x0002c2b8 0x0002c2c0 00:0000 8 j 0x0002c2c0
|
||||
0x0002c2c0 0x0002c2e0 00:0000 32 j 0x0002c2e0
|
||||
0x0002c2e0 0x0002c2f4 00:0000 20 f 0x0002c2f4
|
||||
0x0002c2e0 0x0002c2f4 00:0000 20 j 0x0002c66c f 0x0002c2f4
|
||||
0x0002c2f4 0x0002c304 00:0000 16 j 0x0002c380 f 0x0002c304
|
||||
0x0002c304 0x0002c318 00:0000 20 j 0x0002c384 f 0x0002c318
|
||||
0x0002c318 0x0002c340 00:0000 40 j 0x0002c380 f 0x0002c340
|
||||
|
|
@ -264,7 +264,33 @@ EXPECT=<<EOF
|
|||
0x0002c4b4 0x0002c4c4 00:0000 16 f 0x0002c4c4
|
||||
0x0002c4c4 0x0002c4c8 00:0000 4 j 0x0002c4c8
|
||||
0x0002c4c8 0x0002c4d8 00:0000 16 f 0x0002c4d8
|
||||
0x0002c4d8 0x0002c4e8 00:0000 16
|
||||
0x0002c4d8 0x0002c4e8 00:0000 16 f 0x0002c4e8
|
||||
0x0002c4e8 0x0002c4f8 00:0000 16 j 0x0002c50c
|
||||
0x0002c4f8 0x0002c508 00:0000 16 f 0x0002c508
|
||||
0x0002c508 0x0002c50c 00:0000 4 j 0x0002c50c
|
||||
0x0002c50c 0x0002c534 00:0000 40 j 0x0002c4f8 f 0x0002c534
|
||||
0x0002c534 0x0002c53c 00:0000 8
|
||||
0x0002c53c 0x0002c550 00:0000 20 j 0x0002bfdc f 0x0002c550
|
||||
0x0002c550 0x0002c560 00:0000 16 j 0x0002bed8 f 0x0002c560
|
||||
0x0002c560 0x0002c564 00:0000 4 j 0x0002c564
|
||||
0x0002c564 0x0002c570 00:0000 12 j 0x0002bed4
|
||||
0x0002c570 0x0002c580 00:0000 16 j 0x0002c118 f 0x0002c580
|
||||
0x0002c580 0x0002c58c 00:0000 12 j 0x0002c12c f 0x0002c58c
|
||||
0x0002c58c 0x0002c598 00:0000 12 j 0x0002c200 f 0x0002c598
|
||||
0x0002c598 0x0002c5c4 00:0000 44
|
||||
0x0002c5c4 0x0002c5dc 00:0000 24 j 0x0002c1b8
|
||||
0x0002c5dc 0x0002c60c 00:0000 48 j 0x0002bdec f 0x0002c60c
|
||||
0x0002c60c 0x0002c614 00:0000 8
|
||||
0x0002c614 0x0002c61c 00:0000 8 j 0x0002c0a4 f 0x0002c61c
|
||||
0x0002c61c 0x0002c62c 00:0000 16 j 0x0002c098 f 0x0002c62c
|
||||
0x0002c62c 0x0002c634 00:0000 8 j 0x0002c0a4
|
||||
0x0002c634 0x0002c644 00:0000 16
|
||||
0x0002c644 0x0002c650 00:0000 12 f 0x0002c650
|
||||
0x0002c650 0x0002c66c 00:0000 28 j 0x0002c014
|
||||
0x0002c66c 0x0002c67c 00:0000 16 j 0x0002c69c f 0x0002c67c
|
||||
0x0002c67c 0x0002c694 00:0000 24 f 0x0002c694
|
||||
0x0002c694 0x0002c69c 00:0000 8 j 0x0002c2e0
|
||||
0x0002c69c 0x0002c6a8 00:0000 12
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ EXPECT=<<EOF
|
|||
0x00106cd0 4 50 fcn.00106cd0
|
||||
0x00106d02 1 22 sym.__realloc_r
|
||||
0x0010722c 12 150 sym.__sbrk
|
||||
0x001072c2 15 240 -> 198 sym.___swbuf_r
|
||||
0x001072c2 11 142 sym.___swbuf_r
|
||||
0x001073ba 1 18 sym.___swbuf
|
||||
0x001073d0 5 70 sym.__wcrtomb_r
|
||||
0x00107416 1 20 sym._wcrtomb
|
||||
|
|
@ -280,7 +280,7 @@ EXPECT=<<EOF
|
|||
0x00114130 1 36 fcn.00114130
|
||||
0x00114afc 1 20 sym._vfiprintf
|
||||
0x00114b14 1 90 sym.___sbprintf_1
|
||||
0x00114ba8 15 240 -> 198 sym.___swbuf_r
|
||||
0x00114ba8 11 142 sym.___swbuf_r
|
||||
0x00114ca0 1 18 sym.___swbuf
|
||||
0x00114cb6 5 58 sym.__wctomb_r
|
||||
0x00114cf0 1 18 sym.__write
|
||||
|
|
@ -340,7 +340,7 @@ EXPECT=<<EOF
|
|||
0x00102ec0 7 158 sym._cmd_print
|
||||
0x00102f5e 7 180 sym._cmd_bytedump
|
||||
0x00103012 8 236 sym._cmd_search
|
||||
0x0010333c 10 318 -> 242 sym._cmd_bsize
|
||||
0x0010333c 4 116 sym._cmd_bsize
|
||||
0x0010347a 2 46 sym._cmd_seek
|
||||
0x00103674 10 244 sym._cmd_dump
|
||||
0x00103768 5 190 sym._cmd_load
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ aap
|
|||
aflc
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
440
|
||||
445
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
@ -109,24 +109,24 @@ afb+ 0x100000da0 0x100000e9e 24 0x100000db6 0x100000eb6
|
|||
afb+ 0x100000da0 0x100000db6 26 0x100000e99 0x100000dd0
|
||||
afb+ 0x100000da0 0x100000eb6 4 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000dd0 20 0xffffffffffffffff 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000de4 16 0x100000dfb 0x100000df4
|
||||
afb+ 0x100000da0 0x100000dfb 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000df4 7 0x100000dfb 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e00 16 0x100000e1c 0x100000e10
|
||||
afb+ 0x100000da0 0x100000e1c 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e90 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000eba 6 0xffffffffffffffff 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e10 12 0x100000e25 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e25 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e2a 16 0x100000e46 0x100000e3a
|
||||
afb+ 0x100000da0 0x100000e46 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e3a 12 0x100000e4f 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e4f 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e54 16 0x100000e82 0x100000e64
|
||||
afb+ 0x100000da0 0x100000e82 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e64 16 0x100000e82 0x100000e74
|
||||
afb+ 0x100000da0 0x100000e74 14 0x100000e8b 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e8b 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e90 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e2a 16 0x100000e46 0x100000e3a
|
||||
afb+ 0x100000da0 0x100000e46 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e3a 12 0x100000e4f 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e4f 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e00 16 0x100000e1c 0x100000e10
|
||||
afb+ 0x100000da0 0x100000e1c 9 0x100000eba 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e10 12 0x100000e25 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000e25 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000de4 16 0x100000dfb 0x100000df4
|
||||
afb+ 0x100000da0 0x100000dfb 5 0x100000e99 0xffffffffffffffff
|
||||
afb+ 0x100000da0 0x100000df4 7 0x100000dfb 0xffffffffffffffff
|
||||
afB 64 @ 0x100000da0
|
||||
afc amd64 @ 0x100000da0
|
||||
afvb -40 var_28h int64_t @ 0x100000da0
|
||||
|
|
@ -650,7 +650,7 @@ aac
|
|||
afl~?
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1268
|
||||
1270
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ EXPECT=<<EOF
|
|||
0x00015dc0 8 55 -> 45 sym._obstack_allocated_p
|
||||
0x00015e70 5 41 -> 36 sym._obstack_memory_used
|
||||
0x00015e00 9 73225 -> 102 sym._obstack_free
|
||||
0x00015bd0 3 21 fcn.00015bd0
|
||||
0x00015cc0 8 256 -> 250 sym._obstack_newchunk
|
||||
0x00004070 300 6757 -> 6739 main
|
||||
0x00005bd0 5 153 -> 60 entry.init0
|
||||
|
|
@ -23,6 +24,11 @@ EXPECT=<<EOF
|
|||
0x00015100 95 1137 -> 1129 fcn.00015100
|
||||
0x00013c30 1 17 fcn.00013c30
|
||||
0x0000c940 3 112 -> 109 fcn.0000c940
|
||||
0x0000c790 4 124 -> 117 fcn.0000c790
|
||||
0x00014370 1 19 fcn.00014370
|
||||
0x00013f90 5 65498 -> 148 fcn.00013f90
|
||||
0x00013a40 14 64434 -> 438 fcn.00013a40
|
||||
0x0000c810 50 95704 -> 612 fcn.0000c810
|
||||
0x00014c00 7 82 fcn.00014c00
|
||||
0x0000fcc0 28 485 -> 456 fcn.0000fcc0
|
||||
0x00005f20 8 128 -> 114 fcn.00005f20
|
||||
|
|
@ -42,21 +48,18 @@ EXPECT=<<EOF
|
|||
0x0000e8c0 21 217 -> 211 fcn.0000e8c0
|
||||
0x00006200 5 105 fcn.00006200
|
||||
0x00007250 1 40 fcn.00007250
|
||||
0x00007180 3 85 -> 76 fcn.00007180
|
||||
0x00006fa0 20 473 -> 448 fcn.00006fa0
|
||||
0x00014e40 1 20 fcn.00014e40
|
||||
0x00005c40 45 634 -> 527 fcn.00005c40
|
||||
0x000063e0 18 401 -> 395 fcn.000063e0
|
||||
0x00009380 104 109608 -> 1589 fcn.00009380
|
||||
0x00009380 64 1388 -> 1269 fcn.00009380
|
||||
0x00015020 10 210 -> 199 fcn.00015020
|
||||
0x00006840 9 197 fcn.00006840
|
||||
0x00005fa0 34 596 -> 585 fcn.00005fa0
|
||||
0x00005ec0 6 89 -> 80 fcn.00005ec0
|
||||
0x000065f0 22 379 -> 375 fcn.000065f0
|
||||
0x0000bde0 18 1924 -> 1917 fcn.0000bde0
|
||||
0x0000c790 4 124 -> 117 fcn.0000c790
|
||||
0x00014370 1 19 fcn.00014370
|
||||
0x00013f90 5 65498 -> 148 fcn.00013f90
|
||||
0x00013a40 14 64434 -> 438 fcn.00013a40
|
||||
0x00015580 12 193 -> 186 fcn.00015580
|
||||
0x00014e60 1 56 fcn.00014e60
|
||||
0x00015650 98 1137 -> 1135 fcn.00015650
|
||||
|
|
@ -72,7 +75,6 @@ EXPECT=<<EOF
|
|||
0x000140b0 1 12 fcn.000140b0
|
||||
0x00006c60 22 233 -> 190 fcn.00006c60
|
||||
0x000071e0 37 118072 -> 402 fcn.000071e0
|
||||
0x00007180 3 85 -> 76 fcn.00007180
|
||||
0x00015ad0 7 136 -> 132 fcn.00015ad0
|
||||
0x00010740 40 480 -> 447 fcn.00010740
|
||||
0x000073d0 67 1135 -> 1075 fcn.000073d0
|
||||
|
|
@ -87,6 +89,11 @@ EXPECT=<<EOF
|
|||
0x0000f270 141 2626 -> 2515 fcn.0000f270
|
||||
0x0000d6b0 17 392 -> 366 fcn.0000d6b0
|
||||
0x00016270 12 166 -> 152 fcn.00016270
|
||||
0x000161a0 12 176 -> 164 fcn.000161a0
|
||||
0x00015ea0 6 72 -> 71 fcn.00015ea0
|
||||
0x00015ef0 5 41 -> 36 fcn.00015ef0
|
||||
0x00016010 25 397 -> 361 fcn.00016010
|
||||
0x00015f20 3 66 fcn.00015f20
|
||||
0x00012530 3 71 fcn.00012530
|
||||
0x00010c30 310 6399 -> 6311 fcn.00010c30
|
||||
0x00006910 8 188 -> 175 fcn.00006910
|
||||
|
|
@ -112,13 +119,14 @@ EXPECT=<<EOF
|
|||
0x00009b00 9 204 -> 194 fcn.00009b00
|
||||
0x0000ee80 7 90 -> 82 fcn.0000ee80
|
||||
0x00006580 1 42 fcn.00006580
|
||||
0x0000c810 10 297 -> 292 fcn.0000c810
|
||||
0x00014fe0 4 64 -> 56 fcn.00014fe0
|
||||
0x0000d4d0 5 88 fcn.0000d4d0
|
||||
0x0000d440 7 144 -> 133 fcn.0000d440
|
||||
0x0000f190 1 23 loc.0000f190
|
||||
0x000164a0 8 102 -> 96 fcn.000164a0
|
||||
0x000165b0 24 55032 -> 248 fcn.000165b0
|
||||
0x000165b0 9 139 -> 128 fcn.000165b0
|
||||
0x00016640 5 66 -> 63 fcn.00016640
|
||||
0x00016690 7 89 fcn.00016690
|
||||
0x00014180 4 193 -> 170 fcn.00014180
|
||||
0x0000e3f0 9 83 -> 75 fcn.0000e3f0
|
||||
0x0000d7e0 17 195 -> 166 fcn.0000d7e0
|
||||
|
|
@ -142,14 +150,6 @@ EXPECT=<<EOF
|
|||
0x000145b0 20 67969 -> 1004 fcn.000145b0
|
||||
0x00014d60 8 120 -> 114 fcn.00014d60
|
||||
0x00015bb0 3 21 fcn.00015bb0
|
||||
0x00015bd0 3 21 fcn.00015bd0
|
||||
0x00015ea0 6 72 -> 71 fcn.00015ea0
|
||||
0x00015ef0 5 41 -> 36 fcn.00015ef0
|
||||
0x000161a0 12 176 -> 164 fcn.000161a0
|
||||
0x00016010 25 397 -> 361 fcn.00016010
|
||||
0x00015f20 3 66 fcn.00015f20
|
||||
0x00016640 5 66 -> 63 fcn.00016640
|
||||
0x00016690 7 89 fcn.00016690
|
||||
0x00004000 3 27 fcn.00004000
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ sym._obstack_begin_1
|
|||
sym._obstack_allocated_p
|
||||
sym._obstack_memory_used
|
||||
sym._obstack_free
|
||||
fcn.00015bd0
|
||||
sym._obstack_newchunk
|
||||
main
|
||||
entry.init0
|
||||
|
|
|
|||
|
|
@ -902,7 +902,7 @@ EXPECT=<<EOF
|
|||
0x0045a8c0 132 flirt.__sigsetjmp
|
||||
0x0045abc0 6232 flirt._quicksort
|
||||
0x0045c620 19 flirt.__libc_secure_getenv
|
||||
0x0045ce30 10673 flirt.group_number
|
||||
0x0045ce30 10704 flirt.group_number
|
||||
0x0045f800 13172 flirt._IO_vfprintf_internal
|
||||
0x00462b80 976 flirt.hack_digit
|
||||
0x00465a50 11033 flirt.___printf_fp
|
||||
|
|
|
|||
|
|
@ -1764,7 +1764,7 @@ aaa
|
|||
pd 20 @ dbg.palya
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
; CALL XREFS from sym.main @ +0x1a87, +0x1c7d, +0x23f3, +0x3679
|
||||
; CALL XREFS from dbg.$main @ 0x405237, 0x40542d, 0x405ba3, 0x406e29
|
||||
;-- P$MOZGKIGYO_$$_PALYA$SMALLINT$SMALLINT:
|
||||
/ dbg.palya ();
|
||||
| ; var int64_t var_28h @ rbp-0x28
|
||||
|
|
|
|||
|
|
@ -1848,9 +1848,9 @@ char *
|
|||
uint32_t
|
||||
int64_t
|
||||
char *
|
||||
size_t *
|
||||
size_t
|
||||
void *
|
||||
size_t
|
||||
size_t *
|
||||
wint_t
|
||||
=
|
||||
fcn.0000f770
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ aac
|
|||
aflc
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
794
|
||||
802
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue