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