xref: /csrg-svn/old/dbx/process.c (revision 16617)
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