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 (®s, 0, sizeof (regs));
1171 memset (buf, 0, size);
1172 #if (__arm64__ || __aarch64__ || __s390x__) && defined(PTRACE_GETREGSET)
1173 struct iovec io = {
1174 .iov_base = ®s,
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, ®s, NULL);
1185 #else
1186 /* linux -{arm/mips/riscv/x86/x86_64} */
1187 ret = r_debug_ptrace (dbg, PTRACE_GETREGS, pid, NULL, ®s);
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, ®s, 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