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