rizin/libr/debug/p/debug_gdb.c
pancake a2ebdcb650 Fix memleaks, nullref and undef (clang-analyzer)
Fix multiple inclusions of mk files
2012-08-08 17:19:48 +02:00

261 lines
6.1 KiB
C

/* radare - LGPL - Copyright 2009-2012 - pancake */
#include <r_asm.h>
#include <r_debug.h>
#include "libgdbwrap/include/gdbwrapper.h"
#include "libgdbwrap/gdbwrapper.c"
/* XXX: hacky copypasta from io/p/io_gdb */
typedef struct {
RSocket *fd;
gdbwrap_t *desc;
} RIOGdb;
#define RIOGDB_FD(x) (((RIOGdb*)(x))->fd)
#define RIOGDB_DESC(x) (((RIOGdb*)(x->data))->desc)
#define RIOGDB_IS_VALID(x) (x && x->plugin==&r_io_plugin_gdb && x->data)
#define NUM_REGS 28
#define UNKNOWN -1
#define UNSUPPORTED 0
#define SUPPORTED 1
/* TODO: The IO stuff must be communicated with the r_dbg */
/* a transplant sometimes requires to change the IO */
/* so, for here, we need r_io_plugin_gdb */
/* TODO: rename to gdbwrap? */
static gdbwrap_t *desc = NULL;
static int support_sw_bp = UNKNOWN;
static int support_hw_bp = UNKNOWN;
static int r_debug_gdb_step(RDebug *dbg) {
gdbwrap_stepi (desc);
return R_TRUE;
}
static int r_debug_gdb_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
gdbwrap_readgenreg (desc);
if (!desc)
return R_FALSE;
gdbwrap_getreg_buffer (desc, buf, desc->reg_size*desc->num_registers);
return desc->num_registers*desc->reg_size;
}
static int r_debug_gdb_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) {
gdbwrap_setreg_buffer (desc, buf, desc->reg_size*desc->num_registers);
gdbwrap_shipallreg (desc);
return R_TRUE; // XXX Error check
}
static int r_debug_gdb_continue(RDebug *dbg, int pid, int tid, int sig) {
gdbwrap_continue (desc);
return R_TRUE;
}
static int r_debug_gdb_wait(RDebug *dbg, int pid) {
/* do nothing */
return R_TRUE;
}
static int r_debug_gdb_attach(RDebug *dbg, int pid) {
// XXX TODO PID must be a socket here !!1
RIODesc *d = dbg->iob.io->fd;
if (d && d->plugin && d->plugin->name && d->data) {
if (!strcmp ("gdb", d->plugin->name)) {
RIOGdb *g = d->data;
support_sw_bp = UNKNOWN;
support_hw_bp = UNKNOWN;
if (( desc = g->desc ))
switch (dbg->arch) {
case R_SYS_ARCH_X86:
//TODO Support x86_64
//9 32bit regs for x86
desc->num_registers = 9;
desc->reg_size = 4;
break;
case R_SYS_ARCH_SH:
//28 32bit regs for sh4
desc->num_registers = 28;
desc->reg_size = 4;
break;
case R_SYS_ARCH_ARM:
//TODO Check ARM stubs and fill in
desc->num_registers = 25;
desc->reg_size = 4;
break;
}
//eprintf ("SUCCESS: gdb attach with inferior gdb rio worked\n");
} else {
eprintf ("ERROR: Underlaying IO descriptor is not a GDB one..\n");
}
}
return R_TRUE;
}
static int r_debug_gdb_detach(int pid) {
// XXX TODO PID must be a socket here !!1
// close (pid);
//XXX Maybe we should continue here?
return R_TRUE;
}
static const char *r_debug_gdb_reg_profile(RDebug *dbg) {
int arch = dbg->arch;
switch (arch) {
case R_SYS_ARCH_X86:
case R_SYS_ARCH_ARM:
case R_SYS_ARCH_SH:
break;
default:
arch = r_sys_arch_id (R_SYS_ARCH);
break;
}
switch (arch) {
case R_SYS_ARCH_X86:
return strdup (
"=pc eip\n"
"=sp esp\n"
"=bp ebp\n"
"=a0 eax\n"
"=a1 ebx\n"
"=a2 ecx\n"
"=a3 edi\n"
"gpr eax .32 0 0\n"
"gpr ecx .32 4 0\n"
"gpr edx .32 8 0\n"
"gpr ebx .32 12 0\n"
"gpr esp .32 16 0\n"
"gpr ebp .32 20 0\n"
"gpr esi .32 24 0\n"
"gpr edi .32 28 0\n"
"gpr eip .32 32 0\n"
"gpr eflags .32 36 0\n"
"seg cs .32 40 0\n"
"seg ss .32 44 0\n"
"seg ds .32 48 0\n"
"seg es .32 52 0\n"
"seg fs .32 56 0\n"
"seg gs .32 60 0\n"
);
case R_SYS_ARCH_ARM:
return strdup (
"=pc r15\n"
"=sp r14\n" // XXX
"=a0 r0\n"
"=a1 r1\n"
"=a2 r2\n"
"=a3 r3\n"
"gpr lr .32 56 0\n" // r14
"gpr pc .32 60 0\n" // r15
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr f0 .32 64 0\n"
"gpr f1 .32 68 0\n"
"gpr f2 .32 72 0\n"
"gpr f3 .32 76 0\n"
"gpr f4 .32 80 0\n"
"gpr f5 .32 84 0\n"
"gpr f6 .32 88 0\n"
"gpr f7 .32 92 0\n"
"gpr fps .32 96 0\n"
"gpr cpsr .32 100 0\n"
);
case R_SYS_ARCH_SH:
return strdup (
"=pc pc\n"
"=sp r15\n"
"=bp r14\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr pc .32 64 0\n"
"gpr pr .32 68 0\n"
"gpr sr .32 72 0\n"
"gpr gbr .32 76 0\n"
"gpr mach .32 80 0\n"
"gpr macl .32 84 0\n"
);
}
return NULL;
}
static int r_debug_gdb_breakpoint (void *user, int type, ut64 addr, int hw, int rwx){
if (hw && support_hw_bp!=UNSUPPORTED) {
//TODO Implement gdb hw breakpoint
support_hw_bp = UNSUPPORTED;
return R_FALSE;
}
if (!hw && support_sw_bp!=UNSUPPORTED){
if(!type && gdbwrap_simplesetbp(desc,addr)){
support_sw_bp = SUPPORTED;
return R_TRUE;
} else if (type) {
gdbwrap_simpledelbp(desc,addr);
return R_TRUE;
} else {
support_sw_bp = UNSUPPORTED;
return R_FALSE;
}
return support_sw_bp;
}
return R_FALSE;
}
struct r_debug_plugin_t r_debug_plugin_gdb = {
.name = "gdb",
/* TODO: Add support for more architectures here */
.arch = R_SYS_ARCH_X86 | R_SYS_ARCH_ARM | R_SYS_ARCH_SH,
.bits = R_SYS_BITS_32,
.init = NULL,
.step = r_debug_gdb_step,
.cont = r_debug_gdb_continue,
.attach = &r_debug_gdb_attach,
.detach = &r_debug_gdb_detach,
.wait = &r_debug_gdb_wait,
.pids = NULL,
.tids = NULL,
.threads = NULL,
.kill = NULL,
.frames = NULL,
.map_get = NULL,
.breakpoint = &r_debug_gdb_breakpoint,
.reg_read = &r_debug_gdb_reg_read,
.reg_write = &r_debug_gdb_reg_write,
.reg_profile = (void *)r_debug_gdb_reg_profile,
//.bp_write = &r_debug_gdb_bp_write,
//.bp_read = &r_debug_gdb_bp_read,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_DBG,
.data = &r_debug_plugin_gdb
};
#endif