1 // Derived from Plan 9 from User Space src/libmach/Linux.c
2 // http://code.swtch.com/plan9port/src/tip/src/libmach/Linux.c
3 //
4 // Copyright © 1994-1999 Lucent Technologies Inc.
5 // Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
6 // Portions Copyright © 1997-1999 Vita Nuova Limited.
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
8 // Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
9 // Portions Copyright © 2001-2007 Russ Cox.
10 // Portions Copyright © 2009 The Go Authors. All rights reserved.
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to deal
14 // in the Software without restriction, including without limitation the rights
15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 // copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be included in
20 // all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 // THE SOFTWARE.
29
30 #include <u.h>
31 #include <sys/syscall.h> /* for tkill */
32 #include <unistd.h>
33 #include <dirent.h>
34 #include <sys/ptrace.h>
35 #include <sys/signal.h>
36 #include <sys/wait.h>
37 #include <errno.h>
38 #include <libc.h>
39 #include <bio.h>
40 #include <mach.h>
41 #define Ureg Ureg32
42 #include <ureg_x86.h>
43 #undef Ureg
44 #define Ureg Ureg64
45 #include <ureg_amd64.h>
46 #undef Ureg
47 #undef waitpid
48
49 // The old glibc used with crosstool compilers on thresher
50 // doesn't know these numbers, but the Linux kernel
51 // had them as far back as 2.6.0.
52 #ifndef WSTOPPED
53 #define WSTOPPED 2
54 #define WCONTINUED 8
55 #define WIFCONTINUED(x) ((x) == 0xffff)
56 #endif
57 #ifndef PTRACE_SETOPTIONS
58 #define PTRACE_SETOPTIONS 0x4200
59 #define PTRACE_GETEVENTMSG 0x4201
60 #define PTRACE_O_TRACEFORK 0x2
61 #define PTRACE_O_TRACEVFORK 0x4
62 #define PTRACE_O_TRACECLONE 0x8
63 #define PTRACE_O_TRACEEXEC 0x10
64 #define PTRACE_O_TRACEVFORKDONE 0x20
65 #define PTRACE_O_TRACEEXIT 0x40
66 #define PTRACE_EVENT_FORK 0x1
67 #define PTRACE_EVENT_VFORK 0x2
68 #define PTRACE_EVENT_CLONE 0x3
69 #define PTRACE_EVENT_EXEC 0x4
70 #define PTRACE_EVENT_VFORK_DONE 0x5
71 #define PTRACE_EVENT_EXIT 0x6
72 #endif
73
74 typedef struct Ureg64 Ureg64;
75
76 static Maprw ptracesegrw;
77 static Maprw ptraceregrw;
78
79 // /usr/include/asm-x86_64/user.h
80 struct user_regs_struct {
81 unsigned long r15,r14,r13,r12,rbp,rbx,r11,r10;
82 unsigned long r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
83 unsigned long rip,cs,eflags;
84 unsigned long rsp,ss;
85 unsigned long fs_base, gs_base;
86 unsigned long ds,es,fs,gs;
87 };
88
89 // Linux gets very upset if a debugger forgets the reported state
90 // of a debugged process, so we keep everything we know about
91 // a debugged process in the LinuxThread structure.
92 //
93 // We can poll for state changes by calling waitpid and interpreting
94 // the integer status code that comes back. Wait1 does this.
95 //
96 // If the process is already running, it is an error to PTRACE_CONT it.
97 //
98 // If the process is already stopped, it is an error to stop it again.
99 //
100 // If the process is stopped because of a signal, the debugger must
101 // relay the signal to the PTRACE_CONT call, or else the signal is
102 // dropped.
103 //
104 // If the process exits, the debugger should detach so that the real
105 // parent can reap the zombie.
106 //
107 // On first attach, the debugger should set a handful of flags in order
108 // to catch future events like fork, clone, exec, etc.
109
110 // One for every attached thread.
111 typedef struct LinuxThread LinuxThread;
112 struct LinuxThread
113 {
114 int pid;
115 int tid;
116 int state;
117 int signal;
118 int child;
119 int exitcode;
120 };
121
122 static int trace = 0;
123
124 static LinuxThread **thr;
125 static int nthr;
126 static int mthr;
127
128 static int realpid(int pid);
129
130 enum
131 {
132 Unknown,
133 Detached,
134 Attached,
135 AttachStop,
136 Stopped,
137 Running,
138 Forking,
139 Vforking,
140 VforkDone,
141 Cloning,
142 Execing,
143 Exiting,
144 Exited,
145 Killed,
146
147 NSTATE,
148 };
149
150 static char* statestr[NSTATE] = {
151 "Unknown",
152 "Detached",
153 "Attached",
154 "AttachStop",
155 "Stopped",
156 "Running",
157 "Forking",
158 "Vforking",
159 "VforkDone",
160 "Cloning",
161 "Execing",
162 "Exiting",
163 "Exited",
164 "Killed"
165 };
166
167 static LinuxThread*
168 attachthread(int pid, int tid, int *new, int newstate)
169 {
170 int i, n, status;
171 LinuxThread **p, *t;
172 uintptr flags;
173
174 if(new)
175 *new = 0;
176
177 for(i=0; i<nthr; i++)
178 if((pid == 0 || thr[i]->pid == pid) && thr[i]->tid == tid) {
179 t = thr[i];
180 goto fixup;
181 }
182
183 if(!new)
184 return nil;
185
186 if(nthr >= mthr) {
187 n = mthr;
188 if(n == 0)
189 n = 64;
190 else
191 n *= 2;
192 p = realloc(thr, n*sizeof thr[0]);
193 if(p == nil)
194 return nil;
195 thr = p;
196 mthr = n;
197 }
198
199 t = malloc(sizeof *t);
200 if(t == nil)
201 return nil;
202 memset(t, 0, sizeof *t);
203
204 thr[nthr++] = t;
205 if(pid == 0 && nthr > 0)
206 pid = thr[0]->pid;
207 t->pid = pid;
208 t->tid = tid;
209 t->state = newstate;
210 if(trace)
211 fprint(2, "new thread %d %d\n", t->pid, t->tid);
212 if(new)
213 *new = 1;
214
215 fixup:
216 if(t->state == Detached) {
217 if(ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
218 fprint(2, "ptrace ATTACH %d: %r\n", tid);
219 return nil;
220 }
221 t->state = Attached;
222 }
223
224 if(t->state == Attached) {
225 // wait for stop, so we can set options
226 if(waitpid(tid, &status, __WALL|WUNTRACED|WSTOPPED) < 0)
227 return nil;
228 if(!WIFSTOPPED(status)) {
229 fprint(2, "waitpid %d: status=%#x not stopped\n", tid);
230 return nil;
231 }
232 t->state = AttachStop;
233 }
234
235 if(t->state == AttachStop) {
236 // set options so we'll find out about new threads
237 flags = PTRACE_O_TRACEFORK |
238 PTRACE_O_TRACEVFORK |
239 PTRACE_O_TRACECLONE |
240 PTRACE_O_TRACEEXEC |
241 PTRACE_O_TRACEVFORKDONE;
242 if(ptrace(PTRACE_SETOPTIONS, tid, 0, (void*)flags) < 0) {
243 fprint(2, "ptrace PTRACE_SETOPTIONS %d: %r\n", tid);
244 return nil;
245 }
246 t->state = Stopped;
247 }
248
249 return t;
250 }
251
252 static LinuxThread*
253 findthread(int tid)
254 {
255 return attachthread(0, tid, nil, 0);
256 }
257
258 int
259 procthreadpids(int pid, int *p, int np)
260 {
261 int i, n;
262 LinuxThread *t;
263
264 n = 0;
265 for(i=0; i<nthr; i++) {
266 t = thr[i];
267 if(t->pid == pid) {
268 switch(t->state) {
269 case Exited:
270 case Detached:
271 case Killed:
272 break;
273
274 default:
275 if(n < np)
276 p[n] = t->tid;
277 n++;
278 break;
279 }
280 }
281 }
282 return n;
283 }
284
285 // Execute a single wait and update the corresponding thread.
286 static int
287 wait1(int nohang)
288 {
289 int tid, new, status, event;
290 ulong data;
291 LinuxThread *t;
292 enum
293 {
294 NormalStop = 0x137f
295 };
296
297 if(nohang != 0)
298 nohang = WNOHANG;
299
300 status = 0;
301 tid = waitpid(-1, &status, __WALL|WUNTRACED|WSTOPPED|WCONTINUED|nohang);
302
303 if(tid < 0)
304 return -1;
305 if(tid == 0)
306 return 0;
307
308 if(trace > 0 && status != NormalStop)
309 fprint(2, "TID %d: %#x\n", tid, status);
310
311 t = findthread(tid);
312 if(t == nil) {
313 // Sometimes the kernel tells us about new threads
314 // before we see the parent clone.
315 t = attachthread(0, tid, &new, Stopped);
316 if(t == nil) {
317 fprint(2, "failed to attach to new thread %d\n", tid);
318 return -1;
319 }
320 }
321
322 if(WIFSTOPPED(status)) {
323 t->state = Stopped;
324 t->signal = WSTOPSIG(status);
325 if(trace)
326 fprint(2, "tid %d: stopped %#x%s\n", tid, status,
327 status != NormalStop ? " ***" : "");
328 if(t->signal == SIGTRAP && (event = status>>16) != 0) { // ptrace event
329 switch(event) {
330 case PTRACE_EVENT_FORK:
331 t->state = Forking;
332 goto child;
333
334 case PTRACE_EVENT_VFORK:
335 t->state = Vforking;
336 goto child;
337
338 case PTRACE_EVENT_CLONE:
339 t->state = Cloning;
340 goto child;
341
342 child:
343 if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
344 fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
345 break;
346 }
347 t->child = data;
348 attachthread(t->pid, t->child, &new, Running);
349 break;
350
351 case PTRACE_EVENT_EXEC:
352 t->state = Execing;
353 break;
354
355 case PTRACE_EVENT_VFORK_DONE:
356 t->state = VforkDone;
357 break;
358
359 case PTRACE_EVENT_EXIT:
360 // We won't see this unless we set PTRACE_O_TRACEEXIT.
361 // The debuggers assume that a read or write on a Map
362 // will fail for a thread that has exited. This event
363 // breaks that assumption. It's not a big deal: we
364 // only lose the ability to see the register state at
365 // the time of exit.
366 if(trace)
367 fprint(2, "tid %d: exiting %#x\n", tid, status);
368 t->state = Exiting;
369 if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
370 fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
371 break;
372 }
373 t->exitcode = data;
374 break;
375 }
376 }
377 }
378 if(WIFCONTINUED(status)) {
379 if(trace)
380 fprint(2, "tid %d: continued %#x\n", tid, status);
381 t->state = Running;
382 }
383 if(WIFEXITED(status)) {
384 if(trace)
385 fprint(2, "tid %d: exited %#x\n", tid, status);
386 t->state = Exited;
387 t->exitcode = WEXITSTATUS(status);
388 t->signal = -1;
389 ptrace(PTRACE_DETACH, t->tid, 0, 0);
390 if(trace)
391 fprint(2, "tid %d: detach exited\n", tid);
392 }
393 if(WIFSIGNALED(status)) {
394 if(trace)
395 fprint(2, "tid %d: signaled %#x\n", tid, status);
396 t->state = Exited;
397 t->signal = WTERMSIG(status);
398 t->exitcode = -1;
399 ptrace(PTRACE_DETACH, t->tid, 0, 0);
400 if(trace)
401 fprint(2, "tid %d: detach signaled\n", tid);
402 }
403 return 1;
404 }
405
406 static int
407 waitstop(LinuxThread *t)
408 {
409 while(t->state == Running)
410 if(wait1(0) < 0)
411 return -1;
412 return 0;
413 }
414
415 // Attach to and stop all threads in process pid.
416 // Must stop everyone in order to make sure we set
417 // the "tell me about new threads" option in every
418 // task.
419 int
420 attachallthreads(int pid)
421 {
422 int tid, foundnew, new;
423 char buf[100];
424 DIR *d;
425 struct dirent *de;
426 LinuxThread *t;
427
428 if(pid == 0) {
429 fprint(2, "attachallthreads(0)\n");
430 return -1;
431 }
432
433 pid = realpid(pid);
434
435 snprint(buf, sizeof buf, "/proc/%d/task", pid);
436 if((d = opendir(buf)) == nil) {
437 fprint(2, "opendir %s: %r\n", buf);
438 return -1;
439 }
440
441 // Loop in case new threads are being created right now.
442 // We stop every thread as we find it, so eventually
443 // this has to stop (or the system runs out of procs).
444 do {
445 foundnew = 0;
446 while((de = readdir(d)) != nil) {
447 tid = atoi(de->d_name);
448 if(tid == 0)
449 continue;
450 t = attachthread(pid, tid, &new, Detached);
451 foundnew |= new;
452 if(t)
453 waitstop(t);
454 }
455 rewinddir(d);
456 } while(foundnew);
457 closedir(d);
458
459 return 0;
460 }
461
462 Map*
463 attachproc(int pid, Fhdr *fp)
464 {
465 Map *map;
466
467 if(pid == 0) {
468 fprint(2, "attachproc(0)\n");
469 return nil;
470 }
471
472 if(findthread(pid) == nil && attachallthreads(pid) < 0)
473 return nil;
474
475 map = newmap(0, 4);
476 if (!map)
477 return 0;
478 map->pid = pid;
479 if(mach->regsize)
480 setmap(map, -1, 0, mach->regsize, 0, "regs", ptraceregrw);
481 // if(mach->fpregsize)
482 // setmap(map, -1, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs", ptraceregrw);
483 setmap(map, -1, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "*text", ptracesegrw);
484 setmap(map, -1, fp->dataddr, mach->utop, fp->dataddr, "*data", ptracesegrw);
485 return map;
486 }
487
488 void
489 detachproc(Map *m)
490 {
491 LinuxThread *t;
492
493 t = findthread(m->pid);
494 if(t != nil) {
495 ptrace(PTRACE_DETACH, t->tid, 0, 0);
496 t->state = Detached;
497 if(trace)
498 fprint(2, "tid %d: detachproc\n", t->tid);
499 // TODO(rsc): Reclaim thread structs somehow?
500 }
501 free(m);
502 }
503
504 /* /proc/pid/stat contains
505 pid
506 command in parens
507 0. state
508 1. ppid
509 2. pgrp
510 3. session
511 4. tty_nr
512 5. tpgid
513 6. flags (math=4, traced=10)
514 7. minflt
515 8. cminflt
516 9. majflt
517 10. cmajflt
518 11. utime
519 12. stime
520 13. cutime
521 14. cstime
522 15. priority
523 16. nice
524 17. 0
525 18. itrealvalue
526 19. starttime
527 20. vsize
528 21. rss
529 22. rlim
530 23. startcode
531 24. endcode
532 25. startstack
533 26. kstkesp
534 27. kstkeip
535 28. pending signal bitmap
536 29. blocked signal bitmap
537 30. ignored signal bitmap
538 31. caught signal bitmap
539 32. wchan
540 33. nswap
541 34. cnswap
542 35. exit_signal
543 36. processor
544 */
545
546 static int
547 readstat(int pid, char *buf, int nbuf, char **f, int nf)
548 {
549 int fd, n;
550 char *p;
551
552 snprint(buf, nbuf, "/proc/%d/stat", pid);
553 if((fd = open(buf, OREAD)) < 0){
554 fprint(2, "open %s: %r\n", buf);
555 return -1;
556 }
557 n = read(fd, buf, nbuf-1);
558 close(fd);
559 if(n <= 0){
560 fprint(2, "read %s: %r\n", buf);
561 return -1;
562 }
563 buf[n] = 0;
564
565 /* command name is in parens, no parens afterward */
566 p = strrchr(buf, ')');
567 if(p == nil || *++p != ' '){
568 fprint(2, "bad format in /proc/%d/stat\n", pid);
569 return -1;
570 }
571 ++p;
572
573 nf = tokenize(p, f, nf);
574 if(0) print("code 0x%lux-0x%lux stack 0x%lux kstk 0x%lux keip 0x%lux pending 0x%lux\n",
575 strtoul(f[23], 0, 0), strtoul(f[24], 0, 0), strtoul(f[25], 0, 0),
576 strtoul(f[26], 0, 0), strtoul(f[27], 0, 0), strtoul(f[28], 0, 0));
577
578 return nf;
579 }
580
581 static char*
582 readstatus(int pid, char *buf, int nbuf, char *key)
583 {
584 int fd, n;
585 char *p;
586
587 snprint(buf, nbuf, "/proc/%d/status", pid);
588 if((fd = open(buf, OREAD)) < 0){
589 fprint(2, "open %s: %r\n", buf);
590 return nil;
591 }
592 n = read(fd, buf, nbuf-1);
593 close(fd);
594 if(n <= 0){
595 fprint(2, "read %s: %r\n", buf);
596 return nil;
597 }
598 buf[n] = 0;
599 p = strstr(buf, key);
600 if(p)
601 return p+strlen(key);
602 return nil;
603 }
604
605 int
606 procnotes(int pid, char ***pnotes)
607 {
608 char buf[1024], *f[40];
609 int i, n, nf;
610 char *s, **notes;
611 ulong sigs;
612 extern char *_p9sigstr(int, char*);
613
614 *pnotes = nil;
615 nf = readstat(pid, buf, sizeof buf, f, nelem(f));
616 if(nf <= 28)
617 return -1;
618
619 sigs = strtoul(f[28], 0, 0) & ~(1<<SIGCONT);
620 if(sigs == 0){
621 *pnotes = nil;
622 return 0;
623 }
624
625 notes = malloc(32*sizeof(char*));
626 if(notes == nil)
627 return -1;
628 memset(notes, 0, 32*sizeof(char*));
629 n = 0;
630 for(i=0; i<32; i++){
631 if((sigs&(1<<i)) == 0)
632 continue;
633 if((s = _p9sigstr(i, nil)) == nil)
634 continue;
635 notes[n++] = s;
636 }
637 *pnotes = notes;
638 return n;
639 }
640
641 static int
642 realpid(int pid)
643 {
644 char buf[1024], *p;
645
646 p = readstatus(pid, buf, sizeof buf, "\nTgid:");
647 if(p == nil)
648 return pid;
649 return atoi(p);
650 }
651
652 int
653 ctlproc(int pid, char *msg)
654 {
655 int new;
656 LinuxThread *t;
657 uintptr data;
658
659 while(wait1(1) > 0)
660 ;
661
662 if(strcmp(msg, "attached") == 0){
663 t = attachthread(pid, pid, &new, Attached);
664 if(t == nil)
665 return -1;
666 return 0;
667 }
668
669 if(strcmp(msg, "hang") == 0){
670 if(pid == getpid())
671 return ptrace(PTRACE_TRACEME, 0, 0, 0);
672 werrstr("can only hang self");
673 return -1;
674 }
675
676 t = findthread(pid);
677 if(t == nil) {
678 werrstr("not attached to pid %d", pid);
679 return -1;
680 }
681 if(t->state == Exited) {
682 werrstr("pid %d has exited", pid);
683 return -1;
684 }
685 if(t->state == Killed) {
686 werrstr("pid %d has been killed", pid);
687 return -1;
688 }
689
690 if(strcmp(msg, "kill") == 0) {
691 if(ptrace(PTRACE_KILL, pid, 0, 0) < 0)
692 return -1;
693 t->state = Killed;
694 return 0;
695 }
696 if(strcmp(msg, "startstop") == 0){
697 if(ctlproc(pid, "start") < 0)
698 return -1;
699 return waitstop(t);
700 }
701 if(strcmp(msg, "sysstop") == 0){
702 if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
703 return -1;
704 t->state = Running;
705 return waitstop(t);
706 }
707 if(strcmp(msg, "stop") == 0){
708 if(trace > 1)
709 fprint(2, "tid %d: tkill stop\n", pid);
710 if(t->state == Stopped)
711 return 0;
712 if(syscall(__NR_tkill, pid, SIGSTOP) < 0)
713 return -1;
714 return waitstop(t);
715 }
716 if(strcmp(msg, "step") == 0){
717 if(t->state == Running) {
718 werrstr("cannot single-step unstopped %d", pid);
719 return -1;
720 }
721 if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0)
722 return -1;
723 return waitstop(t);
724 }
725 if(strcmp(msg, "start") == 0) {
726 if(t->state == Running)
727 return 0;
728 data = 0;
729 if(t->state == Stopped && t->signal != SIGSTOP && t->signal != SIGTRAP)
730 data = t->signal;
731 if(trace && data)
732 fprint(2, "tid %d: continue %lud\n", pid, (ulong)data);
733 if(ptrace(PTRACE_CONT, pid, 0, (void*)data) < 0)
734 return -1;
735 t->state = Running;
736 return 0;
737 }
738 if(strcmp(msg, "waitstop") == 0) {
739 return waitstop(t);
740 }
741 werrstr("unknown control message '%s'", msg);
742 return -1;
743 }
744
745 char*
746 proctextfile(int pid)
747 {
748 static char buf[1024], pbuf[128];
749
750 snprint(pbuf, sizeof pbuf, "/proc/%d/exe", pid);
751 if(readlink(pbuf, buf, sizeof buf) >= 0)
752 return strdup(buf);
753 if(access(pbuf, AEXIST) >= 0)
754 return strdup(pbuf);
755 return nil;
756 }
757
758
759 static int
760 ptracerw(int type, int xtype, int isr, int pid, uvlong addr, void *v, uint n)
761 {
762 int i;
763 uintptr u, a;
764 uchar buf[sizeof(uintptr)];
765
766 for(i=0; i<n; i+=sizeof(uintptr)){
767 // Tread carefully here. On recent versions of glibc,
768 // ptrace is a variadic function which means the third
769 // argument will be pushed onto the stack as a uvlong.
770 // This is fine on amd64 but will not work for 386.
771 // We must convert addr to a uintptr.
772 a = addr+i;
773 if(isr){
774 errno = 0;
775 u = ptrace(type, pid, a, 0);
776 if(errno)
777 goto ptraceerr;
778 if(n-i >= sizeof(uintptr))
779 memmove((char*)v+i, &u, sizeof(uintptr));
780 else{
781 memmove(buf, &u, sizeof u);
782 memmove((char*)v+i, buf, n-i);
783 }
784 }else{
785 if(n-i >= sizeof(uintptr))
786 u = *(uintptr*)((char*)v+i);
787 else{
788 errno = 0;
789 u = ptrace(xtype, pid, a, 0);
790 if(errno)
791 return -1;
792 memmove(buf, &u, sizeof u);
793 memmove(buf, (char*)v+i, n-i);
794 memmove(&u, buf, sizeof u);
795 }
796 if(ptrace(type, pid, a, u) < 0)
797 goto ptraceerr;
798 }
799 }
800 return 0;
801
802 ptraceerr:
803 werrstr("ptrace %s addr=%#llux pid=%d: %r", isr ? "read" : "write", addr, pid);
804 return -1;
805 }
806
807 static int
808 ptracesegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
809 {
810 return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA,
811 isr, map->pid, addr, v, n);
812 }
813
814 // If the debugger is compiled as an x86-64 program,
815 // then all the ptrace register read/writes are done on
816 // a 64-bit register set. If the target program
817 // is a 32-bit program, the debugger is expected to
818 // read the bottom half of the relevant registers
819 // out of the 64-bit set.
820
821 // Linux 32-bit is
822 // BX CX DX SI DI BP AX DS ES FS GS OrigAX IP CS EFLAGS SP SS
823
824 // Linux 64-bit is
825 // R15 R14 R13 R12 BP BX R11 R10 R9 R8 AX CX DX SI DI OrigAX IP CS EFLAGS SP SS FSBase GSBase DS ES FS GS
826
827 // Go 32-bit is
828 // DI SI BP NSP BX DX CX AX GS FS ES DS TRAP ECODE PC CS EFLAGS SP SS
829
830 uint go32tolinux32tab[] = {
831 4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16
832 };
833 static int
834 go32tolinux32(uvlong addr)
835 {
836 int r;
837
838 if(addr%4 || addr/4 >= nelem(go32tolinux32tab))
839 return -1;
840 r = go32tolinux32tab[addr/4];
841 if(r < 0)
842 return -1;
843 return r*4;
844 }
845
846 uint go32tolinux64tab[] = {
847 14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20
848 };
849 static int
850 go32tolinux64(uvlong addr)
851 {
852 int r;
853
854 if(addr%4 || addr/4 >= nelem(go32tolinux64tab))
855 return -1;
856 r = go32tolinux64tab[addr/4];
857 if(r < 0)
858 return -1;
859 return r*8;
860 }
861
862 extern Mach mi386;
863 extern Mach mamd64;
864
865 static int
866 go2linux(uvlong addr)
867 {
868 if(sizeof(void*) == 4) {
869 if(mach == &mi386)
870 return go32tolinux32(addr);
871 werrstr("unsupported architecture");
872 return -1;
873 }
874
875 if(mach == &mi386)
876 return go32tolinux64(addr);
877 if(mach != &mamd64) {
878 werrstr("unsupported architecture");
879 return -1;
880 }
881
882 switch(addr){
883 case offsetof(Ureg64, ax):
884 return offsetof(struct user_regs_struct, rax);
885 case offsetof(Ureg64, bx):
886 return offsetof(struct user_regs_struct, rbx);
887 case offsetof(Ureg64, cx):
888 return offsetof(struct user_regs_struct, rcx);
889 case offsetof(Ureg64, dx):
890 return offsetof(struct user_regs_struct, rdx);
891 case offsetof(Ureg64, si):
892 return offsetof(struct user_regs_struct, rsi);
893 case offsetof(Ureg64, di):
894 return offsetof(struct user_regs_struct, rdi);
895 case offsetof(Ureg64, bp):
896 return offsetof(struct user_regs_struct, rbp);
897 case offsetof(Ureg64, r8):
898 return offsetof(struct user_regs_struct, r8);
899 case offsetof(Ureg64, r9):
900 return offsetof(struct user_regs_struct, r9);
901 case offsetof(Ureg64, r10):
902 return offsetof(struct user_regs_struct, r10);
903 case offsetof(Ureg64, r11):
904 return offsetof(struct user_regs_struct, r11);
905 case offsetof(Ureg64, r12):
906 return offsetof(struct user_regs_struct, r12);
907 case offsetof(Ureg64, r13):
908 return offsetof(struct user_regs_struct, r13);
909 case offsetof(Ureg64, r14):
910 return offsetof(struct user_regs_struct, r14);
911 case offsetof(Ureg64, r15):
912 return offsetof(struct user_regs_struct, r15);
913 case offsetof(Ureg64, ds):
914 return offsetof(struct user_regs_struct, ds);
915 case offsetof(Ureg64, es):
916 return offsetof(struct user_regs_struct, es);
917 case offsetof(Ureg64, fs):
918 return offsetof(struct user_regs_struct, fs);
919 case offsetof(Ureg64, gs):
920 return offsetof(struct user_regs_struct, gs);
921 case offsetof(Ureg64, ip):
922 return offsetof(struct user_regs_struct, rip);
923 case offsetof(Ureg64, cs):
924 return offsetof(struct user_regs_struct, cs);
925 case offsetof(Ureg64, flags):
926 return offsetof(struct user_regs_struct, eflags);
927 case offsetof(Ureg64, sp):
928 return offsetof(struct user_regs_struct, rsp);
929 case offsetof(Ureg64, ss):
930 return offsetof(struct user_regs_struct, ss);
931 }
932 return -1;
933 }
934
935 static int
936 ptraceregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
937 {
938 int laddr;
939 uvlong u;
940
941 if((laddr = go2linux(addr)) < 0){
942 if(isr){
943 memset(v, 0, n);
944 return 0;
945 }
946 werrstr("register %llud not available", addr);
947 return -1;
948 }
949
950 if(isr){
951 errno = 0;
952 u = ptrace(PTRACE_PEEKUSER, map->pid, laddr, 0);
953 if(errno)
954 goto ptraceerr;
955 switch(n){
956 case 1:
957 *(uint8*)v = u;
958 break;
959 case 2:
960 *(uint16*)v = u;
961 break;
962 case 4:
963 *(uint32*)v = u;
964 break;
965 case 8:
966 *(uint64*)v = u;
967 break;
968 default:
969 werrstr("bad register size");
970 return -1;
971 }
972 }else{
973 switch(n){
974 case 1:
975 u = *(uint8*)v;
976 break;
977 case 2:
978 u = *(uint16*)v;
979 break;
980 case 4:
981 u = *(uint32*)v;
982 break;
983 case 8:
984 u = *(uint64*)v;
985 break;
986 default:
987 werrstr("bad register size");
988 return -1;
989 }
990 if(ptrace(PTRACE_POKEUSER, map->pid, laddr, (void*)(uintptr)u) < 0)
991 goto ptraceerr;
992 }
993 return 0;
994
995 ptraceerr:
996 werrstr("ptrace %s register laddr=%d pid=%d n=%d: %r", isr ? "read" : "write", laddr, map->pid, n);
997 return -1;
998 }
999
1000 char*
1001 procstatus(int pid)
1002 {
1003 LinuxThread *t;
1004
1005 t = findthread(pid);
1006 if(t == nil)
1007 return "???";
1008
1009 return statestr[t->state];
1010 }