Rizin
unix-like reverse engineering framework and cli tools
bp.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_bp.h>
5 #include <config.h>
6 
8 
10 
12  free(b->name);
13  free(b->bbytes);
14  free(b->obytes);
15  free(b->module_name);
16  free(b->data);
17  free(b->cond);
18  free(b->expr);
19  free(b);
20 }
21 
27  int i;
29  if (!bp) {
30  return NULL;
31  }
32  bp->ctx = *ctx;
33  bp->bps_idx_count = 16;
40  bp->nhwbps = 0;
41  for (i = 0; i < RZ_ARRAY_SIZE(bp_static_plugins); i++) {
43  }
44  memset(&bp->iob, 0, sizeof(bp->iob));
45  return bp;
46 }
47 
49  rz_list_free(bp->bps);
50  rz_list_free(bp->plugins);
51  rz_list_free(bp->traces);
52  free(bp->bps_idx);
53  free(bp);
54  return NULL;
55 }
56 
62  rz_return_val_if_fail(bp && buf, 0);
63  int endian = bp->endian;
64  int bits = bp->ctx.bits_at ? bp->ctx.bits_at(addr, bp->ctx.user) : 0;
65  struct rz_bp_arch_t *b;
66  if (!bp->cur) {
67  return 0;
68  }
69  // find matching size breakpoint
70 repeat:
71  for (int i = 0; i < bp->cur->nbps; i++) {
72  b = &bp->cur->bps[i];
73  if (bp->cur->bps[i].bits) {
74  if (!bits || bits != bp->cur->bps[i].bits) {
75  continue;
76  }
77  }
78  if (bp->cur->bps[i].length == len && bp->cur->bps[i].endian == endian) {
79  memcpy(buf, b->bytes, b->length);
80  return b->length;
81  }
82  }
83  if (len != 4) {
84  len = 4;
85  goto repeat;
86  }
87  /* if not found try to pad with the first one */
88  b = &bp->cur->bps[0];
89  if (len % b->length) {
90  RZ_LOG_ERROR("No matching bpsize\n");
91  return 0;
92  }
93  for (int i = 0; i < len; i++) {
94  memcpy(buf + i, b->bytes, b->length);
95  }
96  return b->length;
97 }
98 
104  RzListIter *iter;
106  rz_list_foreach (bp->bps, iter, b) {
107  if (b->addr == addr) {
108  return b;
109  }
110  }
111  return NULL;
112 }
113 
121  RzListIter *iter;
123  rz_list_foreach (bp->bps, iter, b) {
124  if (!b->hw && b->addr + b->size == addr) {
125  return b;
126  }
127  }
128  return NULL;
129 }
130 
131 static inline bool inRange(RzBreakpointItem *b, ut64 addr) {
132  return (addr >= b->addr && addr < (b->addr + b->size));
133 }
134 
135 static inline bool matchProt(RzBreakpointItem *b, int perm) {
136  return (!perm || (perm && b->perm));
137 }
138 
141  RzListIter *iter;
142  rz_list_foreach (bp->bps, iter, b) {
143  // eprintf ("---ataddr--- 0x%08"PFMT64x" %d %d %x\n", b->addr, b->size, b->recoil, b->perm);
144  // Check addr within range and provided perm matches (or null)
145  if (inRange(b, addr) && matchProt(b, perm)) {
146  return b;
147  }
148  }
149  return NULL;
150 }
151 
153  RzBreakpointItem *b = rz_bp_get_in(bp, addr, 0);
154  if (b) {
155  b->enabled = set;
156  b->togglehits = count;
157  return b;
158  }
159  return NULL;
160 }
161 
163  RzListIter *iter;
165  rz_list_foreach (bp->bps, iter, b) {
166  b->enabled = set;
167  }
168  return true;
169 }
170 
172  // TODO: implement
173  return bp->stepcont;
174 }
175 
177  int i;
178  for (i = 0; i < bp->bps_idx_count; i++) {
179  if (bp->bps_idx[i] == b) {
180  bp->bps_idx[i] = NULL;
181  }
182  }
183  rz_list_delete_data(bp->bps, b);
184 }
185 
190  int i;
191  /* find empty slot */
192  for (i = 0; i < bp->bps_idx_count; i++) {
193  if (!bp->bps_idx[i]) {
194  break;
195  }
196  }
197  if (i == bp->bps_idx_count) {
198  /* allocate new slot */
199  bp->bps_idx_count += 16; // allocate space for 16 more bps
200  RzBreakpointItem **newbps = realloc(bp->bps_idx, bp->bps_idx_count * sizeof(RzBreakpointItem *));
201  if (newbps) {
202  bp->bps_idx = newbps;
203  for (int j = i; j < bp->bps_idx_count; j++) {
204  bp->bps_idx[j] = NULL;
205  }
206  } else {
207  bp->bps_idx_count -= 16; // allocate space for 16 more bps
208  i = 0; // avoid oob below
209  }
210  }
211  /* empty slot */
212  bp->bps_idx[i] = b;
213  bp->nbps++;
214  rz_list_append(bp->bps, b);
215 }
216 
217 /* TODO: detect overlapping of breakpoints */
218 static RzBreakpointItem *rz_bp_add(RzBreakpoint *bp, const ut8 *obytes, ut64 addr, int size, int hw, int perm) {
219  if (addr == UT64_MAX || size < 1) {
220  return NULL;
221  }
222  if (rz_bp_get_in(bp, addr, perm)) {
223  RZ_LOG_ERROR("Breakpoint already set at this address.\n");
224  return NULL;
225  }
227  if (!b) {
228  return NULL;
229  }
230  b->addr = addr;
231  if (bp->baddr > addr) {
232  RZ_LOG_ERROR("base addr should not be larger than the breakpoint address.\n");
233  }
234  if (bp->bpinmaps && !rz_bp_is_valid(bp, b)) {
235  RZ_LOG_WARN("Breakpoint won't be placed since it's not in a valid map.\n"
236  "You can bypass this check by setting dbg.bpinmaps to false.\n");
237  }
238  b->delta = addr - bp->baddr;
239  b->size = size;
240  b->enabled = true;
241  b->perm = perm;
242  b->hw = hw;
243  // NOTE: for hw breakpoints there are no bytes to save/restore
244  if (!hw) {
245  b->bbytes = calloc(size + 16, 1);
246  if (!b->bbytes) {
247  goto err;
248  }
249  if (obytes) {
250  b->obytes = malloc(size);
251  if (!b->obytes) {
252  goto err;
253  }
254  memcpy(b->obytes, obytes, size);
255  } else {
256  b->obytes = NULL;
257  }
258  int ret = rz_bp_get_bytes(bp, b->addr, b->bbytes, size);
259  if (ret != size) {
260  RZ_LOG_ERROR("Cannot get breakpoint bytes. Incorrect architecture/bits selected for software breakpoints?\n");
261  goto err;
262  }
263  }
264  rz_bp_item_insert(bp, b);
265  return b;
266 err:
268  return NULL;
269 }
270 
271 RZ_API int rz_bp_add_fault(RzBreakpoint *bp, ut64 addr, int size, int perm) {
272  // TODO
273  return false;
274 }
275 
282  RzBreakpointItem *item;
283  ut8 *bytes;
284  if (size < 1) {
285  size = rz_bp_size_at(bp, addr);
286  }
287  if (!(bytes = calloc(1, size))) {
288  return NULL;
289  }
290  memset(bytes, 0, size);
291  if (bp->iob.read_at) {
292  bp->iob.read_at(bp->iob.io, addr, bytes, size);
293  }
294  item = rz_bp_add(bp, bytes, addr, size, RZ_BP_TYPE_SW, perm);
295  free(bytes);
296  return item;
297 }
298 
300  return rz_bp_add(bp, NULL, addr, size, RZ_BP_TYPE_HW, perm);
301 }
302 
304  int i;
305  if (!rz_list_empty(bp->bps)) {
306  rz_list_purge(bp->bps);
307  for (i = 0; i < bp->bps_idx_count; i++) {
308  bp->bps_idx[i] = NULL;
309  }
310  return true;
311  }
312  return false;
313 }
314 
316  RzListIter *iter;
318  /* No _safe loop necessary because we return immediately after the delete. */
319  rz_list_foreach (bp->bps, iter, b) {
320  if (b->addr == addr) {
321  unlinkBreakpoint(bp, b);
322  // rz_list_delete (bp->bps, iter);
323  return true;
324  }
325  }
326  return false;
327 }
328 
330  RzBreakpointItem *b = rz_bp_get_in(bp, addr, 0);
331  if (b) {
332  b->trace = set;
333  return true;
334  }
335  return false;
336 }
337 
339  RzListIter *iter;
341  rz_list_foreach (bp->bps, iter, b) {
342  b->trace = set;
343  }
344  return true;
345 }
346 
348  if (idx >= 0 && idx < bp->bps_idx_count) {
349  return bp->bps_idx[idx];
350  }
351  return NULL;
352 }
353 
355  int i;
356  for (i = 0; i < bp->bps_idx_count; i++) {
357  if (bp->bps_idx[i] && bp->bps_idx[i]->addr == addr) {
358  return i;
359  }
360  }
361  return -1;
362 }
363 
365  if (idx >= 0 && idx < bp->bps_idx_count) {
366  rz_list_delete_data(bp->bps, bp->bps_idx[idx]);
367  bp->bps_idx[idx] = 0;
368  return true;
369  }
370  return false;
371 }
372 
378  rz_return_val_if_fail(bp, 0);
379  RzBreakpointArch *bpa;
380  int i, bpsize = 8;
381  if (!bp || !bp->cur) {
382  return 0;
383  }
384  for (i = 0; bp->cur->bps[i].bytes; i++) {
385  bpa = &bp->cur->bps[i];
386  if (bpa->bits && bpa->bits != bits) {
387  continue;
388  }
389  if (bpa->length < bpsize) {
390  bpsize = bpa->length;
391  }
392  }
393  return bpsize;
394 }
395 
400  rz_return_val_if_fail(bp, 0);
401  int bits = bp->ctx.bits_at ? bp->ctx.bits_at(addr, bp->ctx.user) : 0;
402  return rz_bp_size(bp, bits);
403 }
404 
405 // Check if the breakpoint is in a valid map
407  if (!bp->bpinmaps) {
408  return true;
409  }
410  if (!bp->ctx.is_mapped) {
411  return false;
412  }
413  return bp->ctx.is_mapped(b->addr, b->perm, bp->ctx.user);
414 }
415 
424  rz_return_val_if_fail(item, false);
425 
426  char *tmp_cond = NULL;
427  if (cond) {
428  tmp_cond = strdup(cond);
429  if (!tmp_cond) {
430  return false;
431  }
432  }
433  free(item->cond);
434  item->cond = tmp_cond;
435  return true;
436 }
437 
446  rz_return_val_if_fail(item, false);
447 
448  char *tmp_data = NULL;
449  if (data) {
450  tmp_data = strdup(data);
451  if (!tmp_data) {
452  return false;
453  }
454  }
455  free(item->data);
456  item->data = tmp_data;
457  return true;
458 }
459 
468  rz_return_val_if_fail(item, false);
469 
470  char *tmp_expr = NULL;
471  if (expr) {
472  tmp_expr = strdup(expr);
473  if (!tmp_expr) {
474  return false;
475  }
476  }
477  free(item->expr);
478  item->expr = tmp_expr;
479  return true;
480 }
481 
490  rz_return_val_if_fail(item, false);
491 
492  char *tmp_name = NULL;
493  if (name) {
494  tmp_name = strdup(name);
495  if (!tmp_name) {
496  return false;
497  }
498  }
499  free(item->name);
500  item->name = tmp_name;
501  return true;
502 }
size_t len
Definition: 6502dis.c:15
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API RZ_BORROW RzBreakpointItem * rz_bp_get_ending_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr)
Get the breakpoint b that fulfills b->addr + b-> size == addr After hitting a (usually software) brea...
Definition: bp.c:119
RZ_API int rz_bp_set_trace_all(RzBreakpoint *bp, int set)
Definition: bp.c:338
RZ_API bool rz_bp_is_valid(RzBreakpoint *bp, RzBreakpointItem *b)
Definition: bp.c:406
RZ_API int rz_bp_del_index(RzBreakpoint *bp, int idx)
Definition: bp.c:364
RZ_API RzBreakpointItem * rz_bp_get_in(RzBreakpoint *bp, ut64 addr, int perm)
Definition: bp.c:139
static void rz_bp_item_free(RzBreakpointItem *b)
Definition: bp.c:11
static bool matchProt(RzBreakpointItem *b, int perm)
Definition: bp.c:135
static RzBreakpointItem * rz_bp_add(RzBreakpoint *bp, const ut8 *obytes, ut64 addr, int size, int hw, int perm)
Definition: bp.c:218
RZ_LIB_VERSION(rz_bp)
static bool inRange(RzBreakpointItem *b, ut64 addr)
Definition: bp.c:131
RZ_API RzBreakpointItem * rz_bp_get_index(RzBreakpoint *bp, int idx)
Definition: bp.c:347
RZ_API int rz_bp_get_index_at(RzBreakpoint *bp, ut64 addr)
Definition: bp.c:354
RZ_API RzBreakpoint * rz_bp_new(RZ_BORROW RZ_NONNULL RzBreakpointContext *ctx)
Definition: bp.c:26
RZ_API int rz_bp_set_trace(RzBreakpoint *bp, ut64 addr, int set)
Definition: bp.c:329
RZ_API bool rz_bp_item_set_data(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *data)
set the data for a RzBreakpointItem
Definition: bp.c:445
RZ_API RZ_BORROW RzBreakpointItem * rz_bp_get_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr)
Get the breakpoint at exactly addr.
Definition: bp.c:102
RZ_API int rz_bp_size(RZ_NONNULL RzBreakpoint *bp, int bits)
Predict the software breakpoint size to use for the given arch-bitness.
Definition: bp.c:377
static void unlinkBreakpoint(RzBreakpoint *bp, RzBreakpointItem *b)
Definition: bp.c:176
RZ_IPI void rz_bp_item_insert(RzBreakpoint *bp, RzBreakpointItem *b)
Definition: bp.c:189
RZ_API RzBreakpoint * rz_bp_free(RzBreakpoint *bp)
Definition: bp.c:48
RZ_API bool rz_bp_del(RzBreakpoint *bp, ut64 addr)
Definition: bp.c:315
RZ_API bool rz_bp_del_all(RzBreakpoint *bp)
Definition: bp.c:303
RZ_API RzBreakpointItem * rz_bp_add_hw(RzBreakpoint *bp, ut64 addr, int size, int perm)
Definition: bp.c:299
RZ_API RzBreakpointItem * rz_bp_enable(RzBreakpoint *bp, ut64 addr, int set, int count)
Definition: bp.c:152
RZ_API bool rz_bp_item_set_cond(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *cond)
set the condition for a RzBreakpointItem
Definition: bp.c:423
RZ_API int rz_bp_add_fault(RzBreakpoint *bp, ut64 addr, int size, int perm)
Definition: bp.c:271
RZ_API int rz_bp_stepy_continuation(RzBreakpoint *bp)
Definition: bp.c:171
static struct rz_bp_plugin_t * bp_static_plugins[]
Definition: bp.c:9
RZ_API int rz_bp_get_bytes(RZ_NONNULL RzBreakpoint *bp, ut64 addr, RZ_NONNULL ut8 *buf, int len)
Definition: bp.c:61
RZ_API bool rz_bp_enable_all(RzBreakpoint *bp, int set)
Definition: bp.c:162
RZ_API bool rz_bp_item_set_name(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *name)
set the name for a RzBreakpointItem
Definition: bp.c:489
RZ_API bool rz_bp_item_set_expr(RZ_NONNULL RzBreakpointItem *item, RZ_NULLABLE const char *expr)
set the expr for a RzBreakpointItem
Definition: bp.c:467
RZ_API RZ_BORROW RzBreakpointItem * rz_bp_add_sw(RZ_NONNULL RzBreakpoint *bp, ut64 addr, int size, int perm)
Add a software breakpoint size preferred size of the breakpoint, or 0 to determine automatically.
Definition: bp.c:280
RZ_API int rz_bp_size_at(RZ_NONNULL RzBreakpoint *bp, ut64 addr)
Predict the software breakpoint size to use when placing a breakpoint at addr.
Definition: bp.c:399
RZ_API bool rz_bp_plugin_add(RzBreakpoint *bp, RZ_BORROW RZ_NONNULL RzBreakpointPlugin *plugin)
Definition: bp_plugin.c:24
RZ_API RzList * rz_bp_traptrace_new(void)
Definition: bp_traptrace.c:16
#define RZ_BP_STATIC_PLUGINS
Definition: config.h:20
static RzNumCalcValue expr(RzNum *, RzNumCalc *, int)
Definition: calc.c:167
#define RZ_API
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API bool rz_list_delete_data(RZ_NONNULL RzList *list, void *ptr)
Deletes an entry in the list by searching for a pointer.
Definition: list.c:148
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int idx
Definition: setup.py:197
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_BP_TYPE_HW
Definition: rz_bp.h:27
@ RZ_BP_TYPE_SW
Definition: rz_bp.h:26
#define RZ_BP_CONT_NORMAL
Definition: rz_bp.h:16
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
Definition: rz_types.h:233
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_BORROW
Definition: rz_types.h:63
#define UT64_MAX
Definition: rz_types_base.h:86
#define b(i)
Definition: sha256.c:42
#define cond(bop, top, mask, flags)
Definition: z80asm.h:102
int endian
Definition: rz_bp.h:21
int bits
Definition: rz_bp.h:19
int length
Definition: rz_bp.h:20
Outer context of mappings/etc. in which the RzBreakpoint instance will operate in....
Definition: rz_bp.h:71
bool(* is_mapped)(ut64 addr, int perm, void *user)
check if the address is mapped and has the given permissions
Definition: rz_bp.h:73
void * user
Definition: rz_bp.h:72
ut64 addr
Definition: rz_bp.h:45
Definition: rz_bp.h:78
int nhwbps
Definition: rz_bp.h:92
int stepcont
Definition: rz_bp.h:81
PrintfCallback cb_printf
Definition: rz_bp.h:88
int nbps
Definition: rz_bp.h:91
RzBreakpointItem ** bps_idx
Definition: rz_bp.h:94
RzList * plugins
Definition: rz_bp.h:87
bool bpinmaps
Definition: rz_bp.h:83
RzList * traces
Definition: rz_bp.h:86
RzBreakpointContext ctx
Definition: rz_bp.h:80
RzIOBind iob
Definition: rz_bp.h:84
int bps_idx_count
Definition: rz_bp.h:95
RzList * bps
Definition: rz_bp.h:93
ut64 baddr
Definition: rz_bp.h:96
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58