2009-02-05 21:08:46 +00:00
|
|
|
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
|
|
|
|
|
|
|
#include <r_bp.h>
|
2009-04-13 22:47:02 +00:00
|
|
|
#include "../config.h"
|
|
|
|
|
|
|
|
static struct r_bp_handle_t *bp_static_plugins[] =
|
|
|
|
{ R_BP_STATIC_PLUGINS };
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API int r_bp_init(struct r_bp_t *bp)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-13 22:47:02 +00:00
|
|
|
int i;
|
2009-04-12 22:46:44 +00:00
|
|
|
bp->nbps = 0;
|
|
|
|
bp->cur = NULL;
|
2009-09-13 22:37:28 +00:00
|
|
|
bp->stepcont = R_BP_CONT_NORMAL;
|
2009-04-12 22:46:44 +00:00
|
|
|
INIT_LIST_HEAD(&bp->bps);
|
2009-04-15 10:01:12 +00:00
|
|
|
INIT_LIST_HEAD(&bp->plugins);
|
2009-04-13 22:47:02 +00:00
|
|
|
for(i=0;bp_static_plugins[i];i++)
|
|
|
|
r_bp_handle_add(bp, bp_static_plugins[i]);
|
2009-02-05 21:08:46 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API struct r_bp_t *r_bp_new()
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-11 21:22:20 +00:00
|
|
|
struct r_bp_t *bp = MALLOC_STRUCT(struct r_bp_t);
|
2009-09-13 22:37:28 +00:00
|
|
|
if (bp) r_bp_init(bp);
|
2009-02-05 21:08:46 +00:00
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
R_API struct r_bp_t *r_bp_free(struct r_bp_t *bp)
|
2009-04-12 22:46:44 +00:00
|
|
|
{
|
2009-09-13 22:37:28 +00:00
|
|
|
/* XXX : properly destroy bp list */
|
|
|
|
free(bp);
|
|
|
|
return NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
R_API int r_bp_get_bytes(struct r_bp_t *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 */
|
|
|
|
for(i=0;1;i++) {
|
|
|
|
b = &bp->cur->bps[i%bp->cur->nbps];
|
2009-04-12 23:10:22 +00:00
|
|
|
if (b->endian == endian && idx%(i+1)==0) {
|
2009-04-12 22:46:44 +00:00
|
|
|
for(i=0;i<len;) {
|
|
|
|
memcpy(buf+i, b->bytes, len);
|
|
|
|
i += b->length;
|
|
|
|
}
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
R_API int r_bp_at_addr(struct r_bp_t *bp, ut64 addr, int rwx)
|
2009-02-05 21:08:46 +00:00
|
|
|
{
|
2009-04-12 22:46:44 +00:00
|
|
|
struct list_head *pos;
|
|
|
|
struct r_bp_item_t *b;
|
|
|
|
|
|
|
|
if (bp->trace_bp == addr)
|
|
|
|
return R_TRUE;
|
|
|
|
|
|
|
|
list_for_each(pos, &bp->bps) {
|
|
|
|
b = list_entry(pos, struct r_bp_item_t, list);
|
|
|
|
if (addr >= b->addr && addr <= b->addr+b->size && rwx&b->rwx)
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-07-08 11:49:55 +00:00
|
|
|
R_API struct r_bp_item_t *r_bp_enable(struct r_bp_t *bp, ut64 addr, int set)
|
2009-04-12 22:46:44 +00:00
|
|
|
{
|
|
|
|
struct list_head *pos;
|
|
|
|
struct r_bp_item_t *b;
|
|
|
|
list_for_each(pos, &bp->bps) {
|
|
|
|
b = list_entry(pos, struct r_bp_item_t, list);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
R_API int r_bp_stepy_continuation(struct r_bp_t *bp)
|
|
|
|
{
|
|
|
|
// TODO: implement
|
|
|
|
return bp->stepcont;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bp_add_cond(struct r_bp_t *bp, const char *cond)
|
|
|
|
{
|
|
|
|
// TODO: implement contitional breakpoints
|
|
|
|
bp->stepcont = R_TRUE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bp_del_cond(struct r_bp_t *bp, int idx)
|
|
|
|
{
|
|
|
|
// add contitional
|
|
|
|
bp->stepcont = R_FALSE;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-04-12 22:46:44 +00:00
|
|
|
/* TODO: detect overlapping of breakpoints */
|
2009-09-13 22:37:28 +00:00
|
|
|
static struct r_bp_item_t *r_bp_add(struct r_bp_t *bp, const ut8 *obytes, ut64 addr, int size, int hw, int rwx)
|
2009-04-12 22:46:44 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct r_bp_item_t *b;
|
2009-09-13 22:37:28 +00:00
|
|
|
if (r_bp_at_addr(bp, addr, rwx)) {
|
2009-04-12 22:46:44 +00:00
|
|
|
eprintf("Breakpoint already set at this address.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
b = MALLOC_STRUCT(struct r_bp_item_t);
|
|
|
|
b->pids[0] = 0; /* for any pid */
|
|
|
|
b->addr = addr;
|
|
|
|
b->size = size;
|
2009-09-13 22:37:28 +00:00
|
|
|
b->enabled = R_TRUE;
|
2009-04-12 22:46:44 +00:00
|
|
|
b->bbytes = malloc(size+16);
|
2009-09-13 22:37:28 +00:00
|
|
|
if (obytes) {
|
|
|
|
b->obytes = malloc(size);
|
|
|
|
memcpy(b->obytes, obytes, size);
|
|
|
|
} else b->obytes = NULL;
|
2009-04-12 22:46:44 +00:00
|
|
|
/* XXX: endian always in little ?!?!? */
|
2009-09-13 22:37:28 +00:00
|
|
|
ret = r_bp_get_bytes(bp, b->bbytes, size, 0, 0);
|
2009-04-12 22:46:44 +00:00
|
|
|
if (ret == R_FALSE) {
|
|
|
|
fprintf(stderr, "Cannot get breakpoint bytes. No r_bp_set()?\n");
|
|
|
|
free (b->bbytes);
|
|
|
|
free (b);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
b->hw = hw;
|
|
|
|
b->trace = 0;
|
|
|
|
bp->nbps++;
|
|
|
|
list_add_tail(&(b->list), &bp->bps);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
R_API struct r_bp_item_t *r_bp_add_sw(struct r_bp_t *bp, ut64 addr, int size, int rwx)
|
|
|
|
{
|
|
|
|
struct r_bp_item_t *item;
|
|
|
|
ut8 *bytes;
|
|
|
|
bytes = malloc(size);
|
|
|
|
if (bytes == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (bp->iob.read_at) {
|
|
|
|
bp->iob.read_at(bp->iob.io, addr, bytes, size);
|
|
|
|
} else memset(bytes, 0, size);
|
|
|
|
item = r_bp_add(bp, bytes, addr, size, R_BP_TYPE_SW, rwx);
|
|
|
|
free(bytes);
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API struct r_bp_item_t *r_bp_add_hw(struct r_bp_t *bp, ut64 addr, int size, int rwx)
|
|
|
|
{
|
|
|
|
return r_bp_add(bp, NULL, addr, size, R_BP_TYPE_HW, rwx);
|
|
|
|
}
|
|
|
|
|
2009-07-08 11:49:55 +00:00
|
|
|
R_API int r_bp_del(struct r_bp_t *bp, ut64 addr)
|
2009-04-12 22:46:44 +00:00
|
|
|
{
|
|
|
|
struct list_head *pos;
|
|
|
|
struct r_bp_item_t *b;
|
|
|
|
list_for_each(pos, &bp->bps) {
|
|
|
|
b = list_entry(pos, struct r_bp_item_t, list);
|
|
|
|
if (b->addr == addr) {
|
|
|
|
list_del(&b->list);
|
|
|
|
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?
|
|
|
|
R_API int r_bp_set_trace(struct r_bp_t *bp, ut64 addr, int set)
|
2009-04-15 10:01:12 +00:00
|
|
|
{
|
|
|
|
struct list_head *pos;
|
2009-09-13 22:37:28 +00:00
|
|
|
struct r_bp_item_t *b;
|
|
|
|
list_for_each(pos, &bp->bps) {
|
|
|
|
b = list_entry(pos, struct r_bp_item_t, list);
|
|
|
|
if (addr >= b->addr && addr <= b->addr+b->size) {
|
|
|
|
b->trace = set;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-04-15 10:01:12 +00:00
|
|
|
}
|
2009-09-13 22:37:28 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: rename or remove
|
|
|
|
R_API int r_bp_set_trace_bp(struct r_bp_t *bp, ut64 addr, int set)
|
|
|
|
{
|
|
|
|
bp->trace_all = set;
|
|
|
|
bp->trace_bp = addr;
|
|
|
|
return R_TRUE;
|
2009-04-15 10:01:12 +00:00
|
|
|
}
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: deprecate
|
2009-04-11 21:22:20 +00:00
|
|
|
R_API int r_bp_list(struct r_bp_t *bp, int rad)
|
|
|
|
{
|
2009-09-13 22:37:28 +00:00
|
|
|
int n = 0;
|
2009-04-12 22:46:44 +00:00
|
|
|
struct r_bp_item_t *b;
|
|
|
|
struct list_head *pos;
|
|
|
|
eprintf("Breakpoint list:\n");
|
|
|
|
list_for_each(pos, &bp->bps) {
|
|
|
|
b = list_entry(pos, struct r_bp_item_t, list);
|
2009-04-12 23:10:22 +00:00
|
|
|
printf("0x%08llx - 0x%08llx %d %c%c%c %s %s %s\n",
|
2009-04-12 22:46:44 +00:00
|
|
|
b->addr, b->addr+b->size, b->size,
|
|
|
|
(b->rwx & R_BP_READ)?'r':'-',
|
|
|
|
(b->rwx & R_BP_WRITE)?'w':'-',
|
|
|
|
(b->rwx & R_BP_EXEC)?'x':'-',
|
|
|
|
b->hw?"hw":"sw",
|
2009-04-12 23:10:22 +00:00
|
|
|
b->trace?"trace":"break",
|
|
|
|
b->enabled?"enabled":"disabled");
|
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
|
|
|
}
|