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