|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)pcs.c 5.5 (Berkeley) 4/9/89";
3: #endif
4:
5: /*
6: * adb - subprocess control
7: */
8:
9: #include "defs.h"
10: #include "bkpt.h"
11: #include <machine/reg.h> /* for getpc() *//* XXX */
12: #include <sys/file.h>
13: #include <sys/ptrace.h>
14: #include <sys/wait.h>
15:
16: extern char NOBKPT[];
17: extern char SZBKPT[];
18: extern char EXBKPT[];
19: extern char NOPCS[];
20: extern char BADMOD[];
21: extern char NOFORK[];
22: extern char ENDPCS[];
23: extern char BADWAIT[];
24:
25: struct bkpt *bkpthead; /* head of breakpoint list */
26:
27: static long runcount; /* number of times to loop past breakpoints */
28:
29: /* bpstate remembers whether we have installed the breakpoints */
30: static enum { BPOUT, BPIN } bpstate;
31:
32: char *malloc();
33:
34: /* run modes */
35: #define CONTINUOUS 0
36: #define SINGLESTEP 1
37:
38: /* sub process control */
39:
40: subpcs(modif)
41: int modif;
42: {
43: register int check;
44: register struct bkpt *bp;
45: int execsig, runmode;
46: char *comptr;
47:
48: switch (modif) {
49:
50: case 'd':
51: /* delete breakpoint */
52: if ((bp = scanbkpt(dot)) == NULL)
53: error(NOBKPT);
54: bp->state = BKPT_FREE;
55: return;
56:
57: case 'D':
58: /* delete all breapoints */
59: for (bp = bkpthead; bp != NULL; bp = bp->next)
60: bp->state = BKPT_FREE;
61: return;
62:
63: case 'b':
64: case 'B':
65: /* set breakpoint */
66: if ((bp = scanbkpt(dot)) == NULL) {
67: /* find a free one, or make one */
68: for (bp = bkpthead; bp != NULL; bp = bp->next)
69: if (bp->state == BKPT_FREE)
70: break;
71: if (bp == NULL) {
72: bp = (struct bkpt *)malloc(sizeof *bp);
73: if (bp == NULL)
74: error(EXBKPT);
75: bp->next = bkpthead;
76: bkpthead = bp;
77: }
78: }
79: bp->loc = dot;
80: bp->initcnt = bp->count = ecount;
81: bp->state = BKPT_SET;
82: check = MAX_BKPTCOM - 1;
83: comptr = bp->comm;
84: (void) rdc();
85: unreadc();
86: do {
87: *comptr++ = readchar();
88: } while (check-- && lastc != '\n');
89: *comptr = 0;
90: unreadc();
91: if (check == 0)
92: error(SZBKPT);
93: return;
94:
95: case 'k':
96: case 'K':
97: /* kill process */
98: if (pid == 0)
99: error(NOPCS);
100: adbprintf("%d: killed", pid);
101: endpcs();
102: return;
103:
104: case 'r':
105: case 'R':
106: /* run program */
107: endpcs();
108: setup();
109: runcount = ecount;
110: runmode = CONTINUOUS;
111: execsig = 0;
112: /* if starting at a breakpoint, run over it */
113: if (scanbkpt(gavedot ? dot : entrypc()) != NULL)
114: runcount++;
115: break;
116:
117: case 's':
118: case 'S':
119: /* single step, with optional signal */
120: runcount = ecount;
121: if (pid) {
122: runmode = SINGLESTEP;
123: execsig = oexpr() ? expv : signo;
124: } else {
125: setup();
126: runmode = SINGLESTEP;
127: execsig = 0;
128: runcount--;
129: }
130: break;
131:
132: case 'c':
133: case 'C':
134: case 0:
135: /* continue with optional signal */
136: runcount = ecount;
137: if (pid == 0)
138: error(NOPCS);
139: runmode = CONTINUOUS;
140: execsig = oexpr() ? expv : signo;
141: break;
142:
143: default:
144: error(BADMOD);
145: /* NOTREACHED */
146: }
147:
148: if (runcount > 0 && runpcs(runmode, execsig))
149: adbprintf("breakpoint%16t");
150: else
151: adbprintf("stopped at%16t");
152: delbp();
153: printpc();
154: }
155:
156: /*
157: * Print all breakpoints.
158: */
159: printbkpts()
160: {
161: register struct bkpt *b;
162:
163: adbprintf("breakpoints\ncount%8tbkpt%24tcommand\n");
164: for (b = bkpthead; b != NULL; b = b->next) {
165: if (b->state != BKPT_FREE) {
166: adbprintf("%-8.8D", b->count);
167: psymoff("%R", b->loc, SP_INSTR, maxoff, "%24t");
168: prints(b->comm);
169: }
170: }
171: }
172:
173: /*
174: * Remove (restore to original instruction(s)) all breakpoints.
175: */
176: delbp()
177: {
178: register struct bkpt *b;
179:
180: if (bpstate != BPOUT) {
181: for (b = bkpthead; b != NULL; b = b->next)
182: if (b->state != BKPT_FREE && clr_bpt(b))
183: bperr(b, "clear");
184: bpstate = BPOUT;
185: }
186: }
187:
188: /*
189: * Insert all breakpoints.
190: */
191: setbp()
192: {
193: register struct bkpt *b;
194:
195: if (bpstate != BPIN) {
196: for (b = bkpthead; b != NULL; b = b->next)
197: if (b->state != BKPT_FREE && set_bpt(b))
198: bperr(b, "set");
199: bpstate = BPIN;
200: }
201: }
202:
203: static
204: bperr(b, how)
205: struct bkpt *b;
206: char *how;
207: {
208:
209: adbprintf("cannot %s breakpoint: ", how);
210: psymoff("%R", b->loc, SP_INSTR, maxoff, "\n");
211: }
212:
213: /*
214: * Run subprocess for a while.
215: * Return true iff stopped due to breakpoint.
216: */
217: int
218: runpcs(runmode, execsig)
219: int runmode, execsig;
220: {
221: register struct bkpt *bkpt;
222: int rc;
223:
224: /* always set pc, so that expr>pc works too */
225: setpc(gavedot ? dot : getpc());
226: adbprintf("%s: running\n", symfile.name);
227: while (--runcount >= 0) {
228: /* BEGIN XXX (machine dependent?, delete ptrace, etc) */
229: if (runmode == SINGLESTEP)
230: delbp(); /* hardware handles single-stepping */
231: else { /* continuing from a breakpoint is hard */
232: if ((bkpt = scanbkpt(getpc())) != NULL) {
233: execbkpt(bkpt, execsig);
234: execsig = 0;
235: }
236: setbp();
237: }
238: (void) ptrace(runmode == CONTINUOUS ? PT_CONTINUE : PT_STEP,
239: pid, (int *)getpc(), execsig);
240: /* END XXX */
241:
242: /* paranoia, SP_DATA usually sufficient, but this is easy */
243: cacheinval(SP_INSTR | SP_DATA);
244:
245: bpwait();
246: checkerr();
247: execsig = 0;
248: delbp();
249: readregs();
250:
251: if (signo != 0 || (bkpt = scanbkpt(getpc())) == NULL) {
252: execsig = signo;
253: rc = 0;
254: continue;
255: }
256: /* stopped by BPT instruction */
257: #ifdef DEBUG
258: adbprintf("\n BPT code: comm=%s%8tstate=%d",
259: bkpt->comm, bkpt->state);
260: #endif
261: dot = bkpt->loc;
262: switch (bkpt->state) {
263: char *p;
264:
265: case BKPT_SET:
266: bkpt->state = BKPT_TRIPPED;
267: if (*bkpt->comm == '\n')
268: break;
269: p = lp;
270: command(bkpt->comm, ':');
271: lp = p;
272: if (gavedot && edot == 0) /* maybe dot==0 ??? */
273: break;
274: if (--bkpt->count == 0)
275: break;
276: /* FALLTHROUGH */
277:
278: case BKPT_TRIPPED:
279: execbkpt(bkpt, execsig);
280: execsig = 0;
281: runcount++;
282: continue;
283:
284: default:
285: panic("runpcs");
286: /* NOTREACHED */
287: }
288: bkpt->count = bkpt->initcnt;
289: rc = 1;
290: }
291: return (rc);
292: }
293:
294: endpcs()
295: {
296: register struct bkpt *bp;
297:
298: if (pid) {
299: (void) ptrace(PT_KILL, pid, (int *)0, 0); /* XXX */
300: pid = 0;
301: for (bp = bkpthead; bp != NULL; bp = bp->next)
302: if (bp->state != BKPT_FREE)
303: bp->state = BKPT_SET;
304: }
305: bpstate = BPOUT;
306: }
307:
308: #ifdef VFORK
309: nullsig()
310: {
311:
312: }
313: #endif
314:
315: setup()
316: {
317:
318: cacheinval(SP_INSTR | SP_DATA); /* paranoia */
319: (void) close(symfile.fd);
320: symfile.fd = -1;
321: #ifndef VFORK
322: #define vfork fork
323: #endif
324: if ((pid = vfork()) == 0) {
325: (void) ptrace(PT_TRACE_ME, 0, (int *)0, 0); /* XXX */
326: #ifdef VFORK
327: (void) signal(SIGTRAP, nullsig);
328: #endif
329: (void) signal(SIGINT, sigint);
330: (void) signal(SIGQUIT, sigquit);
331: doexec();
332: exit(0);
333: } else if (pid == -1) {
334: pid = 0;
335: error(NOFORK);
336: } else {
337: bpwait();
338: readregs();
339: symfile.fd = open(symfile.name, wtflag);
340: if (errflag) {
341: adbprintf("%s: cannot execute\n", symfile.name);
342: endpcs();
343: error((char *)0);
344: }
345: }
346: bpstate = BPOUT;
347: }
348:
349: /*
350: * Single step over a location containing a breakpoint.
351: */
352: execbkpt(bp, execsig)
353: struct bkpt *bp;
354: int execsig;
355: {
356:
357: #ifdef DEBUG
358: adbprintf("exbkpt: %d\n", bp->count);
359: #endif
360: delbp();
361: (void) ptrace(PT_STEP, pid, (int *)bp->loc, execsig); /* XXX */
362: bp->state = BKPT_SET;
363: bpwait();
364: checkerr();
365: readregs();
366: }
367:
368: static char separators[] = "<> \t\n";
369:
370: doexec()
371: {
372: register char *p, **ap;
373: register int c;
374: char *argl[LINELEN / 2 + 1];
375: char args[LINELEN];
376: extern char **environ;
377: char *index();
378:
379: ap = argl;
380: p = args;
381: *ap++ = symfile.name;
382: do {
383: switch (c = rdc()) {
384:
385: case '\n':
386: break;
387:
388: case '<':
389: setfile(0, O_RDONLY, 0, p, "open");
390: break;
391:
392: case '>':
393: setfile(1, O_CREAT|O_WRONLY, 0666, p, "create");
394: break;
395:
396: default:
397: *ap = p;
398: while (index(separators, c) == NULL) {
399: *p++ = c;
400: c = readchar();
401: }
402: *p++ = '\0';
403: ap++;
404: }
405: } while (c != '\n');
406: unreadc();
407: *ap++ = 0;
408: execve(symfile.name, argl, environ);
409: perror(symfile.name);
410: }
411:
412: static int
413: setfile(fd, flags, mode, namebuf, err)
414: int fd, flags, mode;
415: char *namebuf, *err;
416: {
417: register char *p = namebuf;
418: register int c = rdc();
419:
420: while (index(separators, c) == NULL) {
421: *p++ = c;
422: c = readchar();
423: }
424: *p = 0;
425: (void) close(fd);
426: if (open(namebuf, flags, mode) < 0) {
427: adbprintf("%s: cannot %s\n", namebuf, err);
428: _exit(0);
429: /* NOTREACHED */
430: }
431: }
432:
433: struct bkpt *
434: scanbkpt(a)
435: register addr_t a;
436: {
437: register struct bkpt *bp;
438:
439: for (bp = bkpthead; bp != NULL; bp = bp->next)
440: if (bp->state != BKPT_FREE && bp->loc == a)
441: break;
442: return (bp);
443: }
444:
445: bpwait()
446: {
447: register int w;
448: union wait status;
449:
450: (void) signal(SIGINT, SIG_IGN);
451: while ((w = wait(&status)) != pid && w != -1)
452: /* void */ ;
453: (void) signal(SIGINT, intcatch);
454: if (w == -1) {
455: pid = 0;
456: errflag = BADWAIT;
457: } else if (!WIFSTOPPED(status)) {
458: sigcode = 0;
459: if ((signo = status.w_termsig) != 0)
460: sigprint();
461: if (status.w_coredump) {
462: prints(" - core dumped");
463: (void) close(corefile.fd);
464: setcore();
465: }
466: pid = 0;
467: bpstate = BPOUT;
468: errflag = ENDPCS;
469: } else {
470: signo = status.w_stopsig;
471: sigcode = ptrace(PT_READ_U, pid,
472: &((struct user *)0)->u_code, 0); /* XXX */
473: if (signo != SIGTRAP)
474: sigprint();
475: else
476: signo = 0;
477: flushbuf();
478: }
479: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.