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