1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)process.c 1.16 (Berkeley) 10/13/84"; 4 5 /* 6 * Process management. 7 * 8 * This module contains the routines to manage the execution and 9 * tracing of the debuggee process. 10 */ 11 12 #include "defs.h" 13 #include "process.h" 14 #include "machine.h" 15 #include "events.h" 16 #include "tree.h" 17 #include "eval.h" 18 #include "operators.h" 19 #include "source.h" 20 #include "object.h" 21 #include "mappings.h" 22 #include "main.h" 23 #include "coredump.h" 24 #include <signal.h> 25 #include <errno.h> 26 #include <ptrace.h> 27 #include <sys/param.h> 28 #include <sys/dir.h> 29 #include <sys/user.h> 30 #include <machine/reg.h> 31 #include <sys/stat.h> 32 33 #ifndef public 34 35 typedef struct Process *Process; 36 37 Process process; 38 39 #define DEFSIG -1 40 41 #include "machine.h" 42 43 #endif 44 45 #define NOTSTARTED 1 46 #define STOPPED 0177 47 #define FINISHED 0 48 49 /* 50 * A cache of the instruction segment is kept to reduce the number 51 * of system calls. Might be better just to read the entire 52 * code space into memory. 53 */ 54 55 #define CSIZE 1003 /* size of instruction cache */ 56 57 typedef struct { 58 Word addr; 59 Word val; 60 } CacheWord; 61 62 /* 63 * This structure holds the information we need from the user structure. 64 */ 65 66 struct Process { 67 int pid; /* process being traced */ 68 int mask; /* process status word */ 69 Word reg[NREG]; /* process' registers */ 70 Word oreg[NREG]; /* registers when process last stopped */ 71 short status; /* either STOPPED or FINISHED */ 72 short signo; /* signal that stopped process */ 73 short sigcode; /* auxiliary signal info code */ 74 int exitval; /* return value from exit() */ 75 long sigset; /* bit array of traced signals */ 76 CacheWord word[CSIZE]; /* text segment cache */ 77 Ttyinfo ttyinfo; /* process' terminal characteristics */ 78 Address sigstatus; /* process' handler for current signal */ 79 }; 80 81 /* 82 * These definitions are for the arguments to "pio". 83 */ 84 85 typedef enum { PREAD, PWRITE } PioOp; 86 typedef enum { TEXTSEG, DATASEG } PioSeg; 87 88 private struct Process pbuf; 89 90 #define MAXNCMDARGS 100 /* maximum number of arguments to RUN */ 91 92 extern int errno; 93 94 private Boolean just_started; 95 private int argc; 96 private String argv[MAXNCMDARGS]; 97 private String infile, outfile; 98 99 /* 100 * Initialize process information. 101 */ 102 103 public process_init() 104 { 105 register Integer i; 106 Char buf[10]; 107 108 process = &pbuf; 109 process->status = (coredump) ? STOPPED : NOTSTARTED; 110 setsigtrace(); 111 for (i = 0; i < NREG; i++) { 112 sprintf(buf, "$r%d", i); 113 defregname(identname(buf, false), i); 114 } 115 defregname(identname("$ap", true), ARGP); 116 defregname(identname("$fp", true), FRP); 117 defregname(identname("$sp", true), STKP); 118 defregname(identname("$pc", true), PROGCTR); 119 if (coredump) { 120 coredump_readin(process->mask, process->reg, process->signo); 121 pc = process->reg[PROGCTR]; 122 getsrcpos(); 123 } 124 arginit(); 125 } 126 127 /* 128 * Routines to get at process information from outside this module. 129 */ 130 131 public Word reg(n) 132 Integer n; 133 { 134 register Word w; 135 136 if (n == NREG) { 137 w = process->mask; 138 } else { 139 w = process->reg[n]; 140 } 141 return w; 142 } 143 144 public setreg(n, w) 145 Integer n; 146 Word w; 147 { 148 process->reg[n] = w; 149 } 150 151 /* 152 * Begin execution. 153 * 154 * We set a breakpoint at the end of the code so that the 155 * process data doesn't disappear after the program terminates. 156 */ 157 158 private Boolean remade(); 159 160 public start(argv, infile, outfile) 161 String argv[]; 162 String infile, outfile; 163 { 164 String pargv[4]; 165 Node cond; 166 167 if (coredump) { 168 coredump = false; 169 fclose(corefile); 170 coredump_close(); 171 } 172 if (argv == nil) { 173 argv = pargv; 174 pargv[0] = objname; 175 pargv[1] = nil; 176 } else { 177 argv[argc] = nil; 178 } 179 if (remade(objname)) { 180 reinit(argv, infile, outfile); 181 } 182 pstart(process, argv, infile, outfile); 183 if (process->status == STOPPED) { 184 pc = 0; 185 setcurfunc(program); 186 if (objsize != 0) { 187 cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr())); 188 event_once(cond, buildcmdlist(build(O_ENDX))); 189 } 190 } 191 } 192 193 /* 194 * Check to see if the object file has changed since the symbolic 195 * information last was read. 196 */ 197 198 private time_t modtime; 199 200 private Boolean remade(filename) 201 String filename; 202 { 203 struct stat s; 204 Boolean b; 205 206 stat(filename, &s); 207 b = (Boolean) (modtime != 0 and modtime < s.st_mtime); 208 modtime = s.st_mtime; 209 return b; 210 } 211 212 /* 213 * Set up what signals we want to trace. 214 */ 215 216 private setsigtrace() 217 { 218 register Integer i; 219 register Process p; 220 221 p = process; 222 for (i = 1; i <= NSIG; i++) { 223 psigtrace(p, i, true); 224 } 225 psigtrace(p, SIGHUP, false); 226 psigtrace(p, SIGKILL, false); 227 psigtrace(p, SIGALRM, false); 228 psigtrace(p, SIGTSTP, false); 229 psigtrace(p, SIGCONT, false); 230 psigtrace(p, SIGCHLD, false); 231 } 232 233 /* 234 * Initialize the argument list. 235 */ 236 237 public arginit() 238 { 239 infile = nil; 240 outfile = nil; 241 argv[0] = objname; 242 argc = 1; 243 } 244 245 /* 246 * Add an argument to the list for the debuggee. 247 */ 248 249 public newarg(arg) 250 String arg; 251 { 252 if (argc >= MAXNCMDARGS) { 253 error("too many arguments"); 254 } 255 argv[argc++] = arg; 256 } 257 258 /* 259 * Set the standard input for the debuggee. 260 */ 261 262 public inarg(filename) 263 String filename; 264 { 265 if (infile != nil) { 266 error("multiple input redirects"); 267 } 268 infile = filename; 269 } 270 271 /* 272 * Set the standard output for the debuggee. 273 * Probably should check to avoid overwriting an existing file. 274 */ 275 276 public outarg(filename) 277 String filename; 278 { 279 if (outfile != nil) { 280 error("multiple output redirect"); 281 } 282 outfile = filename; 283 } 284 285 /* 286 * Start debuggee executing. 287 */ 288 289 public run() 290 { 291 process->status = STOPPED; 292 fixbps(); 293 curline = 0; 294 start(argv, infile, outfile); 295 just_started = true; 296 isstopped = false; 297 cont(0); 298 } 299 300 /* 301 * Continue execution wherever we left off. 302 * 303 * Note that this routine never returns. Eventually bpact() will fail 304 * and we'll call printstatus or step will call it. 305 */ 306 307 typedef int Intfunc(); 308 309 private Intfunc *dbintr; 310 private intr(); 311 312 #define succeeds == true 313 #define fails == false 314 315 public cont(signo) 316 integer signo; 317 { 318 integer s; 319 320 dbintr = signal(SIGINT, intr); 321 if (just_started) { 322 just_started = false; 323 } else { 324 if (not isstopped) { 325 error("can't continue execution"); 326 } 327 isstopped = false; 328 stepover(); 329 } 330 s = signo; 331 for (;;) { 332 if (single_stepping) { 333 printnews(); 334 } else { 335 setallbps(); 336 resume(s); 337 unsetallbps(); 338 s = DEFSIG; 339 if (bpact() fails) { 340 printstatus(); 341 } 342 } 343 stepover(); 344 } 345 /* NOTREACHED */ 346 } 347 348 /* 349 * This routine is called if we get an interrupt while "running" px 350 * but actually in the debugger. Could happen, for example, while 351 * processing breakpoints. 352 * 353 * We basically just want to keep going; the assumption is 354 * that when the process resumes it will get the interrupt 355 * which will then be handled. 356 */ 357 358 private intr() 359 { 360 signal(SIGINT, intr); 361 } 362 363 public fixintr() 364 { 365 signal(SIGINT, dbintr); 366 } 367 368 /* 369 * Resume execution. 370 */ 371 372 public resume(signo) 373 int signo; 374 { 375 register Process p; 376 377 p = process; 378 pcont(p, signo); 379 pc = process->reg[PROGCTR]; 380 if (p->status != STOPPED) { 381 if (p->signo != 0) { 382 error("program terminated by signal %d", p->signo); 383 } else if (not runfirst) { 384 error("program unexpectedly exited with %d", p->exitval); 385 } 386 } 387 } 388 389 /* 390 * Continue execution up to the next source line. 391 * 392 * There are two ways to define the next source line depending on what 393 * is desired when a procedure or function call is encountered. Step 394 * stops at the beginning of the procedure or call; next skips over it. 395 */ 396 397 /* 398 * Stepc is what is called when the step command is given. 399 * It has to play with the "isstopped" information. 400 */ 401 402 public stepc() 403 { 404 if (not isstopped) { 405 error("can't continue execution"); 406 } 407 isstopped = false; 408 dostep(false); 409 isstopped = true; 410 } 411 412 public next() 413 { 414 Address oldfrp, newfrp; 415 416 if (not isstopped) { 417 error("can't continue execution"); 418 } 419 isstopped = false; 420 oldfrp = reg(FRP); 421 do { 422 dostep(true); 423 pc = reg(PROGCTR); 424 newfrp = reg(FRP); 425 } while (newfrp < oldfrp and newfrp != 0); 426 isstopped = true; 427 } 428 429 /* 430 * Continue execution until the current function returns, or, 431 * if the given argument is non-nil, until execution returns to 432 * somewhere within the given function. 433 */ 434 435 public rtnfunc (f) 436 Symbol f; 437 { 438 Address addr; 439 Symbol t; 440 441 if (not isstopped) { 442 error("can't continue execution"); 443 } else if (f != nil and not isactive(f)) { 444 error("%s is not active", symname(f)); 445 } else { 446 addr = return_addr(); 447 if (addr == nil) { 448 error("no place to return to"); 449 } else { 450 isstopped = false; 451 contto(addr); 452 if (f != nil) { 453 for (;;) { 454 t = whatblock(pc); 455 addr = return_addr(); 456 if (t == f or addr == nil) break; 457 contto(addr); 458 } 459 } 460 if (bpact() fails) { 461 isstopped = true; 462 printstatus(); 463 } 464 } 465 } 466 } 467 468 /* 469 * Single-step over the current machine instruction. 470 * 471 * If we're single-stepping by source line we want to step to the 472 * next source line. Otherwise we're going to continue so there's 473 * no reason to do all the work necessary to single-step to the next 474 * source line. 475 */ 476 477 public stepover() 478 { 479 Boolean b; 480 481 if (traceexec) { 482 printf("!! stepping over 0x%x\n", process->reg[PROGCTR]); 483 } 484 if (single_stepping) { 485 dostep(false); 486 } else { 487 b = inst_tracing; 488 inst_tracing = true; 489 dostep(false); 490 inst_tracing = b; 491 } 492 if (traceexec) { 493 printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]); 494 } 495 } 496 497 /* 498 * Resume execution up to the given address. It is assumed that 499 * no breakpoints exist between the current address and the one 500 * we're stepping to. This saves us from setting all the breakpoints. 501 */ 502 503 public stepto(addr) 504 Address addr; 505 { 506 xto(addr, false); 507 } 508 509 private contto (addr) 510 Address addr; 511 { 512 xto(addr, true); 513 } 514 515 private xto (addr, catchbps) 516 Address addr; 517 boolean catchbps; 518 { 519 Address curpc; 520 521 if (catchbps) { 522 stepover(); 523 } 524 curpc = process->reg[PROGCTR]; 525 if (addr != curpc) { 526 if (traceexec) { 527 printf("!! stepping from 0x%x to 0x%x\n", curpc, addr); 528 } 529 if (catchbps) { 530 setallbps(); 531 } 532 setbp(addr); 533 resume(DEFSIG); 534 unsetbp(addr); 535 if (catchbps) { 536 unsetallbps(); 537 } 538 if (not isbperr()) { 539 printstatus(); 540 } 541 } 542 } 543 544 /* 545 * Print the status of the process. 546 * This routine does not return. 547 */ 548 549 public printstatus() 550 { 551 int status; 552 553 if (process->status == FINISHED) { 554 exit(0); 555 } else { 556 setcurfunc(whatblock(pc)); 557 getsrcpos(); 558 if (process->signo == SIGINT) { 559 isstopped = true; 560 printerror(); 561 } else if (isbperr() and isstopped) { 562 printf("stopped "); 563 printloc(); 564 putchar('\n'); 565 if (curline > 0) { 566 printlines(curline, curline); 567 } else { 568 printinst(pc, pc); 569 } 570 erecover(); 571 } else { 572 fixintr(); 573 isstopped = true; 574 printerror(); 575 } 576 } 577 } 578 579 /* 580 * Print out the current location in the debuggee. 581 */ 582 583 public printloc() 584 { 585 printf("in "); 586 printname(stdout, curfunc); 587 putchar(' '); 588 if (curline > 0 and not useInstLoc) { 589 printsrcpos(); 590 } else { 591 useInstLoc = false; 592 curline = 0; 593 printf("at 0x%x", pc); 594 } 595 } 596 597 /* 598 * Some functions for testing the state of the process. 599 */ 600 601 public Boolean notstarted(p) 602 Process p; 603 { 604 return (Boolean) (p->status == NOTSTARTED); 605 } 606 607 public Boolean isfinished(p) 608 Process p; 609 { 610 return (Boolean) (p->status == FINISHED); 611 } 612 613 /* 614 * Return the signal number which stopped the process. 615 */ 616 617 public Integer errnum(p) 618 Process p; 619 { 620 return p->signo; 621 } 622 623 public Integer errcode(p) 624 Process p; 625 { 626 return p->sigcode; 627 } 628 629 /* 630 * Return the termination code of the process. 631 */ 632 633 public Integer exitcode(p) 634 Process p; 635 { 636 return p->exitval; 637 } 638 639 /* 640 * These routines are used to access the debuggee process from 641 * outside this module. 642 * 643 * They invoke "pio" which eventually leads to a call to "ptrace". 644 * The system generates an I/O error when a ptrace fails. During reads 645 * these are ignored, during writes they are reported as an error, and 646 * for anything else they cause a fatal error. 647 */ 648 649 extern Intfunc *onsyserr(); 650 651 private badaddr; 652 private read_err(), write_err(); 653 654 /* 655 * Read from the process' instruction area. 656 */ 657 658 public iread(buff, addr, nbytes) 659 char *buff; 660 Address addr; 661 int nbytes; 662 { 663 Intfunc *f; 664 665 f = onsyserr(EIO, read_err); 666 badaddr = addr; 667 if (coredump) { 668 coredump_readtext(buff, addr, nbytes); 669 } else { 670 pio(process, PREAD, TEXTSEG, buff, addr, nbytes); 671 } 672 onsyserr(EIO, f); 673 } 674 675 /* 676 * Write to the process' instruction area, usually in order to set 677 * or unset a breakpoint. 678 */ 679 680 public iwrite(buff, addr, nbytes) 681 char *buff; 682 Address addr; 683 int nbytes; 684 { 685 Intfunc *f; 686 687 if (coredump) { 688 error("no process to write to"); 689 } 690 f = onsyserr(EIO, write_err); 691 badaddr = addr; 692 pio(process, PWRITE, TEXTSEG, buff, addr, nbytes); 693 onsyserr(EIO, f); 694 } 695 696 /* 697 * Read for the process' data area. 698 */ 699 700 public dread(buff, addr, nbytes) 701 char *buff; 702 Address addr; 703 int nbytes; 704 { 705 Intfunc *f; 706 707 f = onsyserr(EIO, read_err); 708 badaddr = addr; 709 if (coredump) { 710 coredump_readdata(buff, addr, nbytes); 711 } else { 712 pio(process, PREAD, DATASEG, buff, addr, nbytes); 713 } 714 onsyserr(EIO, f); 715 } 716 717 /* 718 * Write to the process' data area. 719 */ 720 721 public dwrite(buff, addr, nbytes) 722 char *buff; 723 Address addr; 724 int nbytes; 725 { 726 Intfunc *f; 727 728 if (coredump) { 729 error("no process to write to"); 730 } 731 f = onsyserr(EIO, write_err); 732 badaddr = addr; 733 pio(process, PWRITE, DATASEG, buff, addr, nbytes); 734 onsyserr(EIO, f); 735 } 736 737 /* 738 * Trap for errors in reading or writing to a process. 739 * The current approach is to "ignore" read errors and complain 740 * bitterly about write errors. 741 */ 742 743 private read_err() 744 { 745 /* 746 * Ignore. 747 */ 748 } 749 750 private write_err() 751 { 752 error("can't write to process (address 0x%x)", badaddr); 753 } 754 755 /* 756 * Ptrace interface. 757 */ 758 759 /* 760 * This magic macro enables us to look at the process' registers 761 * in its user structure. 762 */ 763 764 #define regloc(reg) (ctob(UPAGES) + ( sizeof(int) * (reg) )) 765 766 #define WMASK (~(sizeof(Word) - 1)) 767 #define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE)) 768 769 #define FIRSTSIG SIGINT 770 #define LASTSIG SIGQUIT 771 #define ischild(pid) ((pid) == 0) 772 #define traceme() ptrace(PT_TRACE_ME, 0, 0, 0) 773 #define setrep(n) (1 << ((n)-1)) 774 #define istraced(p) (p->sigset&setrep(p->signo)) 775 776 /* 777 * Start up a new process by forking and exec-ing the 778 * given argument list, returning when the process is loaded 779 * and ready to execute. The PROCESS information (pointed to 780 * by the first argument) is appropriately filled. 781 * 782 * If the given PROCESS structure is associated with an already running 783 * process, we terminate it. 784 */ 785 786 /* VARARGS2 */ 787 private pstart(p, argv, infile, outfile) 788 Process p; 789 String argv[]; 790 String infile; 791 String outfile; 792 { 793 int status; 794 795 if (p->pid != 0) { 796 pterm(p); 797 } 798 psigtrace(p, SIGTRAP, true); 799 p->pid = vfork(); 800 if (p->pid == -1) { 801 panic("can't fork"); 802 } 803 if (ischild(p->pid)) { 804 traceme(); 805 if (infile != nil) { 806 infrom(infile); 807 } 808 if (outfile != nil) { 809 outto(outfile); 810 } 811 execv(argv[0], argv); 812 write(2, "can't exec ", 11); 813 write(2, argv[0], strlen(argv[0])); 814 write(2, "\n", 1); 815 _exit(1); 816 } 817 pwait(p->pid, &status); 818 getinfo(p, status); 819 if (p->status != STOPPED) { 820 error("program could not begin execution"); 821 } 822 ptraced(p->pid); 823 } 824 825 /* 826 * Terminate a ptrace'd process. 827 */ 828 829 public pterm (p) 830 Process p; 831 { 832 integer status; 833 834 if (p != nil and p->pid != 0) { 835 ptrace(PT_KILL, p->pid, 0, 0); 836 pwait(p->pid, &status); 837 unptraced(p->pid); 838 } 839 } 840 841 /* 842 * Continue a stopped process. The first argument points to a Process 843 * structure. Before the process is restarted it's user area is modified 844 * according to the values in the structure. When this routine finishes, 845 * the structure has the new values from the process's user area. 846 * 847 * Pcont terminates when the process stops with a signal pending that 848 * is being traced (via psigtrace), or when the process terminates. 849 */ 850 851 private pcont(p, signo) 852 Process p; 853 int signo; 854 { 855 int s, status; 856 857 if (p->pid == 0) { 858 error("program not active"); 859 } 860 s = signo; 861 do { 862 setinfo(p, s); 863 if (traceexec) { 864 printf("!! pcont from 0x%x with signal %d (%d)\n", 865 p->reg[PROGCTR], s, p->signo); 866 fflush(stdout); 867 } 868 sigs_off(); 869 if (ptrace(PT_CONTINUE, p->pid, p->reg[PROGCTR], p->signo) < 0) { 870 panic("error %d trying to continue process", errno); 871 } 872 pwait(p->pid, &status); 873 sigs_on(); 874 getinfo(p, status); 875 if (traceexec and not istraced(p)) { 876 printf("!! ignored signal %d at 0x%x\n", p->signo, p->reg[PROGCTR]); 877 fflush(stdout); 878 } 879 s = p->signo; 880 } while (p->status == STOPPED and not istraced(p)); 881 if (traceexec) { 882 printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo); 883 fflush(stdout); 884 } 885 } 886 887 /* 888 * Single step as best ptrace can. 889 */ 890 891 public pstep(p, signo) 892 Process p; 893 integer signo; 894 { 895 int status; 896 897 setinfo(p, signo); 898 if (traceexec) { 899 printf("!! pstep from pc 0x%x with signal %d (%d)\n", 900 p->reg[PROGCTR], signo, p->signo); 901 fflush(stdout); 902 } 903 sigs_off(); 904 if (ptrace(PT_STEP, p->pid, p->reg[PROGCTR], p->signo) < 0) { 905 panic("error %d trying to step process", errno); 906 } 907 pwait(p->pid, &status); 908 sigs_on(); 909 getinfo(p, status); 910 if (traceexec) { 911 printf("!! pstep to pc 0x%x on signal %d\n", p->reg[PROGCTR], p->signo); 912 fflush(stdout); 913 } 914 if (p->status != STOPPED) { 915 error("program unexpectedly exited with %d\n", p->exitval); 916 } 917 } 918 919 /* 920 * Return from execution when the given signal is pending. 921 */ 922 923 public psigtrace(p, sig, sw) 924 Process p; 925 int sig; 926 Boolean sw; 927 { 928 if (sw) { 929 p->sigset |= setrep(sig); 930 } else { 931 p->sigset &= ~setrep(sig); 932 } 933 } 934 935 /* 936 * Don't catch any signals. 937 * Particularly useful when letting a process finish uninhibited. 938 */ 939 940 public unsetsigtraces(p) 941 Process p; 942 { 943 p->sigset = 0; 944 } 945 946 /* 947 * Turn off attention to signals not being caught. 948 */ 949 950 private Intfunc *sigfunc[NSIG]; 951 952 private sigs_off() 953 { 954 register int i; 955 956 for (i = FIRSTSIG; i < LASTSIG; i++) { 957 if (i != SIGKILL) { 958 sigfunc[i] = signal(i, SIG_IGN); 959 } 960 } 961 } 962 963 /* 964 * Turn back on attention to signals. 965 */ 966 967 private sigs_on() 968 { 969 register int i; 970 971 for (i = FIRSTSIG; i < LASTSIG; i++) { 972 if (i != SIGKILL) { 973 signal(i, sigfunc[i]); 974 } 975 } 976 } 977 978 /* 979 * Get process information from user area. 980 */ 981 982 private int rloc[] ={ 983 R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC 984 }; 985 986 private getinfo(p, status) 987 register Process p; 988 register int status; 989 { 990 register int i; 991 Address addr; 992 993 p->signo = (status&0177); 994 p->exitval = ((status >> 8)&0377); 995 if (p->signo != STOPPED) { 996 p->status = FINISHED; 997 p->pid = 0; 998 p->reg[PROGCTR] = 0; 999 } else { 1000 p->status = p->signo; 1001 p->signo = p->exitval; 1002 p->sigcode = ptrace(PT_READ_U, p->pid, &((struct user *)0)->u_code, 0); 1003 p->exitval = 0; 1004 p->mask = ptrace(PT_READ_U, p->pid, regloc(PS), 0); 1005 for (i = 0; i < NREG; i++) { 1006 p->reg[i] = ptrace(PT_READ_U, p->pid, regloc(rloc[i]), 0); 1007 p->oreg[i] = p->reg[i]; 1008 } 1009 savetty(stdout, &(p->ttyinfo)); 1010 addr = (Address) &(((struct user *) 0)->u_signal[p->signo]); 1011 p->sigstatus = (Address) ptrace(PT_READ_U, p->pid, addr, 0); 1012 } 1013 } 1014 1015 /* 1016 * Set process's user area information from given process structure. 1017 */ 1018 1019 private setinfo(p, signo) 1020 register Process p; 1021 int signo; 1022 { 1023 register int i; 1024 register int r; 1025 1026 if (signo == DEFSIG) { 1027 if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) { 1028 p->signo = 0; 1029 } 1030 } else { 1031 p->signo = signo; 1032 } 1033 for (i = 0; i < NREG; i++) { 1034 if ((r = p->reg[i]) != p->oreg[i]) { 1035 ptrace(PT_WRITE_U, p->pid, regloc(rloc[i]), r); 1036 } 1037 } 1038 restoretty(stdout, &(p->ttyinfo)); 1039 } 1040 1041 /* 1042 * Return the address associated with the current signal. 1043 * (Plus two since the address points to the beginning of a procedure). 1044 */ 1045 1046 public Address usignal (p) 1047 Process p; 1048 { 1049 Address r; 1050 1051 r = p->sigstatus; 1052 if (r != 0 and r != 1) { 1053 r += 2; 1054 } 1055 return r; 1056 } 1057 1058 /* 1059 * Structure for reading and writing by words, but dealing with bytes. 1060 */ 1061 1062 typedef union { 1063 Word pword; 1064 Byte pbyte[sizeof(Word)]; 1065 } Pword; 1066 1067 /* 1068 * Read (write) from (to) the process' address space. 1069 * We must deal with ptrace's inability to look anywhere other 1070 * than at a word boundary. 1071 */ 1072 1073 private Word fetch(); 1074 private store(); 1075 1076 private pio(p, op, seg, buff, addr, nbytes) 1077 Process p; 1078 PioOp op; 1079 PioSeg seg; 1080 char *buff; 1081 Address addr; 1082 int nbytes; 1083 { 1084 register int i; 1085 register Address newaddr; 1086 register char *cp; 1087 char *bufend; 1088 Pword w; 1089 Address wordaddr; 1090 int byteoff; 1091 1092 if (p->status != STOPPED) { 1093 error("program is not active"); 1094 } 1095 cp = buff; 1096 newaddr = addr; 1097 wordaddr = (newaddr&WMASK); 1098 if (wordaddr != newaddr) { 1099 w.pword = fetch(p, seg, wordaddr); 1100 for (i = newaddr - wordaddr; i < sizeof(Word) and nbytes > 0; i++) { 1101 if (op == PREAD) { 1102 *cp++ = w.pbyte[i]; 1103 } else { 1104 w.pbyte[i] = *cp++; 1105 } 1106 nbytes--; 1107 } 1108 if (op == PWRITE) { 1109 store(p, seg, wordaddr, w.pword); 1110 } 1111 newaddr = wordaddr + sizeof(Word); 1112 } 1113 byteoff = (nbytes&(~WMASK)); 1114 nbytes -= byteoff; 1115 bufend = cp + nbytes; 1116 while (cp < bufend) { 1117 if (op == PREAD) { 1118 *((Word *) cp) = fetch(p, seg, newaddr); 1119 } else { 1120 store(p, seg, newaddr, *((Word *) cp)); 1121 } 1122 cp += sizeof(Word); 1123 newaddr += sizeof(Word); 1124 } 1125 if (byteoff > 0) { 1126 w.pword = fetch(p, seg, newaddr); 1127 for (i = 0; i < byteoff; i++) { 1128 if (op == PREAD) { 1129 *cp++ = w.pbyte[i]; 1130 } else { 1131 w.pbyte[i] = *cp++; 1132 } 1133 } 1134 if (op == PWRITE) { 1135 store(p, seg, newaddr, w.pword); 1136 } 1137 } 1138 } 1139 1140 /* 1141 * Get a word from a process at the given address. 1142 * The address is assumed to be on a word boundary. 1143 * 1144 * A simple cache scheme is used to avoid redundant ptrace calls 1145 * to the instruction space since it is assumed to be pure. 1146 * 1147 * It is necessary to use a write-through scheme so that 1148 * breakpoints right next to each other don't interfere. 1149 */ 1150 1151 private Integer nfetchs, nreads, nwrites; 1152 1153 private Word fetch(p, seg, addr) 1154 Process p; 1155 PioSeg seg; 1156 register int addr; 1157 { 1158 register CacheWord *wp; 1159 register Word w; 1160 1161 switch (seg) { 1162 case TEXTSEG: 1163 ++nfetchs; 1164 wp = &p->word[cachehash(addr)]; 1165 if (addr == 0 or wp->addr != addr) { 1166 ++nreads; 1167 w = ptrace(PT_READ_I, p->pid, addr, 0); 1168 wp->addr = addr; 1169 wp->val = w; 1170 } else { 1171 w = wp->val; 1172 } 1173 break; 1174 1175 case DATASEG: 1176 w = ptrace(PT_READ_D, p->pid, addr, 0); 1177 break; 1178 1179 default: 1180 panic("fetch: bad seg %d", seg); 1181 /* NOTREACHED */ 1182 } 1183 return w; 1184 } 1185 1186 /* 1187 * Put a word into the process' address space at the given address. 1188 * The address is assumed to be on a word boundary. 1189 */ 1190 1191 private store(p, seg, addr, data) 1192 Process p; 1193 PioSeg seg; 1194 int addr; 1195 Word data; 1196 { 1197 register CacheWord *wp; 1198 1199 switch (seg) { 1200 case TEXTSEG: 1201 ++nwrites; 1202 wp = &p->word[cachehash(addr)]; 1203 wp->addr = addr; 1204 wp->val = data; 1205 ptrace(PT_WRITE_I, p->pid, addr, data); 1206 break; 1207 1208 case DATASEG: 1209 ptrace(PT_WRITE_D, p->pid, addr, data); 1210 break; 1211 1212 default: 1213 panic("store: bad seg %d", seg); 1214 /* NOTREACHED */ 1215 } 1216 } 1217 1218 public printptraceinfo() 1219 { 1220 printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites); 1221 } 1222 1223 /* 1224 * Redirect input. 1225 * Assuming this is called from a child, we should be careful to avoid 1226 * (possibly) shared standard I/O buffers. 1227 */ 1228 1229 private infrom (filename) 1230 String filename; 1231 { 1232 Fileid in; 1233 1234 in = open(filename, 0); 1235 if (in == -1) { 1236 write(2, "can't read ", 11); 1237 write(2, filename, strlen(filename)); 1238 write(2, "\n", 1); 1239 _exit(1); 1240 } 1241 fswap(0, in); 1242 } 1243 1244 /* 1245 * Redirect standard output. 1246 * Same assumptions as for "infrom" above. 1247 */ 1248 1249 private outto (filename) 1250 String filename; 1251 { 1252 Fileid out; 1253 1254 out = creat(filename, 0666); 1255 if (out == -1) { 1256 write(2, "can't write ", 12); 1257 write(2, filename, strlen(filename)); 1258 write(2, "\n", 1); 1259 _exit(1); 1260 } 1261 fswap(1, out); 1262 } 1263 1264 /* 1265 * Swap file numbers, useful for redirecting standard input or output. 1266 */ 1267 1268 private fswap(oldfd, newfd) 1269 Fileid oldfd; 1270 Fileid newfd; 1271 { 1272 if (oldfd != newfd) { 1273 close(oldfd); 1274 dup(newfd); 1275 close(newfd); 1276 } 1277 } 1278 1279 #define bit(i) (1 << ((i)-1)) 1280 /* 1281 * Signal manipulation routines. 1282 */ 1283 static String signames[NSIG] = { 1284 0, 1285 "HUP", 1286 "INT", 1287 "QUIT", 1288 "ILL", 1289 "TRAP", 1290 "IOT", 1291 "EMT", 1292 "FPE", 1293 "KILL", 1294 "BUS", 1295 "SEGV", 1296 "SYS", 1297 "PIPE", 1298 "ALRM", 1299 "TERM", 1300 0, 1301 "STOP", 1302 "TSTP", 1303 "CONT", 1304 "CHLD", 1305 "TTIN", 1306 "TTOU", 1307 "TINT", 1308 "XCPU", 1309 "XFSZ", 1310 }; 1311 1312 /* 1313 * Map a signal name to a number. 1314 */ 1315 public signalname(s) 1316 String s; 1317 { 1318 register String *p; 1319 1320 if (strneq(s, "SIG", 3)) 1321 s += 3; 1322 for (p = signames; p < &signames[NSIG]; p++) 1323 if (*p && streq(*p, s)) 1324 return (p - signames); 1325 error("%s: Unknown signal.", s); 1326 } 1327 1328 /* 1329 * Print all signals being ignored by the 1330 * debugger. These signals are auotmatically 1331 * passed on to the debugged process. 1332 */ 1333 public printsigsignored(p) 1334 Process p; 1335 { 1336 1337 printsigs(~p->sigset); 1338 } 1339 1340 /* 1341 * Print all signals being intercepted by 1342 * the debugger for the specified process. 1343 */ 1344 public printsigscaught(p) 1345 Process p; 1346 { 1347 1348 printsigs(p->sigset); 1349 } 1350 1351 private printsigs(vec) 1352 register Integer vec; 1353 { 1354 register Integer s; 1355 String sep = ""; 1356 1357 for (s = 1; s < NSIG; s++) 1358 if (vec & bit(s) && signames[s]) { 1359 printf("%s%s", sep, signames[s]); 1360 sep = " "; 1361 } 1362 if (*sep != '\0') { 1363 putchar('\n'); 1364 fflush(stdout); 1365 } 1366 } 1367