2010-03-03 01:41:41 +00:00
|
|
|
/* radare - LGPL - Copyright 2010 pancake<nopcode.org> */
|
|
|
|
|
2009-09-13 22:37:28 +00:00
|
|
|
// TODO: use r_range here??
|
2010-01-21 01:38:52 +00:00
|
|
|
#include <r_bp.h>
|
2010-03-25 09:18:59 +00:00
|
|
|
#include <r_list.h>
|
2009-09-13 22:37:28 +00:00
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API void r_bp_traptrace_free(void *ptr) {
|
|
|
|
RBreakpointTrace *trace = ptr;
|
|
|
|
free (trace->buffer);
|
|
|
|
free (trace->traps);
|
|
|
|
free (trace->bits);
|
|
|
|
free (trace);
|
2009-09-13 22:37:28 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API RList *r_bp_traptrace_new() {
|
2019-11-10 06:06:02 +00:00
|
|
|
RList *list = r_list_new ();
|
2018-09-13 08:17:26 +00:00
|
|
|
if (!list) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
list->free = &r_bp_traptrace_free;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bp_traptrace_enable(RBreakpoint *bp, int enable) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach (bp->traces, iter, trace) {
|
|
|
|
ut8 *buf = (enable)?trace->traps:trace->buffer;
|
2010-03-03 01:41:41 +00:00
|
|
|
bp->iob.write_at (bp->iob.io, trace->addr, buf, trace->length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bp_traptrace_reset(RBreakpoint *bp, int hard) {
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach (bp->traces, iter, trace) {
|
2010-03-03 01:41:41 +00:00
|
|
|
if (hard) {
|
|
|
|
r_bp_traptrace_free (trace);
|
2010-06-13 10:51:44 +00:00
|
|
|
// XXX: This segfaults
|
|
|
|
//r_list_delete (bp->traces, r_list_iter_cur (iter));
|
2018-09-13 08:17:26 +00:00
|
|
|
} else {
|
|
|
|
memset (trace->bits, 0x00, trace->bitlen);
|
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
2010-06-13 10:51:44 +00:00
|
|
|
if (hard) {
|
|
|
|
// XXX: traces not freed correctly (memleak)
|
|
|
|
bp->traces = r_list_new ();
|
|
|
|
bp->traces->free = r_bp_traptrace_free;
|
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 12:34:38 +00:00
|
|
|
// FIX: efficiency
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API ut64 r_bp_traptrace_next(RBreakpoint *bp, ut64 addr) {
|
|
|
|
int i, delta;
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach (bp->traces, iter, trace) {
|
2010-03-03 01:41:41 +00:00
|
|
|
if (addr>=trace->addr && addr<=trace->addr_end) {
|
|
|
|
delta = (int)(addr-trace->addr);
|
|
|
|
for (i=delta; i<trace->length; i++) {
|
2018-09-13 08:17:26 +00:00
|
|
|
if (R_BIT_CHK (trace->bits, i)) {
|
|
|
|
return addr + i;
|
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0LL;
|
2009-09-13 22:37:28 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API int r_bp_traptrace_add(RBreakpoint *bp, ut64 from, ut64 to) {
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
ut8 *buf, *trap, *bits;
|
|
|
|
ut64 len;
|
|
|
|
int bitlen;
|
|
|
|
/* cannot map addr 0 */
|
2018-09-13 08:17:26 +00:00
|
|
|
if (from == 0LL) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
|
|
|
if (from > to) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
len = to-from;
|
2018-09-13 08:17:26 +00:00
|
|
|
if (len >= ST32_MAX) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
buf = (ut8*) malloc ((int)len);
|
2018-09-13 08:17:26 +00:00
|
|
|
if (!buf) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2010-03-03 10:35:03 +00:00
|
|
|
trap = (ut8*) malloc ((int)len+4);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!trap) {
|
2010-03-03 01:41:41 +00:00
|
|
|
free (buf);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
bitlen = (len>>4)+1;
|
|
|
|
bits = malloc (bitlen);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!bits) {
|
2010-03-03 01:41:41 +00:00
|
|
|
free (buf);
|
|
|
|
free (trap);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
// TODO: check return value
|
|
|
|
bp->iob.read_at (bp->iob.io, from, buf, len);
|
|
|
|
memset (bits, 0x00, bitlen);
|
|
|
|
r_bp_get_bytes (bp, trap, len, bp->endian, 0);
|
|
|
|
|
|
|
|
trace = R_NEW (RBreakpointTrace);
|
2015-06-28 12:04:41 +00:00
|
|
|
if (!trace) {
|
|
|
|
free (buf);
|
|
|
|
free (trap);
|
2015-07-02 07:33:05 +00:00
|
|
|
free (bits);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2015-06-28 12:04:41 +00:00
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
trace->addr = from;
|
|
|
|
trace->addr_end = to;
|
|
|
|
trace->bits = bits;
|
|
|
|
trace->traps = trap;
|
|
|
|
trace->buffer = buf;
|
|
|
|
trace->length = len;
|
2015-06-28 12:04:41 +00:00
|
|
|
if (!r_list_append (bp->traces, trace)){
|
|
|
|
free (buf);
|
|
|
|
free (trap);
|
|
|
|
free (trace);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2015-06-28 12:04:41 +00:00
|
|
|
}
|
2009-09-13 22:37:28 +00:00
|
|
|
// read a memory, overwrite it as breakpointing area
|
2019-06-20 04:45:00 +00:00
|
|
|
// every time it is hitted, instruction is restored
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2009-09-13 22:37:28 +00:00
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
|
|
|
|
R_API int r_bp_traptrace_free_at(RBreakpoint *bp, ut64 from) {
|
2015-09-14 00:08:31 +00:00
|
|
|
int ret = false;
|
2012-02-14 17:19:16 +00:00
|
|
|
RListIter *iter, *iter_tmp;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach_safe (bp->traces, iter, iter_tmp, trace) {
|
2010-03-03 01:41:41 +00:00
|
|
|
if (from>=trace->addr && from<=trace->addr_end) {
|
|
|
|
bp->iob.write_at (bp->iob.io, trace->addr,
|
|
|
|
trace->buffer, trace->length);
|
|
|
|
r_bp_traptrace_free (trace);
|
2012-02-14 17:19:16 +00:00
|
|
|
r_list_delete (bp->traces, iter);
|
2015-09-14 00:08:31 +00:00
|
|
|
ret = true;
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bp_traptrace_list(RBreakpoint *bp) {
|
|
|
|
int i;
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach (bp->traces, iter, trace) {
|
2015-12-29 20:41:20 +00:00
|
|
|
for (i = 0; i < trace->bitlen; i++) {
|
2018-09-13 08:17:26 +00:00
|
|
|
if (R_BIT_CHK (trace->bits, i)) {
|
|
|
|
eprintf (" - 0x%08" PFMT64x "\n", trace->addr + (i << 4));
|
|
|
|
}
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bp_traptrace_at(RBreakpoint *bp, ut64 from, int len) {
|
|
|
|
int delta;
|
2010-06-29 23:13:09 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RBreakpointTrace *trace;
|
|
|
|
r_list_foreach (bp->traces, iter, trace) {
|
2010-03-03 01:41:41 +00:00
|
|
|
// TODO: do we really need len?
|
|
|
|
if (from>=trace->addr && from+len<=trace->addr_end) {
|
|
|
|
delta = (int) (from-trace->addr);
|
2018-09-13 08:17:26 +00:00
|
|
|
if (R_BIT_CHK (trace->bits, delta)) {
|
|
|
|
if (trace->traps[delta] == 0x00) {
|
|
|
|
return false; // already traced..debugger should stop
|
|
|
|
}
|
|
|
|
}
|
2012-01-31 02:42:27 +00:00
|
|
|
R_BIT_SET (trace->bits, delta);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-03-03 01:41:41 +00:00
|
|
|
}
|