|
|
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: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)main.c 5.4 (Berkeley) 1/12/88";
15: #endif not lint
16:
17: static char rcsid[] = "$Header: main.c,v 1.4 87/07/08 21:31:27 donn Exp $";
18:
19: /*
20: * Debugger main routine.
21: */
22:
23: #include "defs.h"
24: #include <setjmp.h>
25: #include <signal.h>
26: #include <errno.h>
27: #include "main.h"
28: #include "tree.h"
29: #include "eval.h"
30: #include "debug.h"
31: #include "symbols.h"
32: #include "scanner.h"
33: #include "keywords.h"
34: #include "process.h"
35: #include "runtime.h"
36: #include "source.h"
37: #include "object.h"
38: #include "mappings.h"
39: #include "coredump.h"
40:
41: #ifndef public
42:
43: #define isterm(file) (interactive or isatty(fileno(file)))
44:
45: #ifdef IRIS
46: # include <termio.h>
47:
48: typedef struct termio Ttyinfo;
49: #else
50: # include <sgtty.h>
51: # include <fcntl.h>
52:
53: typedef struct {
54: struct sgttyb sg; /* standard sgttyb structure */
55: struct tchars tc; /* terminal characters */
56: struct ltchars ltc; /* local special characters */
57: integer ldisc; /* line discipline */
58: integer local; /* TIOCLGET */
59: integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */
60: } Ttyinfo;
61: #endif
62:
63: #endif
64:
65: public boolean coredump; /* true if using a core dump */
66: public boolean runfirst; /* run program immediately */
67: public boolean interactive; /* standard input IS a terminal */
68: public boolean lexdebug; /* trace scanner return values */
69: public boolean tracebpts; /* trace create/delete breakpoints */
70: public boolean traceexec; /* trace execution */
71: public boolean tracesyms; /* print symbols are they are read */
72: public boolean traceblocks; /* trace blocks while reading symbols */
73: public boolean vaddrs; /* map addresses through page tables */
74: public boolean quiet; /* don't print heading */
75: public boolean autostrip; /* strip C++ prefixes */
76:
77: public File corefile; /* File id of core dump */
78:
79: public integer versionNumber = 4;
80:
81: #define FIRST_TIME 0 /* initial value setjmp returns */
82:
83: private Boolean initdone = false; /* true if initialization done */
84: private jmp_buf env; /* setjmp/longjmp data */
85: private char outbuf[BUFSIZ]; /* standard output buffer */
86: private char namebuf[512]; /* possible name of object file */
87:
88: private Ttyinfo ttyinfo;
89: private String corename; /* name of core file */
90:
91: private catchintr();
92: private char **scanargs();
93:
94: /*
95: * Main program.
96: */
97:
98: main(argc, argv)
99: int argc;
100: String argv[];
101: {
102: extern integer versionNumber;
103: char **scanargs();
104:
105: if (!(cmdname = rindex(*argv, '/')))
106: cmdname = *argv;
107: else
108: ++cmdname;
109:
110: catcherrs();
111: onsyserr(EINTR, nil);
112: onsyserr(EADDRINUSE, nil);
113: onsyserr(ENXIO, nil);
114: setbuf(stdout, outbuf);
115: argv = scanargs(argc, argv);
116: if (not runfirst and not quiet) {
117: printheading();
118: }
119: openfiles();
120: language_init();
121: symbols_init();
122: process_init();
123: optab_init();
124: if (runfirst) {
125: if (setjmp(env) == FIRST_TIME) {
126: arginit();
127: while (*argv)
128: newarg(*argv++);
129: run();
130: /* NOTREACHED */
131: } else {
132: runfirst = false;
133: }
134: } else {
135: init();
136: }
137: if (setjmp(env) != FIRST_TIME) {
138: restoretty(stdout, &ttyinfo);
139: }
140: signal(SIGINT, catchintr);
141: yyparse();
142: putchar('\n');
143: quit(0);
144: }
145:
146: public printheading ()
147: {
148: extern String date;
149:
150: printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
151: versionNumber, date
152: );
153: fflush(stdout);
154: }
155:
156: /*
157: * Initialize the world, including setting initial input file
158: * if the file exists.
159: */
160:
161: public init()
162: {
163: File f;
164: String home;
165: char buf[100];
166: extern String getenv();
167:
168: savetty(stdout, &ttyinfo);
169: enterkeywords();
170: scanner_init();
171: if (not coredump and not runfirst) {
172: start(nil, nil, nil);
173: }
174: printf("reading symbolic information ...");
175: fflush(stdout);
176: readobj(objname);
177: printf("\n");
178: fflush(stdout);
179: if (coredump) {
180: printf("[using memory image in %s]\n", corename);
181: if (vaddrs) {
182: coredump_getkerinfo();
183: }
184: getsrcpos();
185: setcurfunc(whatblock(pc));
186: } else {
187: setcurfunc(program);
188: }
189: bpinit();
190: f = fopen(initfile, "r");
191: if (f != nil) {
192: fclose(f);
193: setinput(initfile);
194: } else {
195: home = getenv("HOME");
196: if (home != nil) {
197: sprintf(buf, "%s/%s", home, initfile);
198: f = fopen(buf, "r");
199: if (f != nil) {
200: fclose(f);
201: setinput(strdup(buf));
202: }
203: }
204: }
205: initdone = true;
206: }
207:
208: /*
209: * Re-initialize the world, first de-allocating all storage.
210: * This is necessary when the symbol information must be re-read
211: * from the object file when it has changed.
212: *
213: * Before "forgetting" things, we save the current tracing/breakpoint
214: * information to a temp file. Then after re-creating the world,
215: * we read the temp file as commands. This isn't always the right thing;
216: * if a procedure that was being traced is deleted, an error message
217: * will be generated.
218: *
219: * If the argument vector is not nil, then this is re-initialize is being
220: * done in preparation for running the program. Since we want to process
221: * the commands in the temp file before running the program, we add the
222: * run command at the end of the temp file. In this case, reinit longjmps
223: * back to parsing rather than returning.
224: */
225:
226: public reinit(argv, infile, outfile)
227: String *argv;
228: String infile;
229: String outfile;
230: {
231: register Integer i;
232: String tmpfile;
233: extern String mktemp();
234:
235: tmpfile = mktemp("/tmp/dbxXXXX");
236: setout(tmpfile);
237: status();
238: alias(nil, nil, nil);
239: if (argv != nil) {
240: printf("run");
241: for (i = 1; argv[i] != nil; i++) {
242: printf(" %s", argv[i]);
243: }
244: if (infile != nil) {
245: printf(" < %s", infile);
246: }
247: if (outfile != nil) {
248: printf(" > %s", outfile);
249: }
250: putchar('\n');
251: }
252: unsetout();
253: bpfree();
254: objfree();
255: symbols_init();
256: process_init();
257: enterkeywords();
258: scanner_init();
259: readobj(objname);
260: bpinit();
261: fflush(stdout);
262: setinput(tmpfile);
263: unlink(tmpfile);
264: if (argv != nil) {
265: longjmp(env, 1);
266: /* NOTREACHED */
267: }
268: }
269:
270: /*
271: * After a non-fatal error we skip the rest of the current input line, and
272: * jump back to command parsing.
273: */
274:
275: public erecover()
276: {
277: if (initdone) {
278: gobble();
279: longjmp(env, 1);
280: }
281: }
282:
283: /*
284: * This routine is called when an interrupt occurs.
285: */
286:
287: private catchintr()
288: {
289: if (isredirected()) {
290: fflush(stdout);
291: unsetout();
292: }
293: putchar('\n');
294: longjmp(env, 1);
295: }
296:
297: /*
298: * Scan the argument list.
299: */
300:
301: private char **scanargs (argc, argv)
302: int argc;
303: String argv[];
304: {
305: extern char *optarg;
306: extern integer optind;
307: integer ch;
308:
309: runfirst = false;
310: interactive = false;
311: lexdebug = false;
312: tracebpts = false;
313: traceexec = false;
314: tracesyms = false;
315: traceblocks = false;
316: vaddrs = false;
317: quiet = false;
318: autostrip = true;
319: corefile = nil;
320: coredump = true;
321: sourcepath = list_alloc();
322: list_append(list_item("."), nil, sourcepath);
323:
324: while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF)
325: switch((char)ch) {
326: case 'I':
327: list_append(list_item(optarg), nil, sourcepath);
328: break;
329: case 'a':
330: autostrip = false;
331: break;
332: case 'b':
333: tracebpts = true;
334: break;
335: case 'c':
336: initfile = optarg;
337: break;
338: case 'e':
339: traceexec = true;
340: break;
341: case 'i':
342: interactive = true;
343: break;
344: case 'k':
345: vaddrs = true;
346: break;
347: case 'l':
348: #ifdef LEXDEBUG
349: lexdebug = true;
350: #else
351: fatal("\"-l\" only applicable when compiled with LEXDEBUG");
352: #endif
353: break;
354: case 'n':
355: traceblocks = true;
356: break;
357: case 'q':
358: quiet = true;
359: break;
360: case 'r': /* run program before accepting commands */
361: runfirst = true;
362: coredump = false;
363: break;
364: case 's':
365: tracesyms = true;
366: break;
367: case '?':
368: default:
369: fatal("unknown option");
370: }
371: argv += optind;
372: if (*argv) {
373: objname = *argv;
374: if (*++argv && coredump) {
375: corename = *argv;
376: corefile = fopen(*argv, "r");
377: if (corefile == nil)
378: coredump = false;
379: ++argv;
380: }
381: }
382: if (*argv and not runfirst) {
383: fatal("extraneous argument %s", *argv);
384: }
385: return argv;
386: }
387:
388: private openfiles ()
389: {
390: File f;
391: char *tmp;
392:
393: if (objname == nil and isatty(0)) {
394: printf("enter object file name (default is `%s'): ", objname);
395: fflush(stdout);
396: gets(namebuf);
397: if (namebuf[0] != '\0') {
398: objname = namebuf;
399: }
400: }
401: f = fopen(objname, "r");
402: if (f == nil) {
403: fatal("can't read %s", objname);
404: } else {
405: fclose(f);
406: }
407: if (rindex(objname, '/') != nil) {
408: tmp = strdup(objname);
409: *(rindex(tmp, '/')) = '\0';
410: list_append(list_item(tmp), nil, sourcepath);
411: }
412: if (coredump and corefile == nil) {
413: if (vaddrs) {
414: corename = "/dev/mem";
415: corefile = fopen(corename, "r");
416: if (corefile == nil) {
417: panic("can't open /dev/mem");
418: }
419: } else {
420: corename = "core";
421: corefile = fopen(corename, "r");
422: if (corefile == nil) {
423: coredump = false;
424: }
425: }
426: }
427: }
428:
429: /*
430: * Save/restore the state of a tty.
431: */
432:
433: public savetty(f, t)
434: File f;
435: Ttyinfo *t;
436: {
437: # ifdef IRIS
438: ioctl(fileno(f), TCGETA, t);
439: # else
440: ioctl(fileno(f), TIOCGETP, &(t->sg));
441: ioctl(fileno(f), TIOCGETC, &(t->tc));
442: ioctl(fileno(f), TIOCGLTC, &(t->ltc));
443: ioctl(fileno(f), TIOCGETD, &(t->ldisc));
444: ioctl(fileno(f), TIOCLGET, &(t->local));
445: t->fcflags = fcntl(fileno(f), F_GETFL, 0);
446: if ((t->fcflags&FASYNC) != 0) {
447: /* fprintf(stderr, "[async i/o found set -- reset]\n"); */
448: t->fcflags &= ~FASYNC;
449: }
450: # endif
451: }
452:
453: public restoretty(f, t)
454: File f;
455: Ttyinfo *t;
456: {
457: # ifdef IRIS
458: ioctl(fileno(f), TCSETA, t);
459: # else
460: ioctl(fileno(f), TIOCSETN, &(t->sg));
461: ioctl(fileno(f), TIOCSETC, &(t->tc));
462: ioctl(fileno(f), TIOCSLTC, &(t->ltc));
463: ioctl(fileno(f), TIOCSETD, &(t->ldisc));
464: ioctl(fileno(f), TIOCLSET, &(t->local));
465: if ((t->fcflags&FASYNC) != 0) {
466: /* fprintf(stderr, "[async i/o not set]\n"); */
467: t->fcflags &= ~FASYNC;
468: }
469: (void) fcntl(fileno(f), F_SETFL, t->fcflags);
470: # endif
471: }
472:
473: /*
474: * Exit gracefully.
475: */
476:
477: public quit(r)
478: Integer r;
479: {
480: pterm(process);
481: exit(r);
482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.