Rizin
unix-like reverse engineering framework and cli tools
debug_native.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_userconf.h>
5 #include <rz_debug.h>
6 #include <rz_drx.h>
7 #include <rz_core.h>
8 #include <rz_reg.h>
9 #include <rz_lib.h>
10 #include <rz_analysis.h>
11 #include <signal.h>
12 #include <sys/types.h>
13 
14 #include "native/drx.c" // x86 specific
15 #include "rz_cons.h"
16 
17 static int rz_debug_native_continue(RzDebug *dbg, int pid, int tid, int sig);
18 static int rz_debug_native_reg_read(RzDebug *dbg, int type, ut8 *buf, int size);
19 static int rz_debug_native_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size);
20 
21 #include "native/bt.c"
22 
23 #if __UNIX__
24 #include <errno.h>
25 #if !defined(__HAIKU__) && !defined(__sun)
26 #include <sys/ptrace.h>
27 #endif
28 #include <sys/wait.h>
29 #include <signal.h>
30 #endif
31 
32 #if __WINDOWS__
34 // TODO: Move these onto windows.h?
37 #define RZ_DEBUG_REG_T CONTEXT
38 #ifdef NTSTATUS
39 #undef NTSTATUS
40 #endif
41 #ifndef NTSTATUS
42 #define NTSTATUS int
43 #endif
44 
45 #elif __BSD__
46 #include "native/bsd/bsd_debug.h"
47 #include "native/procfs.h"
48 
49 #elif __APPLE__
50 #include <sys/resource.h>
51 #include "native/xnu/xnu_debug.h"
52 
53 #elif __sun
54 
55 #define RZ_DEBUG_REG_T gregset_t
56 #undef DEBUGGER
57 #define DEBUGGER 0
58 #warning No debugger support for SunOS yet
59 
60 #elif __linux__
61 #include <sys/mman.h>
63 #include "native/procfs.h"
64 #ifdef __ANDROID__
65 #define WAIT_ANY -1
66 #ifndef WIFCONTINUED
67 #define WIFCONTINUED(s) ((s) == 0xffff)
68 #endif
69 #endif
70 #if (__x86_64__ || __i386__ || __arm__ || __arm64__) && !defined(__ANDROID__)
72 #endif
73 #else // OS
74 
75 #warning Unsupported debugging platform
76 #undef DEBUGGER
77 #define DEBUGGER 0
78 #endif // ARCH
79 
80 #ifdef __WALL
81 #define WAITPID_FLAGS __WALL
82 #else
83 #define WAITPID_FLAGS 0
84 #endif
85 
86 /* begin of debugger code */
87 #if DEBUGGER
88 
89 #if !__WINDOWS__ && !(__linux__ && !defined(WAIT_ON_ALL_CHILDREN)) && !__APPLE__
90 static int rz_debug_handle_signals(RzDebug *dbg) {
91 #if __KFBSD__ || __NetBSD__
92  return bsd_handle_signals(dbg);
93 #else
94  eprintf("Warning: signal handling is not supported on this platform\n");
95  return 0;
96 #endif
97 }
98 #endif
99 
100 // this is temporal
101 #if __APPLE__ || __linux__
102 
103 static char *rz_debug_native_reg_profile(RzDebug *dbg) {
104 #if __APPLE__
105  return xnu_reg_profile(dbg);
106 #elif __linux__
107  return linux_reg_profile(dbg);
108 #endif
109 }
110 #else
111 
112 #include "native/reg.c" // x86 specific
113 
114 #endif
115 static int rz_debug_native_step(RzDebug *dbg) {
116 #if __APPLE__
117  return xnu_step(dbg);
118 #elif __WINDOWS__
119  return w32_step(dbg);
120 #elif __BSD__
121  int ret = ptrace(PT_STEP, dbg->pid, (caddr_t)1, 0);
122  if (ret != 0) {
123  perror("native-singlestep");
124  return false;
125  }
126  return true;
127 #elif __linux__
128  return linux_step(dbg);
129 #endif
130  return 0;
131 }
132 
133 // return thread id
134 static int rz_debug_native_attach(RzDebug *dbg, int pid) {
135 #if 0
136  if (!dbg || pid == dbg->pid)
137  return dbg->tid;
138 #endif
139 #if __APPLE__
140  return xnu_attach(dbg, pid);
141 #elif __WINDOWS__
142  return w32_attach(dbg, pid);
143 #elif __linux__ || __ANDROID__
144  return linux_attach(dbg, pid);
145 #elif __KFBSD__
146  if (ptrace(PT_ATTACH, pid, 0, 0) != -1) {
147  perror("ptrace (PT_ATTACH)");
148  }
149  return pid;
150 #else
151  int ret = ptrace(PTRACE_ATTACH, pid, 0, 0);
152  if (ret != -1) {
153  eprintf("Trying to attach to %d\n", pid);
154  perror("ptrace (PT_ATTACH)");
155  }
156  return pid;
157 #endif
158 }
159 
160 static int rz_debug_native_detach(RzDebug *dbg, int pid) {
161 #if __APPLE__
162  return xnu_detach(dbg, pid);
163 #elif __WINDOWS__
164  return w32_detach(dbg, pid);
165 #elif __BSD__
166  return ptrace(PT_DETACH, pid, NULL, 0);
167 #else
168  return rz_debug_ptrace(dbg, PTRACE_DETACH, pid, NULL, (rz_ptrace_data_t)(size_t)0);
169 #endif
170 }
171 
172 #if __WINDOWS__
173 static int rz_debug_native_select(RzDebug *dbg, int pid, int tid) {
174  return w32_select(dbg, pid, tid);
175 }
176 #elif __linux__
177 static int rz_debug_native_select(RzDebug *dbg, int pid, int tid) {
178  return linux_select(dbg, pid, tid);
179 }
180 #endif
181 
182 static int rz_debug_native_continue_syscall(RzDebug *dbg, int pid, int num) {
183 // XXX: num is ignored
184 #if __linux__
186  return rz_debug_ptrace(dbg, PTRACE_SYSCALL, pid, 0, 0);
187 #elif __BSD__
188  ut64 pc = rz_debug_reg_get(dbg, "PC");
189  errno = 0;
190  return ptrace(PTRACE_SYSCALL, pid, (void *)(size_t)pc, 0) == 0;
191 #else
192  eprintf("TODO: continue syscall not implemented yet\n");
193  return -1;
194 #endif
195 }
196 
197 #if !__WINDOWS__ && !__APPLE__ && !__BSD__
198 /* Callback to trigger SIGINT signal */
199 static void interrupt_process(RzDebug *dbg) {
200  rz_debug_kill(dbg, dbg->pid, dbg->tid, SIGINT);
202 }
203 #endif
204 
205 static int rz_debug_native_stop(RzDebug *dbg) {
206 #if __linux__
207  // Stop all running threads except the thread reported by waitpid
208  return linux_stop_threads(dbg, dbg->reason.tid);
209 #else
210  return 0;
211 #endif
212 }
213 
214 /* TODO: specify thread? */
215 /* TODO: must return true/false */
216 static int rz_debug_native_continue(RzDebug *dbg, int pid, int tid, int sig) {
217 #if __APPLE__
218  bool ret = xnu_continue(dbg, pid, tid, sig);
219  if (!ret) {
220  return -1;
221  }
222  return tid;
223 #elif __WINDOWS__
224  return w32_continue(dbg, pid, tid, sig);
225 #elif __BSD__
226  void *data = (void *)(size_t)((sig != -1) ? sig : dbg->reason.signum);
227  ut64 pc = rz_debug_reg_get(dbg, "PC");
228  return ptrace(PTRACE_CONT, pid, (void *)(size_t)pc, (int)(size_t)data) == 0;
229 #else
230  int contsig = dbg->reason.signum;
231  int ret = -1;
232 
233  if (sig != -1) {
234  contsig = sig;
235  }
236  /* SIGINT handler for attached processes: dbg.consbreak (disabled by default) */
237  if (dbg->consbreak) {
238  rz_cons_break_push((RzConsBreak)interrupt_process, dbg);
239  }
240 
242  RzDebugPid *th;
243  RzListIter *it;
244  rz_list_foreach (dbg->threads, it, th) {
245  ret = rz_debug_ptrace(dbg, PTRACE_CONT, th->pid, 0, 0);
246  if (ret) {
247  eprintf("Error: (%d) is running or dead.\n", th->pid);
248  }
249  }
250  } else {
251  ret = rz_debug_ptrace(dbg, PTRACE_CONT, tid, NULL, (rz_ptrace_data_t)(size_t)contsig);
252  if (ret) {
253  rz_sys_perror("PTRACE_CONT");
254  }
255  }
256  // return ret >= 0 ? tid : false;
257  return tid;
258 #endif
259 }
260 
261 static RzDebugInfo *rz_debug_native_info(RzDebug *dbg, const char *arg) {
262 #if __APPLE__
263  return xnu_info(dbg, arg);
264 #elif __WINDOWS__
265  return w32_info(dbg, arg);
266 #elif __linux__
267  return linux_info(dbg, arg);
268 #elif __KFBSD__ || __OpenBSD__ || __NetBSD__
269  return bsd_info(dbg, arg);
270 #else
271  return NULL;
272 #endif
273 }
274 
275 #if __WINDOWS__
276 static bool tracelib(RzDebug *dbg, const char *mode, PLIB_ITEM item) {
277  const char *needle = NULL;
278  int tmp = 0;
279  if (mode) {
280  switch (mode[0]) {
281  case 'l': needle = dbg->glob_libs; break;
282  case 'u': needle = dbg->glob_unlibs; break;
283  }
284  }
285  rz_cons_printf("(%d) %sing library at 0x%p (%s) %s\n", item->pid, mode,
286  item->BaseOfDll, item->Path, item->Name);
287  rz_cons_flush();
288  if (needle && strlen(needle)) {
289  tmp = rz_str_glob(item->Name, needle);
290  }
291  return !mode || !needle || tmp;
292 }
293 #endif
294 
295 /*
296  * Wait for an event and start trying to figure out what to do with it.
297  *
298  * Returns RZ_DEBUG_REASON_*
299  */
300 #if __WINDOWS__
301 static RzDebugReasonType rz_debug_native_wait(RzDebug *dbg, int pid) {
303  // Store the original TID to attempt to switch back after handling events that
304  // require switching to the event's thread that shouldn't bother the user
305  int orig_tid = dbg->tid;
306  bool restore_thread = false;
307  W32DbgWInst *wrap = dbg->plugin_data;
308 
309  if (pid == -1) {
310  RZ_LOG_ERROR("rz_debug_native_wait called with pid -1\n");
311  return RZ_DEBUG_REASON_ERROR;
312  }
313 
314  reason = w32_dbg_wait(dbg, pid);
315  RzDebugInfo *r = rz_debug_native_info(dbg, "");
316  if (reason == RZ_DEBUG_REASON_NEW_LIB) {
317  if (r && r->lib) {
318  if (tracelib(dbg, "load", r->lib)) {
319  reason = RZ_DEBUG_REASON_TRAP;
320  }
321 
322  /* Check if autoload PDB is set, and load PDB information if yes */
323  RzCore *core = dbg->corebind.core;
324  bool autoload_pdb = dbg->corebind.cfggeti(core, "pdb.autoload");
325  if (autoload_pdb) {
326  PLIB_ITEM lib = r->lib;
327  RzBinOptions opts = { 0 };
328  opts.obj_opts.baseaddr = (uintptr_t)lib->BaseOfDll;
329  RzBinFile *cur = rz_bin_cur(core->bin);
330  RzBinFile *bf = rz_bin_open(core->bin, lib->Path, &opts);
331  if (bf) {
332  const RzBinInfo *info = rz_bin_object_get_info(bf->o);
335  dbg->corebind.cmdf(core, "idpd");
336  }
337  dbg->corebind.cmd(core, "idp");
338  }
339  rz_bin_file_set_cur_binfile(core->bin, cur);
340  }
341  }
342  } else {
343  RZ_LOG_WARN("Loading unknown library.\n");
344  }
345  restore_thread = true;
346  } else if (reason == RZ_DEBUG_REASON_EXIT_LIB) {
347  RzDebugInfo *r = rz_debug_native_info(dbg, "");
348  if (r && r->lib) {
349  if (tracelib(dbg, "unload", r->lib)) {
350  reason = RZ_DEBUG_REASON_TRAP;
351  }
352  } else {
353  RZ_LOG_WARN("Unloading unknown library.\n");
354  }
355  restore_thread = true;
356  } else if (reason == RZ_DEBUG_REASON_NEW_PID) {
357  if (r && r->thread) {
358  PTHREAD_ITEM item = r->thread;
359  RZ_LOG_INFO("(%d) Created process %d (start @ %p) (teb @ %p)\n", item->pid, item->tid, item->lpStartAddress, item->lpThreadLocalBase);
360  }
361  } else if (reason == RZ_DEBUG_REASON_NEW_TID) {
362  if (r && r->thread) {
363  PTHREAD_ITEM item = r->thread;
364  RZ_LOG_INFO("(%d) Created thread %d (start @ %p) (teb @ %p)\n", item->pid, item->tid, item->lpStartAddress, item->lpThreadLocalBase);
365  }
366  restore_thread = true;
367  } else if (reason == RZ_DEBUG_REASON_EXIT_TID) {
368  PTHREAD_ITEM item = r->thread;
369  if (r && r->thread) {
370  RZ_LOG_INFO("(%d) Finished thread %d Exit code %lu\n", (ut32)item->pid, (ut32)item->tid, item->dwExitCode);
371  }
372  if (dbg->tid != orig_tid && item->tid != orig_tid) {
373  restore_thread = true;
374  }
375  } else if (reason == RZ_DEBUG_REASON_DEAD) {
376  if (r && r->thread) {
377  PTHREAD_ITEM item = r->thread;
378  RZ_LOG_INFO("(%d) Finished process with exit code %lu\n", dbg->main_pid, item->dwExitCode);
379  }
380  dbg->pid = -1;
381  dbg->tid = -1;
382  } else if (reason == RZ_DEBUG_REASON_USERSUSP && dbg->tid != orig_tid) {
383  if (r && r->thread) {
384  PTHREAD_ITEM item = r->thread;
385  RZ_LOG_INFO("(%d) Created DebugBreak thread %d (start @ %p)\n", item->pid, item->tid, item->lpStartAddress);
386  }
387  // DebugProcessBreak creates a new thread that will trigger a breakpoint. We record the
388  // tid here to ignore it once the breakpoint is hit.
389  wrap->break_tid = dbg->tid;
390  restore_thread = true;
391  } else if (reason == RZ_DEBUG_REASON_BREAKPOINT && dbg->tid == wrap->break_tid) {
392  wrap->break_tid = -2;
393  reason = RZ_DEBUG_REASON_NONE;
394  restore_thread = true;
395  }
397 
398  if (restore_thread) {
399  // Attempt to return to the original thread after handling the event
400  dbg->tid = w32_select(dbg, dbg->pid, orig_tid);
401  if (dbg->tid == -1) {
402  dbg->pid = -1;
403  reason = RZ_DEBUG_REASON_DEAD;
404  } else {
405  if (dbg->tid != orig_tid) {
406  reason = RZ_DEBUG_REASON_UNKNOWN;
407  }
408  }
409  }
410 
411  dbg->reason.tid = pid;
412  dbg->reason.type = reason;
413  return reason;
414 }
415 // FIXME: Should WAIT_ON_ALL_CHILDREN be a compilation flag instead of runtime debug config?
416 #elif __linux__ && !defined(WAIT_ON_ALL_CHILDREN) // __WINDOWS__
417 static RzDebugReasonType rz_debug_native_wait(RzDebug *dbg, int pid) {
419 
420  if (pid == -1) {
421  eprintf("ERROR: rz_debug_native_wait called with pid -1\n");
422  return RZ_DEBUG_REASON_ERROR;
423  }
424 
425  reason = linux_dbg_wait(dbg, dbg->tid);
426  dbg->reason.type = reason;
427  return reason;
428 }
429 #else // if __WINDOWS__ & elif __linux__ && !defined (WAIT_ON_ALL_CHILDREN)
430 static RzDebugReasonType rz_debug_native_wait(RzDebug *dbg, int pid) {
432 
433  if (pid == -1) {
434  eprintf("ERROR: rz_debug_native_wait called with pid -1\n");
435  return RZ_DEBUG_REASON_ERROR;
436  }
437 
438 #if __APPLE__
440  do {
441  reason = xnu_wait(dbg, pid);
442  if (reason == RZ_DEBUG_REASON_MACH_RCV_INTERRUPTED) {
443  if (rz_cons_is_breaked()) {
444  // Perhaps check the inferior is still alive,
445  // otherwise xnu_stop will fail.
446  reason = xnu_stop(dbg, pid)
449  } else {
450  // Weird; we'll retry the wait.
451  continue;
452  }
453  }
454  break;
455  } while (true);
457 #else
458  int status = -1;
459  // XXX: this is blocking, ^C will be ignored
460 #ifdef WAIT_ON_ALL_CHILDREN
461  int ret = waitpid(-1, &status, WAITPID_FLAGS);
462 #else
463  int ret = waitpid(-1, &status, 0);
464  if (ret != -1) {
465  reason = RZ_DEBUG_REASON_TRAP;
466  }
467 #endif // WAIT_ON_ALL_CHILDREN
468  if (ret == -1) {
469  rz_sys_perror("waitpid");
470  return RZ_DEBUG_REASON_ERROR;
471  }
472 
473  // eprintf ("rz_debug_native_wait: status=%d (0x%x) (return=%d)\n", status, status, ret);
474 
475 #ifdef WAIT_ON_ALL_CHILDREN
476  if (ret != pid) {
477  reason = RZ_DEBUG_REASON_NEW_PID;
478  eprintf("switching to pid %d\n", ret);
479  rz_debug_select(dbg, ret, ret);
480  }
481 #endif // WAIT_ON_ALL_CHILDREN
482 
483  // TODO: switch status and handle reasons here
484  // FIXME: Remove linux handling from this function?
485 #if __linux__ && defined(PT_GETEVENTMSG)
486  reason = linux_ptrace_event(dbg, pid, status, true);
487 #endif // __linux__
488 
489  /* propagate errors */
490  if (reason == RZ_DEBUG_REASON_ERROR) {
491  return reason;
492  }
493 
494  /* we don't know what to do yet, let's try harder to figure it out. */
495 #if __FreeBSD__
496  if (reason == RZ_DEBUG_REASON_TRAP) {
497 #else
498  if (reason == RZ_DEBUG_REASON_UNKNOWN) {
499 #endif
500  if (WIFEXITED(status)) {
501  eprintf("child exited with status %d\n", WEXITSTATUS(status));
502  reason = RZ_DEBUG_REASON_DEAD;
503  } else if (WIFSIGNALED(status)) {
504  eprintf("child received signal %d\n", WTERMSIG(status));
505  reason = RZ_DEBUG_REASON_SIGNAL;
506  } else if (WIFSTOPPED(status)) {
507  if (WSTOPSIG(status) != SIGTRAP &&
508  WSTOPSIG(status) != SIGSTOP) {
509  eprintf("Child stopped with signal %d\n", WSTOPSIG(status));
510  }
511 
512  /* the ptrace documentation says GETSIGINFO is only necessary for
513  * differentiating the various stops.
514  *
515  * this might modify dbg->reason.signum
516  */
517 #if __OpenBSD__
519 #else
520  if (rz_debug_handle_signals(dbg) != 0) {
521  return RZ_DEBUG_REASON_ERROR;
522  }
523  reason = dbg->reason.type;
524 #endif
525 #ifdef WIFCONTINUED
526  } else if (WIFCONTINUED(status)) {
527  eprintf("child continued...\n");
528  reason = RZ_DEBUG_REASON_NONE;
529 #endif
530  } else if (status == 1) {
531  /* XXX(jjd): does this actually happen? */
532  eprintf("debugger is dead with status 1!\n");
533  reason = RZ_DEBUG_REASON_DEAD;
534  } else if (status == 0) {
535  /* XXX(jjd): does this actually happen? */
536  eprintf("debugger is dead with status 0\n");
537  reason = RZ_DEBUG_REASON_DEAD;
538  } else {
539  if (ret != pid) {
540  reason = RZ_DEBUG_REASON_NEW_PID;
541  } else {
542  /* ugh. still don't know :-/ */
543  eprintf("returning from wait without knowing why...\n");
544  }
545  }
546  }
547 
548  /* if we still don't know what to do, we have a problem... */
549  if (reason == RZ_DEBUG_REASON_UNKNOWN) {
550  eprintf("%s: no idea what happened...\n", __func__);
551  reason = RZ_DEBUG_REASON_ERROR;
552  }
553 #endif // __APPLE__
554  dbg->reason.tid = pid;
555  dbg->reason.type = reason;
556  return reason;
557 }
558 #endif // __WINDOWS__
559 
560 #undef MAXPID
561 #define MAXPID 99999
562 
563 static RzList *rz_debug_native_tids(RzDebug *dbg, int pid) {
564  printf("TODO: Threads: \n");
565  // T
566  return NULL;
567 }
568 
569 static RzList *rz_debug_native_pids(RzDebug *dbg, int pid) {
570  RzList *list = rz_list_new();
571  if (!list) {
572  return NULL;
573  }
574 #if __APPLE__
575  if (pid) {
577  if (p) {
579  }
580  } else {
581  int i;
582  for (i = 1; i < MAXPID; i++) {
584  if (p) {
586  }
587  }
588  }
589 #elif __WINDOWS__
590  return w32_pid_list(dbg, pid, list);
591 #elif __linux__
592  return linux_pid_list(pid, list);
593 #else /* rest is BSD */
594  return bsd_pid_list(dbg, pid, list);
595 #endif
596  return list;
597 }
598 
599 static RzList *rz_debug_native_threads(RzDebug *dbg, int pid) {
600  RzList *list = rz_list_new();
601  if (!list) {
602  eprintf("No list?\n");
603  return NULL;
604  }
605 #if __APPLE__
606  return xnu_thread_list(dbg, pid, list);
607 #elif __WINDOWS__
608  return w32_thread_list(dbg, pid, list);
609 #elif __linux__
610  return linux_thread_list(dbg, pid, list);
611 #else
612  return bsd_thread_list(dbg, pid, list);
613 #endif
614 }
615 
616 #if __sun || __NetBSD__ || __KFBSD__ || __OpenBSD__ || __DragonFly__
617 
618 // Function to read register from Linux, BSD, Android systems
619 static int bsd_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
620  int showfpu = false;
621  int pid = dbg->pid;
622  int ret;
623  if (type < -1) {
624  showfpu = true; // hack for debugging
625  type = -type;
626  }
627  switch (type) {
628  case RZ_REG_TYPE_DRX:
629 #if __i386__ || __x86_64__
630 #if __KFBSD__
631  {
632  // TODO
633  struct dbreg dbr;
634  ret = ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, sizeof(dbr));
635  if (ret != 0)
636  return false;
637  // XXX: maybe the register map is not correct, must review
638  }
639 #endif
640 #endif
641  return true;
642  break;
643  case RZ_REG_TYPE_FPU:
644  case RZ_REG_TYPE_MMX:
645  case RZ_REG_TYPE_XMM:
646  break;
647  case RZ_REG_TYPE_SEG:
648  case RZ_REG_TYPE_FLG:
649  case RZ_REG_TYPE_GPR: {
651  memset(&regs, 0, sizeof(regs));
652  memset(buf, 0, size);
653 #if __NetBSD__ || __OpenBSD__
654  ret = ptrace(PTRACE_GETREGS, pid, (caddr_t)&regs, sizeof(regs));
655 #elif __KFBSD__
656  ret = ptrace(PT_GETREGS, pid, (caddr_t)&regs, 0);
657 #else
658 #warning not implemented for this platform
659  ret = 1;
660 #endif
661  // if perror here says 'no such process' and the
662  // process exists still.. is because there's a
663  // missing call to 'wait'. and the process is not
664  // yet available to accept more ptrace queries.
665  if (ret != 0)
666  return false;
667  if (sizeof(regs) < size)
668  size = sizeof(regs);
669  memcpy(buf, &regs, size);
670  return sizeof(regs);
671  } break;
672  }
673  return true;
674 }
675 #endif // if __sun || __NetBSD__ || __KFBSD__ || __OpenBSD__
676 
677 // TODO: what about float and hardware regs here ???
678 // TODO: add flag for type
679 static int rz_debug_native_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
680  if (size < 1) {
681  return false;
682  }
683 #if __APPLE__
684  return xnu_reg_read(dbg, type, buf, size);
685 #elif __WINDOWS__
686  return w32_reg_read(dbg, type, buf, size);
687 #elif __linux__
688  return linux_reg_read(dbg, type, buf, size);
689 #elif __sun || __NetBSD__ || __KFBSD__ || __OpenBSD__ || __DragonFly__
690  return bsd_reg_read(dbg, type, buf, size);
691 #else
692 #warning dbg-native not supported for this platform
693  return false;
694 #endif
695 }
696 
697 static int rz_debug_native_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
698  // XXX use switch or so
699  if (type == RZ_REG_TYPE_DRX) {
700 #if __i386__ || __x86_64__
701 #if __APPLE__
702  return xnu_reg_write(dbg, type, buf, size);
703 #elif __WINDOWS__
704  return w32_reg_write(dbg, type, buf, size);
705 #elif __linux__
706  return linux_reg_write(dbg, type, buf, size);
707 #else
708  return bsd_reg_write(dbg, type, buf, size);
709 #endif
710 #else // i386/x86-64
711  return false;
712 #endif
713  } else if (type == RZ_REG_TYPE_GPR) {
714 #if __APPLE__
715  return xnu_reg_write(dbg, type, buf, size);
716 #elif __WINDOWS__
717  return w32_reg_write(dbg, type, buf, size);
718 #elif __linux__
719  return linux_reg_write(dbg, type, buf, size);
720 #elif __sun
721  int ret = ptrace(PTRACE_SETREGS, dbg->pid,
722  (void *)(size_t)buf, sizeof(RZ_DEBUG_REG_T));
723  if (sizeof(RZ_DEBUG_REG_T) < size)
724  size = sizeof(RZ_DEBUG_REG_T);
725  return ret == 0;
726 #else
727  return bsd_reg_write(dbg, type, buf, size);
728 #endif
729  } else if (type == RZ_REG_TYPE_FPU) {
730 #if __linux__
731  return linux_reg_write(dbg, type, buf, size);
732 #elif __APPLE__
733  return false;
734 #elif __WINDOWS__
735  return false;
736 #else
737  return bsd_reg_write(dbg, type, buf, size);
738 #endif
739  } // else eprintf ("TODO: reg_write_non-gpr (%d)\n", type);
740  return false;
741 }
742 
743 #if __linux__
744 static int io_perms_to_prot(int io_perms) {
745  int prot_perms = PROT_NONE;
746 
747  if (io_perms & RZ_PERM_R) {
748  prot_perms |= PROT_READ;
749  }
750  if (io_perms & RZ_PERM_W) {
751  prot_perms |= PROT_WRITE;
752  }
753  if (io_perms & RZ_PERM_X) {
754  prot_perms |= PROT_EXEC;
755  }
756  return prot_perms;
757 }
758 
759 #if __linux__
760 static int sys_thp_mode(void) {
761  size_t i;
762  const char *thp[] = {
763  "/sys/kernel/mm/transparent_hugepage/enabled",
764  "/sys/kernel/mm/redhat_transparent_hugepage/enabled",
765  };
766  int ret = 0;
767 
768  for (i = 0; i < RZ_ARRAY_SIZE(thp); i++) {
769  char *val = rz_file_slurp(thp[i], NULL);
770  if (val) {
771  if (strstr(val, "[madvise]")) {
772  ret = 1;
773  } else if (strstr(val, "[always]")) {
774  ret = 2;
775  }
776  free(val);
777  break;
778  }
779  }
780 
781  return ret;
782 }
783 #endif
784 
785 static int linux_map_thp(RzDebug *dbg, ut64 addr, int size) {
786 #if !defined(__ANDROID__) && defined(MADV_HUGEPAGE)
787  RzBuffer *buf = NULL;
788  char code[1024];
789  int ret = true;
790  char *asm_list[] = {
791  "x86", "x86.as",
792  "x64", "x86.as",
793  NULL
794  };
795  // In architectures where rizin is supported, arm and x86, it is 2MB
796  const size_t thpsize = 1 << 21;
797 
798  if ((size % thpsize)) {
799  eprintf("size not a power of huge pages size\n");
800  return false;
801  }
802 
803 #if __linux__
804  // In always mode, is more into mmap syscall level
805  // even though the address might not have the 'hg'
806  // vmflags
807  if (sys_thp_mode() != 1) {
808  eprintf("transparent huge page mode is not in madvise mode\n");
809  return false;
810  }
811 #endif
812 
813  int num = rz_syscall_get_num(dbg->analysis->syscall, "madvise");
814 
815  snprintf(code, sizeof(code),
816  "sc_madvise@syscall(%d);\n"
817  "main@naked(0) { .rarg0 = sc_madvise(0x%08" PFMT64x ",%d, %d);break;\n"
818  "}\n",
819  num, addr, size, MADV_HUGEPAGE);
820  rz_egg_reset(dbg->egg);
821  rz_egg_setup(dbg->egg, dbg->arch, 8 * dbg->bits, 0, 0);
822  rz_egg_load(dbg->egg, code, 0);
823  if (!rz_egg_compile(dbg->egg)) {
824  eprintf("Cannot compile.\n");
825  goto err_linux_map_thp;
826  }
827  if (!rz_egg_assemble_asm(dbg->egg, asm_list)) {
828  eprintf("rz_egg_assemble: invalid assembly\n");
829  goto err_linux_map_thp;
830  }
832  if (buf) {
834  ut64 tmpsz;
835  const ut8 *tmp = rz_buf_data(buf, &tmpsz);
836  ret = rz_debug_execute(dbg, tmp, tmpsz, 1) == 0;
838  }
839 err_linux_map_thp:
840  return ret;
841 #else
842  return false;
843 #endif
844 }
845 
846 static RzDebugMap *linux_map_alloc(RzDebug *dbg, ut64 addr, int size, bool thp) {
847  RzBuffer *buf = NULL;
848  RzDebugMap *map = NULL;
849  char code[1024], *sc_name;
850  int num;
851  /* force to usage of x86.as, not yet working x86.nz */
852  char *asm_list[] = {
853  "x86", "x86.as",
854  "x64", "x86.as",
855  NULL
856  };
857 
858  /* NOTE: Since kernel 2.4, that system call has been superseded by
859  mmap2(2 and nowadays the glibc mmap() wrapper function invokes
860  mmap2(2)). If arch is x86_32 then usage mmap2() */
861  if (!strcmp(dbg->arch, "x86") && dbg->bits == 4) {
862  sc_name = "mmap2";
863  } else {
864  sc_name = "mmap";
865  }
866  num = rz_syscall_get_num(dbg->analysis->syscall, sc_name);
867 #ifndef MAP_ANONYMOUS
868 #define MAP_ANONYMOUS 0x20
869 #endif
870  snprintf(code, sizeof(code),
871  "sc_mmap@syscall(%d);\n"
872  "main@naked(0) { .rarg0 = sc_mmap(0x%08" PFMT64x ",%d,%d,%d,%d,%d);break;\n"
873  "}\n",
875  rz_egg_reset(dbg->egg);
876  rz_egg_setup(dbg->egg, dbg->arch, 8 * dbg->bits, 0, 0);
877  rz_egg_load(dbg->egg, code, 0);
878  if (!rz_egg_compile(dbg->egg)) {
879  eprintf("Cannot compile.\n");
880  goto err_linux_map_alloc;
881  }
882  if (!rz_egg_assemble_asm(dbg->egg, asm_list)) {
883  eprintf("rz_egg_assemble: invalid assembly\n");
884  goto err_linux_map_alloc;
885  }
887  if (buf) {
888  ut64 map_addr;
889 
891  ut64 tmpsz;
892  const ut8 *tmp = rz_buf_data(buf, &tmpsz);
893  map_addr = rz_debug_execute(dbg, tmp, tmpsz, 1);
895  if (map_addr != (ut64)-1) {
896  if (thp) {
897  if (!linux_map_thp(dbg, map_addr, size)) {
898  // Not overly dramatic
899  eprintf("map promotion to huge page failed\n");
900  }
901  }
903  map = rz_debug_map_get(dbg, map_addr);
904  }
905  }
906 err_linux_map_alloc:
907  return map;
908 }
909 
910 static int linux_map_dealloc(RzDebug *dbg, ut64 addr, int size) {
911  RzBuffer *buf = NULL;
912  char code[1024];
913  int ret = 0;
914  char *asm_list[] = {
915  "x86", "x86.as",
916  "x64", "x86.as",
917  NULL
918  };
919  int num = rz_syscall_get_num(dbg->analysis->syscall, "munmap");
920 
921  snprintf(code, sizeof(code),
922  "sc_munmap@syscall(%d);\n"
923  "main@naked(0) { .rarg0 = sc_munmap(0x%08" PFMT64x ",%d);break;\n"
924  "}\n",
925  num, addr, size);
926  rz_egg_reset(dbg->egg);
927  rz_egg_setup(dbg->egg, dbg->arch, 8 * dbg->bits, 0, 0);
928  rz_egg_load(dbg->egg, code, 0);
929  if (!rz_egg_compile(dbg->egg)) {
930  eprintf("Cannot compile.\n");
931  goto err_linux_map_dealloc;
932  }
933  if (!rz_egg_assemble_asm(dbg->egg, asm_list)) {
934  eprintf("rz_egg_assemble: invalid assembly\n");
935  goto err_linux_map_dealloc;
936  }
938  if (buf) {
940  ut64 tmpsz;
941  const ut8 *tmp = rz_buf_data(buf, &tmpsz);
942  ret = rz_debug_execute(dbg, tmp, tmpsz, 1) == 0;
944  }
945 err_linux_map_dealloc:
946  return ret;
947 }
948 #endif
949 
950 static RzDebugMap *rz_debug_native_map_alloc(RzDebug *dbg, ut64 addr, int size, bool thp) {
951 #if __APPLE__
952  (void)thp;
953  return xnu_map_alloc(dbg, addr, size);
954 #elif __WINDOWS__
955  (void)thp;
956  return w32_map_alloc(dbg, addr, size);
957 #elif __linux__
958  return linux_map_alloc(dbg, addr, size, thp);
959 #else
960  // malloc not implemented for this platform
961  return NULL;
962 #endif
963 }
964 
965 static int rz_debug_native_map_dealloc(RzDebug *dbg, ut64 addr, int size) {
966 #if __APPLE__
967  return xnu_map_dealloc(dbg, addr, size);
968 #elif __WINDOWS__
969  return w32_map_dealloc(dbg, addr, size);
970 #elif __linux__
971  return linux_map_dealloc(dbg, addr, size);
972 #else
973  // mdealloc not implemented for this platform
974  return false;
975 #endif
976 }
977 
978 #if !__WINDOWS__ && !__APPLE__
979 static void _map_free(RzDebugMap *map) {
980  if (!map) {
981  return;
982  }
983  free(map->name);
984  free(map->file);
985  free(map);
986 }
987 #endif
988 
990  RzList *list = NULL;
991 #if __KFBSD__
992  int ign;
993  char unkstr[128];
994 #endif
995 #if __APPLE__
996  list = xnu_dbg_maps(dbg, 0);
997 #elif __WINDOWS__
999 #else
1000 #if __sun
1001  char path[1024];
1002  /* TODO: On solaris parse /proc/%d/map */
1003  snprintf(path, sizeof(path) - 1, "pmap %d >&2", ps.tid);
1005 #else
1006  RzDebugMap *map;
1007  int i, perm, unk = 0;
1008  char *pos_c;
1009  char path[1024], line[1024], name[1024];
1010  char region[100], region2[100], perms[5];
1011  FILE *fd;
1012  if (dbg->pid == -1) {
1013  // eprintf ("rz_debug_native_map_get: No selected pid (-1)\n");
1014  return NULL;
1015  }
1016  /* prepend 0x prefix */
1017  region[0] = region2[0] = '0';
1018  region[1] = region2[1] = 'x';
1019 
1020 #if __OpenBSD__
1021  /* OpenBSD has no procfs, so no idea trying. */
1022  return bsd_native_sysctl_map(dbg);
1023 #endif
1024 
1025 #if __KFBSD__
1027  if (list) {
1028  return list;
1029  }
1030  snprintf(path, sizeof(path), "/proc/%d/map", dbg->pid);
1031 #else
1032  snprintf(path, sizeof(path), "/proc/%d/maps", dbg->pid);
1033 #endif
1034  fd = rz_sys_fopen(path, "r");
1035  if (!fd) {
1036  perror(sdb_fmt("Cannot open '%s'", path));
1037  return NULL;
1038  }
1039 
1040  list = rz_list_new();
1041  if (!list) {
1042  fclose(fd);
1043  return NULL;
1044  }
1045  list->free = (RzListFree)_map_free;
1046  while (!feof(fd)) {
1047  size_t line_len;
1048  bool map_is_shared = false;
1049  ut64 map_start, map_end;
1050 
1051  if (!fgets(line, sizeof(line), fd)) {
1052  break;
1053  }
1054  /* kill the newline if we got one */
1055  line_len = strlen(line);
1056  if (line[line_len - 1] == '\n') {
1057  line[line_len - 1] = '\0';
1058  line_len--;
1059  }
1060  /* maps files should not have empty lines */
1061  if (line_len == 0) {
1062  break;
1063  }
1064 #if __KFBSD__
1065  // 0x8070000 0x8072000 2 0 0xc1fde948 rw- 1 0 0x2180 COW NC vnode /usr/bin/gcc
1066  if (sscanf(line, "%s %s %d %d 0x%s %3s %d %d",
1067  &region[2], &region2[2], &ign, &ign,
1068  unkstr, perms, &ign, &ign) != 8) {
1069  eprintf("%s: Unable to parse \"%s\"\n", __func__, path);
1070  rz_list_free(list);
1071  return NULL;
1072  }
1073 
1074  /* snag the file name */
1075  pos_c = strchr(line, '/');
1076  if (pos_c) {
1077  strncpy(name, pos_c, sizeof(name) - 1);
1078  } else {
1079  name[0] = '\0';
1080  }
1081 #else
1082  ut64 offset = 0;
1083  ;
1084  // 7fc8124c4000-7fc81278d000 r--p 00000000 fc:00 17043921 /usr/lib/locale/locale-archive
1085  i = sscanf(line, "%s %s %08" PFMT64x " %*s %*s %[^\n]", &region[2], perms, &offset, name);
1086  if (i == 3) {
1087  name[0] = '\0';
1088  } else if (i != 4) {
1089  eprintf("%s: Unable to parse \"%s\"\n", __func__, path);
1090  eprintf("%s: problematic line: %s\n", __func__, line);
1091  rz_list_free(list);
1092  return NULL;
1093  }
1094 
1095  /* split the region in two */
1096  pos_c = strchr(&region[2], '-');
1097  if (!pos_c) { // should this be an error?
1098  continue;
1099  }
1100  strncpy(&region2[2], pos_c + 1, sizeof(region2) - 2 - 1);
1101 #endif // __KFBSD__
1102  if (!*name) {
1103  snprintf(name, sizeof(name), "unk%d", unk++);
1104  }
1105  perm = 0;
1106  for (i = 0; i < 5 && perms[i]; i++) {
1107  switch (perms[i]) {
1108  case 'r': perm |= RZ_PERM_R; break;
1109  case 'w': perm |= RZ_PERM_W; break;
1110  case 'x': perm |= RZ_PERM_X; break;
1111  case 'p': map_is_shared = false; break;
1112  case 's': map_is_shared = true; break;
1113  }
1114  }
1115 
1116  map_start = rz_num_get(NULL, region);
1117  map_end = rz_num_get(NULL, region2);
1118  if (map_start == map_end || map_end == 0) {
1119  eprintf("%s: ignoring invalid map size: %s - %s\n", __func__, region, region2);
1120  continue;
1121  }
1122  map = rz_debug_map_new(name, map_start, map_end, perm, 0);
1123  if (!map) {
1124  break;
1125  }
1126 #if __linux__
1127  map->offset = offset;
1128  map->shared = map_is_shared;
1129 #endif
1130  map->file = strdup(name);
1132  }
1133  fclose(fd);
1134 #endif // __sun
1135 #endif // __APPLE__
1136  return list;
1137 }
1138 
1139 static RzList *rz_debug_native_modules_get(RzDebug *dbg) {
1140  char *lastname = NULL;
1141  RzDebugMap *map;
1142  RzListIter *iter, *iter2;
1143  RzList *list, *last;
1144  bool must_delete;
1145 #if __APPLE__
1146  list = xnu_dbg_maps(dbg, 1);
1147  if (list && !rz_list_empty(list)) {
1148  return list;
1149  }
1150 #elif __WINDOWS__
1152  if (list && !rz_list_empty(list)) {
1153  return list;
1154  }
1155 #endif
1156  if (!(list = rz_debug_native_map_get(dbg))) {
1157  return NULL;
1158  }
1159  if (!(last = rz_list_newf((RzListFree)rz_debug_map_free))) {
1160  rz_list_free(list);
1161  return NULL;
1162  }
1163  rz_list_foreach_safe (list, iter, iter2, map) {
1164  const char *file = map->file;
1165  if (!map->file) {
1166  file = map->file = strdup(map->name);
1167  }
1168  must_delete = true;
1169  if (file && *file == '/') {
1170  if (!lastname || strcmp(lastname, file)) {
1171  must_delete = false;
1172  }
1173  }
1174  if (must_delete) {
1176  } else {
1177  rz_list_append(last, map);
1178  free(lastname);
1179  lastname = strdup(file);
1180  }
1181  }
1182  list->free = NULL;
1183  free(lastname);
1184  rz_list_free(list);
1185  return last;
1186 }
1187 
1188 static bool rz_debug_native_kill(RzDebug *dbg, int pid, int tid, int sig) {
1189  bool ret = false;
1190  if (pid == 0) {
1191  pid = dbg->pid;
1192  }
1193 #if __WINDOWS__
1194  ret = w32_kill(dbg, pid, tid, sig);
1195 #else
1196 #if 0
1197  if (thread) {
1198 // XXX this is linux>2.5 specific..ugly
1199  if (dbg->tid>0 && (ret = tgkill (dbg->pid, dbg->tid, sig))) {
1200  if (ret != -1)
1201  ret = true;
1202  }
1203  } else {
1204 #endif
1205  if (sig == SIGKILL && dbg->threads) {
1207  dbg->threads = NULL;
1208  }
1209  if ((rz_sys_kill(pid, sig) != -1)) {
1210  ret = true;
1211  }
1212  if (errno == 1) {
1213  ret = -true; // EPERM
1214  }
1215 #if 0
1216 // }
1217 #endif
1218 #endif
1219  return ret;
1220 }
1221 
1222 struct rz_debug_desc_plugin_t rz_debug_desc_plugin_native;
1223 static bool rz_debug_native_init(RzDebug *dbg, void **user) {
1224  dbg->cur->desc = rz_debug_desc_plugin_native;
1225 #if __WINDOWS__
1226  return w32_init(dbg);
1227 #else
1228  return true;
1229 #endif
1230 }
1231 
1232 #if __i386__ || __x86_64__
1233 static void sync_drx_regs(RzDebug *dbg, drxt *regs, size_t num_regs) {
1234  /* sanity check, we rely on this assumption */
1235  if (num_regs != NUM_DRX_REGISTERS) {
1236  eprintf("drx: Unsupported number of registers for get_debug_regs\n");
1237  return;
1238  }
1239 
1240  // sync drx regs
1241 #define R dbg->reg
1242  regs[0] = rz_reg_getv(R, "dr0");
1243  regs[1] = rz_reg_getv(R, "dr1");
1244  regs[2] = rz_reg_getv(R, "dr2");
1245  regs[3] = rz_reg_getv(R, "dr3");
1246  /*
1247  RESERVED
1248  regs[4] = rz_reg_getv (R, "dr4");
1249  regs[5] = rz_reg_getv (R, "dr5");
1250 */
1251  regs[6] = rz_reg_getv(R, "dr6");
1252  regs[7] = rz_reg_getv(R, "dr7");
1253 }
1254 #endif
1255 
1256 #if __i386__ || __x86_64__
1257 static void set_drx_regs(RzDebug *dbg, drxt *regs, size_t num_regs) {
1258  /* sanity check, we rely on this assumption */
1259  if (num_regs != NUM_DRX_REGISTERS) {
1260  eprintf("drx: Unsupported number of registers for get_debug_regs\n");
1261  return;
1262  }
1263 
1264 #define R dbg->reg
1265  rz_reg_setv(R, "dr0", regs[0]);
1266  rz_reg_setv(R, "dr1", regs[1]);
1267  rz_reg_setv(R, "dr2", regs[2]);
1268  rz_reg_setv(R, "dr3", regs[3]);
1269  rz_reg_setv(R, "dr6", regs[6]);
1270  rz_reg_setv(R, "dr7", regs[7]);
1271 }
1272 #endif
1273 
1274 static int rz_debug_native_drx(RzDebug *dbg, int n, ut64 addr, int sz, int rwx, int g, int api_type) {
1275 #if __i386__ || __x86_64__
1276  int retval = false;
1277  drxt regs[NUM_DRX_REGISTERS] = { 0 };
1278  // sync drx regs
1279  sync_drx_regs(dbg, regs, NUM_DRX_REGISTERS);
1280 
1281  switch (api_type) {
1282  case DRX_API_LIST:
1283  drx_list(regs);
1284  retval = false;
1285  break;
1286  case DRX_API_GET_BP:
1287  /* get the index of the breakpoint at addr */
1288  retval = drx_get_at(regs, addr);
1289  break;
1290  case DRX_API_REMOVE_BP:
1291  /* remove hardware breakpoint */
1292  drx_set(regs, n, addr, -1, 0, 0);
1293  retval = true;
1294  break;
1295  case DRX_API_SET_BP:
1296  /* set hardware breakpoint */
1297  drx_set(regs, n, addr, sz, rwx, g);
1298  retval = true;
1299  break;
1300  default:
1301  /* this should not happen, someone misused the API */
1302  eprintf("drx: Unsupported api type in rz_debug_native_drx\n");
1303  retval = false;
1304  }
1305 
1306  set_drx_regs(dbg, regs, NUM_DRX_REGISTERS);
1307 
1308  return retval;
1309 #else
1310  eprintf("drx: Unsupported platform\n");
1311 #endif
1312  return -1;
1313 }
1314 
1315 #if __linux__
1316 
1317 #if __arm__ || __arm64__ || __aarch64__
1318 #include <sys/prctl.h>
1319 #include <sys/uio.h>
1320 
1321 #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
1322 #define NT_ARM_TLS 0x401 /* ARM TLS register */
1323 #define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */
1324 #define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
1325 #define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
1326 
1327 #ifndef PTRACE_GETHBPREGS
1328 #define PTRACE_GETHBPREGS 29
1329 #define PTRACE_SETHBPREGS 30
1330 #endif
1331 
1332 #if __arm__
1333 
1334 static bool ll_arm32_hwbp_set(pid_t pid, ut64 addr, int size, int wp, int type) {
1335  const unsigned byte_mask = (1 << size) - 1;
1336  // const unsigned type = 2; // Write.
1337  const unsigned enable = 1;
1338  const unsigned control = byte_mask << 5 | type << 3 | enable;
1339  (void)ptrace(PTRACE_SETHBPREGS, pid, -1, (void *)(size_t)addr);
1340  return ptrace(PTRACE_SETHBPREGS, pid, -2, &control) != -1;
1341 }
1342 
1343 static bool arm32_hwbp_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
1344  return ll_arm32_hwbp_set(dbg->pid, b->addr, b->size, 0, 1 | 2 | 4);
1345 }
1346 
1347 static bool arm32_hwbp_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
1348  return false; // TODO: hwbp.del not yetimplemented
1349 }
1350 #endif // PTRACE_GETHWBPREGS
1351 #endif // __arm
1352 
1353 #if (__arm64__ || __aarch64__) && defined(PTRACE_GETREGSET)
1354 // type = 2 = write
1355 // static volatile uint8_t var[96] __attribute__((__aligned__(32)));
1356 
1357 static bool ll_arm64_hwbp_set(pid_t pid, ut64 _addr, int size, int wp, ut32 type) {
1358  const volatile uint8_t *addr = (void *)(size_t)_addr; //&var[32 + wp];
1359  const unsigned int offset = (uintptr_t)addr % 8;
1360  const ut32 byte_mask = ((1 << size) - 1) << offset;
1361  const ut32 enable = 1;
1362  const ut32 control = byte_mask << 5 | type << 3 | enable;
1363 
1364  struct user_hwdebug_state dreg_state = { 0 };
1365  struct iovec iov = { 0 };
1366  iov.iov_base = &dreg_state;
1367  iov.iov_len = sizeof(dreg_state);
1368 
1369  if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_HW_WATCH, &iov) == -1) {
1370  // error reading regs
1371  }
1372  memcpy(&dreg_state, iov.iov_base, sizeof(dreg_state));
1373  // wp is not honored here i think... we can't have more than one wp for now..
1374  dreg_state.dbg_regs[0].addr = (uintptr_t)(addr - offset);
1375  dreg_state.dbg_regs[0].ctrl = control;
1376  iov.iov_base = &dreg_state;
1377  iov.iov_len = rz_offsetof(struct user_hwdebug_state, dbg_regs) +
1378  sizeof(dreg_state.dbg_regs[0]);
1379  if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0) {
1380  return true;
1381  }
1382 
1383  if (errno == EIO) {
1384  eprintf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) not supported on this hardware: %s\n",
1385  strerror(errno));
1386  }
1387 
1388  eprintf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed: %s\n", strerror(errno));
1389  return false;
1390 }
1391 
1392 static bool ll_arm64_hwbp_del(pid_t pid, ut64 _addr, int size, int wp, ut32 type) {
1393  // const volatile uint8_t *addr = &var[32 + wp];
1394  // TODO: support multiple watchpoints and find
1395  struct user_hwdebug_state dreg_state = { 0 };
1396  struct iovec iov = { 0 };
1397  iov.iov_base = &dreg_state;
1398  // only delete 1 bp for now
1399  iov.iov_len = rz_offsetof(struct user_hwdebug_state, dbg_regs) +
1400  sizeof(dreg_state.dbg_regs[0]);
1401  if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0) {
1402  return true;
1403  }
1404  if (errno == EIO) {
1405  eprintf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) not supported on this hardware: %s\n",
1406  strerror(errno));
1407  }
1408 
1409  eprintf("ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed: %s\n", strerror(errno));
1410  return false;
1411 }
1412 
1413 static bool arm64_hwbp_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
1414  return ll_arm64_hwbp_set(dbg->pid, b->addr, b->size, 0, 1 | 2 | 4);
1415 }
1416 
1417 static bool arm64_hwbp_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b) {
1418  return ll_arm64_hwbp_del(dbg->pid, b->addr, b->size, 0, 1 | 2 | 4);
1419 }
1420 
1421 #endif // __arm64__
1422 #endif // __linux__
1423 
1424 /*
1425  * set or unset breakpoints...
1426  *
1427  * we only handle the case for hardware breakpoints here. otherwise,
1428  * we let the caller handle the work.
1429  */
1430 static int rz_debug_native_bp(RzBreakpoint *bp, RzBreakpointItem *b, bool set) {
1431  RzDebug *dbg = bp->user;
1432  if (b && b->hw) {
1433 #if __i386__ || __x86_64__
1434  return set
1435  ? drx_add(dbg, bp, b)
1436  : drx_del(dbg, bp, b);
1437 #elif (__arm64__ || __aarch64__) && __linux__
1438  return set
1439  ? arm64_hwbp_add(dbg, bp, b)
1440  : arm64_hwbp_del(dbg, bp, b);
1441 #elif __WINDOWS__
1442  return set
1443  ? w32_hwbp_arm_add(dbg, bp, b)
1444  : w32_hwbp_arm_del(dbg, bp, b);
1445 #elif __arm__ && __linux__
1446  return set
1447  ? arm32_hwbp_add(dbg, bp, b)
1448  : arm32_hwbp_del(dbg, bp, b);
1449 #elif __riscv
1450  dbg = NULL;
1451  return false;
1452 #endif
1453  }
1454  return false;
1455 }
1456 
1457 #if __APPLE__
1458 
1459 static int getMaxFiles(void) {
1460  struct rlimit limit;
1461  if (getrlimit(RLIMIT_NOFILE, &limit) != 0) {
1462  return 1024;
1463  }
1464  return limit.rlim_cur;
1465 }
1466 
1467 static RzList *xnu_desc_list(int pid) {
1468 #if TARGET_OS_IPHONE || __POWERPC__
1469  return NULL;
1470 #else
1471 #define xwrz_testwx(x) ((x & 1) << 2) | (x & 2) | ((x & 4) >> 2)
1472  RzDebugDesc *desc;
1473  RzList *ret = rz_list_new();
1474  struct vnode_fdinfowithpath vi;
1475  int i, nb, type = 0;
1476  int maxfd = getMaxFiles();
1477 
1478  for (i = 0; i < maxfd; i++) {
1479  nb = proc_pidfdinfo(pid, i, PROC_PIDFDVNODEPATHINFO, &vi, sizeof(vi));
1480  if (nb < 1) {
1481  continue;
1482  }
1483  if (nb < sizeof(vi)) {
1484  perror("too few bytes");
1485  break;
1486  }
1487  // printf ("FD %d RWX %x ", i, vi.pfi.fi_openflags);
1488  // printf ("PATH %s\n", vi.pvip.vip_path);
1490  vi.pvip.vip_path,
1491  xwrz_testwx(vi.pfi.fi_openflags),
1492  type, 0);
1493  rz_list_append(ret, desc);
1494  }
1495  return ret;
1496 #endif
1497 }
1498 #endif
1499 
1500 static RzList *rz_debug_desc_native_list(int pid) {
1501 #if __APPLE__
1502  return xnu_desc_list(pid);
1503 #elif __WINDOWS__
1504  return w32_desc_list(pid);
1505 #elif __KFBSD__ || __NetBSD__
1506  return bsd_desc_list(pid);
1507 #elif __linux__
1508  return linux_desc_list(pid);
1509 #else
1510 #warning list filedescriptors not supported for this platform
1511  return NULL;
1512 #endif
1513 }
1514 
1515 static int rz_debug_native_map_protect(RzDebug *dbg, ut64 addr, int size, int perms) {
1516 #if __WINDOWS__
1517  return w32_map_protect(dbg, addr, size, perms);
1518 #elif __APPLE__
1519  return xnu_map_protect(dbg, addr, size, perms);
1520 #elif __linux__
1521  RzBuffer *buf = NULL;
1522  char code[1024];
1523  int num;
1524 
1525  num = rz_syscall_get_num(dbg->analysis->syscall, "mprotect");
1526  snprintf(code, sizeof(code),
1527  "sc@syscall(%d);\n"
1528  "main@global(0) { sc(%p,%d,%d);\n"
1529  ":int3\n"
1530  "}\n",
1531  num, (void *)(size_t)addr, size, io_perms_to_prot(perms));
1532 
1533  rz_egg_reset(dbg->egg);
1534  rz_egg_setup(dbg->egg, dbg->arch, 8 * dbg->bits, 0, 0);
1535  rz_egg_load(dbg->egg, code, 0);
1536  if (!rz_egg_compile(dbg->egg)) {
1537  eprintf("Cannot compile.\n");
1538  return false;
1539  }
1540  if (!rz_egg_assemble(dbg->egg)) {
1541  eprintf("rz_egg_assemble: invalid assembly\n");
1542  return false;
1543  }
1544  buf = rz_egg_get_bin(dbg->egg);
1545  if (buf) {
1547  ut64 tmpsz;
1548  const ut8 *tmp = rz_buf_data(buf, &tmpsz);
1549  rz_debug_execute(dbg, tmp, tmpsz, 1);
1551  return true;
1552  }
1553 
1554  return false;
1555 #else
1556  // mprotect not implemented for this platform
1557  return false;
1558 #endif
1559 }
1560 
1561 static int rz_debug_desc_native_open(const char *path) {
1562  return 0;
1563 }
1564 
1565 #if 0
1566 static int rz_debug_setup_ownership (int fd, RzDebug *dbg) {
1568 
1569  if (!info) {
1570  eprintf ("Error while getting debug info.\n");
1571  return -1;
1572  }
1573  fchown (fd, info->uid, info->gid);
1575  return 0;
1576 }
1577 #endif
1578 
1579 static bool rz_debug_gcore(RzDebug *dbg, char *path, RzBuffer *dest) {
1580 #if __APPLE__
1581  (void)path;
1582  return xnu_generate_corefile(dbg, dest);
1583 #elif __linux__ && (__x86_64__ || __i386__ || __arm__ || __arm64__)
1584  (void)path;
1585 #if __ANDROID__
1586  return false;
1587 #else
1588  return linux_generate_corefile(dbg, dest);
1589 #endif
1590 #elif __KFBSD__ || __NetBSD__
1591  return bsd_generate_corefile(dbg, path, dest);
1592 #else
1593  return false;
1594 #endif
1595 }
1596 
1597 struct rz_debug_desc_plugin_t rz_debug_desc_plugin_native = {
1598  .open = rz_debug_desc_native_open,
1599  .list = rz_debug_desc_native_list,
1600 };
1601 
1603  .name = "native",
1604  .license = "LGPL3",
1605 #if __i386__
1606  .bits = RZ_SYS_BITS_32,
1607  .arch = "x86",
1608  .canstep = 1,
1609 #elif __x86_64__
1610  .bits = RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
1611  .arch = "x86",
1612  .canstep = 1, // XXX it's 1 on some platforms...
1613 #elif __aarch64__ || __arm64__
1615  .arch = "arm",
1616 #if __WINDOWS__
1617  .canstep = 0,
1618 #else
1619  .canstep = 1,
1620 #endif
1621 #elif __arm__
1623  .arch = "arm",
1624  .canstep = 0,
1625 #elif __mips__
1626  .bits = RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
1627  .arch = "mips",
1628  .canstep = 0,
1629 #elif __powerpc__
1630 #if __powerpc64__
1631  .bits = RZ_SYS_BITS_32 | RZ_SYS_BITS_64,
1632 #else
1633  .bits = RZ_SYS_BITS_32,
1634 #endif
1635  .arch = "ppc",
1636  .canstep = 1,
1637 #else
1638  .bits = 0,
1639  .arch = 0,
1640  .canstep = 0,
1641 #ifdef _MSC_VER
1642 #pragma message("Unsupported architecture")
1643 #else
1644 #warning Unsupported architecture
1645 #endif
1646 #endif
1647  .init = &rz_debug_native_init,
1648  .step = &rz_debug_native_step,
1649  .cont = &rz_debug_native_continue,
1650  .stop = &rz_debug_native_stop,
1651  .contsc = &rz_debug_native_continue_syscall,
1652  .attach = &rz_debug_native_attach,
1653  .detach = &rz_debug_native_detach,
1654 // TODO: add native select for other platforms?
1655 #if __WINDOWS__ || __linux__
1656  .select = &rz_debug_native_select,
1657 #endif
1658  .pids = &rz_debug_native_pids,
1659  .tids = &rz_debug_native_tids,
1660  .threads = &rz_debug_native_threads,
1661  .wait = &rz_debug_native_wait,
1662  .kill = &rz_debug_native_kill,
1663  .frames = &rz_debug_native_frames, // rename to backtrace ?
1664  .reg_profile = rz_debug_native_reg_profile,
1665  .reg_read = rz_debug_native_reg_read,
1666  .info = rz_debug_native_info,
1667  .reg_write = (void *)&rz_debug_native_reg_write,
1668  .map_alloc = rz_debug_native_map_alloc,
1669  .map_dealloc = rz_debug_native_map_dealloc,
1670  .map_get = rz_debug_native_map_get,
1671  .modules_get = rz_debug_native_modules_get,
1672  .map_protect = rz_debug_native_map_protect,
1673  .breakpoint = rz_debug_native_bp,
1674  .drx = rz_debug_native_drx,
1675  .gcore = rz_debug_gcore,
1676 };
1677 
1678 #ifndef RZ_PLUGIN_INCORE
1680  .type = RZ_LIB_TYPE_DBG,
1681  .data = &rz_debug_plugin_native,
1682  .version = RZ_VERSION
1683 };
1684 #endif // RZ_PLUGIN_INCORE
1685 
1686 //#endif
1687 #else // DEBUGGER
1689  NULL // .name = "native",
1690 };
1691 
1692 #endif // DEBUGGER
RZ_API RzLibStruct rizin_plugin
static char * regs[]
Definition: analysis_sh.c:203
lzma_index ** i
Definition: index.h:629
#define R(x, b, m)
Definition: arc.h:168
RZ_API int rz_reg_arena_push(RzReg *reg)
Definition: arena.c:236
RZ_API void rz_reg_arena_pop(RzReg *reg)
Definition: arena.c:216
ut16 val
Definition: armass64_const.h:6
RZ_API bool rz_bin_file_set_cur_binfile(RzBin *bin, RzBinFile *bf)
Definition: bfile.c:288
RZ_API RzBinFile * rz_bin_open(RzBin *bin, const char *file, RzBinOptions *opt)
Definition: bin.c:200
RZ_API RzBinFile * rz_bin_cur(RzBin *bin)
Definition: bin.c:895
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
const char * desc
Definition: bin_vsf.c:19
RZ_API const RzBinInfo * rz_bin_object_get_info(RZ_NONNULL RzBinObject *obj)
Get the RzBinInfo of the binary object.
Definition: bobj.c:734
RzList * bsd_desc_list(int pid)
Definition: bsd_debug.c:444
int bsd_handle_signals(RzDebug *dbg)
Definition: bsd_debug.c:65
RzList * bsd_pid_list(RzDebug *dbg, int pid, RzList *list)
Definition: bsd_debug.c:281
RzList * bsd_native_sysctl_map(RzDebug *dbg)
Definition: bsd_debug.c:353
int bsd_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
Definition: bsd_debug.c:119
RzList * bsd_thread_list(RzDebug *dbg, int pid, RzList *list)
Definition: bsd_debug.c:637
bool bsd_generate_corefile(RzDebug *dbg, char *path, RzBuffer *dest)
Definition: bsd_debug.c:139
RzDebugInfo * bsd_info(RzDebug *dbg, const char *arg)
Definition: bsd_debug.c:149
#define RZ_DEBUG_REG_T
Definition: bsd_debug.h:8
static RzList * rz_debug_native_frames(RzDebug *dbg, ut64 at)
Definition: bt.c:46
#define SIGKILL
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
RZ_API RzDebugDesc * rz_debug_desc_new(int fd, char *path, int perm, int type, int off)
Definition: ddesc.c:8
static char * rz_debug_native_reg_profile(RzDebug *dbg)
Definition: reg.c:7
static RzList * rz_debug_native_map_get(RzDebug *dbg)
Definition: debug_bf.c:173
#define WAITPID_FLAGS
Definition: debug_native.c:83
RzDebugPlugin rz_debug_plugin_native
static int rz_debug_native_continue(RzDebug *dbg, int pid, int tid, int sig)
static int rz_debug_native_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
static int rz_debug_native_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
uint32_t ut32
RzDebug * dbg
Definition: desil.c:30
RZ_API RzDebugMap * rz_debug_map_get(RzDebug *dbg, ut64 addr)
Definition: dmap.c:65
RZ_API void rz_debug_map_free(RzDebugMap *map)
Definition: dmap.c:77
RZ_API bool rz_debug_map_sync(RzDebug *dbg)
Definition: dmap.c:33
RZ_API RzDebugMap * rz_debug_map_new(char *name, ut64 addr, ut64 addr_end, int perm, int user)
Definition: dmap.c:7
RZ_API ut64 rz_debug_reg_get(RzDebug *dbg, const char *name)
Definition: dreg.c:99
int drx_get_at(drxt *drx, ut64 at_addr)
Definition: drx.c:161
bool drx_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
Definition: drx.c:209
#define drxt
Definition: drx.c:44
void drx_list(drxt *drx)
Definition: drx.c:178
bool drx_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
Definition: drx.c:220
int drx_set(drxt *drx, int n, ut64 addr, int len, int rwx, int global)
Definition: drx.c:83
RZ_API void rz_egg_reset(RzEgg *egg)
Definition: egg.c:128
RZ_API bool rz_egg_assemble_asm(RzEgg *egg, char **asm_list)
Definition: egg.c:346
RZ_API int rz_egg_compile(RzEgg *egg)
Definition: egg.c:394
RZ_API RzBuffer * rz_egg_get_bin(RzEgg *egg)
Definition: egg.c:423
RZ_API void rz_egg_load(RzEgg *egg, const char *code, int format)
Definition: egg.c:202
RZ_API bool rz_egg_assemble(RzEgg *egg)
Definition: egg.c:390
RZ_API bool rz_egg_setup(RzEgg *egg, const char *arch, int bits, int endian, const char *os)
Definition: egg.c:139
struct @667 g
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
#define NT_ARM_HW_WATCH
Definition: glibc_elf.h:791
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API int rz_debug_kill(RzDebug *dbg, int pid, int tid, int sig)
Definition: debug.c:1598
RZ_API RzDebugInfo * rz_debug_info(RzDebug *dbg, const char *arg)
Definition: debug.c:18
RZ_API ut64 rz_debug_execute(RzDebug *dbg, const ut8 *buf, int len, int restore)
Definition: debug.c:510
RZ_API bool rz_debug_select(RzDebug *dbg, int pid, int tid)
Definition: debug.c:595
RZ_API void rz_debug_info_free(RzDebugInfo *rdi)
Definition: debug.c:28
static void list(RzEgg *egg)
Definition: rz-gg.c:52
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 void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
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
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
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")
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid ptrace
Definition: sflib.h:57
int linux_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
Definition: linux_debug.c:1090
bool linux_generate_corefile(RzDebug *dbg, RzBuffer *dest)
char * linux_reg_profile(RzDebug *dbg)
Definition: linux_debug.c:55
int linux_attach(RzDebug *dbg, int pid)
Definition: linux_debug.c:718
RzList * linux_pid_list(int pid, RzList *list)
Definition: linux_debug.c:838
bool linux_stop_threads(RzDebug *dbg, int except)
Definition: linux_debug.c:660
RzDebugReasonType linux_dbg_wait(RzDebug *dbg, int pid)
Definition: linux_debug.c:502
#define MAXPID
RzList * linux_thread_list(RzDebug *dbg, int pid, RzList *list)
Definition: linux_debug.c:875
bool linux_set_options(RzDebug *dbg, int pid)
Definition: linux_debug.c:383
RzList * linux_desc_list(int pid)
Definition: linux_debug.c:1319
RzDebugInfo * linux_info(RzDebug *dbg, const char *arg)
Definition: linux_debug.c:745
int linux_step(RzDebug *dbg)
Definition: linux_debug.c:369
int linux_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
Definition: linux_debug.c:1265
bool linux_select(RzDebug *dbg, int pid, int tid)
Definition: linux_debug.c:444
RzDebugReasonType linux_ptrace_event(RzDebug *dbg, int pid, int status, bool dowait)
char * dest
Definition: lz4.h:697
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
string FILE
Definition: benchmark.py:21
line
Definition: setup.py:34
RZ_API ut64 rz_reg_getv(RzReg *reg, const char *name)
Definition: reg.c:332
RZ_API ut64 rz_reg_setv(RzReg *reg, const char *name, ut64 val)
Definition: reg.c:326
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_DEPRECATE RZ_API RZ_BORROW ut8 * rz_buf_data(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut64 *size)
Return a borrowed array of bytes representing the buffer data.
Definition: buf.c:1287
RzDebugReasonType
Definition: rz_debug.h:89
@ RZ_DEBUG_REASON_NEW_TID
Definition: rz_debug.h:106
@ RZ_DEBUG_REASON_DEAD
Definition: rz_debug.h:90
@ RZ_DEBUG_REASON_UNKNOWN
Definition: rz_debug.h:103
@ RZ_DEBUG_REASON_BREAKPOINT
Definition: rz_debug.h:94
@ RZ_DEBUG_REASON_USERSUSP
Definition: rz_debug.h:115
@ RZ_DEBUG_REASON_TRAP
Definition: rz_debug.h:111
@ RZ_DEBUG_REASON_ERROR
Definition: rz_debug.h:104
@ RZ_DEBUG_REASON_NEW_LIB
Definition: rz_debug.h:107
@ RZ_DEBUG_REASON_EXIT_LIB
Definition: rz_debug.h:110
@ RZ_DEBUG_REASON_NONE
Definition: rz_debug.h:91
@ RZ_DEBUG_REASON_NEW_PID
Definition: rz_debug.h:105
@ RZ_DEBUG_REASON_EXIT_TID
Definition: rz_debug.h:109
@ RZ_DEBUG_REASON_SIGNAL
Definition: rz_debug.h:92
@ DRX_API_SET_BP
Definition: rz_drx.h:7
@ DRX_API_GET_BP
Definition: rz_drx.h:6
@ DRX_API_REMOVE_BP
Definition: rz_drx.h:8
@ DRX_API_LIST
Definition: rz_drx.h:5
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
@ RZ_LIB_TYPE_DBG
Definition: rz_lib.h:70
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
@ RZ_REG_TYPE_SEG
Definition: rz_reg.h:28
@ RZ_REG_TYPE_MMX
Definition: rz_reg.h:24
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
@ RZ_REG_TYPE_FLG
Definition: rz_reg.h:27
@ RZ_REG_TYPE_FPU
Definition: rz_reg.h:23
@ RZ_REG_TYPE_DRX
Definition: rz_reg.h:22
@ RZ_REG_TYPE_XMM
Definition: rz_reg.h:25
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API bool rz_str_glob(const char *str, const char *glob)
Definition: str.c:2368
#define rz_sys_xsystem(cmd)
Definition: rz_sys.h:83
RZ_API int rz_sys_kill(int pid, int sig)
Send signal sig to process with pid pid.
Definition: sys.c:1850
RZ_API FILE * rz_sys_fopen(const char *path, const char *mode)
Definition: sys.c:1815
@ RZ_SYS_BITS_32
Definition: rz_sys.h:20
@ RZ_SYS_BITS_64
Definition: rz_sys.h:21
@ RZ_SYS_BITS_16
Definition: rz_sys.h:19
#define rz_sys_perror(x)
Definition: rz_types.h:336
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_PERM_W
Definition: rz_types.h:94
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define rz_offsetof(type, member)
Definition: rz_types.h:360
#define PFMT64x
Definition: rz_types.h:393
#define RZ_VERSION
Definition: rz_version.h:8
#define PT_STEP
Definition: sftypes.h:594
#define PT_ATTACH
Definition: sftypes.h:618
#define PROT_READ
Definition: sftypes.h:95
#define PROT_WRITE
Definition: sftypes.h:96
#define PT_DETACH
Definition: sftypes.h:622
#define MAP_PRIVATE
Definition: sftypes.h:102
int size_t
Definition: sftypes.h:40
#define PROT_NONE
Definition: sftypes.h:98
#define EIO
Definition: sftypes.h:115
#define PROT_EXEC
Definition: sftypes.h:97
int caddr_t
Definition: sftypes.h:62
int pid_t
Definition: sftypes.h:38
unsigned char uint8_t
Definition: sftypes.h:31
@ PTRACE_SETREGS
Definition: sftypes.h:603
@ PTRACE_CONT
Definition: sftypes.h:584
@ PTRACE_GETREGS
Definition: sftypes.h:598
@ PTRACE_ATTACH
Definition: sftypes.h:617
@ PTRACE_SYSCALL
Definition: sftypes.h:635
@ PTRACE_DETACH
Definition: sftypes.h:621
#define MAP_ANONYMOUS
Definition: sftypes.h:106
#define PT_GETREGS
Definition: sftypes.h:599
#define b(i)
Definition: sha256.c:42
_W64 unsigned int uintptr_t
void * BaseOfDll
char * Path
char * Name
DWORD dwExitCode
LPVOID lpThreadLocalBase
LPVOID lpStartAddress
DWORD break_tid
Definition: w32dbg_wrap.h:42
Definition: inftree9.h:24
Definition: gzappend.c:170
Definition: sftypes.h:73
Definition: z80asm.h:102
RzSyscall * syscall
Definition: rz_analysis.h:570
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
char * debug_file_name
Definition: rz_bin.h:223
Definition: rz_bp.h:78
void * user
Definition: rz_bp.h:79
RzCoreCmd cmd
Definition: rz_bind.h:32
void * core
Definition: rz_bind.h:31
RzCoreCmdF cmdf
Definition: rz_bind.h:33
RzCoreConfigGetI cfggeti
Definition: rz_bind.h:43
RzBin * bin
Definition: rz_core.h:298
int(* open)(const char *path)
Definition: rz_debug.h:327
const char * version
Definition: rz_debug.h:362
RzDebugDescPlugin desc
Definition: rz_debug.h:403
const char * name
Definition: rz_debug.h:359
RzCoreBind corebind
Definition: rz_debug.h:314
RzList * threads
Definition: rz_debug.h:251
bool consbreak
Definition: rz_debug.h:271
bool continue_all_threads
Definition: rz_debug.h:272
RzDebugReason reason
Definition: rz_debug.h:276
char * glob_unlibs
Definition: rz_debug.h:270
struct rz_debug_plugin_t * cur
Definition: rz_debug.h:295
RzEgg * egg
Definition: rz_debug.h:318
RzAnalysis * analysis
Definition: rz_debug.h:305
char * glob_libs
Definition: rz_debug.h:269
char * arch
Definition: rz_debug.h:242
int n_threads
Definition: rz_debug.h:250
RzReg * reg
Definition: rz_debug.h:286
int bits
Definition: rz_debug.h:243
void * plugin_data
Definition: rz_debug.h:296
int main_pid
Definition: rz_debug.h:246
static uv_buf_t iov
Definition: main.c:15
RZ_API int rz_syscall_get_num(RzSyscall *s, const char *str)
Definition: syscall.c:376
control
RzDebugInfo * w32_info(RzDebug *dbg, const char *arg)
int w32_hwbp_arm_del(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
int w32_attach(RzDebug *dbg, int pid)
int w32_step(RzDebug *dbg)
int w32_map_protect(RzDebug *dbg, ut64 addr, int size, int perms)
RzList * w32_thread_list(RzDebug *dbg, int pid, RzList *list)
int w32_map_dealloc(RzDebug *dbg, ut64 addr, int size)
int w32_init(RzDebug *dbg)
Definition: windows_debug.c:37
int w32_dbg_wait(RzDebug *dbg, int pid)
RzList * w32_pid_list(RzDebug *dbg, int pid, RzList *list)
int w32_kill(RzDebug *dbg, int pid, int tid, int sig)
int w32_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
static int io_perms_to_prot(int io_perms)
int w32_hwbp_arm_add(RzDebug *dbg, RzBreakpoint *bp, RzBreakpointItem *b)
int w32_continue(RzDebug *dbg, int pid, int tid, int sig)
int w32_detach(RzDebug *dbg, int pid)
int w32_select(RzDebug *dbg, int pid, int tid)
int w32_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
RzList * w32_desc_list(int pid)
RzDebugMap * w32_map_alloc(RzDebug *dbg, ut64 addr, int size)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
RZ_API RzList * rz_w32_dbg_maps(RzDebug *dbg)
Definition: windows_maps.c:245
RZ_API RzList * rz_w32_dbg_modules(RzDebug *dbg)
Definition: windows_maps.c:76
char * xnu_reg_profile(RzDebug *dbg)
Definition: xnu_debug.c:252
bool xnu_step(RzDebug *dbg)
Definition: xnu_debug.c:112
int xnu_map_dealloc(RzDebug *dbg, ut64 addr, int size)
Definition: xnu_debug.c:368
int xnu_continue(RzDebug *dbg, int pid, int tid, int sig)
Definition: xnu_debug.c:227
RzDebugMap * xnu_map_alloc(RzDebug *dbg, ut64 addr, int size)
Definition: xnu_debug.c:346
bool xnu_generate_corefile(RzDebug *dbg, RzBuffer *dest)
Definition: xnu_debug.c:827
int xnu_map_protect(RzDebug *dbg, ut64 addr, int size, int perms)
Definition: xnu_debug.c:486
RzList * xnu_dbg_maps(RzDebug *dbg, int only_modules)
Definition: xnu_debug.c:1225
RzDebugPid * xnu_get_pid(int pid)
Definition: xnu_debug.c:907
int xnu_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size)
Definition: xnu_debug.c:279
int xnu_detach(RzDebug *dbg, int pid)
Definition: xnu_debug.c:160
int xnu_stop(RzDebug *dbg, int pid)
Definition: xnu_debug.c:194
int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size)
Definition: xnu_debug.c:315
int xnu_wait(RzDebug *dbg, int pid)
Definition: xnu_debug.c:108
int xnu_attach(RzDebug *dbg, int pid)
Definition: xnu_debug.c:133
RzList * xnu_thread_list(RzDebug *dbg, int pid, RzList *list)
Definition: xnu_debug.c:453
#define xwrz_testwx(x)
Definition: xnu_debug.c:571
RzDebugInfo * xnu_info(RzDebug *dbg, const char *arg)
Definition: xnu_debug.c:397
#define RZ_DEBUG_REASON_MACH_RCV_INTERRUPTED
Definition: xnu_debug.h:261
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int addr
Definition: z80asm.c:58