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