/* restore program counter after breakpoint hit */ static int r_debug_recoil(RDebug *dbg) { int recoil; RRegItem *ri; if (r_debug_is_dead (dbg)) { return false; } r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false); ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], -1); dbg->reason.bpi = NULL; if (ri) { ut64 addr = r_reg_get_value (dbg->reg, ri); recoil = r_bp_recoil (dbg->bp, addr - dbg->bpsize); //eprintf ("[R2] Breakpoint recoil at 0x%"PFMT64x" = %d\n", addr, recoil); if (recoil < 1) recoil = 0; // XXX Hack :D if (recoil) { dbg->in_recoil = true; dbg->reason.type = R_DEBUG_REASON_BREAKPOINT; dbg->reason.bpi = r_bp_get_at (dbg->bp, addr-recoil); dbg->reason.addr = addr - recoil; r_reg_set_value (dbg->reg, ri, addr-recoil); if (r_reg_get_value (dbg->reg, ri) != (addr-recoil)) { eprintf ("r_debug_recoil: Cannot set program counter\n"); return false; } r_debug_reg_sync (dbg, R_REG_TYPE_GPR, true); //eprintf ("[BP Hit] Setting pc to 0x%"PFMT64x"\n", (addr-recoil)); return true; } } else { eprintf ("r_debug_recoil: Cannot get program counter\n"); } return false; }
/* restore program counter after breakpoint hit */ static int r_debug_recoil(RDebug *dbg) { int recoil; RRegItem *ri; if (r_debug_is_dead (dbg)) return R_FALSE; r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE); ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], -1); dbg->reason.bpi = NULL; if (ri) { ut64 addr = r_reg_get_value (dbg->reg, ri); recoil = r_bp_recoil (dbg->bp, addr); //eprintf ("[R2] Breakpoint recoil at 0x%"PFMT64x" = %d\n", addr, recoil); #if __arm__ if (recoil<1) recoil = 0; // XXX Hack :D #else if (recoil<1) recoil = 0; //1; // XXX Hack :D (x86 only?) #endif if (recoil) { dbg->reason.type = R_DEBUG_REASON_BREAKPOINT; dbg->reason.bpi = r_bp_get_at (dbg->bp, addr-recoil); dbg->reason.addr = addr - recoil; r_reg_set_value (dbg->reg, ri, addr-recoil); if (r_reg_get_value (dbg->reg, ri) != (addr-recoil)) { eprintf ("r_debug_recoil: Cannot set program counter\n"); return R_FALSE; } r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_TRUE); //eprintf ("[BP Hit] Setting pc to 0x%"PFMT64x"\n", (addr-recoil)); return R_TRUE; } } else eprintf ("r_debug_recoil: Cannot get program counter\n"); return R_FALSE; }
/* * Save 4096 bytes from %esp * TODO: Add support for reverse stack architectures * Also known as r_debug_inject() */ R_API ut64 r_debug_execute(RDebug *dbg, const ut8 *buf, int len, int restore) { int orig_sz; ut8 stackbackup[4096]; ut8 *backup, *orig = NULL; RRegItem *ri, *risp, *ripc; ut64 rsp, rpc, ra0 = 0LL; if (r_debug_is_dead (dbg)) return R_FALSE; ripc = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], R_REG_TYPE_GPR); risp = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_SP], R_REG_TYPE_GPR); if (ripc) { r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE); orig = r_reg_get_bytes (dbg->reg, -1, &orig_sz); if (orig == NULL) { eprintf ("Cannot get register arena bytes\n"); return 0LL; } rpc = r_reg_get_value (dbg->reg, ripc); rsp = r_reg_get_value (dbg->reg, risp); backup = malloc (len); if (backup == NULL) { free (orig); return 0LL; } dbg->iob.read_at (dbg->iob.io, rpc, backup, len); dbg->iob.read_at (dbg->iob.io, rsp, stackbackup, len); r_bp_add_sw (dbg->bp, rpc+len, dbg->bpsize, R_BP_PROT_EXEC); /* execute code here */ dbg->iob.write_at (dbg->iob.io, rpc, buf, len); //r_bp_add_sw (dbg->bp, rpc+len, 4, R_BP_PROT_EXEC); r_debug_continue (dbg); //r_bp_del (dbg->bp, rpc+len); /* TODO: check if stopped in breakpoint or not */ r_bp_del (dbg->bp, rpc+len); dbg->iob.write_at (dbg->iob.io, rpc, backup, len); if (restore) { dbg->iob.write_at (dbg->iob.io, rsp, stackbackup, len); } r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_FALSE); ri = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_A0], R_REG_TYPE_GPR); ra0 = r_reg_get_value (dbg->reg, ri); if (restore) { r_reg_set_bytes (dbg->reg, -1, orig, orig_sz); } else { r_reg_set_value (dbg->reg, ripc, rpc); } r_debug_reg_sync (dbg, R_REG_TYPE_GPR, R_TRUE); free (backup); free (orig); eprintf ("ra0=0x%08"PFMT64x"\n", ra0); } else eprintf ("r_debug_execute: Cannot get program counter\n"); return (ra0); }
// XXX: Do this work correctly? static RList *backtrace_x86_64_anal(RDebug *dbg, ut64 at) { int i; ut8 buf[8]; RDebugFrame *frame; ut64 ptr, ebp2 = UT64_MAX; ut64 _rip, _rbp; RList *list; RReg *reg = dbg->reg; RIOBind *bio = &dbg->iob; RAnalFunction *fcn; _rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR)); if (at == UT64_MAX) { //_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR)); _rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR)); } else { _rbp = at; } list = r_list_new (); list->free = free; bio->read_at (bio->io, _rip, (ut8*)&buf, 8); // TODO : frame->size by using esil to emulate first instructions fcn = r_anal_get_fcn_in (dbg->anal, _rip, R_ANAL_FCN_TYPE_NULL); if (fcn) { frame = R_NEW0 (RDebugFrame); frame->addr = _rip; frame->size = 0; frame->sp = _rbp; frame->bp = _rbp + 8; // XXX r_list_append (list, frame); } for (i=1; i<dbg->btdepth; i++) { // TODO: make those two reads in a shot bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8); if (ebp2 == UT64_MAX) break; bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8); if (!ptr || !_rbp) break; //fcn = r_anal_get_fcn_in (dbg->anal, ptr, R_ANAL_FCN_TYPE_NULL); frame = R_NEW0 (RDebugFrame); frame->addr = ptr; frame->size = 0; frame->sp = _rbp; frame->bp = _rbp + 8; //frame->name = (fcn && fcn->name) ? strdup (fcn->name) : NULL; r_list_append (list, frame); _rbp = ebp2; } return list; }
static RList *backtrace_x86_64(RDebug *dbg, ut64 at) { int i; ut8 buf[8]; RDebugFrame *frame; ut64 ptr, ebp2; ut64 _rip, _rsp, _rbp = 0; RList *list; RReg *reg = dbg->reg; RIOBind *bio = &dbg->iob; _rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR)); if (at == UT64_MAX) { _rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR)); _rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR)); } else { _rsp = _rbp = at; } list = r_list_new (); list->free = free; bio->read_at (bio->io, _rip, (ut8*)&buf, 8); /* %rbp=old rbp, %rbp+4 points to ret */ /* Plugin before function prelude: push %rbp ; mov %rsp, %rbp */ if (!memcmp (buf, "\x55\x89\xe5", 3) || !memcmp (buf, "\x89\xe5\x57", 3)) { if (!bio->read_at (bio->io, _rsp, (ut8*)&ptr, 8)) { eprintf ("read error at 0x%08"PFMT64x"\n", _rsp); r_list_purge (list); free (list); return false; } frame = R_NEW0 (RDebugFrame); frame->addr = ptr; frame->size = 0; // TODO ? r_list_append (list, frame); _rbp = ptr; } for (i=1; i<dbg->btdepth; i++) { // TODO: make those two reads in a shot bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8); if (ebp2 == UT64_MAX) break; bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8); if (!ptr || !_rbp) break; frame = R_NEW0 (RDebugFrame); frame->addr = ptr; frame->size = 0; // TODO ? r_list_append (list, frame); _rbp = ebp2; } return list; }
R_API int r_debug_continue_until(RDebug *dbg, ut64 addr) { // TODO: use breakpoint+continue... more efficient RRegItem *ripc = r_reg_get (dbg->reg, dbg->reg->name[R_REG_NAME_PC], R_REG_TYPE_GPR); int n = 0; ut64 pc = r_reg_get_value (dbg->reg, ripc); while (pc != addr && !r_debug_is_dead (dbg)) { r_debug_step (dbg, 1); // TODO: obey breakpoints too? /* TODO: check if the debugger stops at the right address */ pc = r_reg_get_value (dbg->reg, ripc); n++; } return n; }
static int r_debug_gdb_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) { if (!reg_buf) { // we cannot write registers before we once read them return -1; } int buflen = 0; int bits = dbg->anal->bits; free(r_reg_get_bytes(dbg->reg, type, &buflen)); // some implementations of the gdb protocol are acting weird. // so winedbg is not able to write registers through the <G> packet // and also it does not return the whole gdb register profile after // calling <g> // so this workaround resizes the small register profile buffer // to the whole set and fills the rest with 0 if (buf_size < buflen) { ut8* new_buf = realloc (reg_buf, buflen * sizeof (ut8)); if (!new_buf) { return -1; } reg_buf = new_buf; memset (new_buf + buf_size, 0, buflen - buf_size); } RRegItem* current = NULL; for (;;) { current = r_reg_next_diff (dbg->reg, type, reg_buf, buflen, current, bits); if (!current) break; ut64 val = r_reg_get_value (dbg->reg, current); int bytes = bits / 8; gdbr_write_reg (desc, current->name, (char*)&val, bytes); } return true; }
static ut64 esil_get (RAnalEsil *e, const char *s) { RRegItem *item; // check for register if (!s) return 0LL; item = r_reg_get (e->anal->reg, s, 0); // GPR only wtf? if (item) return r_reg_get_value (e->anal->reg, item); return r_num_get (NULL, s); }
static void ios_hwstep_enable32 (RDebug *dbg, task_t port, int enable) { int i; static ARMDebugState32 olds; ARMDebugState32 ds; mach_msg_type_number_t count = ARM_DEBUG_STATE32_COUNT; (void) thread_get_state (port, ARM_DEBUG_STATE32, (thread_state_t)&ds, &count); //static ut64 chainstep = UT64_MAX; if (enable) { RIOBind *bio = &dbg->iob; ut32 pc = r_reg_get_value (dbg->reg, r_reg_get (dbg->reg, "pc", R_REG_TYPE_GPR)); ut32 cpsr = r_reg_get_value (dbg->reg, r_reg_get (dbg->reg, "cpsr", R_REG_TYPE_GPR)); for (i = 0; i < 16 ; i++) { ds.bcr[i] = ds.bvr[i] = 0; } olds = ds; //chainstep = UT64_MAX; // state = old_state; ds.bvr[i] = pc & (UT32_MAX >> 2) << 2; ds.bcr[i] = BCR_M_IMVA_MISMATCH | S_USER | BCR_ENABLE; if (cpsr & 0x20) { ut16 op; if (pc & 2) { ds.bcr[i] |= BAS_IMVA_2_3; } else { ds.bcr[i] |= BAS_IMVA_0_1; } /* check for thumb */ bio->read_at (bio->io, pc, (void *)&op, 2); if (isThumb32 (op)) { eprintf ("Thumb32 chain stepping not supported yet\n"); //chainstep = pc + 2; } else { ds.bcr[i] |= BAS_IMVA_ALL; } } else { ds.bcr[i] |= BAS_IMVA_ALL; } } else {
static ut32 i8051_reg_read (RReg *reg, const char *regname) { if (reg) { RRegItem *item = r_reg_get (reg, regname, R_REG_TYPE_GPR); if (item) { return r_reg_get_value (reg, item); } } return 0; }
int reg_read(RAnalEsil *esil, const char *regname, ut64 *num) { RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1); if (reg) { if (num) *num = r_reg_get_value (esil->anal->reg, reg); return 1; } return 0; }
R_API char *r_reg_get_bvalue(RReg *reg, RRegItem *item) { char *out; ut64 num; if (!item->flags) return NULL; out = malloc (strlen (item->flags)+1); num = r_reg_get_value (reg, item); r_str_bits (out, (ut8*)&num, strlen (item->flags)*8, item->flags); return out; }
// mul*value+regbase+regidx+delta R_API ut64 r_anal_value_to_ut64(RAnal *anal, RAnalValue *val) { ut64 num; if (val==NULL) return 0LL; num = val->base + (val->delta*(val->mul?val->mul:1)); if (val->reg) num += r_reg_get_value (anal->reg, val->reg); if (val->regdelta) num += r_reg_get_value (anal->reg, val->regdelta); switch (val->memref) { case 1: case 2: case 4: case 8: //anal->bio ... eprintf ("TODO: memref for to_ut64 not supported\n"); break; } return num; }
void show_regs(struct r_reg_t *reg, int bitsize) { RList *reglist; RListIter *iter; RRegItem *ri; printf("%d bit registers:\n", bitsize); reglist = r_reg_get_list(reg, bitsize==1? R_REG_TYPE_FLG: R_REG_TYPE_GPR); r_list_foreach (reglist, iter, ri) { if (ri->size == bitsize) printf(" - %s : 0x%08"PFMT64x"\n", ri->name, r_reg_get_value(reg, ri)); } }
R_API R_HEAP char *r_reg_get_bvalue(RReg *reg, RRegItem *item) { char *out = NULL; if (reg && item && item->flags) { out = malloc (strlen (item->flags) + 1); if (out) { ut64 num = r_reg_get_value (reg, item); r_str_bits (out, (ut8 *)&num, strlen (item->flags) * 8, item->flags); } } return out; }
static RList *backtrace_fuzzy(RDebug *dbg, ut64 at) { ut8 *stack, *ptr; int wordsize = dbg->bits; // XXX, dbg->bits is wordsize not bits ut64 sp; RIOBind *bio = &dbg->iob; int i, stacksize; ut64 *p64, addr = 0LL; ut32 *p32; ut16 *p16; ut64 cursp, oldsp; RList *list; stacksize = 1024*512; // 512KB .. should get the size from the regions if possible stack = malloc (stacksize); if (at == UT64_MAX) { RRegItem *ri; RReg *reg = dbg->reg; const char *spname = r_reg_get_name (reg, R_REG_NAME_SP); if (!spname) { eprintf ("Cannot find stack pointer register\n"); free (stack); return NULL; } ri = r_reg_get (reg, spname, R_REG_TYPE_GPR); if (!ri) { eprintf ("Cannot find stack pointer register\n"); free (stack); return NULL; } sp = r_reg_get_value (reg, ri); } else { sp = at; } list = r_list_new (); list->free = free; cursp = oldsp = sp; (void)bio->read_at (bio->io, sp, stack, stacksize); ptr = stack; for (i=0; i<dbg->btdepth; i++) { p64 = (ut64*)ptr; p32 = (ut32*)ptr; p16 = (ut16*)ptr; switch (wordsize) { case 8: addr = *p64; break; case 4: addr = *p32; break; case 2: addr = *p16; break; default: eprintf ("Invalid word size with asm.bits\n"); r_list_free (list); return NULL; } if (iscallret (dbg, addr)) { RDebugFrame *frame = R_NEW0 (RDebugFrame); frame->addr = addr; frame->size = cursp - oldsp; frame->sp = cursp; frame->bp = oldsp; //addr + (i * wordsize); // -4 || -8 // eprintf ("--------------> 0x%llx (%d)\n", addr, frame->size); r_list_append (list, frame); oldsp = cursp; } ptr += wordsize; cursp += wordsize; } return list; }
R_API int r_debug_reg_list(RDebug *dbg, int type, int size, int rad, const char *use_color) { int i, delta, from, to, cols, n = 0; const char *fmt, *fmt2, *kwhites; RListIter *iter; RRegItem *item; RList *head; ut64 diff; if (!dbg || !dbg->reg) return R_FALSE; if (!(dbg->reg->bits & size)) { // TODO: verify if 32bit exists, otherwise use 64 or 8? size = 32; } //if (dbg->h && dbg->h->bits & R_SYS_BITS_64) { if (dbg->bits & R_SYS_BITS_64) { fmt = "%s = 0x%08"PFMT64x"%s"; fmt2 = "%4s 0x%08"PFMT64x"%s"; cols = 3; kwhites = " "; } else { fmt = " %s = 0x%08"PFMT64x"%s"; fmt2 = " %3s 0x%08"PFMT64x"%s"; cols = 4; kwhites = " "; } if (rad=='j') dbg->printf ("{"); if (type == -1) { from = 0; to = R_REG_TYPE_LAST; } else { from = type; to = from +1; } for (i=from; i<to; i++) { head = r_reg_get_list (dbg->reg, i); if (!head) continue; r_list_foreach (head, iter, item) { ut64 value; if (type != -1) { if (type != item->type) continue; if (size != 0 && size != item->size) continue; } value = r_reg_get_value (dbg->reg, item); r_reg_arena_swap (dbg->reg, R_FALSE); diff = r_reg_get_value (dbg->reg, item); r_reg_arena_swap (dbg->reg, R_FALSE); delta = value-diff; switch (rad) { case 'j': dbg->printf ("%s\"%s\":%"PFMT64d, n?",":"", item->name, value); break; case 1: case '*': dbg->printf ("f %s 1 0x%"PFMT64x"\n", item->name, value); break; case 'd': case 2: { char *str, whites[16], content[128]; int len; strcpy (whites, kwhites); if (delta && use_color) dbg->printf (use_color); if (item->flags) { str = r_reg_get_bvalue (dbg->reg, item); len = strlen (str); strcpy (whites, " "); len = (len>9)?9:(9-len); whites[len] = 0; dbg->printf (" %s = %s%s", item->name, str, ((n+1)%cols)? whites: "\n"); free (str); } else { snprintf (content, sizeof(content), fmt2, item->name, value, ""); len = strlen (content); len -= 4; if (len>10) { len -= 10; len = (len>9)?9:(9-len); whites[len] = 0; } dbg->printf (fmt2, item->name, value, ((n+1)%cols)? whites: "\n"); } if (delta && use_color) dbg->printf (Color_RESET); } break; case 3: if (delta) { char woot[64]; snprintf (woot, sizeof (woot), " was 0x%08"PFMT64x" delta %d\n", diff, delta); dbg->printf (fmt, item->name, value, woot); } break; default: if (delta && use_color) dbg->printf (use_color); dbg->printf (fmt, item->name, value, "\n"); if (delta && use_color) dbg->printf (Color_RESET); break; } n++; } }
int main() { int i; int foo[128]; const char *type; struct r_reg_t *reg; for (i=0;i<128;i++) foo[i] = i; reg = r_reg_new (); r_reg_set_profile (reg, "./test.regs"); r_reg_read_regs (reg, (const ut8 *)foo, sizeof(foo)); { ut64 a; RRegItem *item; item = r_reg_get (reg, "eflags", R_REG_TYPE_GPR); r_reg_set_value (reg, item, 0x00000346); //0xffffffffffff); a = r_reg_get_value (reg, item); eprintf ("A32 = 0x%x\n", (int)a); if ((int)a != -1) { eprintf ("1 FAIL\n"); } print_eflags_bits (reg); item = r_reg_get (reg, "zf", R_REG_TYPE_GPR); a = r_reg_get_value (reg, item); eprintf ("A = %d\n", (int)a); if (a != 1) { eprintf ("2 FAIL\n"); } item = r_reg_get (reg, "zf", R_REG_TYPE_GPR); r_reg_set_value (reg, item, 1); a = r_reg_get_value (reg, item); eprintf ("A = %d\n", (int)a); if (a != 1) { eprintf ("3 FAIL\n"); } r_reg_set_value (reg, item, 0); a = r_reg_get_value (reg, item); eprintf ("A = %d\n", (int)a); if (a != 0) { eprintf ("4 FAIL\n"); } } show_regs (reg, 1); //32); exit (0); show_regs (reg, 32); /* --- */ r_reg_set_profile(reg, "../p/x86-linux.regs"); printf ("Program counter is named: %s\n", r_reg_get_name (reg, R_REG_NAME_PC)); show_regs (reg, 32); r_reg_set_value(reg, r_reg_get(reg, "eax", -1), 0x414141); r_reg_set_value(reg, r_reg_get(reg, "ecx", -1), 666); show_regs(reg, 32); r_reg_set_value(reg, r_reg_get(reg, "al", -1), 0x22); show_regs(reg, 33); r_reg_set_value (reg, r_reg_get (reg, "zero", -1), 0); show_regs (reg, 1); r_reg_set_value (reg, r_reg_get (reg, "zero", -1), 1); show_regs (reg, 1); for (i=0; (type=r_reg_get_type (i));i++) printf (" - %s\n", type); r_reg_arena_push (reg); r_reg_arena_pop (reg); r_reg_arena_push (reg); r_reg_arena_push (reg); r_reg_arena_push (reg); r_reg_arena_pop (reg); r_reg_arena_pop (reg); r_reg_arena_push (reg); r_reg_arena_pop (reg); r_reg_arena_pop (reg); /* r_reg_arena_pop(reg); r_reg_arena_pop(reg); r_reg_arena_pop(reg); r_reg_arena_pop(reg); */ return 0; }
R_API int r_debug_reg_list(RDebug *dbg, int type, int size, int rad, const char *use_color) { int i, delta, from, to, cols, n = 0; const char *fmt, *fmt2, *kwhites; int colwidth = 20; RListIter *iter; RRegItem *item; RList *head; RPrint *pr = NULL; ut64 diff; if (!dbg || !dbg->reg) { return false; } if (dbg->corebind.core) { pr = ((RCore*)dbg->corebind.core)->print; } if (!(dbg->reg->bits & size)) { // TODO: verify if 32bit exists, otherwise use 64 or 8? size = 32; } if (dbg->bits & R_SYS_BITS_64) { fmt = "%s = 0x%08"PFMT64x"%s"; fmt2 = "%s%4s%s 0x%08"PFMT64x"%s"; kwhites = " "; colwidth = dbg->regcols? 20: 25; cols = 3; } else { fmt = "%s = 0x%08"PFMT64x"%s"; fmt2 = "%s%4s%s 0x%08"PFMT64x"%s"; kwhites = " "; colwidth = 20; cols = 4; } if (dbg->regcols) { cols = dbg->regcols; } if (rad == 'j') dbg->cb_printf ("{"); if (type == -1) { from = 0; to = R_REG_TYPE_LAST; } else { from = type; to = from +1; } int itmidx = -1; dbg->creg = NULL; for (i = from; i < to; i++) { head = r_reg_get_list (dbg->reg, i); if (!head) continue; r_list_foreach (head, iter, item) { ut64 value; #if 0 bool is_arm = dbg->arch && strstr (dbg->arch, "arm"); /* the thumb flag in the cpsr register shouldnt forbid us to switch between arm or thumb */ /* this code must run only after a step maybe ... need some discussion, disabling for now */ if (is_arm && (rad == 1 || rad == '*') && item->size == 1) { if (!strcmp (item->name, "tf")) { bool is_thumb = r_reg_get_value (dbg->reg, item); int new_bits = is_thumb? 16: 32; if (dbg->anal->bits != new_bits) dbg->cb_printf ("e asm.bits=%d\n", new_bits); } continue; } #endif if (type != -1) { if (type != item->type) continue; if (size != 0 && size != item->size) continue; } value = r_reg_get_value (dbg->reg, item); r_reg_arena_swap (dbg->reg, false); diff = r_reg_get_value (dbg->reg, item); r_reg_arena_swap (dbg->reg, false); delta = value-diff; itmidx++; switch (rad) { case 'j': dbg->cb_printf ("%s\"%s\":%"PFMT64d, n?",":"", item->name, value); break; case '-': dbg->cb_printf ("f-%s\n", item->name); break; case 1: case '*': dbg->cb_printf ("f %s 1 0x%"PFMT64x"\n", item->name, value); break; case 'd': case 2: { int len, highlight = use_color && pr && pr->cur_enabled && itmidx == pr->cur; char *str, whites[32], content[128]; const char *a = "", *b = ""; if (highlight) { a = Color_INVERT; b = Color_INVERT_RESET; dbg->creg = item->name; } strcpy (whites, kwhites); if (delta && use_color) { dbg->cb_printf (use_color); } if (item->flags) { str = r_reg_get_bvalue (dbg->reg, item); len = 12 - strlen (str); memset (whites, ' ', sizeof (whites)); whites[len] = 0; dbg->cb_printf (" %s%s%s %s%s", a, item->name, b, str, ((n+1)%cols)? whites: "\n"); free (str); } else { snprintf (content, sizeof (content), fmt2, "", item->name, "", value, ""); len = colwidth - strlen (content); if (len < 0) len = 0; memset (whites, ' ', sizeof (whites)); whites[len] = 0; dbg->cb_printf (fmt2, a, item->name, b, value, ((n+1)%cols)? whites: "\n"); } if (highlight) { dbg->cb_printf (Color_INVERT_RESET); } if (delta && use_color) { dbg->cb_printf (Color_RESET); } } break; case 3: if (delta) { char woot[64]; snprintf (woot, sizeof (woot), " was 0x%08"PFMT64x" delta %d\n", diff, delta); dbg->cb_printf (fmt, item->name, value, woot); } break; default: if (delta && use_color) { dbg->cb_printf (use_color); dbg->cb_printf (fmt, item->name, value, Color_RESET"\n"); } else { dbg->cb_printf (fmt, item->name, value, "\n"); } break; } n++; } }
R_API ut64 r_reg_get_value_by_role(RReg *reg, RRegisterId role) { // TODO use mapping from RRegisterId to RRegItem (via RRegSet) return r_reg_get_value (reg, r_reg_get (reg, r_reg_get_name (reg, role), -1)); }
// XXX: RVM must be inside RAnal ???? imho no. rsyscall must provide ret reg info //XXX: may overflow. this is vulnerable. needs fix R_API char *r_anal_cc_to_string (RAnal *anal, RAnalCC* cc) { RSyscallItem *si; RAnalFunction *fcn; char str[1024], buf[64]; int i, eax = 0; // eax = arg0 int str_len = 0; int buf_len = 0; str[0] = 0; switch (cc->type) { case R_ANAL_CC_TYPE_FASTCALL: // INT { RRegItem *item; const char *a0 = r_reg_get_name (anal->reg, R_REG_NAME_A0); // A0 or RET ?? item = r_reg_get (anal->reg, a0, R_REG_TYPE_GPR); if (!item) { //eprintf ("cannot get reg a0\n"); return R_FALSE; } eax = (int)r_reg_get_value (anal->reg, item); si = r_syscall_get (anal->syscall, eax, (int)cc->jump); if (si) { //DEBUG r_cons_printf (" ; sc[0x%x][%d]=%s(", (int)analop.value, eax, si->name); snprintf (str, sizeof (str), "%s (", si->name); for (i=0; i<si->args; i++) { const char *reg = r_syscall_reg (anal->syscall, i+1, si->args); if (!reg) break; // no registers? item = r_reg_get (anal->reg, reg, R_REG_TYPE_GPR); if (item) { snprintf (buf, sizeof (buf), "0x%"PFMT64x, r_reg_get_value (anal->reg, item)); strcat (str, buf); // XXX: do not use strcat } //else eprintf ("Unknown reg '%s'\n", reg); if (i<si->args-1) strcat (str, ","); // XXX: do not use strcat } strcat (str, ")"); } else { int n = (int)cc->jump; //if (n == 3) return NULL; // XXX: hack for x86 snprintf (str, sizeof (str), "syscall[0x%x][%d]=?", n, eax); } } break; case R_ANAL_CC_TYPE_STDCALL: // CALL fcn = r_anal_fcn_find (anal, cc->jump, R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM|R_ANAL_FCN_TYPE_IMP); if (fcn && fcn->name) snprintf (str, sizeof (str), "%s(", fcn->name); else if (cc->jump != -1LL) snprintf (str, sizeof (str), "0x%08"PFMT64x"(", cc->jump); else strncpy (str, "unk(", sizeof (str)-1); str_len = strlen (str); if (fcn) cc->nargs = (fcn->nargs>cc->nargs?fcn->nargs:cc->nargs); if (cc->nargs>8) { //eprintf ("too many arguments for stdcall. chop to 8\n"); cc->nargs = 8; } // TODO: optimize string concat for (i=0; i<cc->nargs; i++) { if (cc->args[cc->nargs-i] != -1LL) snprintf (buf, sizeof (buf), "0x%"PFMT64x, cc->args[cc->nargs-i]); else strncpy (buf, "unk", sizeof (buf)-1); buf_len = strlen (buf); if ((buf_len+str_len+5)>=sizeof (str)) { strcat (str, "..."); break; } strcat (str, buf); str_len += buf_len; if (i<cc->nargs-1) strcat (str, ", "); } strcat (str, ")"); break; } return strdup (str); }