mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-28 01:56:12 +00:00
Add support for indexed breakpoint management
This commit is contained in:
parent
e64f0458d3
commit
ef35aaaa7e
113
libr/bp/bp.c
113
libr/bp/bp.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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<='~')
|
||||
|
Loading…
x
Reference in New Issue
Block a user