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