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

@ -311,20 +311,20 @@ static int try_walkthrough_jmptbl(RAnal *anal, RAnalFunction *fcn, int depth, ut
anal->iob.read_at (anal->iob.io, ptr, jmptbl, MAX_JMPTBL_SIZE);
for (offs = 0; offs + sz - 1 < MAX_JMPTBL_SIZE; offs += sz) {
switch (sz) {
case 1:
jmpptr = r_read_le8 (jmptbl + offs);
case 1:
jmpptr = r_read_le8 (jmptbl + offs);
break;
case 2:
jmpptr = r_read_le16 (jmptbl + offs);
case 2:
jmpptr = r_read_le16 (jmptbl + offs);
break;
case 4:
jmpptr = r_read_le32 (jmptbl + offs);
case 4:
jmpptr = r_read_le32 (jmptbl + offs);
break;
case 8:
jmpptr = r_read_le32 (jmptbl + offs);
case 8:
jmpptr = r_read_le32 (jmptbl + offs);
break; // XXX
default:
jmpptr = r_read_le64 (jmptbl + offs);
default:
jmpptr = r_read_le64 (jmptbl + offs);
break;
}
if (!anal->iob.is_valid_offset (anal->iob.io, jmpptr, 0)) {
@ -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') {
@ -2333,7 +2347,7 @@ static void func_walk_blocks (RCore *core, RAnalFunction *f, char input, char ty
RAnalBlock *b;
RAnalFunction *tmp_func;
RListIter *locs_it = NULL;
if (f->fcn_locs) {
locs_it = f->fcn_locs->head;
}
@ -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);
}
}
@ -3955,13 +3971,13 @@ static int cmd_print(void *data, const char *input) {
ut64 v = (ut64)r_read_ble16 (core->block + i, p->big_endian);
if (p && p->colorfor) {
a = p->colorfor (p->user, v, true);
if (a && *a) {
b = Color_RESET;
} else {
a = b = "";
if (a && *a) {
b = Color_RESET;
} else {
a = b = "";
}
} else {
a = b = "";
} else {
a = b = "";
}
f = r_flag_get_at (core->flags, v, true);
fn = NULL;
@ -3998,13 +4014,13 @@ static int cmd_print(void *data, const char *input) {
ut64 v = r_read_ble64 (core->block + i, p->big_endian);
if (p && p->colorfor) {
a = p->colorfor (p->user, v, true);
if (a && *a) {
b = Color_RESET;
} else {
a = b = "";
if (a && *a) {
b = Color_RESET;
} else {
a = b = "";
}
} else {
a = b = "";
} else {
a = b = "";
}
f = r_flag_get_at (core->flags, v, true);
fn = NULL;

View File

@ -360,7 +360,7 @@ static void ds_comment_esil(RDisasmState *ds, bool up, bool end, const char *for
if (up) {
ds_comment_lineup (ds);
}
}
}
r_cons_printf_list (format, ap);
va_end (ap);
@ -944,7 +944,7 @@ static void ds_show_xrefs(RDisasmState *ds) {
}
ds_pre_xrefs (ds);
//those extra space to align
ds_comment (ds, false, " %s; %s XREF from 0x%08"PFMT64x" (%s)%s\n",
ds_comment (ds, false, " %s; %s XREF from 0x%08"PFMT64x" (%s)%s\n",
COLOR (ds, pal_comment), r_anal_xrefs_type_tostring (refi->type),
refi->addr, name, COLOR_RESET (ds));
R_FREE (name);
@ -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;
@ -3123,10 +3123,10 @@ static void ds_print_esil_anal(RDisasmState *ds) {
ds_comment_esil (ds, true, false, ds->pal_comment);
}
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 &&
ds_comment_esil (ds, ds->show_color? false : true, false,
"; %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;
@ -3209,8 +3209,8 @@ 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);
print_fcn_arg (core, arg_orig_c_type, arg_name,
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 {