1 /* radare - LGPL - Copyright 2009-2019 - pancake */
2 
3 #include <r_userconf.h>
4 
5 #if DEBUGGER
6 #include <r_debug.h>
7 #include <r_asm.h>
8 #include <r_reg.h>
9 #include <r_lib.h>
10 #include <r_anal.h>
11 #include <signal.h>
12 #include <sys/uio.h>
13 #include <errno.h>
14 #include "linux_debug.h"
15 #include "../procfs.h"
16 
17 #include <sys/syscall.h>
18 #include <unistd.h>
19 #include <elf.h>
20 
21 #include "linux_ptrace.h"
22 
23 #ifdef __GLIBC__
24 #define HAVE_YMM 1
25 #else
26 #define HAVE_YMM 0
27 #endif
28 
linux_reg_profile(RDebug * dbg)29 char *linux_reg_profile (RDebug *dbg) {
30 #if __arm__
31 #	include "reg/linux-arm.h"
32 #elif __riscv
33 #	include "reg/linux-riscv64.h"
34 #elif __arm64__ || __aarch64__
35 #	include "reg/linux-arm64.h"
36 #elif __mips__
37 	if ((dbg->bits & R_SYS_BITS_32) && (dbg->bp->endian == 1)) {
38 #		include "reg/linux-mips.h"
39 	} else {
40 #		include "reg/linux-mips64.h"
41 	}
42 #elif (__i386__ || __x86_64__)
43 	if (dbg->bits & R_SYS_BITS_32) {
44 #if __x86_64__
45 #		include "reg/linux-x64-32.h"
46 #else
47 #		include "reg/linux-x86.h"
48 #endif
49 	} else {
50 #		include "reg/linux-x64.h"
51 	}
52 #elif __powerpc__
53 	if (dbg->bits & R_SYS_BITS_32) {
54 #		include "reg/linux-ppc.h"
55 	} else {
56 #		include "reg/linux-ppc64.h"
57 	}
58 #elif __s390x__
59 #	include "reg/linux-s390x.h"
60 #else
61 #	error "Unsupported Linux CPU"
62 	return NULL;
63 #endif
64 }
65 
66 static void linux_detach_all(RDebug *dbg);
67 static char *read_link(int pid, const char *file);
68 static bool linux_attach_single_pid(RDebug *dbg, int ptid);
69 static void linux_remove_thread(RDebug *dbg, int pid);
70 static void linux_add_new_thread(RDebug *dbg, int tid);
71 static bool linux_stop_thread(RDebug *dbg, int tid);
72 static bool linux_kill_thread(int tid, int signo);
73 static void linux_dbg_wait_break_main(RDebug *dbg);
74 static void linux_dbg_wait_break(RDebug *dbg);
75 static RDebugReasonType linux_handle_new_task(RDebug *dbg, int tid);
76 
linux_handle_signals(RDebug * dbg,int tid)77 int linux_handle_signals(RDebug *dbg, int tid) {
78 	siginfo_t siginfo = { 0 };
79 	int ret = r_debug_ptrace (dbg, PTRACE_GETSIGINFO, tid, 0, (r_ptrace_data_t)(size_t)&siginfo);
80 	if (ret == -1) {
81 		/* ESRCH means the process already went away :-/ */
82 		if (errno == ESRCH) {
83 			dbg->reason.type = R_DEBUG_REASON_DEAD;
84 			return true;
85 		}
86 		r_sys_perror ("ptrace GETSIGINFO");
87 		return false;
88 	}
89 
90 	if (siginfo.si_signo > 0) {
91 		//siginfo_t newsiginfo = {0};
92 		//ptrace (PTRACE_SETSIGINFO, dbg->pid, 0, &siginfo);
93 		dbg->reason.type = R_DEBUG_REASON_SIGNAL;
94 		dbg->reason.signum = siginfo.si_signo;
95 		dbg->stopaddr = (ut64)(size_t)siginfo.si_addr;
96 		//dbg->errno = siginfo.si_errno;
97 		// siginfo.si_code -> HWBKPT, USER, KERNEL or WHAT
98 		// TODO: DO MORE RDEBUGREASON HERE
99 		switch (dbg->reason.signum) {
100 		case SIGTRAP:
101 		{
102 			if (dbg->glob_libs || dbg->glob_unlibs) {
103 				ut64 pc_addr = r_debug_reg_get (dbg, "PC");
104 				RBreakpointItem *b = r_bp_get_at (dbg->bp, pc_addr - dbg->bpsize);
105 				if (b && b->internal) {
106 					char *p = strstr (b->data, "dbg.");
107 					if (p) {
108 						if (r_str_startswith (p, "dbg.libs")) {
109 							const char *name;
110 							if (strstr (b->data, "sym.imp.dlopen")) {
111 								name = r_reg_get_name (dbg->reg, R_REG_NAME_A0);
112 							} else {
113 								name = r_reg_get_name (dbg->reg, R_REG_NAME_A1);
114 							}
115 							b->data = r_str_appendf (b->data, ";ps@r:%s", name);
116 							dbg->reason.type = R_DEBUG_REASON_NEW_LIB;
117 							break;
118 						} else if (r_str_startswith (p, "dbg.unlibs")) {
119 							dbg->reason.type = R_DEBUG_REASON_EXIT_LIB;
120 							break;
121 						}
122 					}
123 				}
124 			}
125 			if (dbg->reason.type != R_DEBUG_REASON_NEW_LIB &&
126 				dbg->reason.type != R_DEBUG_REASON_EXIT_LIB) {
127 				if (siginfo.si_code == TRAP_TRACE) {
128 					dbg->reason.type = R_DEBUG_REASON_STEP;
129 				} else {
130 					dbg->reason.bp_addr = (ut64)(size_t)siginfo.si_addr;
131 					dbg->reason.type = R_DEBUG_REASON_BREAKPOINT;
132 					// Switch to the thread that hit the breakpoint
133 					r_debug_select (dbg, dbg->pid, tid);
134 					dbg->tid = tid;
135 				}
136 			}
137 		} break;
138 		case SIGINT:
139 			dbg->reason.type = R_DEBUG_REASON_USERSUSP;
140 			break;
141 		case SIGABRT: // 6 / SIGIOT // SIGABRT
142 			dbg->reason.type = R_DEBUG_REASON_ABORT;
143 			break;
144 		case SIGSEGV:
145 			dbg->reason.type = R_DEBUG_REASON_SEGFAULT;
146 			break;
147 		case SIGCHLD:
148 			dbg->reason.type = R_DEBUG_REASON_SIGNAL;
149 			break;
150 		default:
151 			break;
152 		}
153 		if (dbg->reason.signum != SIGTRAP &&
154 			(dbg->reason.signum != SIGINT || !r_cons_is_breaked ())) {
155 			eprintf ("[+] SIGNAL %d errno=%d addr=0x%08"PFMT64x
156 				" code=%d si_pid=%d ret=%d\n",
157 				siginfo.si_signo, siginfo.si_errno,
158 				(ut64) (size_t)siginfo.si_addr, siginfo.si_code, siginfo.si_pid, ret);
159 		}
160 		return true;
161 	}
162 	return false;
163 }
164 
165 #if __ANDROID__
166 #undef PT_GETEVENTMSG
167 #define PT_GETEVENTMSG
168 #endif
169 
170 // Used to remove breakpoints before detaching from a fork, without it the child
171 // will die upon hitting a breakpoint while not being traced
linux_remove_fork_bps(RDebug * dbg)172 static void linux_remove_fork_bps(RDebug *dbg) {
173 	RListIter *iter;
174 	RBreakpointItem *b;
175 	int prev_pid = dbg->pid;
176 	int prev_tid = dbg->tid;
177 
178 	// Set dbg tid to the new child temporarily
179 	dbg->pid = dbg->forked_pid;
180 	dbg->tid = dbg->forked_pid;
181 	r_debug_select (dbg, dbg->forked_pid, dbg->forked_pid);
182 
183 	// Unset all hw breakpoints in the child process
184 	r_debug_reg_sync (dbg, R_REG_TYPE_DRX, false);
185 	r_list_foreach (dbg->bp->bps, iter, b) {
186 		r_debug_drx_unset (dbg, r_bp_get_index_at (dbg->bp, b->addr));
187 	}
188 	r_debug_reg_sync (dbg, R_REG_TYPE_DRX, true);
189 
190 	// Unset software breakpoints in the child process
191 	r_debug_bp_update (dbg);
192 	r_bp_restore (dbg->bp, false);
193 
194 	// Return to the parent
195 	dbg->pid = prev_pid;
196 	dbg->tid = prev_tid;
197 	r_debug_select (dbg, dbg->pid, dbg->pid);
198 
199 	// Restore sw breakpoints in the parent
200 	r_bp_restore (dbg->bp, true);
201 }
202 
203 #ifdef PT_GETEVENTMSG
204 /*
205  * @brief Handle PTRACE_EVENT_* when receiving SIGTRAP
206  *
207  * @param dowait Do waitpid to consume any signal in the newly created task
208  * @return RDebugReasonType,
209  * - R_DEBUG_REASON_UNKNOWN if the ptrace_event cannot be handled,
210  * - R_DEBUG_REASON_ERROR if a ptrace command failed.
211  *
212  * NOTE: This API was added in Linux 2.5.46
213  */
linux_ptrace_event(RDebug * dbg,int ptid,int status,bool dowait)214 RDebugReasonType linux_ptrace_event (RDebug *dbg, int ptid, int status, bool dowait) {
215 	ut32 pt_evt;
216 #if __powerpc64__ || __arm64__ || __aarch64__ || __x86_64__
217 	ut64 data;
218 #else
219 	ut32 data;
220 #endif
221 	/* we only handle stops with SIGTRAP here */
222 	if (!WIFSTOPPED (status) || WSTOPSIG (status) != SIGTRAP) {
223 		return R_DEBUG_REASON_UNKNOWN;
224 	}
225 
226 	pt_evt = status >> 16;
227 	switch (pt_evt) {
228 	case 0:
229 		/* NOTE: this case is handled by linux_handle_signals */
230 		break;
231 	case PTRACE_EVENT_CLONE:
232 		// Get the tid of the new thread
233 		if (r_debug_ptrace (dbg, PTRACE_GETEVENTMSG, ptid, 0, (r_ptrace_data_t)(size_t)&data) == -1) {
234 			r_sys_perror ("ptrace GETEVENTMSG");
235 			return R_DEBUG_REASON_ERROR;
236 		}
237 		if (dowait) {
238 			// The new child has a pending SIGSTOP.  We can't affect it until it
239 			// hits the SIGSTOP, but we're already attached.  */
240 			if (waitpid ((int)data, &status, 0) == -1) {
241 				perror ("waitpid");
242 			}
243 		}
244 
245 		linux_add_new_thread (dbg, (int)data);
246 		if (dbg->trace_clone) {
247 			r_debug_select (dbg, dbg->pid, (int)data);
248 		}
249 		eprintf ("(%d) Created thread %d\n", ptid, (int)data);
250 		return R_DEBUG_REASON_NEW_TID;
251 	case PTRACE_EVENT_VFORK:
252 	case PTRACE_EVENT_FORK:
253 		// Get the pid of the new process
254 		if (r_debug_ptrace (dbg, PTRACE_GETEVENTMSG, ptid, 0, (r_ptrace_data_t)(size_t)&data) == -1) {
255 			r_sys_perror ("ptrace GETEVENTMSG");
256 			return R_DEBUG_REASON_ERROR;
257 		}
258 		dbg->forked_pid = data;
259 		if (dowait) {
260 			// The new child has a pending SIGSTOP. We can't affect it until it
261 			// hits the SIGSTOP, but we're already attached.  */
262 			if (waitpid (dbg->forked_pid, &status, 0) == -1) {
263 				perror ("waitpid");
264 			}
265 		}
266 		eprintf ("(%d) Created process %d\n", ptid, (int)data);
267 		if (!dbg->trace_forks) {
268 			// We need to do this even if the new process will be detached since the
269 			// breakpoints are inherited from the parent
270 			linux_remove_fork_bps (dbg);
271 			if (r_debug_ptrace (dbg, PTRACE_DETACH, dbg->forked_pid, NULL, (r_ptrace_data_t)(size_t)NULL) == -1) {
272 				perror ("PTRACE_DETACH");
273 			}
274 		}
275 		return R_DEBUG_REASON_NEW_PID;
276 	case PTRACE_EVENT_EXIT:
277 		// Get the exit status of the exiting task
278 		if (r_debug_ptrace (dbg, PTRACE_GETEVENTMSG, ptid, 0, (r_ptrace_data_t)(size_t)&data) == -1) {
279 			r_sys_perror ("ptrace GETEVENTMSG");
280 			return R_DEBUG_REASON_ERROR;
281 		}
282 		//TODO: Check other processes exit if dbg->trace_forks is on
283 		if (ptid != dbg->pid) {
284 			eprintf ("(%d) Thread exited with status=0x%"PFMT64x"\n", ptid, (ut64)data);
285 			return R_DEBUG_REASON_EXIT_TID;
286 		} else {
287 			eprintf ("(%d) Process exited with status=0x%"PFMT64x"\n", ptid, (ut64)data);
288 			return R_DEBUG_REASON_EXIT_PID;
289 		}
290 	default:
291 		eprintf ("Unknown PTRACE_EVENT encountered: %d\n", pt_evt);
292 		break;
293 	}
294 	return R_DEBUG_REASON_UNKNOWN;
295 }
296 #endif
297 
298 /*
299  * @brief Search for the parent of the newly created task and
300  * handle the pending SIGTRAP with PTRACE_EVENT_*
301  *
302  * @param tid, TID of the new task
303  * @return RDebugReasonType, Debug reason
304  */
linux_handle_new_task(RDebug * dbg,int tid)305 static RDebugReasonType linux_handle_new_task(RDebug *dbg, int tid) {
306 	int ret, status;
307 	if (dbg->threads) {
308 		RDebugPid *th;
309 		RListIter *it;
310 		// Search for SIGTRAP with PTRACE_EVENT_* in other threads.
311 		r_list_foreach (dbg->threads, it, th) {
312 			if (th->pid == tid) {
313 				continue;
314 			}
315 			// Retrieve the signal without consuming it with PTRACE_GETSIGINFO
316 			siginfo_t siginfo = { 0 };
317 			ret = r_debug_ptrace (dbg, PTRACE_GETSIGINFO, th->pid, 0, (r_ptrace_data_t)(size_t)&siginfo);
318 			// Skip if PTRACE_GETSIGINFO fails when the thread is running.
319 			if (ret == -1) {
320 				continue;
321 			}
322 #ifdef PT_GETEVENTMSG
323 			// NOTE: This API was added in Linux 2.5.46
324 			if (siginfo.si_signo == SIGTRAP) {
325 				// si_code = (SIGTRAP | PTRACE_EVENT_* << 8)
326 				int pt_evt = siginfo.si_code >> 8;
327 				// Handle PTRACE_EVENT_* that creates a new task (fork/clone)
328 				switch (pt_evt) {
329 				case PTRACE_EVENT_CLONE:
330 				case PTRACE_EVENT_VFORK:
331 				case PTRACE_EVENT_FORK:
332 					ret = waitpid (th->pid, &status, 0);
333 					return linux_ptrace_event (dbg, ret, status, false);
334 				default:
335 					break;
336 				}
337 			}
338 #endif
339 		}
340 	}
341 	return R_DEBUG_REASON_UNKNOWN;
342 }
343 
linux_step(RDebug * dbg)344 int linux_step(RDebug *dbg) {
345 	int ret = false;
346 	int pid = dbg->tid;
347 	ret = r_debug_ptrace (dbg, PTRACE_SINGLESTEP, pid, 0, 0);
348 	//XXX(jjd): why?? //linux_handle_signals (dbg);
349 	if (ret == -1) {
350 		perror ("native-singlestep");
351 		ret = false;
352 	} else {
353 		ret = true;
354 	}
355 	return ret;
356 }
357 
linux_set_options(RDebug * dbg,int pid)358 bool linux_set_options(RDebug *dbg, int pid) {
359 	int traceflags = 0;
360 	traceflags |= PTRACE_O_TRACEFORK;
361 	traceflags |= PTRACE_O_TRACEVFORK;
362 	traceflags |= PTRACE_O_TRACECLONE;
363 	if (dbg->trace_forks) {
364 		traceflags |= PTRACE_O_TRACEVFORKDONE;
365 	}
366 	if (dbg->trace_execs) {
367 		traceflags |= PTRACE_O_TRACEEXEC;
368 	}
369 	if (dbg->trace_aftersyscall) {
370 		traceflags |= PTRACE_O_TRACEEXIT;
371 	}
372 	/* SIGTRAP | 0x80 on signal handler .. not supported on all archs */
373 	traceflags |= PTRACE_O_TRACESYSGOOD;
374 
375 	// PTRACE_SETOPTIONS can fail because of the asynchronous nature of ptrace
376 	// If the target is traced, the loop will always end with success
377 	while (r_debug_ptrace (dbg, PTRACE_SETOPTIONS, pid, 0, (r_ptrace_data_t)(size_t)traceflags) == -1) {
378 		void *bed = r_cons_sleep_begin ();
379 		usleep (1000);
380 		r_cons_sleep_end (bed);
381 	}
382 	return true;
383 }
384 
linux_detach_all(RDebug * dbg)385 static void linux_detach_all(RDebug *dbg) {
386 	RList *th_list = dbg->threads;
387 	if (th_list) {
388 		RDebugPid *th;
389 		RListIter *it;
390 		r_list_foreach (th_list, it, th) {
391 			if (th->pid != dbg->main_pid) {
392 				if (r_debug_ptrace (dbg, PTRACE_DETACH, th->pid, NULL, (r_ptrace_data_t)(size_t)NULL) == -1) {
393 					perror ("PTRACE_DETACH");
394 				}
395 			}
396 		}
397 	}
398 
399 	// Detaching from main proc
400 	if (r_debug_ptrace (dbg, PTRACE_DETACH, dbg->main_pid, NULL, (r_ptrace_data_t)(size_t)NULL) == -1) {
401 		perror ("PTRACE_DETACH");
402 	}
403 }
404 
linux_remove_thread(RDebug * dbg,int tid)405 static void linux_remove_thread(RDebug *dbg, int tid) {
406 	if (dbg->threads) {
407 		RDebugPid *th;
408 		RListIter *it;
409 		r_list_foreach (dbg->threads, it, th) {
410 			if (th->pid == tid) {
411 				r_list_delete (dbg->threads, it);
412 				dbg->n_threads--;
413 				break;
414 			}
415 		}
416 	}
417 }
418 
linux_select(RDebug * dbg,int pid,int tid)419 bool linux_select(RDebug *dbg, int pid, int tid) {
420 	if (dbg->pid != -1 && dbg->pid != pid) {
421 		return linux_attach_new_process (dbg, pid);
422 	}
423 	return linux_attach (dbg, tid);
424 }
425 
linux_attach_new_process(RDebug * dbg,int pid)426 bool linux_attach_new_process(RDebug *dbg, int pid) {
427 	linux_detach_all (dbg);
428 	if (dbg->threads) {
429 		r_list_free (dbg->threads);
430 		dbg->threads = NULL;
431 	}
432 
433 	if (!linux_attach (dbg, pid)) {
434 		return false;
435 	}
436 
437 	// Call select to syncrhonize the thread's data.
438 	dbg->pid = pid;
439 	dbg->tid = pid;
440 	r_debug_select (dbg, pid, pid);
441 
442 	return true;
443 }
444 
linux_dbg_wait_break_main(RDebug * dbg)445 static void linux_dbg_wait_break_main(RDebug *dbg) {
446 	// Get the debugger and debuggee process group ID
447 	pid_t dpgid = getpgid (0);
448 	if (dpgid == -1) {
449 		r_sys_perror ("getpgid");
450 		return;
451 	}
452 	pid_t tpgid = getpgid (dbg->pid);
453 	if (tpgid == -1) {
454 		r_sys_perror ("getpgid");
455 		return;
456 	}
457 
458 	// If the debuggee process is created by the debugger, do nothing because
459 	// SIGINT is already sent to both the debugger and debuggee in the same
460 	// process group.
461 
462 	// If the debuggee is attached by the debugger, send SIGINT to the debuggee
463 	// in another process group.
464 	if (dpgid != tpgid) {
465 		if (!linux_kill_thread (dbg->pid, SIGINT)) {
466 			eprintf ("Could not interrupt pid (%d)\n", dbg->pid);
467 		}
468 	}
469 }
470 
linux_dbg_wait_break(RDebug * dbg)471 static void linux_dbg_wait_break(RDebug *dbg) {
472 	if (!linux_kill_thread (dbg->pid, SIGINT)) {
473 		eprintf ("Could not interrupt pid (%d)\n", dbg->pid);
474 	}
475 }
476 
linux_dbg_wait(RDebug * dbg,int pid)477 RDebugReasonType linux_dbg_wait(RDebug *dbg, int pid) {
478 	RDebugReasonType reason = R_DEBUG_REASON_UNKNOWN;
479 	int tid = pid;
480 	int status, flags = __WALL;
481 	int ret = -1;
482 
483 	if (pid == -1) {
484 		flags |= WNOHANG;
485 	}
486 
487 	for (;;) {
488 		// In the main context, SIGINT is propagated to the debuggee if it is
489 		// in the same process group. Otherwise, the task is running in
490 		// background and SIGINT will not be propagated to the debuggee.
491 		if (r_cons_context_is_main ()) {
492 			r_cons_break_push ((RConsBreak)linux_dbg_wait_break_main, dbg);
493 		} else {
494 			r_cons_break_push ((RConsBreak)linux_dbg_wait_break, dbg);
495 		}
496 		void *bed = r_cons_sleep_begin ();
497 		if (dbg->continue_all_threads) {
498 			ret = waitpid (-1, &status, flags);
499 		} else {
500 			ret = waitpid (pid, &status, flags);
501 		}
502 		r_cons_sleep_end (bed);
503 		r_cons_break_pop ();
504 
505 		if (ret < 0) {
506 			// Continue when interrupted by user;
507 			if (errno == EINTR) {
508 				continue;
509 			}
510 			perror ("waitpid");
511 			break;
512 		} else if (ret == 0) {
513 			// Unset WNOHANG to call next waitpid in blocking mode.
514 			flags &= ~WNOHANG;
515 		} else {
516 			tid = ret;
517 
518 			// Handle SIGTRAP with PTRACE_EVENT_*
519 			reason = linux_ptrace_event (dbg, tid, status, true);
520 			if (reason != R_DEBUG_REASON_UNKNOWN) {
521 				break;
522 			}
523 
524 			if (WIFEXITED (status)) {
525 				if (tid == dbg->main_pid) {
526 					r_list_free (dbg->threads);
527 					dbg->threads = NULL;
528 					reason = R_DEBUG_REASON_DEAD;
529 					eprintf ("(%d) Process terminated with status %d\n", tid, WEXITSTATUS (status));
530 					break;
531 				} else {
532 					eprintf ("(%d) Child terminated with status %d\n", tid, WEXITSTATUS (status));
533 					linux_remove_thread (dbg, tid);
534 					continue;
535 				}
536 			} else if (WIFSIGNALED (status)) {
537 				eprintf ("child received signal %d\n", WTERMSIG (status));
538 				reason = R_DEBUG_REASON_SIGNAL;
539 			} else if (WIFSTOPPED (status)) {
540 				// If tid is not in the thread list and stopped by SIGSTOP,
541 				// handle it as a new task.
542 				if (!r_list_find (dbg->threads, &tid, &match_pid) &&
543 					WSTOPSIG (status) == SIGSTOP) {
544 					reason = linux_handle_new_task (dbg, tid);
545 					if (reason != R_DEBUG_REASON_UNKNOWN) {
546 						break;
547 					}
548 				}
549 
550 				if (linux_handle_signals (dbg, tid)) {
551 					reason = dbg->reason.type;
552 				} else {
553 					eprintf ("can't handle signals\n");
554 					return R_DEBUG_REASON_ERROR;
555 				}
556 #ifdef WIFCONTINUED
557 			} else if (WIFCONTINUED (status)) {
558 				eprintf ("child continued...\n");
559 				reason = R_DEBUG_REASON_NONE;
560 #endif
561 			} else if (status == 1) {
562 				eprintf ("EEK DEAD DEBUGEE!\n");
563 				reason = R_DEBUG_REASON_DEAD;
564 			} else if (status == 0) {
565 				eprintf ("STATUS=0?!?!?!?\n");
566 				reason = R_DEBUG_REASON_DEAD;
567 			} else {
568 				if (ret != tid) {
569 					reason = R_DEBUG_REASON_NEW_PID;
570 				} else {
571 					eprintf ("CRAP. returning from wait without knowing why...\n");
572 				}
573 			}
574 			if (reason != R_DEBUG_REASON_UNKNOWN) {
575 				break;
576 			}
577 		}
578 	}
579 	dbg->reason.tid = tid;
580 	return reason;
581 }
582 
match_pid(const void * pid_o,const void * th_o)583 int match_pid(const void *pid_o, const void *th_o) {
584 	int pid = *(int *)pid_o;
585 	RDebugPid *th = (RDebugPid *)th_o;
586 	return (pid == th->pid)? 0 : 1;
587 }
588 
linux_add_new_thread(RDebug * dbg,int tid)589 static void linux_add_new_thread(RDebug *dbg, int tid) {
590 	int uid = getuid(); // XXX
591 	char info[1024] = {0};
592 	RDebugPid *tid_info;
593 
594 	if (!procfs_pid_slurp (tid, "status", info, sizeof (info))) {
595 		tid_info = fill_pid_info (info, NULL, tid);
596 	} else {
597 		tid_info = r_debug_pid_new ("new_path", tid, uid, 's', 0);
598 	}
599 	linux_set_options (dbg, tid);
600 	r_list_append (dbg->threads, tid_info);
601 	dbg->n_threads++;
602 }
603 
linux_kill_thread(int tid,int signo)604 static bool linux_kill_thread(int tid, int signo) {
605 	int ret = syscall (__NR_tkill, tid, signo);
606 
607 	if (ret == -1) {
608 		perror ("tkill");
609 		return false;
610 	}
611 
612 	return true;
613 }
614 
linux_stop_thread(RDebug * dbg,int tid)615 static bool linux_stop_thread(RDebug *dbg, int tid) {
616 	int status, ret;
617 	siginfo_t siginfo = { 0 };
618 
619 	// Return if the thread is already stopped
620 	ret = r_debug_ptrace (dbg, PTRACE_GETSIGINFO, tid, 0,
621 		(r_ptrace_data_t) (intptr_t)&siginfo);
622 	if (ret == 0) {
623 		return true;
624 	}
625 
626 	if (linux_kill_thread (tid, SIGSTOP)) {
627 		if ((ret = waitpid (tid, &status, 0)) == -1) {
628 			perror ("waitpid");
629 		}
630 		return ret == tid;
631 	}
632 	return false;
633 }
634 
linux_stop_threads(RDebug * dbg,int except)635 bool linux_stop_threads(RDebug *dbg, int except) {
636 	bool ret = true;
637 	if (dbg->threads) {
638 		RDebugPid *th;
639 		RListIter *it;
640 		r_list_foreach (dbg->threads, it, th) {
641 			if (th->pid && th->pid != except) {
642 				if (!linux_stop_thread (dbg, th->pid)) {
643 					ret = false;
644 				}
645 			}
646 		}
647 	}
648 	return ret;
649 }
650 
linux_attach_single_pid(RDebug * dbg,int ptid)651 static bool linux_attach_single_pid(RDebug *dbg, int ptid) {
652 	siginfo_t sig = { 0 };
653 
654 	if (ptid < 0) {
655 		return false;
656 	}
657 
658 	// Safely check if the PID has already been attached to avoid printing errors.
659 	// Attaching to a process that has already been started with PTRACE_TRACEME.
660 	// sets errno to "Operation not permitted" which may be misleading.
661 	// GETSIGINFO can be called multiple times and would fail without attachment.
662 	if (r_debug_ptrace (dbg, PTRACE_GETSIGINFO, ptid, NULL,
663 		(r_ptrace_data_t)&sig) == -1) {
664 		if (r_debug_ptrace (dbg, PTRACE_ATTACH, ptid, NULL, NULL) == -1) {
665 			perror ("ptrace (PT_ATTACH)");
666 			return false;
667 		}
668 
669 		// Make sure SIGSTOP is delivered and wait for it since we can't affect the pid
670 		// until it hits SIGSTOP.
671 		if (!linux_stop_thread (dbg, ptid)) {
672 			eprintf ("Could not stop pid (%d)\n", ptid);
673 			return false;
674 		}
675 	}
676 
677 	if (!linux_set_options (dbg, ptid)) {
678 		eprintf("failed set_options on %d\n", ptid);
679 		return false;
680 	}
681 	return true;
682 }
683 
get_pid_thread_list(RDebug * dbg,int main_pid)684 static RList *get_pid_thread_list(RDebug *dbg, int main_pid) {
685 	RList *list = r_list_new ();
686 	if (list) {
687 		list = linux_thread_list (dbg, main_pid, list);
688 		dbg->main_pid = main_pid;
689 	}
690 	return list;
691 }
692 
linux_attach(RDebug * dbg,int pid)693 int linux_attach(RDebug *dbg, int pid) {
694 	// First time we run: We try to attach to all "possible" threads and to the main pid
695 	if (!dbg->threads) {
696 		dbg->threads = get_pid_thread_list (dbg, pid);
697 	} else {
698 		// This means we did a first run, so we probably attached to all possible threads already.
699 		// So check if the requested thread is being traced already. If not, attach it
700 		if (!r_list_find (dbg->threads, &pid, &match_pid)) {
701 			linux_attach_single_pid (dbg, pid);
702 		}
703 	}
704 	return pid;
705 }
706 
read_link(int pid,const char * file)707 static char *read_link(int pid, const char *file) {
708 	char path[1024] = {0};
709 	char buf[1024] = {0};
710 
711 	snprintf (path, sizeof (path), "/proc/%d/%s", pid, file);
712 	int ret = readlink (path, buf, sizeof (buf));
713 	if (ret > 0) {
714 		buf[sizeof (buf) - 1] = '\0';
715 		return strdup (buf);
716 	}
717 	return NULL;
718 }
719 
linux_info(RDebug * dbg,const char * arg)720 RDebugInfo *linux_info(RDebug *dbg, const char *arg) {
721 	char proc_buff[1024];
722 	RDebugInfo *rdi = R_NEW0 (RDebugInfo);
723 	if (!rdi) {
724 		return NULL;
725 	}
726 
727 	RList *th_list;
728 	bool list_alloc = false;
729 	if (dbg->threads) {
730 		th_list = dbg->threads;
731 	} else {
732 		th_list = r_list_new ();
733 		list_alloc = true;
734 		if (th_list) {
735 			th_list = linux_thread_list (dbg, dbg->pid, th_list);
736 		}
737 	}
738 	RDebugPid *th;
739 	RListIter *it;
740 	bool found = false;
741 	r_list_foreach (th_list, it, th) {
742 		if (th->pid == dbg->pid) {
743 			found = true;
744 			break;
745 		}
746 	}
747 	rdi->pid = dbg->pid;
748 	rdi->tid = dbg->tid;
749 	rdi->uid = found ? th->uid : -1;
750 	rdi->gid = found ? th->gid : -1;
751 	rdi->cwd = read_link (rdi->pid, "cwd");
752 	rdi->exe = read_link (rdi->pid, "exe");
753 	snprintf (proc_buff, sizeof (proc_buff), "/proc/%d/cmdline", rdi->pid);
754 	rdi->cmdline = r_file_slurp (proc_buff, NULL);
755 	snprintf (proc_buff, sizeof (proc_buff), "/proc/%d/stack", rdi->pid);
756 	rdi->kernel_stack = r_file_slurp (proc_buff, NULL);
757 	rdi->status = found ? th->status : R_DBG_PROC_STOP;
758 	if (list_alloc) {
759 		r_list_free (th_list);
760 	}
761 	return rdi;
762 }
763 
fill_pid_info(const char * info,const char * path,int tid)764 RDebugPid *fill_pid_info(const char *info, const char *path, int tid) {
765 	RDebugPid *pid_info = R_NEW0 (RDebugPid);
766 	if (!pid_info) {
767 		return NULL;
768 	}
769 	char *ptr = strstr (info, "State:");
770 	if (ptr) {
771 		switch (*(ptr + 7)) {
772 		case 'R':
773 			pid_info->status = R_DBG_PROC_RUN;
774 			break;
775 		case 'S':
776 			pid_info->status = R_DBG_PROC_SLEEP;
777 			break;
778 		case 'T':
779 		case 't':
780 			pid_info->status = R_DBG_PROC_STOP;
781 			break;
782 		case 'Z':
783 			pid_info->status = R_DBG_PROC_ZOMBIE;
784 			break;
785 		case 'X':
786 			pid_info->status = R_DBG_PROC_DEAD;
787 			break;
788 		default:
789 			pid_info->status = R_DBG_PROC_SLEEP;
790 			break;
791 		}
792 	}
793 	ptr = strstr (info, "PPid:");
794 	if (ptr) {
795 		pid_info->ppid = atoi (ptr + 5);
796 	}
797 	ptr = strstr (info, "Uid:");
798 	if (ptr) {
799 		pid_info->uid = atoi (ptr + 5);
800 	}
801 	ptr = strstr (info, "Gid:");
802 	if (ptr) {
803 		pid_info->gid = atoi (ptr + 5);
804 	}
805 
806 	pid_info->pid = tid;
807 	pid_info->path = path ? strdup (path) : NULL;
808 	pid_info->runnable = true;
809 	pid_info->pc = 0;
810 	return pid_info;
811 }
812 
linux_pid_list(int pid,RList * list)813 RList *linux_pid_list(int pid, RList *list) {
814 	list->free = (RListFree)&r_debug_pid_free;
815 	DIR *dh = NULL;
816 	struct dirent *de = NULL;
817 	char path[PATH_MAX], info[PATH_MAX];
818 	int i = -1;
819 	RDebugPid *pid_info = NULL;
820 	dh = opendir ("/proc");
821 	if (!dh) {
822 		r_sys_perror ("opendir /proc");
823 		r_list_free (list);
824 		return NULL;
825 	}
826 	while ((de = readdir (dh))) {
827 		path[0] = 0;
828 		info[0] = 0;
829 		// For each existing pid file
830 		if ((i = atoi (de->d_name)) <= 0) {
831 			continue;
832 		}
833 
834 		procfs_pid_slurp (i, "cmdline", path, sizeof (path));
835 		if (!procfs_pid_slurp (i, "status", info, sizeof (info))) {
836 			// Get information about pid (status, pc, etc.)
837 			pid_info = fill_pid_info (info, path, i);
838 		} else {
839 			pid_info = r_debug_pid_new (path, i, 0, R_DBG_PROC_STOP, 0);
840 		}
841 		// Unless pid 0 is requested, only add the requested pid and it's child processes
842 		if (0 == pid || i == pid || pid_info->ppid == pid) {
843 			r_list_append (list, pid_info);
844 		}
845 	}
846 	closedir (dh);
847 	return list;
848 }
849 
linux_thread_list(RDebug * dbg,int pid,RList * list)850 RList *linux_thread_list(RDebug *dbg, int pid, RList *list) {
851 	int i = 0, thid = 0;
852 	char *ptr, buf[PATH_MAX];
853 	RDebugPid *pid_info = NULL;
854 	ut64 pc = 0;
855 	int prev_tid = dbg->tid;
856 
857 	if (!pid) {
858 		r_list_free (list);
859 		return NULL;
860 	}
861 
862 	list->free = (RListFree)&r_debug_pid_free;
863 	/* if this process has a task directory, use that */
864 	snprintf (buf, sizeof (buf), "/proc/%d/task", pid);
865 	if (r_file_is_directory (buf)) {
866 		struct dirent *de;
867 		DIR *dh = opendir (buf);
868 		// Update the process' memory maps to set correct paths
869 		dbg->corebind.syncDebugMaps (dbg->corebind.core);
870 		while ((de = readdir (dh))) {
871 			if (!strcmp (de->d_name, ".") || !strcmp (de->d_name, "..")) {
872 				continue;
873 			}
874 			int tid = atoi (de->d_name);
875 			char info[PATH_MAX];
876 			int uid = 0;
877 			if (!procfs_pid_slurp (tid, "status", info, sizeof (info))) {
878 				ptr = strstr (info, "Uid:");
879 				if (ptr) {
880 					uid = atoi (ptr + 4);
881 				}
882 				ptr = strstr (info, "Tgid:");
883 				if (ptr) {
884 					int tgid = atoi (ptr + 5);
885 					if (tgid != pid) {
886 						/* Ignore threads that aren't in the pid's thread group */
887 						continue;
888 					}
889 				}
890 			}
891 
892 			// Switch to the currently inspected thread to get it's program counter
893 			if (dbg->tid != tid) {
894 				linux_attach_single_pid (dbg, tid);
895 				dbg->tid = tid;
896 			}
897 
898 			r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false);
899 			pc = r_debug_reg_get (dbg, "PC");
900 
901 			if (!procfs_pid_slurp (tid, "status", info, sizeof (info))) {
902 				// Get information about pid (status, pc, etc.)
903 				pid_info = fill_pid_info (info, NULL, tid);
904 				pid_info->pc = pc;
905 			} else {
906 				pid_info = r_debug_pid_new (NULL, tid, uid, 's', pc);
907 			}
908 			r_list_append (list, pid_info);
909 			dbg->n_threads++;
910 		}
911 		closedir (dh);
912 		// Return to the original thread
913 		linux_attach_single_pid (dbg, prev_tid);
914 		dbg->tid = prev_tid;
915 		r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false);
916 	} else {
917 		/* Some linux configurations might hide threads from /proc, use this workaround instead */
918 #undef MAXPID
919 #define MAXPID 99999
920 		/* otherwise, brute force the pids */
921 		for (i = pid; i < MAXPID; i++) { // XXX
922 			if (procfs_pid_slurp (i, "status", buf, sizeof(buf)) == -1) {
923 				continue;
924 			}
925 			int uid = 0;
926 			/* look for a thread group id */
927 			ptr = strstr (buf, "Uid:");
928 			if (ptr) {
929 				uid = atoi (ptr + 4);
930 			}
931 			ptr = strstr (buf, "Tgid:");
932 			if (ptr) {
933 				int tgid = atoi (ptr + 5);
934 
935 				/* if it is not in our thread group, we don't want it */
936 				if (tgid != pid) {
937 					continue;
938 				}
939 
940 				if (procfs_pid_slurp (i, "comm", buf, sizeof(buf)) == -1) {
941 					/* fall back to auto-id */
942 					snprintf (buf, sizeof(buf), "thread_%d", thid++);
943 				}
944 				r_list_append (list, r_debug_pid_new (buf, i, uid, 's', 0));
945 			}
946 		}
947 	}
948 	return list;
949 }
950 
951 #define PRINT_FPU(fpregs) \
952 	r_cons_printf ("cwd = 0x%04x  ; control   ", (fpregs).cwd);\
953 	r_cons_printf ("swd = 0x%04x  ; status\n", (fpregs).swd);\
954 	r_cons_printf ("ftw = 0x%04x              ", (fpregs).ftw);\
955 	r_cons_printf ("fop = 0x%04x\n", (fpregs).fop);\
956 	r_cons_printf ("rip = 0x%016"PFMT64x"  ", (ut64)(fpregs).rip);\
957 	r_cons_printf ("rdp = 0x%016"PFMT64x"\n", (ut64)(fpregs).rdp);\
958 	r_cons_printf ("mxcsr = 0x%08x        ", (fpregs).mxcsr);\
959 	r_cons_printf ("mxcr_mask = 0x%08x\n", (fpregs).mxcr_mask)\
960 
961 #define PRINT_FPU_NOXMM(fpregs) \
962 	r_cons_printf ("cwd = 0x%04lx  ; control   ", (fpregs).cwd);\
963 	r_cons_printf ("swd = 0x%04lx  ; status\n", (fpregs).swd);\
964 	r_cons_printf ("twd = 0x%04lx              ", (fpregs).twd);\
965 	r_cons_printf ("fip = 0x%04lx          \n", (fpregs).fip);\
966 	r_cons_printf ("fcs = 0x%04lx              ", (fpregs).fcs);\
967 	r_cons_printf ("foo = 0x%04lx          \n", (fpregs).foo);\
968 	r_cons_printf ("fos = 0x%04lx              ", (fpregs).fos)
969 
print_fpu(void * f)970 static void print_fpu(void *f){
971 #if __x86_64__
972 	int i,j;
973 	struct user_fpregs_struct fpregs = *(struct user_fpregs_struct *)f;
974 #if __ANDROID__
975 	PRINT_FPU (fpregs);
976 	for (i = 0;i < 8; i++) {
977 		ut64 *b = (ut64 *)&fpregs.st_space[i*4];
978 		ut32 *c = (ut32*)&fpregs.st_space;
979 		float *f = (float *)&fpregs.st_space;
980 		c = c + (i * 4);
981 		f = f + (i * 4);
982 		r_cons_printf ("st%d =%0.3lg (0x%016"PFMT64x") | %0.3f (%08x) | "\
983 			"%0.3f (%08x) \n", i,
984 			(double)*((double*)&fpregs.st_space[i*4]), *b, (float) f[0],
985 			c[0], (float) f[1], c[1]);
986 	}
987 #else
988 	r_cons_printf ("---- x86-64 ----\n");
989 	PRINT_FPU (fpregs);
990 	r_cons_printf ("size = 0x%08x\n", (ut32)sizeof (fpregs));
991 	for (i = 0; i < 16; i++) {
992 		ut32 *a = (ut32 *)&fpregs.xmm_space;
993 		a = a + (i * 4);
994 		r_cons_printf ("xmm%d = %08x %08x %08x %08x   ", i, (int)a[0], (int)a[1],
995 					   (int)a[2], (int)a[3] );
996 		if (i < 8) {
997 			ut64 *st_u64 = (ut64*)&fpregs.st_space[i * 4];
998 			ut8 *st_u8 = (ut8 *)&fpregs.st_space[i * 4];
999 			long double *st_ld = (long double *)&fpregs.st_space[i * 4];
1000 			r_cons_printf ("mm%d = 0x%016" PFMT64x " | st%d = ", i, *st_u64, i);
1001 			// print as hex TBYTE - always little endian
1002 			for (j = 9; j >= 0; j--) {
1003 				r_cons_printf ("%02x", st_u8[j]);
1004 			}
1005 			// Using %Lf and %Le even though we do not show the extra precision to avoid another cast
1006 			// %f with (double)*st_ld would also work
1007 			r_cons_printf (" %Le %Lf\n", *st_ld, *st_ld);
1008 		} else {
1009 			r_cons_printf ("\n");
1010 		}
1011 	}
1012 #endif // __ANDROID__
1013 #elif __i386__
1014 	int i,j;
1015 #if __ANDROID__
1016 	struct user_fpxregs_struct fpxregs = *(struct user_fpxregs_struct*)f;
1017 	r_cons_printf ("---- x86-32 ----\n");
1018 	r_cons_printf ("cwd = 0x%04x  ; control   ", fpxregs.cwd);
1019 	r_cons_printf ("swd = 0x%04x  ; status\n", fpxregs.swd);
1020 	r_cons_printf ("twd = 0x%04x ", fpxregs.twd);
1021 	r_cons_printf ("fop = 0x%04x\n", fpxregs.fop);
1022 	r_cons_printf ("fip = 0x%08x\n", (ut32)fpxregs.fip);
1023 	r_cons_printf ("fcs = 0x%08x\n", (ut32)fpxregs.fcs);
1024 	r_cons_printf ("foo = 0x%08x\n", (ut32)fpxregs.foo);
1025 	r_cons_printf ("fos = 0x%08x\n", (ut32)fpxregs.fos);
1026 	r_cons_printf ("mxcsr = 0x%08x\n", (ut32)fpxregs.mxcsr);
1027 	for(i = 0; i < 8; i++) {
1028 		ut32 *a = (ut32*)(&fpxregs.xmm_space);
1029 		ut64 *b = (ut64 *)(&fpxregs.st_space[i * 4]);
1030 		ut32 *c = (ut32*)&fpxregs.st_space;
1031 		float *f = (float *)&fpxregs.st_space;
1032 		a = a + (i * 4);
1033 		c = c + (i * 4);
1034 		f = f + (i * 4);
1035 		r_cons_printf ("xmm%d = %08x %08x %08x %08x   ", i, (int)a[0],
1036 			(int)a[1], (int)a[2], (int)a[3] );
1037 		r_cons_printf ("st%d = %0.3lg (0x%016"PFMT64x") | %0.3f (0x%08x) | "\
1038 			"%0.3f (0x%08x)\n", i,
1039 			(double)*((double*)(&fpxregs.st_space[i*4])), b[0],
1040 			f[0], c[0], f[1], c[1]);
1041 	}
1042 #else
1043 	struct user_fpregs_struct fpregs = *(struct user_fpregs_struct *)f;
1044 	r_cons_printf ("---- x86-32-noxmm ----\n");
1045 	PRINT_FPU_NOXMM (fpregs);
1046 	for(i = 0; i < 8; i++) {
1047 		ut64 *b = (ut64 *)(&fpregs.st_space[i*4]);
1048 		double *d = (double*)b;
1049 		ut32 *c = (ut32*)&fpregs.st_space;
1050 		float *f = (float *)&fpregs.st_space;
1051 		c = c + (i * 4);
1052 		f = f + (i * 4);
1053 		r_cons_printf ("st%d = %0.3lg (0x%016"PFMT64x") | %0.3f (0x%08x) | "\
1054 			"%0.3f (0x%08x)\n", i, d[0], b[0], f[0], c[0], f[1], c[1]);
1055 	}
1056 #endif
1057 #else
1058 #warning print_fpu not implemented for this platform
1059 #endif
1060 }
1061 
linux_reg_read(RDebug * dbg,int type,ut8 * buf,int size)1062 int linux_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
1063 	bool showfpu = false;
1064 	int pid = dbg->tid;
1065 	int ret = 0;
1066 	if (type < -1) {
1067 		showfpu = true;
1068 		type = -type;
1069 	}
1070 	switch (type) {
1071 	case R_REG_TYPE_DRX:
1072 #if __POWERPC__
1073 		// no drx for powerpc
1074 		return false;
1075 #elif __i386__ || __x86_64__
1076 #if !__ANDROID__
1077 	{
1078 		int i;
1079 		for (i = 0; i < 8; i++) { //DR0-DR7
1080 			if (i == 4 || i == 5) {
1081 				continue;
1082 			}
1083 			long ret = r_debug_ptrace (dbg, PTRACE_PEEKUSER, pid,
1084 					(void *)r_offsetof (struct user, u_debugreg[i]), 0);
1085 			if ((i+1) * sizeof (ret) > size) {
1086 				eprintf ("linux_reg_get: Buffer too small %d\n", size);
1087 				break;
1088 			}
1089 			memcpy (buf + (i * sizeof (ret)), &ret, sizeof (ret));
1090 		}
1091 		struct user a;
1092 		return sizeof (a.u_debugreg);
1093 	}
1094 #else
1095 	#warning Android X86 does not support DRX
1096 #endif
1097 #endif
1098 		return true;
1099 		break;
1100 	case R_REG_TYPE_FPU:
1101 	case R_REG_TYPE_MMX:
1102 	case R_REG_TYPE_XMM:
1103 #if __POWERPC__
1104 		return false;
1105 #elif __x86_64__ || __i386__
1106 		{
1107 		struct user_fpregs_struct fpregs;
1108 		if (type == R_REG_TYPE_FPU) {
1109 #if __x86_64__
1110 			ret = r_debug_ptrace (dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1111 			if (ret != 0) {
1112 				r_sys_perror ("PTRACE_GETFPREGS");
1113 				return false;
1114 			}
1115 			if (showfpu) {
1116 				print_fpu ((void *)&fpregs);
1117 			}
1118 			size = R_MIN (sizeof (fpregs), size);
1119 			memcpy (buf, &fpregs, size);
1120 			return size;
1121 #elif __i386__
1122 #if !__ANDROID__
1123 			struct user_fpxregs_struct fpxregs;
1124 			ret = r_debug_ptrace (dbg, PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
1125 			if (ret == 0) {
1126 				if (showfpu) {
1127 					print_fpu ((void *)&fpxregs);
1128 				}
1129 				size = R_MIN (sizeof (fpxregs), size);
1130 				memcpy (buf, &fpxregs, size);
1131 				return size;
1132 			} else {
1133 				ret = r_debug_ptrace (dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1134 				if (showfpu) {
1135 					print_fpu ((void *)&fpregs);
1136 				}
1137 				if (ret != 0) {
1138 					r_sys_perror ("PTRACE_GETFPREGS");
1139 					return false;
1140 				}
1141 				size = R_MIN (sizeof (fpregs), size);
1142 				memcpy (buf, &fpregs, size);
1143 				return size;
1144 			}
1145 #else
1146 			ret = r_debug_ptrace (dbg, PTRACE_GETFPREGS, pid, NULL, &fpregs);
1147 			if (showfpu) {
1148 				print_fpu ((void *)&fpregs);
1149 			}
1150 			if (ret != 0) {
1151 				r_sys_perror ("PTRACE_GETFPREGS");
1152 				return false;
1153 			}
1154 			size = R_MIN (sizeof (fpregs), size);
1155 			memcpy (buf, &fpregs, size);
1156 			return size;
1157 #endif // !__ANDROID__
1158 #endif // __i386__
1159 		}
1160 		}
1161 #else
1162 	#warning getfpregs not implemented for this platform
1163 #endif
1164 		break;
1165 	case R_REG_TYPE_SEG:
1166 	case R_REG_TYPE_FLG:
1167 	case R_REG_TYPE_GPR:
1168 		{
1169 			R_DEBUG_REG_T regs;
1170 			memset (&regs, 0, sizeof (regs));
1171 			memset (buf, 0, size);
1172 #if (__arm64__ || __aarch64__ || __s390x__) && defined(PTRACE_GETREGSET)
1173 			struct iovec io = {
1174 				.iov_base = &regs,
1175 				.iov_len = sizeof (regs)
1176 			};
1177 			ret = r_debug_ptrace (dbg, PTRACE_GETREGSET, pid, 1, &io);
1178 			// ret = ptrace (PTRACE_GETREGSET, pid, (void*)(size_t)(NT_PRSTATUS), NULL); // &io);
1179 			if (ret != 0) {
1180 				r_sys_perror("PTRACE_GETREGSET");
1181 				return false;
1182 			}
1183 #elif __BSD__ && (__POWERPC__ || __sparc__)
1184 			ret = r_debug_ptrace (dbg, PTRACE_GETREGS, pid, &regs, NULL);
1185 #else
1186 			/* linux -{arm/mips/riscv/x86/x86_64} */
1187 			ret = r_debug_ptrace (dbg, PTRACE_GETREGS, pid, NULL, &regs);
1188 #endif
1189 			/*
1190 			 * if perror here says 'no such process' and the
1191 			 * process exists still.. is because there's a missing call
1192 			 * to 'wait'. and the process is not yet available to accept
1193 			 * more ptrace queries.
1194 			 */
1195 			if (ret != 0) {
1196 				r_sys_perror ("PTRACE_GETREGS");
1197 				return false;
1198 			}
1199 			size = R_MIN (sizeof (regs), size);
1200 			memcpy (buf, &regs, size);
1201 			return size;
1202 		}
1203 		break;
1204 	case R_REG_TYPE_YMM:
1205 		{
1206 #if HAVE_YMM && __x86_64__ && defined(PTRACE_GETREGSET)
1207 		ut32 ymm_space[128];	// full ymm registers
1208 		struct _xstate xstate;
1209 		struct iovec iov;
1210 		iov.iov_base = &xstate;
1211 		iov.iov_len = sizeof(struct _xstate);
1212 		ret = r_debug_ptrace (dbg, PTRACE_GETREGSET, pid, (void*)NT_X86_XSTATE, &iov);
1213 		if (ret != 0) {
1214 			r_sys_perror ("PTRACE_GETREGSET");
1215 			return false;
1216 		}
1217 		// stitch together xstate.fpstate._xmm and xstate.ymmh assuming LE
1218 		int ri,rj;
1219 		for (ri = 0; ri < 16; ri++)	{
1220 			for (rj=0; rj < 4; rj++)	{
1221 #ifdef __ANDROID__
1222 				ymm_space[ri*8+rj] = ((struct _libc_fpstate*) &xstate.fpstate)->_xmm[ri].element[rj];
1223 #else
1224 				ymm_space[ri*8+rj] = xstate.fpstate._xmm[ri].element[rj];
1225 #endif
1226 			}
1227 			for (rj=0; rj < 4; rj++)	{
1228 				ymm_space[ri*8+(rj+4)] = xstate.ymmh.ymmh_space[ri*4+rj];
1229 			}
1230 		}
1231 		size = R_MIN (sizeof (ymm_space), size);
1232 		memcpy (buf, &ymm_space, size);
1233 		return size;
1234 #endif
1235 		return false;
1236 		}
1237 		break;
1238 	}
1239 	return false;
1240 }
1241 
linux_reg_write(RDebug * dbg,int type,const ut8 * buf,int size)1242 int linux_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) {
1243 	int pid = dbg->tid;
1244 
1245 	if (type == R_REG_TYPE_DRX) {
1246 #if !__ANDROID__ && (__i386__ || __x86_64__)
1247 		int i;
1248 		long *val = (long*)buf;
1249 		for (i = 0; i < 8; i++) { // DR0-DR7
1250 			if (i == 4 || i == 5) {
1251 				continue;
1252 			}
1253 			if (r_debug_ptrace (dbg, PTRACE_POKEUSER, pid,
1254 					(void *)r_offsetof (struct user, u_debugreg[i]), (r_ptrace_data_t)val[i])) {
1255 				eprintf ("ptrace error for dr %d\n", i);
1256 				r_sys_perror ("ptrace POKEUSER");
1257 			}
1258 		}
1259 		return sizeof (R_DEBUG_REG_T);
1260 #else
1261 		return false;
1262 #endif
1263 	}
1264 	if (type == R_REG_TYPE_GPR) {
1265 #if __arm64__ || __aarch64__ || __s390x__
1266 		struct iovec io = {
1267 			.iov_base = (void*)buf,
1268 			.iov_len = sizeof (R_DEBUG_REG_T)
1269 		};
1270 		int ret = r_debug_ptrace (dbg, PTRACE_SETREGSET, pid, (void*)(size_t)NT_PRSTATUS, (r_ptrace_data_t)(size_t)&io);
1271 #elif __POWERPC__ || __sparc__
1272 		int ret = r_debug_ptrace (dbg, PTRACE_SETREGS, pid, buf, NULL);
1273 #else
1274 		int ret = r_debug_ptrace (dbg, PTRACE_SETREGS, pid, 0, (void*)buf);
1275 #endif
1276 #if DEAD_CODE
1277 		if (size > sizeof (R_DEBUG_REG_T)) {
1278 			size = sizeof (R_DEBUG_REG_T);
1279 		}
1280 #endif
1281 		if (ret == -1) {
1282 			r_sys_perror ("reg_write");
1283 			return false;
1284 		}
1285 		return true;
1286 	}
1287 	if (type == R_REG_TYPE_FPU) {
1288 #if __i386__ || __x86_64__
1289 		int ret = r_debug_ptrace (dbg, PTRACE_SETFPREGS, pid, 0, (void*)buf);
1290 		return (ret != 0) ? false : true;
1291 #endif
1292 	}
1293 	return false;
1294 }
1295 
linux_desc_list(int pid)1296 RList *linux_desc_list (int pid) {
1297 	RList *ret = NULL;
1298 	char path[512], file[512], buf[512];
1299 	struct dirent *de;
1300 	RDebugDesc *desc;
1301 	int type, perm;
1302 	int len, len2;
1303 	struct stat st;
1304 	DIR *dd = NULL;
1305 
1306 	snprintf (path, sizeof (path), "/proc/%i/fd/", pid);
1307 	if (!(dd = opendir (path))) {
1308 		r_sys_perror ("opendir /proc/x/fd");
1309 		return NULL;
1310 	}
1311 	ret = r_list_new ();
1312 	if (!ret) {
1313 		closedir (dd);
1314 		return NULL;
1315 	}
1316 	ret->free = (RListFree)r_debug_desc_free;
1317 	while ((de = (struct dirent *)readdir(dd))) {
1318 		if (de->d_name[0] == '.') {
1319 			continue;
1320 		}
1321 		len = strlen (path);
1322 		len2 = strlen (de->d_name);
1323 		if (len + len2 + 1 >= sizeof(file)) {
1324 			r_list_free (ret);
1325 			closedir (dd);
1326 			eprintf ("Filename is too long");
1327 			return NULL;
1328 		}
1329 		memcpy (file, path, len);
1330 		memcpy (file + len, de->d_name, len2 + 1);
1331 		buf[0] = 0;
1332 		if (readlink (file, buf, sizeof (buf) - 1) == -1) {
1333 			return NULL;
1334 		}
1335 		buf[sizeof (buf) - 1] = 0;
1336 		type = perm = 0;
1337 		if (stat (file, &st) != -1) {
1338 			type  = st.st_mode & S_IFIFO  ? 'P':
1339 #ifdef S_IFSOCK
1340 				st.st_mode & S_IFSOCK ? 'S':
1341 #endif
1342 				st.st_mode & S_IFCHR  ? 'C':'-';
1343 		}
1344 		if (lstat(path, &st) != -1) {
1345 			if (st.st_mode & S_IRUSR) {
1346 				perm |= R_PERM_R;
1347 			}
1348 			if (st.st_mode & S_IWUSR) {
1349 				perm |= R_PERM_W;
1350 			}
1351 		}
1352 		//TODO: Offset
1353 		desc = r_debug_desc_new (atoi (de->d_name), buf, perm, type, 0);
1354 		if (!desc) {
1355 			break;
1356 		}
1357 		r_list_append (ret, desc);
1358 	}
1359 	closedir (dd);
1360 	return ret;
1361 }
1362 
1363 #endif
1364