2011-02-04 10:30:08 +00:00
|
|
|
/* radare2 - LGPL - Copyright 2009-2011 pancake<nopcode.org> */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
#include <r_bp.h>
|
2009-04-13 22:47:02 +00:00
|
|
|
#include "../config.h"
|
|
|
|
|
2010-05-25 23:42:22 +00:00
|
|
|
static struct r_bp_plugin_t *bp_static_plugins[] =
|
2009-04-13 22:47:02 +00:00
|
|
|
{ R_BP_STATIC_PLUGINS };
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-05-20 15:40:58 +00:00
|
|
|
R_API RBreakpoint *r_bp_new() {
|
2010-05-28 00:44:51 +00:00
|
|
|
RBreakpointPlugin *static_plugin;
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpoint *bp = R_NEW (RBreakpoint);
|
2010-01-21 01:38:52 +00:00
|
|
|
if (bp) {
|
2010-06-29 23:13:09 +00:00
|
|
|
int i;
|
2010-01-21 01:38:52 +00:00
|
|
|
bp->cur = NULL;
|
|
|
|
bp->nbps = 0;
|
2010-03-03 01:41:41 +00:00
|
|
|
bp->trace_bp = R_FALSE;
|
2010-01-21 01:38:52 +00:00
|
|
|
bp->stepcont = R_BP_CONT_NORMAL;
|
|
|
|
bp->breakpoint = NULL;
|
2010-03-03 01:41:41 +00:00
|
|
|
bp->endian = 0; // little by default
|
|
|
|
bp->traces = r_bp_traptrace_new ();
|
2010-06-29 23:13:09 +00:00
|
|
|
bp->printf = (PrintfCallback)printf;
|
|
|
|
bp->bps = r_list_new ();
|
|
|
|
bp->plugins = r_list_new ();
|
2010-05-28 00:44:51 +00:00
|
|
|
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);
|
|
|
|
}
|
2010-06-29 23:13:09 +00:00
|
|
|
memset (&bp->iob, 0, sizeof (bp->iob));
|
2010-01-21 01:38:52 +00:00
|
|
|
}
|
|
|
|
return bp;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API RBreakpoint *r_bp_free(RBreakpoint *bp) {
|
2009-09-13 22:37:28 +00:00
|
|
|
/* XXX : properly destroy bp list */
|
2010-01-21 01:38:52 +00:00
|
|
|
free (bp);
|
2009-09-13 22:37:28 +00:00
|
|
|
return NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_get_bytes(RBreakpoint *bp, ut8 *buf, int len, int endian, int idx) {
|
2009-04-12 22:46:44 +00:00
|
|
|
int i;
|
|
|
|
struct r_bp_arch_t *b;
|
|
|
|
if (bp->cur) {
|
|
|
|
/* XXX: can be buggy huh : infinite loop is possible */
|
2010-03-03 12:34:38 +00:00
|
|
|
for (i=0; 1; i++) {
|
2009-04-12 22:46:44 +00:00
|
|
|
b = &bp->cur->bps[i%bp->cur->nbps];
|
2009-04-12 23:10:22 +00:00
|
|
|
if (b->endian == endian && idx%(i+1)==0) {
|
2010-03-03 12:34:38 +00:00
|
|
|
for (i=0; i<len;) {
|
|
|
|
memcpy (buf+i, b->bytes, b->length);
|
2009-04-12 22:46:44 +00:00
|
|
|
i += b->length;
|
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
return b->length;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
return 0;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
|
2010-07-12 23:20:57 +00:00
|
|
|
R_API RBreakpointItem *r_bp_get(RBreakpoint *bp, ut64 addr) {
|
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointItem *b;
|
|
|
|
r_list_foreach(bp->bps, iter, b)
|
|
|
|
if (b->addr == addr)
|
|
|
|
return b;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-03-02 23:13:22 +00:00
|
|
|
R_API RBreakpointItem *r_bp_at_addr(RBreakpoint *bp, ut64 addr, int rwx) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpointItem *b;
|
2011-05-11 18:08:19 +00:00
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (bp->bps, iter, b) {
|
|
|
|
// eprintf ("---ataddr--- 0x%08"PFMT64x" %d %d %x\n", b->addr, b->size, b->recoil, b->rwx);
|
|
|
|
//Check addr within range and provided rwx matches (or null)
|
|
|
|
if (addr>=b->addr && addr<=(b->addr+b->size) && (!rwx || rwx&b->rwx))
|
2010-01-21 01:38:52 +00:00
|
|
|
return b;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
return NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API struct r_bp_item_t *r_bp_enable(RBreakpoint *bp, ut64 addr, int set) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointItem *b;
|
|
|
|
r_list_foreach(bp->bps, iter, b) {
|
2009-04-12 22:46:44 +00:00
|
|
|
if (addr >= b->addr && addr <= b->addr+b->size) {
|
|
|
|
b->enabled = set;
|
2009-04-15 10:01:12 +00:00
|
|
|
return b;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-15 10:01:12 +00:00
|
|
|
return NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_stepy_continuation(RBreakpoint *bp) {
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: implement
|
|
|
|
return bp->stepcont;
|
|
|
|
}
|
|
|
|
|
2009-04-12 22:46:44 +00:00
|
|
|
/* TODO: detect overlapping of breakpoints */
|
2010-03-03 01:41:41 +00:00
|
|
|
static RBreakpointItem *r_bp_add(RBreakpoint *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx) {
|
2009-04-12 22:46:44 +00:00
|
|
|
int ret;
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpointItem *b;
|
2010-01-21 01:38:52 +00:00
|
|
|
if (r_bp_at_addr (bp, addr, rwx)) {
|
|
|
|
eprintf ("Breakpoint already set at this address.\n");
|
2009-04-12 22:46:44 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-01-22 04:06:12 +00:00
|
|
|
b = R_NEW (RBreakpointItem);
|
2009-04-12 22:46:44 +00:00
|
|
|
b->pids[0] = 0; /* for any pid */
|
|
|
|
b->addr = addr;
|
2010-07-12 23:20:57 +00:00
|
|
|
b->data = NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
b->size = size;
|
2009-09-13 22:37:28 +00:00
|
|
|
b->enabled = R_TRUE;
|
2009-04-12 22:46:44 +00:00
|
|
|
b->hw = hw;
|
|
|
|
b->trace = 0;
|
2010-01-21 01:38:52 +00:00
|
|
|
|
|
|
|
if (hw) {
|
|
|
|
b->bbytes = NULL;
|
|
|
|
b->obytes = NULL;
|
|
|
|
b->recoil = 0;
|
|
|
|
} else {
|
|
|
|
b->bbytes = malloc (size+16);
|
|
|
|
if (obytes) {
|
2010-06-29 23:13:09 +00:00
|
|
|
b->obytes = malloc (size);
|
2010-01-21 01:38:52 +00:00
|
|
|
memcpy (b->obytes, obytes, size);
|
|
|
|
} else b->obytes = NULL;
|
|
|
|
/* XXX: endian .. use bp->endian */
|
|
|
|
// XXX for hw breakpoints there are no bytes
|
|
|
|
ret = r_bp_get_bytes (bp, b->bbytes, size, 0, 0);
|
|
|
|
if (ret == 0) {
|
|
|
|
eprintf ("Cannot get breakpoint bytes. No r_bp_use()?\n");
|
|
|
|
free (b->obytes);
|
|
|
|
free (b->bbytes);
|
|
|
|
free (b);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
b->recoil = ret;
|
|
|
|
}
|
|
|
|
|
2009-04-12 22:46:44 +00:00
|
|
|
bp->nbps++;
|
2010-06-29 23:13:09 +00:00
|
|
|
r_list_append (bp->bps, b);
|
2009-04-12 22:46:44 +00:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_add_fault(RBreakpoint *bp, ut64 addr, int size, int rwx) {
|
2009-12-24 02:17:53 +00:00
|
|
|
// TODO
|
2010-01-04 00:25:52 +00:00
|
|
|
return R_FALSE;
|
2009-12-24 02:17:53 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API struct r_bp_item_t *r_bp_add_sw(RBreakpoint *bp, ut64 addr, int size, int rwx) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpointItem *item;
|
2009-09-13 22:37:28 +00:00
|
|
|
ut8 *bytes;
|
2010-01-21 01:38:52 +00:00
|
|
|
if (size<1)
|
|
|
|
size = 1;
|
|
|
|
bytes = malloc (size);
|
2009-09-13 22:37:28 +00:00
|
|
|
if (bytes == NULL)
|
|
|
|
return NULL;
|
2010-03-03 12:34:38 +00:00
|
|
|
if (bp->iob.read_at)
|
2010-01-21 01:38:52 +00:00
|
|
|
bp->iob.read_at (bp->iob.io, addr, bytes, size);
|
2010-03-03 12:34:38 +00:00
|
|
|
else memset (bytes, 0, size);
|
2010-01-21 01:38:52 +00:00
|
|
|
item = r_bp_add (bp, bytes, addr, size, R_BP_TYPE_SW, rwx);
|
|
|
|
free (bytes);
|
2009-09-13 22:37:28 +00:00
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API struct r_bp_item_t *r_bp_add_hw(RBreakpoint *bp, ut64 addr, int size, int rwx) {
|
2010-01-21 01:38:52 +00:00
|
|
|
return r_bp_add (bp, NULL, addr, size, R_BP_TYPE_HW, rwx);
|
2009-09-13 22:37:28 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_del(RBreakpoint *bp, ut64 addr) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointItem *b;
|
2012-02-14 17:10:52 +00:00
|
|
|
/* No _safe loop necessary because we return immediately after the delete. */
|
2010-06-29 23:13:09 +00:00
|
|
|
r_list_foreach (bp->bps, iter, b) {
|
2009-04-12 22:46:44 +00:00
|
|
|
if (b->addr == addr) {
|
2010-06-29 23:13:09 +00:00
|
|
|
r_list_delete (bp->bps, iter);
|
2009-04-12 22:46:44 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
2009-04-11 21:22:20 +00:00
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: rename or drop?
|
2010-01-21 01:38:52 +00:00
|
|
|
// TODO: use a r_bp_item instead of address
|
|
|
|
// TODO: we can just drop it.. its just b->trace = R_TRUE or so..
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_set_trace(RBreakpoint *bp, ut64 addr, int set) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointItem *b;
|
|
|
|
r_list_foreach (bp->bps, iter, b) {
|
2009-09-13 22:37:28 +00:00
|
|
|
if (addr >= b->addr && addr <= b->addr+b->size) {
|
|
|
|
b->trace = set;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-04-15 10:01:12 +00:00
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
return R_FALSE;
|
2009-09-13 22:37:28 +00:00
|
|
|
}
|
|
|
|
|
2010-01-21 01:38:52 +00:00
|
|
|
#if 0
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: rename or remove
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_set_trace_bp(RBreakpoint *bp, ut64 addr, int set)
|
2009-09-13 22:37:28 +00:00
|
|
|
{
|
|
|
|
bp->trace_all = set;
|
|
|
|
bp->trace_bp = addr;
|
|
|
|
return R_TRUE;
|
2009-04-15 10:01:12 +00:00
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
#endif
|
2009-04-15 10:01:12 +00:00
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: deprecate
|
2010-03-03 12:34:38 +00:00
|
|
|
R_API int r_bp_list(RBreakpoint *bp, int rad) {
|
2009-09-13 22:37:28 +00:00
|
|
|
int n = 0;
|
2010-06-29 23:13:09 +00:00
|
|
|
RBreakpointItem *b;
|
|
|
|
RListIter *iter;
|
2012-02-27 02:07:32 +00:00
|
|
|
//eprintf ("Breakpoint list:\n");
|
2010-06-29 23:13:09 +00:00
|
|
|
r_list_foreach (bp->bps, iter, b) {
|
2011-06-20 22:50:07 +00:00
|
|
|
bp->printf ("0x%08"PFMT64x" - 0x%08"PFMT64x" %d %c%c%c %s %s %s cmd=\"%s\"\n",
|
2009-04-12 22:46:44 +00:00
|
|
|
b->addr, b->addr+b->size, b->size,
|
2011-06-20 22:50:07 +00:00
|
|
|
(b->rwx & R_BP_PROT_READ)? 'r': '-',
|
|
|
|
(b->rwx & R_BP_PROT_WRITE)? 'w': '-',
|
|
|
|
(b->rwx & R_BP_PROT_EXEC)? 'x': '-',
|
|
|
|
b->hw? "hw": "sw",
|
|
|
|
b->trace? "trace": "break",
|
|
|
|
b->enabled? "enabled": "disabled",
|
|
|
|
b->data? b->data: "");
|
2009-04-12 22:46:44 +00:00
|
|
|
/* TODO: Show list of pids and trace points, conditionals */
|
2009-09-13 22:37:28 +00:00
|
|
|
n++;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
2009-09-13 22:37:28 +00:00
|
|
|
return n;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|