Add support for indexed breakpoint management

This commit is contained in:
pancake 2014-10-28 11:14:30 +01:00
parent e64f0458d3
commit ef35aaaa7e
5 changed files with 195 additions and 73 deletions

View File

@ -15,28 +15,24 @@ static void r_bp_item_free (RBreakpointItem *b) {
}
R_API RBreakpoint *r_bp_new() {
RBreakpoint *bp = R_NEW0 (RBreakpoint);
RBreakpointPlugin *static_plugin;
RBreakpoint *bp = R_NEW (RBreakpoint);
if (bp) {
int i;
bp->cur = NULL;
bp->nbps = 0;
bp->trace_bp = R_FALSE;
bp->stepcont = R_BP_CONT_NORMAL;
bp->breakpoint = NULL;
bp->endian = 0; // little by default
bp->traces = r_bp_traptrace_new ();
bp->printf = (PrintfCallback)printf;
bp->bps = r_list_newf ((RListFree)r_bp_item_free);
bp->plugins = r_list_newf ((RListFree)free);
for (i=0; bp_static_plugins[i]; i++) {
static_plugin = R_NEW (RBreakpointPlugin);
memcpy (static_plugin, bp_static_plugins[i],
sizeof (RBreakpointPlugin));
r_bp_plugin_add (bp, static_plugin);
}
memset (&bp->iob, 0, sizeof (bp->iob));
int i;
if (!bp) return NULL;
bp->bps_idx_count = 16;
bp->bps_idx = R_NEWS0 (RBreakpointItem*, bp->bps_idx_count);
bp->stepcont = R_BP_CONT_NORMAL;
bp->traces = r_bp_traptrace_new ();
bp->printf = (PrintfCallback)printf;
bp->bps = r_list_newf ((RListFree)r_bp_item_free);
bp->plugins = r_list_newf ((RListFree)free);
for (i=0; bp_static_plugins[i]; i++) {
static_plugin = R_NEW (RBreakpointPlugin);
memcpy (static_plugin, bp_static_plugins[i],
sizeof (RBreakpointPlugin));
r_bp_plugin_add (bp, static_plugin);
}
memset (&bp->iob, 0, sizeof (bp->iob));
return bp;
}
@ -96,13 +92,10 @@ R_API RBreakpointItem *r_bp_get_in(RBreakpoint *bp, ut64 addr, int rwx) {
}
R_API RBreakpointItem *r_bp_enable(RBreakpoint *bp, ut64 addr, int set) {
RListIter *iter;
RBreakpointItem *b;
r_list_foreach(bp->bps, iter, b) {
if (addr >= b->addr && addr <= b->addr+b->size) {
b->enabled = set;
return b;
}
RBreakpointItem *b = r_bp_get_in (bp, addr, 0);
if (b) {
b->enabled = set;
return b;
}
return NULL;
}
@ -116,17 +109,19 @@ R_API int r_bp_stepy_continuation(RBreakpoint *bp) {
static RBreakpointItem *r_bp_add(RBreakpoint *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx) {
int ret;
RBreakpointItem *b;
if (addr == UT64_MAX || size<1)
return NULL;
if (r_bp_get_in (bp, addr, rwx)) {
eprintf ("Breakpoint already set at this address.\n");
return NULL;
}
b = R_NEW0 (RBreakpointItem);
b = r_bp_item_new (bp);
b->addr = addr;
b->size = size;
b->enabled = R_TRUE;
b->hw = hw;
if (!hw) {
b->bbytes = malloc (size+16);
b->bbytes = calloc (size+16, 1);
if (obytes) {
b->obytes = malloc (size);
memcpy (b->obytes, obytes, size);
@ -151,7 +146,7 @@ R_API int r_bp_add_fault(RBreakpoint *bp, ut64 addr, int size, int rwx) {
return R_FALSE;
}
R_API RBreakpoint* r_bp_add_sw(RBreakpoint *bp, ut64 addr, int size, int rwx) {
R_API RBreakpointItem* r_bp_add_sw(RBreakpoint *bp, ut64 addr, int size, int rwx) {
RBreakpointItem *item;
ut8 *bytes;
if (size<1)
@ -191,31 +186,15 @@ R_API int r_bp_del(RBreakpoint *bp, ut64 addr) {
return R_FALSE;
}
// TODO: rename or drop?
// TODO: use a r_bp_item instead of address
// TODO: we can just drop it.. its just b->trace = R_TRUE or so..
R_API int r_bp_set_trace(RBreakpoint *bp, ut64 addr, int set) {
RListIter *iter;
RBreakpointItem *b;
r_list_foreach (bp->bps, iter, b) {
if (addr >= b->addr && addr <= b->addr+b->size) {
b->trace = set;
return R_TRUE;
}
RBreakpointItem *b = r_bp_get_in (bp, addr, 0);
if (b) {
b->trace = set;
return R_TRUE;
}
return R_FALSE;
}
#if 0
// TODO: rename or remove
R_API int r_bp_set_trace_bp(RBreakpoint *bp, ut64 addr, int set)
{
bp->trace_all = set;
bp->trace_bp = addr;
return R_TRUE;
}
#endif
// TODO: deprecate
R_API int r_bp_list(RBreakpoint *bp, int rad) {
int n = 0;
@ -237,3 +216,37 @@ R_API int r_bp_list(RBreakpoint *bp, int rad) {
}
return n;
}
R_API RBreakpointItem *r_bp_item_new (RBreakpoint *bp) {
int i, j;
/* find empty slot */
for (i=0; i<bp->bps_idx_count; i++) {
if (!bp->bps_idx[i]) {
goto return_slot;
}
}
/* allocate new slot */
bp->bps_idx_count += 16; // alocate space for 16 more bps
bp->bps_idx = realloc (bp->bps_idx, bp->bps_idx_count*sizeof(RBreakpointItem*));
for (j=i;j<bp->bps_idx_count;j++)
bp->bps_idx[j] = NULL;
return_slot:
/* empty slot */
return (bp->bps_idx[i] = R_NEW0 (RBreakpointItem));
}
R_API RBreakpointItem *r_bp_get_index(RBreakpoint *bp, int idx) {
if (idx>=0 && idx<bp->bps_idx_count)
return bp->bps_idx[idx];
return NULL;
}
R_API int r_bp_del_index(RBreakpoint *bp, int idx) {
if (idx>=0 && idx<bp->bps_idx_count) {
r_list_delete_data (bp->bps, bp->bps_idx[idx]);
free (bp->bps_idx[idx]);
bp->bps_idx[idx] = NULL;
return R_TRUE;
}
return R_FALSE;
}

View File

@ -877,18 +877,47 @@ static void r_core_cmd_bp(RCore *core, const char *input) {
const char *p;
RList *list;
ut64 addr;
p = strchr (input, ' ');
if (p) {
addr = r_num_math (core->num, p+1);
} else addr = 0;
switch (input[1]) {
case 't':
addr = UT64_MAX;
if (input[2]==' ' && input[3])
addr = r_num_math (core->num, input+2);
i = 0;
list = r_debug_frames (core->dbg, addr);
r_list_foreach (list, iter, frame) {
r_cons_printf ("%d 0x%08"PFMT64x" %d\n",
i++, frame->addr, frame->size);
switch (input[2]) {
case 'e':
if (!r_bp_set_trace (core->dbg->bp, addr, R_TRUE))
eprintf ("Cannot set tracepoint\n");
break;
case 'd':
if (!r_bp_set_trace (core->dbg->bp, addr, R_FALSE))
eprintf ("Cannot unset tracepoint\n");
break;
case 's':
{
RBreakpointItem *bpi = r_bp_get_at (core->dbg->bp, addr);
if (bpi) {
bpi->trace = !!!bpi->trace;
} else {
eprintf ("Cannot unset tracepoint\n");
}
}
break;
case 0:
addr = UT64_MAX;
if (input[2]==' ' && input[3])
addr = r_num_math (core->num, input+2);
i = 0;
list = r_debug_frames (core->dbg, addr);
r_list_foreach (list, iter, frame) {
r_cons_printf ("%d 0x%08"PFMT64x" %d\n",
i++, frame->addr, frame->size);
}
r_list_purge (list);
break;
default:
eprintf ("See db?\n");
break;
}
r_list_purge (list);
break;
case '*': r_bp_list (core->dbg->bp, 1); break;
case '\0': r_bp_list (core->dbg->bp, 0); break;
@ -951,6 +980,68 @@ static void r_core_cmd_bp(RCore *core, const char *input) {
} else eprintf ("Can't place a breakpoint here. No mapped memory\n");
}
break;
case 'i':
switch (input[2]) {
case 0: // "dbi"
{
int i = 0;
for (i=0;i<core->dbg->bp->bps_idx_count;i++) {
RBreakpointItem *bpi = core->dbg->bp->bps_idx[i];
if (bpi) {
r_cons_printf ("%d 0x%08"PFMT64x" E:%d T:%d\n",
i, bpi->addr, bpi->enabled, bpi->trace);
}
}
}
break;
case 'e': // "dbie"
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->enabled = R_FALSE; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
case 'd': // "dbid"
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->enabled = R_FALSE; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
case 's': // "dbis"
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->enabled = !!!bpi->enabled; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
case 't': // "dbite" "dbitd" ...
switch (input[3]) {
case 'e':
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->trace = R_TRUE; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
case 'd':
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->trace = R_FALSE; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
case 's':
{
RBreakpointItem *bpi = r_bp_get_index (core->dbg->bp, addr);
if (bpi) { bpi->trace = !!!bpi->trace; }
else { eprintf ("Cannot unset tracepoint\n"); }
}
break;
}
break;
}
break;
case '?':
default:{
const char* help_msg[] = {
@ -963,8 +1054,21 @@ static void r_core_cmd_bp(RCore *core, const char *input) {
"dbc", " <address> <cmd>", "Run command when breakpoint is hit",
"dbd", " <address>", "Disable breakpoint",
"dbe", " <address>", "Enable breakpoint",
"dbs", " <address>", "Toggle breakpoint",
"dbte", " <address>", "Enable Breakpoint Trace",
"dbtd", " <address>", "Disable Breakpoint Trace",
"dbts", " <address>", "Swap Breakpoint Trace",
//
"dbi", "", "List breakpoint indexes",
"dbie", " <index>", "Enable breakpoint by index",
"dbid", " <index>", "Disable breakpoint by index",
"dbis", " <index>", "Swap Nth breakpoint",
"dbite", " <index>", "Enable breakpoint Trace by index",
"dbitd", " <index>", "Disable breakpoint Trace by index",
"dbits", " <index>", "Swap Nth breakpoint trace",
//
"dbh", " x86", "Set/list breakpoint plugin handlers",
"dbs", " <address>", "Toggle breakpoint\n",
NULL};
r_core_cmd_help (core, help_msg);
}

View File

@ -564,8 +564,8 @@ static char *getbitfield(void *_core, const char *name, ut64 val) {
// TODO: return string instead of printing it. reuse from 'drr'
R_API const char *r_core_anal_hasrefs(RCore *core, ut64 value) {
ut64 type;
int bits = core->assembler->bits;
RList *list = r_reg_get_list (core->dbg->reg, R_REG_TYPE_GPR);
//int bits = core->assembler->bits;
//RList *list = r_reg_get_list (core->dbg->reg, R_REG_TYPE_GPR);
RAnalFunction *fcn;
RFlagItem *fi;
fi = r_flag_get_i (core->flags, value);

View File

@ -57,19 +57,20 @@ typedef struct r_bp_item_t {
} RBreakpointItem;
typedef struct r_bp_t {
int trace_all;
ut64 trace_bp;
int nbps;
void *user;
int stepcont;
int endian;
RIOBind iob; // compile time dependency
RBreakpointPlugin *cur;
RList *bps;
RList *traces;
RList *traces; // XXX
RList *plugins;
PrintfCallback printf;
RBreakpointCallback breakpoint;
void *user;
/* storage of breakpoints */
int nbps;
RList *bps; // list of breakpoints
RBreakpointItem **bps_idx;
int bps_idx_count;
} RBreakpoint;
enum {
@ -103,13 +104,17 @@ R_API void r_bp_plugin_list(RBreakpoint *bp);
R_API int r_bp_in(RBreakpoint *bp, ut64 addr, int rwx);
// deprecate?
R_API int r_bp_list(RBreakpoint *bp, int rad);
/* bp item attribs setters */
R_API int r_bp_get_bytes(RBreakpoint *bp, ut8 *buf, int len, int endian, int idx);
R_API int r_bp_set_trace(RBreakpoint *bp, ut64 addr, int set);
// deprecate and use r_bp_get_at/->trace ?
//R_API int r_bp_set_trace_bp(RBreakpoint *bp, ut64 addr, int set);
R_API RBreakpointItem *r_bp_enable(RBreakpoint *bp, ut64 addr, int set);
/* index api */
R_API int r_bp_del_index(RBreakpoint *bp, int idx);
R_API RBreakpointItem *r_bp_get_index(RBreakpoint *bp, int idx);
R_API RBreakpointItem *r_bp_item_new (RBreakpoint *bp);
R_API RBreakpointItem *r_bp_get_at (RBreakpoint *bp, ut64 addr);
R_API RBreakpointItem *r_bp_get_in (RBreakpoint *bp, ut64 addr, int rwx);

View File

@ -176,10 +176,10 @@ typedef void (*PrintfCallback)(const char *str, ...);
#define BITS2BYTES(x) (((x)/8)+(((x)%8)?1:0))
#define ZERO_FILL(x) memset (&x, 0, sizeof (x))
#define R_NEWS0(x,y) (x*)memset (malloc(sizeof(x)*y), 0, sizeof(x)*y);
#define R_NEWS0(x,y) (x*)calloc(sizeof(x),y)
#define R_NEWS(x,y) (x*)malloc(sizeof(x)*y)
#define R_NEW(x) (x*)malloc(sizeof(x))
#define R_NEW0(x) (x*)calloc(1,sizeof(x))
#define R_NEW(x) (x*)malloc(sizeof(x))
// TODO: Make R_NEW_COPY be 1 arg, not two
#define R_NEW_COPY(x,y) x=(void*)malloc(sizeof(y));memcpy(x,y,sizeof(y))
#define IS_PRINTABLE(x) (x>=' '&&x<='~')