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