xref: /csrg-svn/old/dbx/process.c (revision 16928)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)process.c	1.14 (Berkeley) 08/12/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 
1284 #define	bit(i)		(1 << ((i)-1))
1285 /*
1286  * Signal manipulation routines.
1287  */
1288 static String signames[NSIG] = {
1289 	0,
1290 	"HUP",
1291 	"INT",
1292 	"QUIT",
1293 	"ILL",
1294 	"TRAP",
1295 	"IOT",
1296 	"EMT",
1297 	"FPE",
1298 	"KILL",
1299 	"BUS",
1300 	"SEGV",
1301 	"SYS",
1302 	"PIPE",
1303 	"ALRM",
1304 	"TERM",
1305 	0,
1306 	"STOP",
1307 	"TSTP",
1308 	"CONT",
1309 	"CHLD",
1310 	"TTIN",
1311 	"TTOU",
1312 	"TINT",
1313 	"XCPU",
1314 	"XFSZ",
1315 };
1316 
1317 /*
1318  * Map a signal name to a number.
1319  */
1320 public signalname(s)
1321 String s;
1322 {
1323 	register String *p;
1324 
1325 	for (p = signames; p < &signames[NSIG]; p++)
1326 		if (*p && streq(*p, s))
1327 			return (p - signames);
1328 	error("%s: Unknown signal.", s);
1329 }
1330 
1331 /*
1332  * Print all signals being ignored by the
1333  * debugger.  These signals are auotmatically
1334  * passed on to the debugged process.
1335  */
1336 public printsigsignored(vec)
1337 long vec;
1338 {
1339 	register Integer s;
1340 	String sep = "";
1341 
1342 	for (s = 1; s < NSIG; s++)
1343 		if ((vec & bit(s)) && signames[s]) {
1344 			printf("%s%s", sep, signames[s]);
1345 			sep = " ";
1346 		}
1347 	if (*sep != '\0') {
1348 		putchar('\n');
1349 		fflush(stdout);
1350 	}
1351 }
1352 
1353 /*
1354  * Print all signals being intercepted by
1355  * the debugger for the specified process.
1356  */
1357 public printsigscaught(vec)
1358 long vec;
1359 {
1360 	register Integer s;
1361 	String sep = "";
1362 
1363 	for (s = 1; s < NSIG; s++)
1364 		if ((vec & bit(s)) == 0 && signames[s]) {
1365 			printf("%s%s", sep, signames[s]);
1366 			sep = " ";
1367 		}
1368 	if (*sep != '\0') {
1369 		putchar('\n');
1370 		fflush(stdout);
1371 	}
1372 }
1373 
1374