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