From ec2ac9c64086e49cc9d7ed836c85f9c67374f7cf Mon Sep 17 00:00:00 2001 From: pancake Date: Thu, 29 Oct 2015 23:37:51 +0100 Subject: [PATCH] Initial implementation of asm.emuwrite and asm.emu for CALL and UCALL --- libr/core/anal.c | 2 +- libr/core/config.c | 1 + libr/core/disasm.c | 45 ++++++++++++++++++++++++++++++---- libr/debug/arg.c | 21 ++++++++++++++-- libr/include/r_anal.h | 56 +++++++++++++++++++++---------------------- 5 files changed, 89 insertions(+), 36 deletions(-) diff --git a/libr/core/anal.c b/libr/core/anal.c index 7b7d4d079f..f34da504f0 100644 --- a/libr/core/anal.c +++ b/libr/core/anal.c @@ -2099,7 +2099,7 @@ static int is_string (const ut8 *buf, int size, int *len) { int i; if (size<1) return 0; - if (size>3 && buf[0] &&!buf[1]&&buf[2]&&!buf[3]) { + if (size>3 && buf[0] && !buf[1] && buf[2] && !buf[3]) { *len = 1; // XXX: TODO: Measure wide string length return 2; // is wide } diff --git a/libr/core/config.c b/libr/core/config.c index 6d9fb809e6..ded6b8710f 100644 --- a/libr/core/config.c +++ b/libr/core/config.c @@ -1279,6 +1279,7 @@ R_API int r_core_config_init(RCore *core) { SETPREF("asm.dwarf", "false", "Show dwarf comment at disassembly"); SETPREF("asm.esil", "false", "Show ESIL instead of mnemonic"); SETPREF("asm.emu", "false", "Run ESIL emulation analysis on disasm"); + SETPREF("asm.emuwrite", "false", "Allow asm.emu to modify memory (WARNING)"); SETPREF("asm.filter", "true", "Replace numeric values by flags (e.g. 0x4003e0 -> sym.imp.printf)"); SETPREF("asm.fcnlines", "true", "Show function boundary lines"); SETPREF("asm.flags", "true", "Show flags"); diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 0048235969..3bf58e0d8e 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -5,6 +5,7 @@ #define HASRETRY 1 #define HAVE_LOCALS 1 +#define DEFAULT_NARGS 4 static const char* r_vline_a[] = { "|", // LINE_VERT @@ -66,6 +67,7 @@ typedef struct r_disam_options_t { int asm_demangle; int show_offset; int show_emu; + int show_emu_write; int show_section; int show_offseg; int show_flags; @@ -308,6 +310,7 @@ static RDisasmState * handle_init_ds (RCore * core) { ds->show_offset = r_config_get_i (core->config, "asm.offset"); ds->show_section = r_config_get_i (core->config, "asm.section"); ds->show_emu = r_config_get_i (core->config, "asm.emu"); + ds->show_emu_write = r_config_get_i (core->config, "asm.emuwrite"); ds->show_offseg = r_config_get_i (core->config, "asm.segoff"); ds->show_flags = r_config_get_i (core->config, "asm.flags"); ds->show_bytes = r_config_get_i (core->config, "asm.bytes"); @@ -2193,6 +2196,14 @@ static void handle_print_relocs (RCore *core, RDisasmState *ds) { static int likely = 0; static int show_slow = 0; +static int mymemwrite0(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) { + return 0; +} + +static int mymemwrite1(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) { + return 1; +} + static int myregwrite(RAnalEsil *esil, const char *name, ut64 val) { char str[64], *msg = NULL; ut32 *n32 = (ut32*)str; @@ -2264,7 +2275,7 @@ static void handle_print_esil_anal_fini(RCore *core, RDisasmState *ds) { static void handle_print_esil_anal(RCore *core, RDisasmState *ds) { RAnalEsil *esil = core->anal->esil; const char *pc; - int ioc; + int i, ioc, nargs; if (!esil || !ds->show_comments) { return; } @@ -2280,22 +2291,46 @@ static void handle_print_esil_anal(RCore *core, RDisasmState *ds) { r_reg_setv (core->anal->reg, pc, ds->at + ds->analop.size); show_slow = ds->show_slow; // hacky global esil->cb.hook_reg_write = myregwrite; + if (ds->show_emu_write) { + esil->cb.hook_mem_write = mymemwrite0; + } else { + esil->cb.hook_mem_write = mymemwrite1; + } likely = 0; r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&ds->analop.esil)); r_anal_esil_stack_free (esil); - if (ds->analop.type == R_ANAL_OP_TYPE_SWI) { - char *s = cmd_syscall_dostr(core, -1); + switch (ds->analop.type) { + case R_ANAL_OP_TYPE_SWI: { + char *s = cmd_syscall_dostr (core, -1); if (s) { r_cons_printf ("; %s", s); free (s); } - } - if (ds->analop.type == R_ANAL_OP_TYPE_CJMP) { + } break; + case R_ANAL_OP_TYPE_CJMP: if (likely) { r_cons_printf ("; likely"); } else { r_cons_printf ("; unlikely"); } + break; + case R_ANAL_OP_TYPE_UCALL: + case R_ANAL_OP_TYPE_CALL: + { + ut64 pcv = r_reg_getv (core->anal->reg, pc); + RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, pcv, 0); + if (fcn) { + nargs = fcn->nargs; + } else { + nargs = DEFAULT_NARGS; + } + } + r_cons_printf ("\n; CALL: "); + for (i = 0; i < nargs; i++) { + ut64 v = r_debug_arg_get (core->dbg, R_ANAL_CC_TYPE_STDCALL, i); + r_cons_printf ("%s0x%"PFMT64x, i?", ":"", v); + } + break; } r_config_set_i (core->config, "io.cache", ioc); } diff --git a/libr/debug/arg.c b/libr/debug/arg.c index 2005f764f3..d0223cfbbb 100644 --- a/libr/debug/arg.c +++ b/libr/debug/arg.c @@ -12,7 +12,24 @@ R_API ut64 r_debug_arg_get (RDebug *dbg, int cctype, int num) { return r_debug_reg_get (dbg, reg); case R_ANAL_CC_TYPE_STDCALL: case R_ANAL_CC_TYPE_PASCAL: - /* TODO: get from stack */ + { + ut32 n32; + ut64 n64; + ut64 sp = r_debug_reg_get (dbg, "sp"); + if (dbg->bits == 64) { + sp += 8; // skip return address, asume we are inside the call + sp += 8 * num; + dbg->iob.read_at (dbg->iob.io, sp, (ut8*)&n64, sizeof(ut64)); + // TODO: honor endianness of platform + return (ut64)n64; + } else { + sp += 4; // skip return address, asume we are inside the call + sp += 4 * num; + dbg->iob.read_at (dbg->iob.io, sp, (ut8*)&n32, sizeof(ut32)); + // TODO: honor endianness of platform + return (ut64)n32; + } + } break; } snprintf (reg, 30, "a%d", num); @@ -26,7 +43,7 @@ R_API bool r_debug_arg_set (RDebug *dbg, int cctype, int num, ut64 val) { case R_ANAL_CC_TYPE_NONE: case R_ANAL_CC_TYPE_SYSV: case R_ANAL_CC_TYPE_FASTCALL: - sprintf (reg, 30, "a%d", num); + snprintf (reg, 30, "a%d", num); return r_debug_reg_set (dbg, reg, val); case R_ANAL_CC_TYPE_STDCALL: case R_ANAL_CC_TYPE_PASCAL: diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 0f071e425d..2767e62943 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -277,38 +277,38 @@ typedef struct r_anal_fcn_store_t { /* Store various function information, * variables, arguments, refs and even * description */ - typedef struct r_anal_type_function_t { - char* name; - char* dsc; // For producing nice listings - ut32 size; - int bits; // ((> bits 0) (set-bits bits)) - short type; - /*item_list *rets; // Type of return value */ - short rets; - short fmod; // static, inline or volatile? - /* TODO: Change to RAnalCC ??? */ - short call; // calling convention - char* attr; // __attribute__(()) list - ut64 addr; - int stack; - int ninstr; - int nargs; // Function arguments counter - int depth; - RAnalType *args; // list of arguments +typedef struct r_anal_type_function_t { + char* name; + char* dsc; // For producing nice listings + ut32 size; + int bits; // ((> bits 0) (set-bits bits)) + short type; + /*item_list *rets; // Type of return value */ + short rets; + short fmod; // static, inline or volatile? + /* TODO: Change to RAnalCC ??? */ + short call; // calling convention + char* attr; // __attribute__(()) list + ut64 addr; + int stack; + int ninstr; + int nargs; // Function arguments counter + int depth; + RAnalType *args; // list of arguments #if USE_VARSUBS - RAnalVarSub varsubs[R_ANAL_VARSUBS]; + RAnalVarSub varsubs[R_ANAL_VARSUBS]; #endif - ut8 *fingerprint; // TODO: make is fuzzy and smarter - RAnalDiff *diff; - RList *locs; // list of local variables - //RList *locals; // list of local labels -> moved to anal->sdb_fcns - RList *bbs; - RList *vars; + ut8 *fingerprint; // TODO: make is fuzzy and smarter + RAnalDiff *diff; + RList *locs; // list of local variables + //RList *locals; // list of local labels -> moved to anal->sdb_fcns + RList *bbs; + RList *vars; #if FCN_OLD - RList *refs; - RList *xrefs; + RList *refs; + RList *xrefs; #endif - } RAnalFunction; +} RAnalFunction; struct r_anal_type_t { char *name;