|
|
1.1 root 1: /*
2: * A debugger.
3: * Runtime support.
4: */
5: #include <stdio.h>
6: #include <ctype.h>
7: #include <errno.h>
8: #include "trace.h"
9: #if NOUT
10: #include <n.out.h>
11: #else
12: #include <l.out.h>
13: #endif
14: #include <sys/uproc.h>
15: #include <signal.h>
16:
17: /*
18: * Talk to the user and try to solve his problems.
19: */
20: process()
21: {
22: register BPT *bp;
23: register int n;
24: register int nibflag;
25: register int bptflag;
26: register vaddr_t pc;
27: register vaddr_t fp;
28: register int f;
29:
30: /*
31: * Let the user speak.
32: */
33: top:
34: bptflag = 0;
35: execute(":x\n");
36: for (;;) {
37: /*
38: * Initialise flags.
39: */
40: bitflag = 0;
41: nibflag = 0;
42:
43: /*
44: * If in single step mode, set up for single step.
45: */
46: if (sinmode!=SNULL && sinmode!=SWAIT) {
47: bitflag = 1;
48: if (sinmode == SCONT)
49: setcont();
50: }
51:
52: /*
53: * Place all breakpoints.
54: */
55: pc = getpc();
56: for (n=NBPT, bp=&bpt[0]; n--; bp++) {
57: if (bp->b_flag == 0)
58: continue;
59: add = bp->b_badd;
60: if (getb(1, bp->b_bins, sizeof(BIN)) == 0) {
61: fprintf( stderr, "cannot read\n");
62: printb(bp->b_badd);
63: goto err;
64: }
65: if (bptflag!=0 && bp->b_badd==pc) {
66: bitflag = 1;
67: continue;
68: }
69: add = bp->b_badd;
70: if (putb(1, bin, sizeof(BIN)) == 0) {
71: fprintf( stderr, "cannot install\n");
72: printb(bp->b_badd);
73: goto err;
74: }
75: }
76: bptflag = 0;
77:
78: /*
79: * Set flags and call machine dependent restore routine.
80: */
81: if (testbpt(pc) != 0)
82: nibflag = 1;
83: if (restret() == 0)
84: goto err;
85:
86: /*
87: * Start up the child.
88: */
89: errno = 0;
90: ptrace(bitflag?9:7, pid, (int *)1, 0);
91: if (errno) {
92: printr("Ptrace error (%d)", errno);
93: goto err;
94: }
95: if (waitc() == 0)
96: goto err;
97:
98: /*
99: * Get registers and call machine dependent trap routine.
100: */
101: if (trapint() == 0)
102: goto err;
103: if (setregs() == 0)
104: goto err;
105: if ((f=settrap()) == 0)
106: goto err;
107: /*
108: * Replace breakpoints with instructions.
109: */
110: for (n=NBPT, bp=&bpt[0]; n--; bp++) {
111: if (bp->b_flag == 0)
112: continue;
113: add = bp->b_badd;
114: if (putb(1, bp->b_bins, sizeof(BIN)) == 0) {
115: fprintf( stderr, "cannot replace instr\n");
116: printb(bp->b_badd);
117: goto err;
118: }
119: }
120:
121: /*
122: * If trap was not a breakpoint, tell the user, accept input.
123: */
124: if (f != SIGTRAP) {
125: execute(":f\n:x\n");
126: continue;
127: }
128:
129: /*
130: * Find the breakpoint we are at.
131: */
132: pc = getpc() - sizeof(BIN);
133: if (bitflag==0 || nibflag!=0) {
134: for (n=NBPT, bp=&bpt[0]; n--; bp++) {
135: if (bp->b_flag == 0)
136: continue;
137: if (bp->b_badd != pc)
138: continue;
139: setpc((vaddr_t)pc);
140: bptflag = 1;
141: break;
142: }
143: }
144:
145: /*
146: * If in single step mode, execute command.
147: */
148: switch (sinmode) {
149: case SSTEP:
150: case SCONT:
151: execute(sinp);
152: if (--sindecr == 0)
153: execute(":x\n");
154: continue;
155: case SCSET:
156: for (n=0, bp=&bpt[0]; n<NBPT; n++, bp++)
157: bp->b_flag &= ~BSIN;
158: sinmode = SWAIT;
159: intcont();
160: break;
161: }
162:
163: /*
164: * If we got an unexpected trace trap or unknown
165: * breakpoint, we handle it here.
166: */
167: if (bp == NULL) {
168: if (bitflag==0 || nibflag!=0)
169: execute(":f\n:x\n");
170: continue;
171: }
172:
173: /*
174: * Single step breakpoints have highest priority.
175: */
176: fp = getfp();
177: if ((bp->b_flag&BSIN) != 0) {
178: if (bp->b_sfpt==0 || bp->b_sfpt==fp) {
179: bp->b_flag &= ~BSIN;
180: if (sinmode == SWAIT) {
181: sinmode = SCONT;
182: execute(sinp);
183: if (--sindecr == 0)
184: execute(":x\n");
185: continue;
186: }
187: }
188: }
189:
190: /*
191: * Return breakpoints are next.
192: */
193: if ((bp->b_flag&BRET) != 0) {
194: if (fp == bp->b_rfpt) {
195: bp->b_flag &= ~BRET;
196: execute(bp->b_rcom);
197: continue;
198: }
199: }
200:
201: /*
202: * Your conventional everyday ordinary breakpoint.
203: */
204: if ((bp->b_flag&BBPT) != 0) {
205: execute(bp->b_bcom);
206: continue;
207: }
208: }
209:
210: /*
211: * Something is terribly wrong. Kill off our child,
212: * and generally reset everything to the start.
213: */
214: err:
215: killc();
216: reslout();
217: bptinit();
218: goto top;
219:
220: /*
221: * They say psychiatry is one of the hardest occupations.
222: * I think I agree.
223: */
224: }
225:
226: /*
227: * Reset segmentation for an l.out.
228: */
229: reslout()
230: {
231: struct ldheader ldh;
232:
233: clramap();
234: objflag = 0;
235: fseek(lfp, (long)0, 0);
236: if (fread(&ldh, sizeof(ldh), 1, lfp) != 1) {
237: printr("Can't read object file");
238: return (0);
239: }
240: canlout(&ldh);
241: if (ldh.l_magic != L_MAGIC) {
242: printr("not an object file");
243: return (0);
244: }
245: objflag = 1;
246: setaseg(&ldh);
247: return (1);
248: }
249:
250: /*
251: * Given a command line in `miscbuf', parse the command line, kill the
252: * current child and start up a new one. 0 is returned on success, 1
253: * on failure.
254: */
255: runfile()
256: {
257: register char *bp, *cp;
258: register int c;
259: char *ifn, *ofn, *argl[ARGSIZE];
260: int qflag, aflag, n;
261:
262: killc();
263: if (objflag == 0) {
264: printe("No l.out");
265: return (1);
266: }
267: ifn = NULL;
268: ofn = NULL;
269: qflag = 0;
270: aflag = 0;
271: n = 0;
272: bp = miscbuf;
273: cp = miscbuf;
274: c = *bp++;
275: while (c != '\n') {
276: switch (c) {
277: case '<':
278: ifn = cp;
279: c = *bp++;
280: break;
281: case '>':
282: ofn = cp;
283: if ((c=*bp++) == '>') {
284: aflag = 1;
285: c = *bp++;
286: }
287: break;
288: default:
289: if (n >= ARGSIZE-1) {
290: printe("Too many arguments");
291: return (1);
292: }
293: argl[n++] = cp;
294: }
295: while (qflag || !isascii(c) || !isspace(c)) {
296: if (c == '\n')
297: break;
298: if (c == '"') {
299: qflag ^= 1;
300: c = *bp++;
301: continue;
302: }
303: if (c == '\\') {
304: if ((c=*bp++) == '\n') {
305: printe("Syntax error");
306: return (1);
307: }
308: }
309: *cp++ = c;
310: c = *bp++;
311: }
312: if (qflag) {
313: printe("Missing \"");
314: return (1);
315: }
316: *cp++ = '\0';
317: if (c == '\n')
318: break;
319: while (isascii(c) && isspace(c))
320: c = *bp++;
321: }
322: if (n == 0)
323: argl[n++] = lfn;
324: argl[n] = NULL;
325: if (startup(argl, ifn, ofn, aflag) == 0)
326: return (1);
327: return (0);
328: }
329:
330: /*
331: * Start execution of the child. `argv' is the argument list, `ifnp' is
332: * the name of the input file, `ofnp' is the name of the output file and
333: * `appf' tells us whether the output file is opened for append or write.
334: */
335: startup(argv, ifnp, ofnp, appf)
336: char **argv;
337: char *ifnp;
338: char *ofnp;
339: {
340: register int n;
341:
342: if ((pid=fork()) < 0) {
343: printr("Cannot fork");
344: return (0);
345: }
346: if (pid == 0) {
347: if (ifnp != NULL) {
348: if ((n=open(ifnp, 0)) < 0)
349: panic("Cannot open %s", ifnp);
350: dup2(n, 0);
351: close(n);
352: }
353: if (ofnp != NULL) {
354: n = -1;
355: if (appf) {
356: if ((n=open(ofnp, 1)) >= 0)
357: lseek(n, 0L, 2);
358: }
359: if (n < 0) {
360: if ((n=creat(ofnp, 0644)) < 0)
361: panic("%s: cannot create", ofnp);
362: }
363: dup2(n, 1);
364: close(n);
365: }
366: ptrace(0, 0, NULL, 0);
367: execv(lfn, argv);
368: exit(1);
369: }
370: if (waitc() == 0)
371: return (0);
372: clramap();
373: DSPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0,
374: getp, putp, 1);
375: ISPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0,
376: getp, putp, 0);
377: USPACE = setsmap(NULL, (fsize_t)0, (fsize_t)UPASIZE, (fsize_t)0,
378: getp, putp, 2);
379: excflag = 1;
380: regflag = 1;
381: return (1);
382: }
383:
384: /*
385: * Given a newly started child, find out necessary information.
386: */
387: shiftup()
388: {
389: if (trapint() == 0)
390: return (0);
391: if (setregs() == 0)
392: return (0);
393: return (settrap());
394: }
395:
396: /*
397: * Kill off our child.
398: */
399: killc()
400: {
401: if (excflag) {
402: ptrace(8, pid, 0, 0);
403: waitc();
404: }
405: excflag = 0;
406: regflag = 0;
407: trapstr = NULL;
408: }
409:
410: /*
411: * Wait for the traced process to stop.
412: */
413: waitc()
414: {
415: register int p;
416: int s;
417:
418: while ((p=wait(&s)) != pid) {
419: if (p >= 0) {
420: printr("Adopted a child %d", p);
421: continue;
422: }
423: if (intflag == 0) {
424: excflag = 0;
425: printr("Nonexistant child");
426: return (0);
427: }
428: intflag = 0;
429: }
430: if ((s&0377) != 0177) {
431: excflag = 0;
432: printr("Child process terminated (%d)", (s>>8)&0377);
433: return (0);
434: }
435: return (1);
436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.