diff --git a/libr/anal/anal.c b/libr/anal/anal.c index 44a4ce24ce..65242e19c9 100644 --- a/libr/anal/anal.c +++ b/libr/anal/anal.c @@ -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 (); diff --git a/libr/anal/bb.c b/libr/anal/bb.c index 8289939c45..577bb897b7 100644 --- a/libr/anal/bb.c +++ b/libr/anal/bb.c @@ -3,6 +3,7 @@ #include #include #include +#include #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; } diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 055296e288..1a8effb4a0 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -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: diff --git a/libr/core/cmd_print.c b/libr/core/cmd_print.c index 1452b1364e..4e2c3ec82c 100644 --- a/libr/core/cmd_print.c +++ b/libr/core/cmd_print.c @@ -7,6 +7,7 @@ #include "r_types.h" #include "r_util.h" #include "ht.h" +#include #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; diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 30f8ff1709..85b44b8ecd 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -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); diff --git a/libr/core/graph.c b/libr/core/graph.c index fcf7402f54..370806fe44 100644 --- a/libr/core/graph.c +++ b/libr/core/graph.c @@ -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; } diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index d52a4b49ed..05e0ed88ce 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -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 {