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