/* * 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); }
static int r_debug_wind_reg_read (RDebug *dbg, int type, ut8 *buf, int size) { (void)type; int ret = wind_read_reg(wctx, buf, size); if (!ret || size != ret) return -1; r_reg_set_bytes (dbg->reg, R_REG_TYPE_ALL, buf, ret); // Report as if no register has been written as we've already updated the arena here return 0; }
R_API int r_debug_reg_sync(RDebug *dbg, int type, int write) { int i, size; if (!dbg || !dbg->reg || !dbg->h) return R_FALSE; // Theres no point in syncing a dead target if (r_debug_is_dead (dbg)) return R_FALSE; // Check if the functions needed are available if (write && !dbg->h->reg_write) return R_FALSE; if (!write && !dbg->h->reg_read) return R_FALSE; // Sync all the types sequentially if asked i = (type == R_REG_TYPE_ALL) ? R_REG_TYPE_GPR : type; do { if (write) { ut8 *buf = r_reg_get_bytes (dbg->reg, i, &size); if (!buf || !dbg->h->reg_write (dbg, i, buf, size)) { if (i==0) eprintf ("r_debug_reg: error writing registers %d to %d\n", i, dbg->pid); return R_FALSE; } } else { //int bufsize = R_MAX (1024, dbg->reg->size*2); // i know. its hacky int bufsize = dbg->reg->size; ut8 *buf = malloc (bufsize); if (!buf) return R_FALSE; //we have already checked dbg->h and dbg->h->reg_read above size = dbg->h->reg_read (dbg, i, buf, bufsize); // we need to check against zero because reg_read can return R_FALSE if (!size) { eprintf ("r_debug_reg: error reading registers\n"); free (buf); return R_FALSE; } else r_reg_set_bytes (dbg->reg, i, buf, R_MIN(size, bufsize)); free (buf); } // DO NOT BREAK R_REG_TYPE_ALL PLEASE // break; // Continue the syncronization or just stop if it was asked only for a single type of regs } while ((type==R_REG_TYPE_ALL) && (i++ < R_REG_TYPE_LAST)); return R_TRUE; }
R_API int r_debug_reg_sync(RDebug *dbg, int type, int write) { int i, size; if (!dbg || !dbg->reg || !dbg->h) return R_FALSE; // Theres no point in syncing a dead target if (r_debug_is_dead(dbg)) return R_FALSE; // Check if the functions needed are available if (write && !dbg->h->reg_write) return R_FALSE; if (!write && !dbg->h->reg_read) return R_FALSE; // Sync all the types sequentially if asked i = (type == R_REG_TYPE_ALL) ? R_REG_TYPE_GPR : type; do { if (write) { ut8 *buf = r_reg_get_bytes (dbg->reg, i, &size); if (!buf || !dbg->h->reg_write (dbg, i, buf, size)) { eprintf ("r_debug_reg: error writing registers\n"); return R_FALSE; } } else { // TODO : Get an exact size of the profile ut8 buf[2048]; size = dbg->h->reg_read (dbg, i, buf, sizeof (buf)); if (!size) { eprintf ("r_debug_reg: error reading registers\n"); return R_FALSE; } r_reg_set_bytes (dbg->reg, i, buf, size); } // Continue the syncronization or just stop if it was asked only for a single type of regs } while(i++ < R_REG_TYPE_LAST && type != R_REG_TYPE_ALL); return R_TRUE; }
R_API int r_debug_reg_sync(RDebug *dbg, int type, int write) { ut8 buf[4096]; // XXX hacky! int next, size, ret = R_FALSE; if (!dbg || !dbg->reg || dbg->pid == -1) return R_FALSE; if (type == -1) { type = R_REG_TYPE_GPR; next = R_REG_TYPE_DRX; } else next = 0; repeat: if (write) { if (dbg && dbg->h && dbg->h->reg_write) { ut8 *buf = r_reg_get_bytes (dbg->reg, type, &size); if (!dbg->h->reg_write (dbg, type, buf, sizeof (buf))) eprintf ("r_debug_reg: error writing registers\n"); else ret = R_TRUE; } //else eprintf ("r_debug_reg: cannot set registers\n"); } else { /* read registers from debugger backend to dbg->regs */ if (dbg && dbg->h && dbg->h->reg_read) { size = dbg->h->reg_read (dbg, type, buf, sizeof (buf)); if (size == 0) { eprintf ("r_debug_reg: error reading registers pid=%d\n", dbg->pid); } else { ret = r_reg_set_bytes (dbg->reg, type, buf, size); } } //else eprintf ("r_debug_reg: cannot read registers\n"); } if (next) { type = next; switch (next) { case R_REG_TYPE_FPU: next = R_REG_TYPE_DRX; break; case R_REG_TYPE_DRX: next = 0; break; default: next = 0; break; } goto repeat; } return ret; }
R_API int r_debug_reg_sync(RDebug *dbg, int type, int write) { int i, n, size; if (!dbg || !dbg->reg || !dbg->h) { return false; } // Theres no point in syncing a dead target if (r_debug_is_dead (dbg)) { return false; } // Check if the functions needed are available if (write && !dbg->h->reg_write) { return false; } if (!write && !dbg->h->reg_read) { return false; } // Sync all the types sequentially if asked i = (type == R_REG_TYPE_ALL)? R_REG_TYPE_GPR: type; // Check to get the correct arena when using @ into reg profile (arena!=type) // if request type is positive and the request regset dont have regs if (i >= R_REG_TYPE_GPR && dbg->reg->regset[i].regs && !dbg->reg->regset[i].regs->length) { // seek into the other arena for redirections. for (n = R_REG_TYPE_GPR; n < R_REG_TYPE_LAST; n++) { // get regset mask int mask = dbg->reg->regset[n].maskregstype; // convert request arena to mask value int v = ((int)1 << i); // skip checks on same request arena and check if this arena have inside the request arena type if (n != i && (mask & v)) { //eprintf(" req = %i arena = %i mask = %x search = %x \n", i, n, mask, v); //eprintf(" request arena %i found at arena %i\n", i, n ); // if this arena have the request arena type, force to use this arena. i = n; break; } } } do { if (write) { ut8 *buf = r_reg_get_bytes (dbg->reg, i, &size); if (!buf || !dbg->h->reg_write (dbg, i, buf, size)) { if (!i) { eprintf ("r_debug_reg: error writing " "registers %d to %d\n", i, dbg->tid); } free (buf); return false; } free (buf); } else { // int bufsize = R_MAX (1024, dbg->reg->size*2); // i know. its hacky int bufsize = dbg->reg->size; //int bufsize = dbg->reg->regset[i].arena->size; if (bufsize > 0) { ut8 *buf = calloc (1 + 1, bufsize); if (!buf) { return false; } //we have already checked dbg->h and dbg->h->reg_read above size = dbg->h->reg_read (dbg, i, buf, bufsize); // we need to check against zero because reg_read can return false if (size > 0) { r_reg_set_bytes (dbg->reg, i, buf, size); //R_MIN (size, bufsize)); // free (buf); // return true; } free (buf); } } // DO NOT BREAK R_REG_TYPE_ALL PLEASE // break; // Continue the syncronization or just stop if it was asked only for a single type of regs i++; } while ((type == R_REG_TYPE_ALL) && (i < R_REG_TYPE_LAST)); return true; }