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 (&regs, 0, sizeof(regs));
671 		memset (buf, 0, size);
672 		#if __NetBSD__ || __OpenBSD__
673 			ret = ptrace (PTRACE_GETREGS, pid, (caddr_t)&regs, sizeof (regs));
674 		#elif __KFBSD__
675 			ret = ptrace(PT_GETREGS, pid, (caddr_t)&regs, 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, &regs, 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 				&region[2], &region2[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]", &region[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 (&region[2], '-');
1088 		if (!pos_c) { // should this be an error?
1089 			continue;
1090 		}
1091 		strncpy (&region2[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