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