R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) { ut64 num; if (!item->flags) return UT64_MAX; num = r_str_bits_from_string (str, item->flags); if (num == UT64_MAX) r_reg_set_value (reg, item, r_num_math (NULL, str)); else r_reg_set_value (reg, item, num); return num; }
/* 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; }
/* 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; }
/* * 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); }
int reg_write(RAnalEsil *esil, const char *regname, ut64 num) { RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1); if (reg) { if (num) r_reg_set_value (esil->anal->reg, reg,num); return 1; } return 0; }
int gb_write(emu *e, ut64 addr, ut8 *buf, ut32 len) { if(0x2000 <= addr && addr < 0x4000) { if(buf[0] == 0x20 || buf[0] == 0x40 || buf[0] == 0x60) return r_reg_set_value(e->reg, r_reg_get(e->reg, "mbcrom", -1), 0); if(!buf[0]) return r_reg_set_value(e->reg, r_reg_get(e->reg, "mbcrom", -1), 0); return r_reg_set_value(e->reg, r_reg_get(e->reg, "mbcrom", -1), buf[0]-1); } if(0x4000 <= addr && addr < 0x6000) { if(!buf[0]) return r_reg_set_value(e->reg, r_reg_get(e->reg, "mbcram", -1), 0); return r_reg_set_value(e->reg, r_reg_get(e->reg, "mbcram", -1), buf[0]-1); } if(0xa000 <= addr && addr < 0xc000) return emu_write(e, addr + (r_reg_getv(e->reg, "mbcram") << 16), buf, len); return emu_write(e, addr, buf, len); }
static int esil_set (RAnalEsil *e, const char *s, ut64 n) { if (e->anal && e->anal->reg) { RRegItem *item; item = r_reg_get (e->anal->reg, s, 0); // GPR only wtf? eprintf ("SET (%p)\n", item); if (item) return r_reg_set_value (e->anal->reg, item, n); } return R_TRUE; }
R_API boolt r_anal_cc_update (RAnal *anal, RAnalCC *cc, RAnalOp *op) { RRegItem *it; cc->off = op->addr; switch (op->type) { case R_ANAL_OP_TYPE_CALL: case R_ANAL_OP_TYPE_UCALL: cc->type = R_ANAL_CC_TYPE_STDCALL; // TODO: check if next instruction after call is restoring stack cc->jump = op->jump; return R_FALSE; case R_ANAL_OP_TYPE_SWI: // syscall cc->type = R_ANAL_CC_TYPE_FASTCALL; cc->off = op->jump; cc->jump = op->val; // syscall number return R_FALSE; case R_ANAL_OP_TYPE_XOR: if (op->src[0] && op->src[0]->reg && op->dst && op->dst->reg && op->dst->reg->name) { char *n1 = op->dst->reg->name; char *n2 = op->src[0]->reg->name; // XXX: must handle XOR operation properly // if n1 == n2 then set to 0 if (!strcmp (n1, n2)) { it = r_reg_get (anal->reg, n1, R_REG_TYPE_GPR); r_reg_set_value (anal->reg, it, 0); } } return R_TRUE; case R_ANAL_OP_TYPE_MOV: if (op->dst && op->dst->reg) { it = r_reg_get (anal->reg, op->dst->reg->name, R_REG_TYPE_GPR); if (it && op->src[0]) r_reg_set_value (anal->reg, it, op->src[0]->imm); } return R_TRUE; case R_ANAL_OP_TYPE_PUSH: case R_ANAL_OP_TYPE_UPUSH: // add argument cc->nargs ++; if (cc->nargs>0 && cc->nargs < R_ANAL_CC_ARGS) cc->args[cc->nargs] = op->val; return R_TRUE; } // must update internal stuff to recognize parm return R_TRUE; }
static bool i8051_reg_write (RReg *reg, const char *regname, ut32 num) { if (reg) { RRegItem *item = r_reg_get (reg, regname, R_REG_TYPE_GPR); if (item) { r_reg_set_value (reg, item, num); return true; } } return false; }
R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) { ut64 num = UT64_MAX; if (item && item->flags && str) { num = r_str_bits_from_string (str, item->flags); if (num == UT64_MAX) { num = r_num_math (NULL, str); } r_reg_set_value (reg, item, num); } return num; }
R_API int r_anal_value_set_ut64(RAnal *anal, RAnalValue *val, ut64 num) { if (val->memref) { if (anal->iob.io) { ut8 data[8]; ut64 addr = r_anal_value_to_ut64 (anal, val); r_mem_set_num (data, val->memref, num, anal->big_endian); anal->iob.write_at (anal->iob.io, addr, data, val->memref); } else eprintf ("No IO binded to r_anal\n"); } else { if (val->reg) r_reg_set_value (anal->reg, val->reg, num); } return R_FALSE; //is this necessary }
int gb_set_reg_profile(emu *e) { int ret = r_anal_set_reg_profile (e->anal); e->reg = e->anal->reg; r_reg_set_value (e->reg, r_reg_get (e->reg,"mpc",-1), ((RBinAddr *) r_list_get_n (r_bin_get_entries (e->bin), 0))->offset); r_reg_set_value (e->reg, r_reg_get (e->reg,"sp",-1), 0xfffe); r_reg_set_value (e->reg, r_reg_get (e->reg,"af",-1), 0x01b0); r_reg_set_value (e->reg, r_reg_get (e->reg,"bc",-1), 0x0013); r_reg_set_value (e->reg, r_reg_get (e->reg,"de",-1), 0x00d8); r_reg_set_value (e->reg, r_reg_get (e->reg,"hl",-1), 0x014d); r_reg_set_value (e->reg, r_reg_get (e->reg,"ime",-1), R_TRUE); return ret; }
static int esil_6502_init (RAnalEsil *esil) { if (esil->anal && esil->anal->reg) { //initial values r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "pc", -1), 0x0000); r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "sp", -1), 0xff); r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "a", -1), 0x00); r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "x", -1), 0x00); r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "y", -1), 0x00); r_reg_set_value (esil->anal->reg, r_reg_get (esil->anal->reg, "flags", -1), 0x00); } return true; }
/* * Recoiling after a breakpoint has two stages: * 1. remove the breakpoint and fix the program counter. * 2. on resume, single step once and then replace the breakpoint. * * Thus, we have two functions to handle these situations. * r_debug_bp_hit handles stage 1. * r_debug_recoil handles stage 2. */ static int r_debug_bp_hit(RDebug *dbg, RRegItem *pc_ri, ut64 pc, RBreakpointItem **pb) { RBreakpointItem *b; if (!pb) { eprintf ("BreakpointItem is NULL!\n"); return false; } /* initialize the output parameter */ *pb = NULL; /* if we are tracing, update the tracing data */ if (dbg->trace->enabled) { r_debug_trace_pc (dbg, pc); } /* remove all sw breakpoints for now. we'll set them back in stage 2 * * this is necessary because while stopped we don't want any breakpoints in * the code messing up our analysis. */ if (!r_bp_restore (dbg->bp, false)) { // unset sw breakpoints return false; } /* if we are recoiling, tell r_debug_step that we ignored a breakpoint * event */ if (!dbg->swstep && dbg->recoil_mode != R_DBG_RECOIL_NONE) { dbg->reason.bp_addr = 0; return true; } /* The MIPS ptrace has a different behaviour */ # if __mips__ /* see if we really have a breakpoint here... */ b = r_bp_get_at (dbg->bp, pc); if (!b) { /* we don't. nothing left to do */ return true; } # else int pc_off = dbg->bpsize; /* see if we really have a breakpoint here... */ b = r_bp_get_at (dbg->bp, pc - dbg->bpsize); if (!b) { /* we don't. nothing left to do */ /* Some targets set pc to breakpoint */ b = r_bp_get_at (dbg->bp, pc); if (!b) { return true; } pc_off = 0; } /* set the pc value back */ if (pc_off) { pc -= pc_off; if (!r_reg_set_value (dbg->reg, pc_ri, pc)) { eprintf ("failed to set PC!\n"); return false; } if (!r_debug_reg_sync (dbg, R_REG_TYPE_GPR, true)) { eprintf ("cannot set registers!\n"); return false; } } # endif *pb = b; /* if we are on a software stepping breakpoint, we hide what is going on... */ if (b->swstep) { dbg->reason.bp_addr = 0; return true; } /* setup our stage 2 */ dbg->reason.bp_addr = b->addr; /* inform the user of what happened */ if (dbg->hitinfo) { eprintf ("hit %spoint at: %"PFMT64x "\n", b->trace ? "trace" : "break", pc); } /* now that we've cleaned up after the breakpoint, call the other * potential breakpoint handlers */ if (dbg->corebind.core && dbg->corebind.bphit) { dbg->corebind.bphit (dbg->corebind.core, b); } return true; }
int gb_step (emu *e, ut8 *buf) { int ret = R_FALSE; GBCpuStats *cpu = (GBCpuStats *)e->data; cpu->cycles += e->anop->cycles; r_reg_set_value (e->reg, r_reg_get (e->reg, "pc", -1), r_reg_getv(e->reg, "pc") + e->op->size); switch (e->anop->type) { case R_ANAL_OP_TYPE_NOP: ret = R_TRUE; case R_ANAL_OP_TYPE_TRAP: case R_ANAL_OP_TYPE_ILL: break; case R_ANAL_OP_TYPE_MOV: ret = gb_mov (e); break; case R_ANAL_OP_TYPE_PUSH: ret = gb_push (e); break; case R_ANAL_OP_TYPE_POP: ret = gb_pop (e); break; case R_ANAL_OP_TYPE_JMP: ret = gb_jmp (e); break; case R_ANAL_OP_TYPE_CJMP: ret = gb_cjmp (e); break; case R_ANAL_OP_TYPE_UJMP: ret = gb_ujmp (e); break; case R_ANAL_OP_TYPE_UCALL: case R_ANAL_OP_TYPE_CALL: ret = gb_call (e); break; case R_ANAL_OP_TYPE_CCALL: ret = gb_ccall (e); break; case R_ANAL_OP_TYPE_RET: ret = gb_ret (e); break; case R_ANAL_OP_TYPE_CRET: ret = gb_cret (e); break; case R_ANAL_OP_TYPE_CMP: ret = gb_cp (e); break; case R_ANAL_OP_TYPE_SUB: ret = gb_sub (e); break; case R_ANAL_OP_TYPE_ADD: ret = gb_add (e); break; case R_ANAL_OP_TYPE_XOR: ret = gb_xor (e); break; case R_ANAL_OP_TYPE_AND: ret = gb_and (e); break; case R_ANAL_OP_TYPE_OR: ret = gb_or (e); break; case R_ANAL_OP_TYPE_ACMP: ret = gb_bit (e); break; case R_ANAL_OP_TYPE_ROL: ret = gb_rol (e); break; case R_ANAL_OP_TYPE_STORE: ret = gb_store (e); break; case R_ANAL_OP_TYPE_LOAD: ret = gb_load (e); break; } gb_interrupts (e); cpu->cycles &= 0xffffff; //prevent overflows cpu->prev_cycles = cpu->cycles; return ret; }
R_API bool r_reg_set_value_by_role(RReg *reg, RRegisterId role, ut64 val) { // TODO use mapping from RRegisterId to RRegItem (via RRegSet) RRegItem *r = r_reg_get (reg, r_reg_get_name (reg, role), -1); return r_reg_set_value (reg, r, val); }
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; }
/* * Recoiling after a breakpoint has two stages: * 1. remove the breakpoint and fix the program counter. * 2. on resume, single step once and then replace the breakpoint. * * Thus, we have two functions to handle these situations. * r_debug_bp_hit handles stage 1. * r_debug_recoil handles stage 2. */ static int r_debug_bp_hit(RDebug *dbg, RRegItem *pc_ri, ut64 pc) { RBreakpointItem *b; /* if we are tracing, update the tracing data */ if (dbg->trace->enabled) { r_debug_trace_pc (dbg, pc); } /* remove all sw breakpoints for now. we'll set them back in stage 2 * * this is necessary because while stopped we don't want any breakpoints in * the code messing up our analysis. */ if (!r_bp_restore (dbg->bp, false)) { // unset sw breakpoints return false; } /* if we are recoiling, tell r_debug_step that we ignored a breakpoint * event */ if (!dbg->swstep && dbg->recoil_mode != R_DBG_RECOIL_NONE) { dbg->reason.bp_addr = 0; return true; } /* see if we really have a breakpoint here... */ b = r_bp_get_at (dbg->bp, pc - dbg->bpsize); if (!b) { /* we don't. nothing left to do */ return true; } /* set the pc value back */ pc -= b->size; if (!r_reg_set_value (dbg->reg, pc_ri, pc)) { eprintf ("failed to set PC!\n"); return false; } if (!r_debug_reg_sync (dbg, R_REG_TYPE_GPR, true)) { eprintf ("cannot set registers!\n"); return false; } /* if we are on a software stepping breakpoint, we hide what is going on... */ if (b->swstep) { dbg->reason.bp_addr = 0; return true; } /* setup our stage 2 */ dbg->reason.bp_addr = b->addr; /* inform the user of what happened */ eprintf ("hit %spoint at: %"PFMT64x "\n", b->trace ? "trace" : "break", pc); /* now that we've cleaned up after the breakpoint, call the other * potential breakpoint handlers */ if (dbg->corebind.core && dbg->corebind.bphit) { dbg->corebind.bphit (dbg->corebind.core, b); } /* XXX(jjd): i don't think this goes here... if (b->trace) { r_debug_step (dbg, 1); goto repeat; } */ return true; }