|
|
1.1 root 1: /*
2: * db/db3.c
3: * A debugger.
4: * Command execution and display routines.
5: */
6:
7: #include "db.h"
8: #include <signal.h>
9:
10: /*
11: * Execute a command.
12: * Return 1 if more commands may be read,
13: * 0 to stop reading commands (for :e, :c, :s).
14: */
15: int
16: command(vp) register VAL *vp;
17: {
18: register int c, sig;
19:
20: switch (c = getn()) {
21:
22: /* [addr]:a Print address (default: .) */
23: case 'a':
24: if (getn() != '\n')
25: break;
26: putaddr(val_segn(vp), lvalue(vp, dot));
27: putx('\n');
28: return 1;
29:
30: /* [addr]:b[r][cmd] Set [return] breakpoint */
31: case 'b':
32: if (!IS_OBJ)
33: break;
34: if ((c = getn()) != 'r') {
35: ungetn(c);
36: c = 'b';
37: }
38: getline("i+.:a\ni+.?i\n:x");
39: /* FIX_ME :br only works at current pc, not at specified addr. */
40: if ((c == 'r' && bpt_setr(miscbuf) == 0)
41: || (c != 'r' && bpt_set(BBPT, lvalue(vp, dot), 0L, miscbuf) == 0))
42: printe("Cannot set breakpoint");
43: return 1;
44:
45: /* [addr]:c Continue */
46: case 'c':
47: if (getn() != '\n')
48: break;
49: else
50: c = '\n';
51: if (execflag == 0)
52: break;
53: if (nvalue(vp) == 0)
54: set_pc(lvalue(vp, (ADDR_T)0));
55: step_mode = SNULL;
56: return 0;
57:
58: /* [addr]:d[r][s] Delete breakpoint */
59: case 'd':
60: if (!IS_OBJ)
61: break;
62: if ((c = getn()) != 'r' && c != 's') {
63: ungetn(c);
64: c = 'b';
65: }
66: if (getn() != '\n')
67: break;
68: if (bpt_del(c, lvalue(vp, dot)) == 0)
69: printe("Cannot delete breakpoint");
70: return 1;
71:
72: /* [addr]:eargs Execute */
73: case 'e':
74: if (nvalue(vp) == 0)
75: set_pc(lvalue(vp, (ADDR_T)0));
76: getline("");
77: return runfile();
78:
79: /* :f Print fault type */
80: case 'f':
81: if (getn() != '\n')
82: break;
83: sig = get_sig();
84: printx("%s\n", (sig == 0) ? "no fault"
85: : (sig > NSIG) ? "bad signal number"
86: : signame[sig]);
87: return 1;
88:
89: /* :h[f] Print help info */
90: case 'h':
91: if ((c = getn()) != 'f')
92: ungetn(c);
93: if (getn() != '\n')
94: break;
95: helpinfo(c == 'f');
96: return 1;
97:
98: /* [n]:k ??? send a signal ??? */
99: case 'k':
100: if (execflag == 0)
101: break;
102: if (getn() != '\n')
103: break;
104: if (nvalue(vp) != 0) {
105: printe("No signal specified");
106: return 1;
107: }
108: printr("Cannot send %d", (int)rvalue(vp, 0L));
109: return 1;
110:
111: /* :m Print segmentation map */
112: case 'm':
113: if (getn() != '\n')
114: break;
115: map_print();
116: return 1;
117:
118: /* case 'n': Documented but not implemented? */
119:
120: #ifndef NOCANON
121: /* [expr]:o Change canon type, UNDOCUMENTED... */
122: case 'o':
123: if (getn() != '\n')
124: break;
125: cantype = rvalue(vp, 0L);
126: return 1;
127: #endif
128:
129: /* :p Print breakpoints */
130: case 'p':
131: if (getn() != '\n')
132: break;
133: bpt_display();
134: return 1;
135:
136: /* [expr]:q Quit */
137: case 'q':
138: if (getn() != '\n')
139: break;
140: if (rvalue(vp, 1L))
141: leave();
142: return 1;
143:
144: /* :r[N] Print registers [including NDP] */
145: case 'r':
146: if ((c = getn()) == 'N')
147: c = R_ALL;
148: else {
149: ungetn(c);
150: c = R_GEN;
151: }
152: if (getn() != '\n')
153: break;
154: if (reg_flag == R_INVALID)
155: break;
156: display_reg(c);
157: return 1;
158:
159: /* [addr][,n]:s[c] Single step [n times] [over calls] */
160: case 's':
161: if (execflag == 0)
162: break;
163: if (nvalue(vp) == 0)
164: set_pc(lvalue(vp, (ADDR_T)0));
165: step_count = rvalue(&vp[1], 1L);
166: if ((c = getn()) != 'c') {
167: step_mode = SSTEP;
168: ungetn(c);
169: } else
170: step_mode = SCONT;
171: getline("i+.?i");
172: step_cmd = save_cmd(step_cmd, miscbuf);
173: return 0;
174:
175: /* [expr]:t Call traceback [expr levels] */
176: case 't':
177: if (getn() != '\n')
178: break;
179: else
180: c = '\n';
181: if (reg_flag == R_INVALID)
182: break;
183: traceback((int)rvalue(vp, 0L));
184: return 1;
185:
186: /* [expr]:x Read and execute stdin */
187: case 'x':
188: if (getn() != '\n')
189: break;
190: if (rvalue(vp, 1L)) {
191: step_prev = step_mode;
192: step_mode = SNULL;
193: add_input(IFILE, (char *)stdin);
194: }
195: return 1;
196: }
197: printe("Illegal command");
198: while (c != '\n')
199: c = getn();
200: return 1;
201: }
202:
203: /*
204: * Print out data from segment 's' according to the given format "t1 t2".
205: */
206: char *
207: conform(sp, s, t1, t2) register char *sp; int s, t1, t2;
208: {
209: register char *lp;
210: char c;
211: unsigned char uc;
212: short sh;
213: unsigned short us;
214: int i;
215: unsigned int ui;
216: long l;
217: unsigned char v[3];
218: ADDR_T p;
219: #ifndef NOFP
220: float f;
221: double d;
222: struct _fpreg fpreg;
223: #endif
224:
225: dbprintf(("conform(... s=%d t1=%c t2=%c)\n", s, t1, t2));
226: switch (t1) {
227:
228: case 'b': /* byte */
229: if (getb(s, &uc, sizeof(uc)) == 0)
230: return NULL;
231: modsize = sizeof(uc);
232:
233: /* Sign-extend or 0-extend depending on display format. */
234: if (t2 != 'd')
235: i = ui = (unsigned int)uc;
236: else
237: i = c = uc;
238: sprintf(sp, get_format(t1, t2), i);
239: break;
240: case 'c': /* char with escapes */
241: if (getb(s, &uc, sizeof(uc)) == 0)
242: return NULL;
243: modsize = sizeof(uc);
244: return printable(sp, uc);
245: case 'C': /* char */
246: if (getb(s, &uc, sizeof(uc)) == 0)
247: return NULL;
248: modsize = sizeof(uc);
249: *sp++ = (uc >= 0x20 && uc < 0x7F) ? uc : '.';
250: return sp;
251: #ifndef NOFP
252: case 'f': /* float */
253: if (getb(s, (char *)&f, sizeof(f)) == 0)
254: return NULL;
255: modsize = sizeof(f);
256: sprintf(sp, get_format(t1, t2), f);
257: break;
258: case 'F': /* double */
259: if (getb(s, (char *)&d, sizeof(d)) == 0)
260: return NULL;
261: modsize = sizeof(d);
262: sprintf(sp, get_format(t1, t2), d);
263: break;
264: case 'N': /* NDP fp register */
265: if (getb(s, (char *)&fpreg, sizeof(fpreg)) == 0)
266: return NULL;
267: if (get_fp_reg(&fpreg, &d) == 0)
268: return NULL;
269: modsize = sizeof(fpreg);
270: sprintf(sp, get_format('F', t2), d);
271: break;
272: #endif
273: case 'h':
274: if (getb(s, (char *)&us, sizeof(us)) == 0)
275: return NULL;
276: modsize = sizeof(us);
277:
278: /* Sign-extend or 0-extend depending on display format. */
279: if (t2 != 'd')
280: i = ui = us;
281: else
282: i = sh = us;
283: sprintf(sp, get_format(t1, t2), i);
284: break;
285: case 'i': /* machine instruction */
286: modsize = INLEN;
287: return disassemble(sp, s);
288: case 'l': /* long */
289: if (getb(s, (char *)&l, sizeof(l)) == 0)
290: return NULL;
291: modsize = sizeof(l);
292: sprintf(sp, get_format(t1, t2), l);
293: break;
294: case 'p': /* pointer */
295: if (getb(s, (char *)&p, sizeof(p)) == 0)
296: return NULL;
297: modsize = sizeof(p);
298: return cvt_addr(sp, find_seg(p), p);
299: case 's': /* string with escapes */
300: case 'S': /* string */
301: lp = &sp[DISSIZE];
302: for (;;) {
303: if (getb(s, &uc, sizeof(uc)) == 0)
304: return NULL;
305: if (uc == '\0')
306: break;
307: if (t1 == 's')
308: sp = printable(sp, uc);
309: else
310: *sp++ = uc;
311: if (sp > lp)
312: return NULL;
313: }
314: modsize = sizeof(i);
315: return sp;
316: case 'v': /* l3 */
317: if (getb(s, (char *)v, sizeof(v)) == 0)
318: return NULL;
319: modsize = sizeof(v);
320: l3tol(&l, v, 1);
321: sprintf(sp, get_format(t1, t2), l);
322: break;
323: case 'w': /* word */
324: if (getb(s, (char *)&us, sizeof(us)) == 0)
325: return NULL;
326: modsize = sizeof(us);
327: sprintf(sp, get_format(t1, t2), (int)us);
328: break;
329: case 'Y': /* time */
330: modsize = sizeof(i);
331: return gettime(sp, s);
332: default:
333: return NULL;
334: }
335: return strchr(sp, '\0');
336: }
337:
338: /*
339: * Print out 'n' data items from segment 's'.
340: */
341: int
342: display(s, n) int s, n;
343: {
344: register char *sp1, *sp2, *fs;
345: register int c, r, t1, t2;
346: register char *sp3, *fp;
347: register ADDR_T nad, pad, uad;
348:
349: dbprintf(("display(%d, %d) dot=%x\n", s, n, dot));
350: r = 1;
351: t2 = '\0';
352: add = nad = pad = uad = dot;
353: sp1 = miscbuf;
354: sp3 = &sp1[DISSIZE];
355: fs = seg_format[s];
356: while (n--) {
357: fp = fs;
358: for (;;) {
359: c = *fp++;
360: if (isascii(c) && isdigit(c)) {
361: r = 0;
362: do {
363: r = r*10 + c-'0';
364: c = *fp++;
365: } while (isascii(c) && isdigit(c));
366: --fp;
367: continue;
368: }
369: switch (c) {
370: case '^':
371: add = uad;
372: continue;
373: case '+':
374: add += r;
375: r = 1;
376: continue;
377: case '-':
378: add -= r;
379: r = 1;
380: continue;
381: case 'n':
382: *sp1 = '\0';
383: flushb(nad);
384: sp1 = miscbuf;
385: nad = add;
386: continue;
387: case 'd':
388: case 'o':
389: case 'u':
390: case 'x':
391: t2 = c;
392: continue;
393: default:
394: t1 = c;
395: if (t1=='\0' && t2=='\0')
396: break;
397: if (t1 == '\0')
398: t1 = 'w';
399: if (t2 == '\0')
400: t2 = DDCHR;
401: uad = add;
402: while (r--) {
403: if (testint())
404: return 1;
405: *sp1++ = ' ';
406: pad = add;
407: sp2 = conform(sp1, s, t1, t2);
408: if (sp2 == NULL) {
409: *--sp1 = '\0';
410: if (sp1 != miscbuf)
411: flushb(nad);
412: dbprintf(("add=0x%lX cseg=%d\n", add, cseg));
413: return printe("Addressing error");
414: }
415: if (sp2 <= sp3)
416: sp1 = sp2;
417: else {
418: *--sp1 = '\0';
419: flushb(nad);
420: *sp2 = '\0';
421: *sp1 = ' ';
422: sp2 = sp1;
423: sp1 = miscbuf;
424: while (*sp2)
425: *sp1++ = *sp2++;
426: nad = pad;
427: }
428: if (c == 'i') {
429: *sp1++ = '\0';
430: flushb(nad);
431: sp1 = miscbuf;
432: nad = add;
433: }
434: }
435: r = 1;
436: t2 = '\0';
437: if (c != '\0')
438: continue;
439: }
440: break;
441: }
442: old_add = add;
443: }
444: if (sp1 != miscbuf) {
445: *sp1 = '\0';
446: flushb(nad);
447: }
448: return 1;
449: }
450:
451: /*
452: * Execute a command string.
453: */
454: void
455: execute(cmd) char *cmd;
456: {
457: register INP *ip;
458:
459: dbprintf(("execute(%s)\n", cmd));
460:
461: /* Delete input list starting at "inpp". */
462: while ((ip = inpp) != (INP *)NULL) {
463: inpp = ip->i_next;
464: nfree(ip);
465: }
466: ungotc = '\0'; /* clear ungot character */
467:
468: /* Muck with some globals. */
469: modsize = sizeof(int);
470: step_prev = SNULL;
471: dot = get_pc();
472:
473: /* Add string "cmd" to the input list and process it. */
474: if (cmd != NULL) {
475: add_input(ICORE, cmd);
476: request();
477: }
478:
479: /* Check for interrupt. */
480: testint();
481: }
482:
483: /*
484: * Flush the output buffer.
485: * Print the given address 'addr' before the contents of the buffer
486: * and set dot to it.
487: */
488: void
489: flushb(addr) ADDR_T addr;
490: {
491: dot = addr;
492: printx(addr_fmt, dot);
493: printx("\t%s\n", miscbuf);
494: }
495:
496: /*
497: * Display help info.
498: * The flag is false for :h, true for :hf.
499: */
500: void
501: helpinfo(flag) int flag;
502: {
503: printf(flag
504: ? "[addr][,n]?[ft]\tDisplay formatted information.\n"
505: "Display formats:\n"
506: "\tb\tbyte\n"
507: "\tc\tchar, control and non-chars escaped\n"
508: "\tC\tchar, control and non-chars print as '.'\n"
509: "\td\tdecimal\n"
510: "\tf\tfloat\n"
511: "\tF\tdouble\n"
512: "\ti\tdisassembled machine instruction\n"
513: "\tl\tlong\n"
514: "\tn\toutput '\\n'\n"
515: "\tN\tNDP (80387) floating point register (10 bytes)\n"
516: "\to\toctal\n"
517: "\tp\tsymbolic address\n"
518: "\ts\tstring (NUL-terminated) with escapes\n"
519: "\tS\tstring (NUL-terminated)\n"
520: "\tu\tunsigned\n"
521: "\tv\tfilesystem l3 block address (3 bytes)\n"
522: "\tw\tword\n"
523: "\tx\thexadecimal\n"
524: "\tY\ttime\n"
525: "[doux] specify numeric bases (decimal, octal, unsigned decimal, hexadecimal).\n"
526: "Each may be followed by [bwl] to indicate a datum size [byte, word, long].\n"
527: : "Requests:\n"
528: "\t[addr][,n]?[ft]\tDisplay formatted information.\n"
529: "\t\t\tFormats: bcCdfFilnNopsSuvwxY [see :hf for details]\n"
530: "\taddr?\t\tPrint address\n"
531: "\t[addr]=\t\tPrint address\n"
532: "\t[addr]=val...\tPatch address with val...\n"
533: "\t?\t\tPrint last error message\n"
534: "\t!cmd\t\tSend cmd to system\n"
535: "\t[addr]:a\tPrint address\n"
536: "\t[addr]:b[cmd]\tSet breakpoint [to execute cmd]\n"
537: "\t:br[cmd]\tSet return breakpoint [to execute cmd]\n"
538: "\t[addr]:c\tContinue [from addr]\n"
539: "\t[addr]:d[r][s]\tDelete breakpoint\n"
540: "\t[addr]:e args\tExecute\n"
541: "\t:f\t\tPrint fault type\n"
542: "\t:h[f]\t\tPrint help information [about display formats]\n"
543: /* "\t:k\t\t???\n" */
544: "\t:m\t\tPrint segmentation map\n"
545: #ifndef NOCANON
546: "\t[expr]:o\t\tSet canonization type\n"
547: #endif
548: "\t:p\t\tPrint breakpoints\n"
549: "\t[expr]:q\tQuit\n"
550: "\t:r[N]\t\tPrint registers [including NDP]\n"
551: "\t[addr][,n]:s[c]\tSingle step [over calls]\n"
552: "\t[expr]:t\tPrint traceback [to expr levels]\n"
553: "\t[expr]:x\tRead commands from stdin\n"
554: );
555: }
556:
557: /*
558: * Get a long representing the current time and convert it.
559: */
560: char *
561: gettime(sp, s) register char *sp; int s;
562: {
563: long l;
564:
565: if (getb(s, (char *)&l, sizeof(l)) == 0)
566: return NULL;
567: memcpy(sp, ctime(&l), 24);
568: return sp + 24;
569: }
570:
571: /*
572: * If the given character is unprintable,
573: * convert it into an escape sequence.
574: */
575: char *
576: printable(sp, c) register char *sp; register int c;
577: {
578: *sp++ = '\\';
579: switch (c) {
580: case '\0': *sp++ = '0'; break;
581: case '\b': *sp++ = 'b'; break;
582: case '\n': *sp++ = 'n'; break;
583: case '\f': *sp++ = 'f'; break;
584: case '\r': *sp++ = 'r'; break;
585: case '\\': *sp++ = '\\'; break;
586: default:
587: if (c<040 || c>=0177) {
588: sprintf(sp, "%03o", c);
589: while (*sp)
590: sp++;
591: break;
592: }
593: sp[-1] = c;
594: break;
595: }
596: return sp;
597: }
598:
599: /*
600: * Talk to the user and try to solve his problems.
601: */
602: void
603: process()
604: {
605: static char *xcmd = ":x\n";
606: static char *fxcmd = ":f\n:x\n";
607: register BPT *bp;
608: register ADDR_T pc, fp;
609: register int n;
610: register int bpt_next, bpt_skipped;
611: int step_flag; /* 0==not step, 1==step, 2==syscall */
612:
613: /*
614: * Reverse-engineered pseudocode, minus global variable garbage.
615: *
616: * forever:
617: * execute(":x\n") <= Preload interpreter stack.
618: * (Will come back after traced process traps, e.g. after ":e".)
619: * forever:
620: * See if at call instruction.
621: * Install breakpoints, except at current instruction.
622: * See if current instruction is a breakpoint opcode.
623: * Start up traced process, full speed or single step.
624: * Report any error from ptrace call.
625: * Wait for traced process.
626: * Fetch registers and signal received from traced process.
627: * Replace breakpoints with instructions.
628: * If signal to child was not SIGTRAP
629: * display message
630: * execute(":f\n:x\n");
631: * continue inner loop
632: * Back up instruction pointer to start of the breakpoint.
633: * If single stepping
634: * Execute single step command string (step_cmd).
635: * If last single step in count
636: * execute(":x\n")
637: * end forever
638: * end forever
639: *
640: */
641: top:
642: execute(xcmd);
643: for (;;) {
644:
645: /*
646: * If in single step mode, set up for single step.
647: * If in SCONT mode (for :sc),
648: * change to SCALL mode at call instruction.
649: */
650: if (step_mode != SNULL && step_mode != SWAIT) {
651: /* Single stepping. */
652: step_flag = 1;
653: if (step_mode == SCONT && is_call())
654: step_mode = SCALL;
655: } else
656: step_flag = 0;
657:
658: /* Place all breakpoints. */
659: if (reg_flag != R_INVALID)
660: pc = get_pc();
661: for (bpt_skipped = 0, bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
662:
663: /* Skip unused table entries. */
664: if (bp->b_flag == 0)
665: continue;
666:
667: /*
668: * If there is a breakpoint at the current PC,
669: * we do not want to install it, or we'll get nowhere.
670: * But if we are not single-stepping, we really want
671: * the breakpoint reinstalled after doing a single step.
672: * Kludge the mode to SSTEP and set 'bpt_skipped' in
673: * this case so SNULL mode gets restored after a step.
674: */
675: if (reg_flag!=R_INVALID && bp->b_badd == pc) {
676: if (step_mode == SNULL) {
677: step_mode = SSTEP;
678: bpt_skipped = step_flag = 1;
679: }
680: continue;
681: }
682:
683: /* Install a breakpoint. */
684: add = bp->b_badd;
685: dbprintf(("setting breakpoint @ %lX\n", add));
686: if (putb(ISEG, bin, sizeof(BIN)) == 0) {
687: printb(bp->b_badd);
688: goto err;
689: }
690: }
691:
692: /* Set 'bpt_next' if next instruction is a breakpoint. */
693: bpt_next = (reg_flag!=R_INVALID && bpt_test(pc));
694:
695: /* Watch out for system calls if single stepping. */
696: if (is_syscall(&step_flag) == 0)
697: goto err;
698:
699: /* Run the child. */
700: if (runc() == 0)
701: goto err;
702:
703: /* Restore if we have stepped past system call. */
704: if (step_flag == 2 && rest_syscall(&step_flag) == 0)
705: goto err;
706:
707: /* Replace breakpoints with instructions. */
708: dbprintf(("Replace breakpoints with instructions\n"));
709: for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
710: if (bp->b_flag == 0)
711: continue; /* unused */
712: dbprintf(("Restore instruction %X in bpt[%d]\n", bp->b_bins[0] & 0xFF, bp - bpt));
713: add = bp->b_badd;
714: if (putb(ISEG, bp->b_bins, sizeof(BIN)) == 0) {
715: printb(bp->b_badd);
716: goto err;
717: }
718: }
719:
720: /*
721: * If latest signal to traced process was not SIGTRAP,
722: * tell the user, then accept input.
723: */
724: if (get_sig() != SIGTRAP) {
725: if (get_sig() != SIGINT)
726: printr("Traced process did not stop at a breakpoint");
727: printf("Traced process: ");
728: execute(fxcmd);
729: continue;
730: }
731:
732: /* Resume running following skipped breakpoint. */
733: if (bpt_skipped) {
734: step_mode = SNULL;
735: continue;
736: }
737:
738: /*
739: * Find the breakpoint we are at.
740: * Back up pc to start of the breakpoint.
741: */
742: bp = (BPT *)NULL;
743: pc = get_pc() - sizeof(BIN);
744: dbprintf(("find bpt: --pc=%x step_flag=%d bpt_next=%d\n", pc, step_flag, bpt_next));
745: if (step_flag == 0 || bpt_next) {
746: for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
747: if (bp->b_flag == 0)
748: continue;
749: if (bp->b_badd != pc)
750: continue;
751: dbprintf(("found bpt[%d] at %x\n", bp-bpt, pc));
752: set_pc(pc);
753: break;
754: }
755: if (bp == &bpt[NBPT])
756: bp = (BPT *)NULL; /* unknown */
757: }
758:
759: /* If in single step mode, execute command. */
760: dbprintf(("step_mode=%d\n", step_mode));
761: switch (step_mode) {
762: case SSTEP:
763: case SCONT:
764: execute(step_cmd);
765: if (--step_count == 0)
766: execute(xcmd);
767: continue;
768: case SCALL:
769: /*
770: * :sc has stepped into call with step_mode SCALL.
771: * Clear other BSIN breakpoints, place a BSIN breakpoint
772: * at the return address, and set step_mode SWAIT
773: * to run until the return is executed.
774: */
775: for (n = 0; n < NBPT; n++)
776: bpt[n].b_flag &= ~BSIN;
777: step_mode = SWAIT;
778: set_ra_bpt(); /* set BSIN bpt at return address */
779: break;
780: }
781:
782: /*
783: * Handle an unexpected trace trap or unknown breakpoint.
784: * One way this can happen: if the child does not handle
785: * SIGINT, type "100:s" followed by "<Ctrl-C>" and ":c".
786: * The child is interrupted, the parent prints "Interrupted"
787: * and prompts, ":c" resumes the child with SNULL (step_flag 0),
788: * and the child then hits the actual breakpoint.
789: * t
790: */
791: if (bp == (BPT *)NULL) {
792: dbprintf(("step_mode=%d step_flag=%d bpt_next=%d\n", step_mode, step_flag, bpt_next));
793: if (step_flag == 0 || bpt_next) {
794: printf("Unexpected ");
795: execute(fxcmd);
796: }
797: continue;
798: }
799:
800: /* Single step breakpoints have highest priority. */
801: fp = get_fp();
802: if (bp->b_flag & BSIN) {
803: if (bp->b_sfpt==0 || bp->b_sfpt == fp) {
804: bp->b_flag &= ~BSIN;
805: if (step_mode == SWAIT) {
806: /*
807: * We hit the return from a called
808: * function with :sc, restore SCONT mode.
809: */
810: step_mode = SCONT;
811: execute(step_cmd);
812: if (--step_count == 0)
813: execute(xcmd);
814: continue;
815: }
816: }
817: }
818:
819: /* Return breakpoints are next. */
820: if (bp->b_flag & BRET) {
821: if (bp->b_rfpt == fp) {
822: bp->b_flag &= ~BRET;
823: execute(bp->b_rcom);
824: continue;
825: }
826: }
827:
828: /* Your conventional everyday ordinary breakpoint. */
829: if (bp->b_flag & BBPT) {
830: execute(bp->b_bcom);
831: continue;
832: }
833: }
834:
835: /*
836: * Something is terribly wrong.
837: * Kill off our child and generally reset everything to the start.
838: */
839: err:
840: killc();
841: initialize();
842: map_init();
843: if (IS_LOUT)
844: setloutseg();
845: else if (IS_COFF)
846: setcoffseg();
847: goto top;
848: }
849:
850: /*
851: * Parse requests and execute them.
852: * This is a loop which eats input and process it,
853: * using command() to execute commands.
854: * It returns when command() returns 0 or on '\n' for single step.
855: */
856: void
857: request()
858: {
859: static int ttyflag = -1;
860: register int c;
861: register char *cp;
862: register unsigned segn;
863: register ADDR_T l, d;
864: VAL val[VALSIZE];
865:
866: for(;;) {
867: /* Prompt if appropriate. */
868: if (ttyflag == -1)
869: ttyflag = isatty(fileno(stdin));
870: if (ttyflag && inpp->i_type==IFILE && inpp->i_u.i_filp==stdin) {
871: printf(prompt);
872: fflush(stdout);
873: }
874: if ((c = getn()) == EOF)
875: break;
876:
877: /* !cmd Execute cmd */
878: if (c == '!') {
879: syscall();
880: continue;
881: }
882:
883: /* ? Print fault type */
884: if (c == '?') {
885: if ((c = getn()) != '\n') {
886: printe("Syntax error");
887: goto next;
888: }
889: printr("%s", (lasterr == NULL) ? "No error" : lasterr);
890: continue;
891: }
892: ungetn(c);
893: if (expr_list(val) == 0) /* get expression list */
894: goto next;
895:
896: switch (c = getn()) {
897:
898: /* : indicates commands, handled by command(). */
899: case ':':
900: step_prev = SNULL;
901: if (command(val) == 0)
902: return;
903: continue;
904:
905: /* \n indicates more of the same, single step or display */
906: case '\n':
907: if (nvalue(&val[0]) && step_prev != SNULL) {
908: if (execflag == 0) {
909: step_prev = SNULL;
910: printe("Cannot single step");
911: continue;
912: }
913: step_mode = step_prev;
914: step_count = rvalue(&val[1], 1L);
915: return;
916: }
917: /* else fall through to print value */
918:
919: /* addr\n Print value */
920: /* [addr]=val Assign value */
921: /* [addr]? Print value */
922: case '=':
923: ungetn(c);
924: /* fall through... */
925: case '?':
926: step_prev = SNULL;
927: segn = val_segn(&val[0]);
928: if ((c = getn()) == '=') {
929: l = lvalue(&val[0], dot);
930: if ((c = getn()) == '\n') {
931: dbprintf(("print seg=%d loc=%lx fmt=%s\n", segn, l, addr_fmt));
932: printx(addr_fmt, l);
933: printx("\n");
934: continue;
935: }
936: ungetn(c);
937: dbprintf(("assign to seg=%d loc=%lx\n", segn, l));
938: if (setdata(segn, l) == 0)
939: break;
940: continue;
941: }
942: if (c != '\n') {
943: cp = &seg_format[segn][0];
944: while (c != '\n') {
945: *cp++ = c;
946: c = getn();
947: }
948: *cp++ = '\0';
949: dbprintf(("new seg_format[%d]=%s\n", segn, seg_format[segn]));
950: }
951: d = dot;
952: l = old_add;
953: dot = lvalue(&val[0], old_add);
954: display(segn, (int)rvalue(&val[1], 1L));
955: if (segn != USEG)
956: cseg = segn; /* set cseg unless USEG */
957: else {
958: dot = d; /* restore dot, old_add if USEG */
959: old_add = l;
960: }
961: continue;
962:
963: default:
964: step_prev = SNULL;
965: printe("Syntax error");
966: break;
967: }
968: next:
969: while ((c = getn()) != '\n')
970: ;
971: }
972: }
973:
974: /*
975: * Parse the command line in 'miscbuf',
976: * kill the current child and start up a new one.
977: * Return 0 on success, 1 on failure.
978: */
979: int
980: runfile()
981: {
982: register char *bp, *cp;
983: register int c;
984: char *ifn, *ofn, *argl[ARGSIZE];
985: int qflag, aflag, n;
986:
987: killc();
988: if (!IS_OBJ) {
989: printe("No executable");
990: return 1;
991: }
992: ifn = ofn = NULL;
993: aflag = qflag = n = 0;
994: for (bp = cp = miscbuf, c = *bp++; c != '\n'; ) {
995: switch (c) {
996: case '<':
997: ifn = cp;
998: c = *bp++;
999: break;
1000: case '>':
1001: ofn = cp;
1002: if ((c = *bp++) == '>') {
1003: aflag = 1;
1004: c = *bp++;
1005: }
1006: break;
1007: default:
1008: if (n >= ARGSIZE-1) {
1009: printe("Too many arguments");
1010: return 1;
1011: }
1012: argl[n++] = cp;
1013: }
1014: while (qflag || !isascii(c) || !isspace(c)) {
1015: if (c == '\n')
1016: break;
1017: if (c == '"') {
1018: qflag ^= 1;
1019: c = *bp++;
1020: continue;
1021: }
1022: if (c == '\\') {
1023: if ((c=*bp++) == '\n') {
1024: printe("Syntax error");
1025: return 1;
1026: }
1027: }
1028: *cp++ = c;
1029: c = *bp++;
1030: }
1031: if (qflag) {
1032: printe("Missing '\"'");
1033: return 1;
1034: }
1035: *cp++ = '\0';
1036: if (c == '\n')
1037: break;
1038: while (isascii(c) && isspace(c))
1039: c = *bp++;
1040: }
1041: if (n == 0)
1042: argl[n++] = lfn;
1043: argl[n] = NULL;
1044: return startc(argl, ifn, ofn, aflag) == 0;
1045: }
1046:
1047: /*
1048: * Given a pointer to an allocated buffer and a pointer to a command string,
1049: * copy the command string to the allocated buffer.
1050: * If the buffer hasn't been allocated, allocate it.
1051: */
1052: char *
1053: save_cmd(buf, s) register char *buf, *s;
1054: {
1055: if (buf == NULL)
1056: buf = nalloc(COMSIZE, "command buffer");
1057: buf[COMSIZE-1] = '\0';
1058: return strncpy(buf, s, COMSIZE-1);
1059: }
1060:
1061: /*
1062: * Change the value of a location.
1063: */
1064: int
1065: setdata(segn, a) int segn; ADDR_T a;
1066: {
1067: register char *cp;
1068: register int n;
1069: register int c;
1070: char b[1];
1071: char l3[3];
1072: int i[1];
1073: long l[1];
1074: VAL val[VALSIZE];
1075:
1076: if (expr_list(val) == 0)
1077: return 0;
1078: if ((c = getn()) != '\n')
1079: return 0;
1080: for (n = 0; n < VALSIZE; n++, a += modsize) {
1081: if (nvalue(&val[n]))
1082: continue;
1083: l[0] = rvalue(&val[n], 0L);
1084: switch (modsize) {
1085: case (sizeof(char)):
1086: b[0] = l[0];
1087: cp = b;
1088: break;
1089: case (sizeof(short)):
1090: i[0] = l[0];
1091: cp = (char *)i;
1092: break;
1093: case (sizeof(l3)):
1094: ltol3(l3, l, 1);
1095: cp = l3;
1096: break;
1097: case (sizeof(long)):
1098: cp = (char *)l;
1099: break;
1100: default:
1101: printe("Bad change type");
1102: return 1;
1103: }
1104: add = a;
1105: if (putb(segn, cp, modsize) == 0) {
1106: printe("Cannot change value");
1107: return 1;
1108: }
1109: }
1110: if (segn == USEG) {
1111: /* Reread required registers after writing register data. */
1112: reg_flag = R_INVALID;
1113: get_regs(R_SOME);
1114: }
1115: return 1;
1116: }
1117:
1118: /*
1119: * Send a command to the shell.
1120: * Return its exit status.
1121: */
1122: int
1123: syscall()
1124: {
1125: register int c, status;
1126: register char *cp;
1127:
1128: for (cp = miscbuf; (c = getn()) != '\n'; )
1129: *cp++ = c;
1130: *cp = '\0';
1131: status = system(miscbuf);
1132: testint();
1133: printf("!\n");
1134: return status;
1135: }
1136:
1137: /* end of db/db3.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.