github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/libmach/linux.c (about) 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 USED(seg); 811 812 return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA, 813 isr, map->pid, addr, v, n); 814 } 815 816 // If the debugger is compiled as an x86-64 program, 817 // then all the ptrace register read/writes are done on 818 // a 64-bit register set. If the target program 819 // is a 32-bit program, the debugger is expected to 820 // read the bottom half of the relevant registers 821 // out of the 64-bit set. 822 823 // Linux 32-bit is 824 // BX CX DX SI DI BP AX DS ES FS GS OrigAX IP CS EFLAGS SP SS 825 826 // Linux 64-bit is 827 // 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 828 829 // Go 32-bit is 830 // DI SI BP NSP BX DX CX AX GS FS ES DS TRAP ECODE PC CS EFLAGS SP SS 831 832 uint go32tolinux32tab[] = { 833 4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16 834 }; 835 static int 836 go32tolinux32(uvlong addr) 837 { 838 int r; 839 840 if(addr%4 || addr/4 >= nelem(go32tolinux32tab)) 841 return -1; 842 r = go32tolinux32tab[addr/4]; 843 if(r < 0) 844 return -1; 845 return r*4; 846 } 847 848 uint go32tolinux64tab[] = { 849 14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20 850 }; 851 static int 852 go32tolinux64(uvlong addr) 853 { 854 int r; 855 856 if(addr%4 || addr/4 >= nelem(go32tolinux64tab)) 857 return -1; 858 r = go32tolinux64tab[addr/4]; 859 if(r < 0) 860 return -1; 861 return r*8; 862 } 863 864 extern Mach mi386; 865 extern Mach mamd64; 866 867 static int 868 go2linux(uvlong addr) 869 { 870 if(sizeof(void*) == 4) { 871 if(mach == &mi386) 872 return go32tolinux32(addr); 873 werrstr("unsupported architecture"); 874 return -1; 875 } 876 877 if(mach == &mi386) 878 return go32tolinux64(addr); 879 if(mach != &mamd64) { 880 werrstr("unsupported architecture"); 881 return -1; 882 } 883 884 switch(addr){ 885 case offsetof(Ureg64, ax): 886 return offsetof(struct user_regs_struct, rax); 887 case offsetof(Ureg64, bx): 888 return offsetof(struct user_regs_struct, rbx); 889 case offsetof(Ureg64, cx): 890 return offsetof(struct user_regs_struct, rcx); 891 case offsetof(Ureg64, dx): 892 return offsetof(struct user_regs_struct, rdx); 893 case offsetof(Ureg64, si): 894 return offsetof(struct user_regs_struct, rsi); 895 case offsetof(Ureg64, di): 896 return offsetof(struct user_regs_struct, rdi); 897 case offsetof(Ureg64, bp): 898 return offsetof(struct user_regs_struct, rbp); 899 case offsetof(Ureg64, r8): 900 return offsetof(struct user_regs_struct, r8); 901 case offsetof(Ureg64, r9): 902 return offsetof(struct user_regs_struct, r9); 903 case offsetof(Ureg64, r10): 904 return offsetof(struct user_regs_struct, r10); 905 case offsetof(Ureg64, r11): 906 return offsetof(struct user_regs_struct, r11); 907 case offsetof(Ureg64, r12): 908 return offsetof(struct user_regs_struct, r12); 909 case offsetof(Ureg64, r13): 910 return offsetof(struct user_regs_struct, r13); 911 case offsetof(Ureg64, r14): 912 return offsetof(struct user_regs_struct, r14); 913 case offsetof(Ureg64, r15): 914 return offsetof(struct user_regs_struct, r15); 915 case offsetof(Ureg64, ds): 916 return offsetof(struct user_regs_struct, ds); 917 case offsetof(Ureg64, es): 918 return offsetof(struct user_regs_struct, es); 919 case offsetof(Ureg64, fs): 920 return offsetof(struct user_regs_struct, fs); 921 case offsetof(Ureg64, gs): 922 return offsetof(struct user_regs_struct, gs); 923 case offsetof(Ureg64, ip): 924 return offsetof(struct user_regs_struct, rip); 925 case offsetof(Ureg64, cs): 926 return offsetof(struct user_regs_struct, cs); 927 case offsetof(Ureg64, flags): 928 return offsetof(struct user_regs_struct, eflags); 929 case offsetof(Ureg64, sp): 930 return offsetof(struct user_regs_struct, rsp); 931 case offsetof(Ureg64, ss): 932 return offsetof(struct user_regs_struct, ss); 933 } 934 return -1; 935 } 936 937 static int 938 ptraceregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr) 939 { 940 int laddr; 941 uvlong u; 942 943 USED(seg); 944 945 if((laddr = go2linux(addr)) < 0){ 946 if(isr){ 947 memset(v, 0, n); 948 return 0; 949 } 950 werrstr("register %llud not available", addr); 951 return -1; 952 } 953 954 if(isr){ 955 errno = 0; 956 u = ptrace(PTRACE_PEEKUSER, map->pid, laddr, 0); 957 if(errno) 958 goto ptraceerr; 959 switch(n){ 960 case 1: 961 *(uint8*)v = u; 962 break; 963 case 2: 964 *(uint16*)v = u; 965 break; 966 case 4: 967 *(uint32*)v = u; 968 break; 969 case 8: 970 *(uint64*)v = u; 971 break; 972 default: 973 werrstr("bad register size"); 974 return -1; 975 } 976 }else{ 977 switch(n){ 978 case 1: 979 u = *(uint8*)v; 980 break; 981 case 2: 982 u = *(uint16*)v; 983 break; 984 case 4: 985 u = *(uint32*)v; 986 break; 987 case 8: 988 u = *(uint64*)v; 989 break; 990 default: 991 werrstr("bad register size"); 992 return -1; 993 } 994 if(ptrace(PTRACE_POKEUSER, map->pid, laddr, (void*)(uintptr)u) < 0) 995 goto ptraceerr; 996 } 997 return 0; 998 999 ptraceerr: 1000 werrstr("ptrace %s register laddr=%d pid=%d n=%d: %r", isr ? "read" : "write", laddr, map->pid, n); 1001 return -1; 1002 } 1003 1004 char* 1005 procstatus(int pid) 1006 { 1007 LinuxThread *t; 1008 1009 t = findthread(pid); 1010 if(t == nil) 1011 return "???"; 1012 1013 return statestr[t->state]; 1014 }