1 /* radare - LGPL - Copyright 2010 pancake<nopcode.org> */
2
3 // TODO: use r_range here??
4 #include <r_bp.h>
5 #include <r_list.h>
6
r_bp_traptrace_free(void * ptr)7 R_API void r_bp_traptrace_free(void *ptr) {
8 RBreakpointTrace *trace = ptr;
9 free (trace->buffer);
10 free (trace->traps);
11 free (trace->bits);
12 free (trace);
13 }
14
r_bp_traptrace_new(void)15 R_API RList *r_bp_traptrace_new(void) {
16 RList *list = r_list_new ();
17 if (!list) {
18 return NULL;
19 }
20 list->free = &r_bp_traptrace_free;
21 return list;
22 }
23
r_bp_traptrace_enable(RBreakpoint * bp,int enable)24 R_API void r_bp_traptrace_enable(RBreakpoint *bp, int enable) {
25 RListIter *iter;
26 RBreakpointTrace *trace;
27 r_list_foreach (bp->traces, iter, trace) {
28 ut8 *buf = (enable)?trace->traps:trace->buffer;
29 bp->iob.write_at (bp->iob.io, trace->addr, buf, trace->length);
30 }
31 }
32
r_bp_traptrace_reset(RBreakpoint * bp,int hard)33 R_API void r_bp_traptrace_reset(RBreakpoint *bp, int hard) {
34 RListIter *iter;
35 RBreakpointTrace *trace;
36 r_list_foreach (bp->traces, iter, trace) {
37 if (hard) {
38 r_bp_traptrace_free (trace);
39 // XXX: This segfaults
40 //r_list_delete (bp->traces, r_list_iter_cur (iter));
41 } else {
42 memset (trace->bits, 0x00, trace->bitlen);
43 }
44 }
45 if (hard) {
46 // XXX: traces not freed correctly (memleak)
47 bp->traces = r_list_new ();
48 bp->traces->free = r_bp_traptrace_free;
49 }
50 }
51
52 // FIX: efficiency
r_bp_traptrace_next(RBreakpoint * bp,ut64 addr)53 R_API ut64 r_bp_traptrace_next(RBreakpoint *bp, ut64 addr) {
54 int i, delta;
55 RListIter *iter;
56 RBreakpointTrace *trace;
57 r_list_foreach (bp->traces, iter, trace) {
58 if (addr>=trace->addr && addr<=trace->addr_end) {
59 delta = (int)(addr-trace->addr);
60 for (i=delta; i<trace->length; i++) {
61 if (R_BIT_CHK (trace->bits, i)) {
62 return addr + i;
63 }
64 }
65 }
66 }
67 return 0LL;
68 }
69
r_bp_traptrace_add(RBreakpoint * bp,ut64 from,ut64 to)70 R_API int r_bp_traptrace_add(RBreakpoint *bp, ut64 from, ut64 to) {
71 RBreakpointTrace *trace;
72 ut8 *buf, *trap, *bits;
73 ut64 len;
74 int bitlen;
75 /* cannot map addr 0 */
76 if (from == 0LL) {
77 return false;
78 }
79 if (from > to) {
80 return false;
81 }
82 len = to-from;
83 if (len >= ST32_MAX) {
84 return false;
85 }
86 buf = (ut8*) malloc ((int)len);
87 if (!buf) {
88 return false;
89 }
90 trap = (ut8*) malloc ((int)len+4);
91 if (!trap) {
92 free (buf);
93 return false;
94 }
95 bitlen = (len>>4)+1;
96 bits = malloc (bitlen);
97 if (!bits) {
98 free (buf);
99 free (trap);
100 return false;
101 }
102 // TODO: check return value
103 bp->iob.read_at (bp->iob.io, from, buf, len);
104 memset (bits, 0x00, bitlen);
105 r_bp_get_bytes (bp, trap, len, bp->endian, 0);
106
107 trace = R_NEW (RBreakpointTrace);
108 if (!trace) {
109 free (buf);
110 free (trap);
111 free (bits);
112 return false;
113 }
114 trace->addr = from;
115 trace->addr_end = to;
116 trace->bits = bits;
117 trace->traps = trap;
118 trace->buffer = buf;
119 trace->length = len;
120 if (!r_list_append (bp->traces, trace)){
121 free (buf);
122 free (trap);
123 free (trace);
124 return false;
125 }
126 // read a memory, overwrite it as breakpointing area
127 // every time it is hitted, instruction is restored
128 return true;
129 }
130
r_bp_traptrace_free_at(RBreakpoint * bp,ut64 from)131 R_API int r_bp_traptrace_free_at(RBreakpoint *bp, ut64 from) {
132 int ret = false;
133 RListIter *iter, *iter_tmp;
134 RBreakpointTrace *trace;
135 r_list_foreach_safe (bp->traces, iter, iter_tmp, trace) {
136 if (from>=trace->addr && from<=trace->addr_end) {
137 bp->iob.write_at (bp->iob.io, trace->addr,
138 trace->buffer, trace->length);
139 r_bp_traptrace_free (trace);
140 r_list_delete (bp->traces, iter);
141 ret = true;
142 }
143 }
144 return ret;
145 }
146
r_bp_traptrace_list(RBreakpoint * bp)147 R_API void r_bp_traptrace_list(RBreakpoint *bp) {
148 int i;
149 RListIter *iter;
150 RBreakpointTrace *trace;
151 r_list_foreach (bp->traces, iter, trace) {
152 for (i = 0; i < trace->bitlen; i++) {
153 if (R_BIT_CHK (trace->bits, i)) {
154 eprintf (" - 0x%08" PFMT64x "\n", trace->addr + (i << 4));
155 }
156 }
157 }
158 }
159
r_bp_traptrace_at(RBreakpoint * bp,ut64 from,int len)160 R_API int r_bp_traptrace_at(RBreakpoint *bp, ut64 from, int len) {
161 int delta;
162 RListIter *iter;
163 RBreakpointTrace *trace;
164 r_list_foreach (bp->traces, iter, trace) {
165 // TODO: do we really need len?
166 if (from>=trace->addr && from+len<=trace->addr_end) {
167 delta = (int) (from-trace->addr);
168 if (R_BIT_CHK (trace->bits, delta)) {
169 if (trace->traps[delta] == 0x00) {
170 return false; // already traced..debugger should stop
171 }
172 }
173 R_BIT_SET (trace->bits, delta);
174 return true;
175 }
176 }
177 return false;
178 }
179