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