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