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