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