|
|
1.1 root 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) 1/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.