Fix #4554 stackptr calculation on pdr and graph

- blocks have their stackptr
- inherit from parent when visited hierarchically (in pdr and graph)
- add the global anal->stackptr as a starting value for disasm, defaults to 0
This commit is contained in:
mrmacete 2017-01-31 10:00:24 +01:00 committed by pancake
parent 90feff3957
commit d50ba765eb
7 changed files with 89 additions and 43 deletions

View File

@ -71,6 +71,7 @@ R_API RAnal *r_anal_new() {
r_flag_bind_init (anal->flb);
anal->reg = r_reg_new ();
anal->last_disasm_reg = NULL;
anal->stackptr = 0;
anal->bits_ranges = r_list_newf (free);
anal->lineswidth = 0;
anal->fcns = r_anal_fcn_list_new ();

View File

@ -3,6 +3,7 @@
#include <r_anal.h>
#include <r_util.h>
#include <r_list.h>
#include <limits.h>
#define DFLT_NINSTR 3
@ -23,6 +24,8 @@ R_API RAnalBlock *r_anal_bb_new() {
bb->op_pos = R_NEWS0 (ut16, DFLT_NINSTR);
bb->op_pos_size = DFLT_NINSTR;
bb->parent_reg_arena = NULL;
bb->stackptr = 0;
bb->parent_stackptr = INT_MAX;
return bb;
}

View File

@ -671,6 +671,10 @@ repeat:
if (fcn->stack > 0 && (int)op.val > 0) {
fcn->maxstack = fcn->stack;
}
bb->stackptr += op.stackptr;
break;
case R_ANAL_STACK_RESET:
bb->stackptr = 0;
break;
// TODO: use fcn->stack to know our stackframe
case R_ANAL_STACK_SET:

View File

@ -7,6 +7,7 @@
#include "r_types.h"
#include "r_util.h"
#include "ht.h"
#include <limits.h>
#define R_CORE_MAX_DISASM (1024*1024*8)
@ -2297,15 +2298,23 @@ static void pr_bb (RCore * core, RAnalFunction * fcn, RAnalBlock * b, bool emu,
r_reg_arena_poke (core->anal->reg, saved_arena);
}
}
if (b->parent_stackptr != INT_MAX) {
core->anal->stackptr = b->parent_stackptr;
}
p_type == 'D'
? r_core_cmdf (core, "pD %"PFMT64d" @0x%"PFMT64x, b->size, b->addr)
: r_core_cmdf (core, "pI %"PFMT64d" @0x%"PFMT64x, b->size, b->addr);
if (b->jump != UT64_MAX) {
if (b->jump > b->addr && emu && core->anal->last_disasm_reg != NULL) {
if (b->jump > b->addr) {
RAnalBlock * jumpbb = r_anal_bb_get_jumpbb (fcn, b);
if (jumpbb && !jumpbb->parent_reg_arena) {
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
if (jumpbb) {
if (emu && core->anal->last_disasm_reg != NULL && !jumpbb->parent_reg_arena) {
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
}
if (jumpbb->parent_stackptr == INT_MAX) {
jumpbb->parent_stackptr = core->anal->stackptr + b->stackptr;
}
}
}
if (p_type == 'D') {
@ -2313,10 +2322,15 @@ static void pr_bb (RCore * core, RAnalFunction * fcn, RAnalBlock * b, bool emu,
}
}
if (b->fail != UT64_MAX) {
if (b->fail > b->addr && emu && core->anal->last_disasm_reg != NULL) {
if (b->fail > b->addr) {
RAnalBlock * failbb = r_anal_bb_get_failbb (fcn, b);
if (failbb && !failbb->parent_reg_arena) {
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
if (failbb) {
if (emu && core->anal->last_disasm_reg != NULL && !failbb->parent_reg_arena) {
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
}
if (failbb->parent_stackptr == INT_MAX) {
failbb->parent_stackptr = core->anal->stackptr + b->stackptr;
}
}
}
if (p_type == 'D') {
@ -2389,6 +2403,7 @@ static void func_walk_blocks (RCore *core, RAnalFunction *f, char input, char ty
bool emu = r_config_get_i (core->config, "asm.emu");
ut64 saved_gp = 0;
ut8 *saved_arena;
int saved_stackptr = core->anal->stackptr;
if (emu) {
saved_gp = core->anal->gp;
saved_arena = r_reg_arena_peek (core->anal->reg);
@ -2418,6 +2433,7 @@ static void func_walk_blocks (RCore *core, RAnalFunction *f, char input, char ty
R_FREE (saved_arena);
}
}
core->anal->stackptr = saved_stackptr;
r_config_set_i (core->config, "asm.lines", asm_lines);
}
}

View File

@ -1162,7 +1162,7 @@ static void ds_show_functions(RDisasmState *ds) {
if (ds->show_fcnlines) {
ds->pre = r_str_concat (ds->pre, " ");
}
ds->stackptr = 0;
ds->stackptr = core->anal->stackptr;
if (ds->show_vars) {
char spaces[32];
RAnalVar *var;
@ -3124,9 +3124,9 @@ static void ds_print_esil_anal(RDisasmState *ds) {
}
ds_align_comment (ds);
ds_comment_esil (ds, ds->show_color? false : true, false,
"; %s%s%s(", r_str_get (fcn_type), (fcn_type && *fcn_type &&
"; %s%s%s(", r_str_get (fcn_type), (fcn_type && *fcn_type &&
fcn_type[strlen (fcn_type) - 1] == '*') ? "" : " ",
r_str_get (key));
r_str_get (key));
if (!nargs) {
ds_comment_esil (ds, false, true, "void)");
break;
@ -3210,7 +3210,7 @@ static void ds_print_esil_anal(RDisasmState *ds) {
if (fmt) {
//it may need ds_comment_esil
print_fcn_arg (core, arg_orig_c_type, arg_name,
fmt, arg_addr, on_stack);
fmt, arg_addr, on_stack);
ds_comment_esil (ds, false, false, i!=(nargs - 1)?", ":")");
}
free (arg_orig_c_type);
@ -3439,6 +3439,7 @@ toro:
len = ds->l = core->blocksize;
}
ds->stackptr = core->anal->stackptr;
r_cons_break_push (NULL, NULL);
r_anal_build_range_on_hints (core->anal);
for (i = idx = ret = 0; idx < len && ds->lines < ds->l; idx += inc, i++, ds->index += inc, ds->lines++) {
@ -4254,6 +4255,7 @@ R_API int r_core_print_fcn_disasm(RPrint *p, RCore *core, ut64 addr, int l, int
ds->len = r_anal_fcn_size (fcn);
ds->addr = fcn->addr;
ds->fcn = fcn;
ds->stackptr = core->anal->stackptr;
r_list_foreach (fcn->bbs, bb_iter, bb) {
r_list_add_sorted (bb_list, bb, cmpaddr);

View File

@ -1695,20 +1695,33 @@ static char *get_bb_body(RCore *core, RAnalBlock *b, int opts, RAnalFunction *fc
r_reg_arena_poke (core->anal->reg, saved_arena);
}
}
if (b->parent_stackptr != INT_MAX) {
core->anal->stackptr = b->parent_stackptr;
}
char * body = get_body (core, b->addr, b->size, opts);
if (b->jump != UT64_MAX) {
if (b->jump > b->addr && emu && core->anal->last_disasm_reg != NULL) {
if (b->jump > b->addr) {
RAnalBlock * jumpbb = r_anal_bb_get_jumpbb (fcn, b);
if (jumpbb && !jumpbb->parent_reg_arena) {
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
if (jumpbb) {
if (emu && core->anal->last_disasm_reg != NULL && !jumpbb->parent_reg_arena) {
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
}
if (jumpbb->parent_stackptr == INT_MAX) {
jumpbb->parent_stackptr = core->anal->stackptr + b->stackptr;
}
}
}
}
if (b->fail != UT64_MAX) {
if (b->fail > b->addr && emu && core->anal->last_disasm_reg != NULL) {
if (b->fail > b->addr) {
RAnalBlock * failbb = r_anal_bb_get_failbb (fcn, b);
if (failbb && !failbb->parent_reg_arena) {
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
if (failbb) {
if (emu && core->anal->last_disasm_reg != NULL && !failbb->parent_reg_arena) {
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
}
if (failbb->parent_stackptr == INT_MAX) {
failbb->parent_stackptr = core->anal->stackptr + b->stackptr;
}
}
}
}
@ -1725,6 +1738,7 @@ static void get_bbupdate(RAGraph *g, RCore *core, RAnalFunction *fcn) {
bool emu = r_config_get_i (core->config, "asm.emu");
ut64 saved_gp = core->anal->gp;
ut8 *saved_arena = NULL;
int saved_stackptr = core->anal->stackptr;
core->keep_asmqjmps = false;
if (emu) {
@ -1763,6 +1777,7 @@ static void get_bbupdate(RAGraph *g, RCore *core, RAnalFunction *fcn) {
R_FREE (saved_arena);
}
}
core->anal->stackptr = saved_stackptr;
}
/* build the RGraph inside the RAGraph g, starting from the Basic Blocks */
@ -1775,6 +1790,7 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) {
int ret = false;
ut64 saved_gp = core->anal->gp;
ut8 *saved_arena = NULL;
int saved_stackptr = core->anal->stackptr;
core->keep_asmqjmps = false;
if (!fcn) {
@ -1858,6 +1874,7 @@ cleanup:
R_FREE (saved_arena);
}
}
core->anal->stackptr = saved_stackptr;
return ret;
}

View File

@ -647,6 +647,7 @@ typedef struct r_anal_t {
//RList *noreturn;
RList /*RAnalRange*/ *bits_ranges;
RListComparator columnSort;
int stackptr;
} RAnal;
typedef RAnalFunction *(* RAnalGetFcnIn)(RAnal *anal, ut64 addr, int type);
@ -789,6 +790,8 @@ typedef struct r_anal_bb_t {
struct r_anal_bb_t *jumpbb;
RList /*struct r_anal_bb_t*/ *cases;
ut8 *parent_reg_arena;
int stackptr;
int parent_stackptr;
} RAnalBlock;
typedef enum {