Commit | Line | Data |
---|---|---|
2a24676e | 1 | /* |
8a90f3aa KB |
2 | * Copyright (c) 1983 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
6ecf3d85 | 5 | * %sccs.include.redist.c% |
2a24676e DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
8a90f3aa | 10 | "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ |
2a24676e | 11 | All rights reserved.\n"; |
8a90f3aa | 12 | #endif /* not lint */ |
00102538 | 13 | |
2a24676e | 14 | #ifndef lint |
6ecf3d85 | 15 | static char sccsid[] = "@(#)main.c 5.7 (Berkeley) %G%"; |
8a90f3aa | 16 | #endif /* not lint */ |
00102538 ML |
17 | |
18 | /* | |
19 | * Debugger main routine. | |
20 | */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include <setjmp.h> | |
24 | #include <signal.h> | |
25 | #include <errno.h> | |
26 | #include "main.h" | |
9606e7b9 | 27 | #include "tree.h" |
0022c355 ML |
28 | #include "eval.h" |
29 | #include "debug.h" | |
1c5b15ac | 30 | #include "symbols.h" |
00102538 | 31 | #include "scanner.h" |
0022c355 | 32 | #include "keywords.h" |
00102538 | 33 | #include "process.h" |
2fd0f574 | 34 | #include "runtime.h" |
00102538 ML |
35 | #include "source.h" |
36 | #include "object.h" | |
1c5b15ac | 37 | #include "mappings.h" |
0022c355 | 38 | #include "coredump.h" |
dc0e9d50 | 39 | #include "pathnames.h" |
00102538 ML |
40 | |
41 | #ifndef public | |
42 | ||
43 | #define isterm(file) (interactive or isatty(fileno(file))) | |
44 | ||
9606e7b9 DS |
45 | #ifdef IRIS |
46 | # include <termio.h> | |
39144fe1 | 47 | |
9606e7b9 DS |
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 | |
39144fe1 | 62 | |
00102538 ML |
63 | #endif |
64 | ||
0022c355 ML |
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 */ | |
9606e7b9 DS |
74 | public boolean quiet; /* don't print heading */ |
75 | public boolean autostrip; /* strip C++ prefixes */ | |
00102538 ML |
76 | |
77 | public File corefile; /* File id of core dump */ | |
78 | ||
9606e7b9 DS |
79 | public integer versionNumber = 4; |
80 | ||
00102538 ML |
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 */ | |
0022c355 | 85 | private char outbuf[BUFSIZ]; /* standard output buffer */ |
00102538 | 86 | private char namebuf[512]; /* possible name of object file */ |
00102538 | 87 | |
39144fe1 | 88 | private Ttyinfo ttyinfo; |
0022c355 | 89 | private String corename; /* name of core file */ |
39144fe1 | 90 | |
00102538 | 91 | private catchintr(); |
9606e7b9 | 92 | private char **scanargs(); |
00102538 ML |
93 | |
94 | /* | |
95 | * Main program. | |
96 | */ | |
97 | ||
98 | main(argc, argv) | |
99 | int argc; | |
100 | String argv[]; | |
101 | { | |
2fd0f574 | 102 | extern integer versionNumber; |
ef9fed8e KB |
103 | char **scanargs(); |
104 | ||
105 | if (!(cmdname = rindex(*argv, '/'))) | |
106 | cmdname = *argv; | |
107 | else | |
108 | ++cmdname; | |
00102538 | 109 | |
00102538 ML |
110 | catcherrs(); |
111 | onsyserr(EINTR, nil); | |
9606e7b9 DS |
112 | onsyserr(EADDRINUSE, nil); |
113 | onsyserr(ENXIO, nil); | |
0022c355 | 114 | setbuf(stdout, outbuf); |
ef9fed8e | 115 | argv = scanargs(argc, argv); |
9606e7b9 DS |
116 | if (not runfirst and not quiet) { |
117 | printheading(); | |
118 | } | |
119 | openfiles(); | |
00102538 | 120 | language_init(); |
0022c355 | 121 | symbols_init(); |
00102538 | 122 | process_init(); |
31bb8678 | 123 | optab_init(); |
00102538 ML |
124 | if (runfirst) { |
125 | if (setjmp(env) == FIRST_TIME) { | |
126 | arginit(); | |
ef9fed8e KB |
127 | while (*argv) |
128 | newarg(*argv++); | |
00102538 ML |
129 | run(); |
130 | /* NOTREACHED */ | |
131 | } else { | |
132 | runfirst = false; | |
133 | } | |
134 | } else { | |
135 | init(); | |
136 | } | |
2fd0f574 SL |
137 | if (setjmp(env) != FIRST_TIME) { |
138 | restoretty(stdout, &ttyinfo); | |
139 | } | |
00102538 ML |
140 | signal(SIGINT, catchintr); |
141 | yyparse(); | |
142 | putchar('\n'); | |
143 | quit(0); | |
144 | } | |
145 | ||
9606e7b9 DS |
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 | ||
00102538 ML |
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 | ||
39144fe1 | 168 | savetty(stdout, &ttyinfo); |
00102538 ML |
169 | enterkeywords(); |
170 | scanner_init(); | |
171 | if (not coredump and not runfirst) { | |
172 | start(nil, nil, nil); | |
173 | } | |
39144fe1 ML |
174 | printf("reading symbolic information ..."); |
175 | fflush(stdout); | |
00102538 | 176 | readobj(objname); |
39144fe1 ML |
177 | printf("\n"); |
178 | fflush(stdout); | |
1c5b15ac | 179 | if (coredump) { |
0022c355 ML |
180 | printf("[using memory image in %s]\n", corename); |
181 | if (vaddrs) { | |
182 | coredump_getkerinfo(); | |
183 | } | |
9606e7b9 | 184 | getsrcpos(); |
2fd0f574 | 185 | setcurfunc(whatblock(pc)); |
1c5b15ac | 186 | } else { |
2fd0f574 | 187 | setcurfunc(program); |
1c5b15ac | 188 | } |
00102538 ML |
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 | ||
dc0e9d50 | 235 | tmpfile = mktemp(_PATH_TMP); |
00102538 ML |
236 | setout(tmpfile); |
237 | status(); | |
0022c355 | 238 | alias(nil, nil, nil); |
00102538 ML |
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(); | |
0022c355 | 255 | symbols_init(); |
00102538 ML |
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 | /* | |
0022c355 ML |
271 | * After a non-fatal error we skip the rest of the current input line, and |
272 | * jump back to command parsing. | |
00102538 ML |
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 | { | |
0022c355 ML |
289 | if (isredirected()) { |
290 | fflush(stdout); | |
291 | unsetout(); | |
292 | } | |
00102538 ML |
293 | putchar('\n'); |
294 | longjmp(env, 1); | |
295 | } | |
296 | ||
297 | /* | |
298 | * Scan the argument list. | |
299 | */ | |
300 | ||
9606e7b9 | 301 | private char **scanargs (argc, argv) |
00102538 ML |
302 | int argc; |
303 | String argv[]; | |
304 | { | |
ef9fed8e | 305 | extern char *optarg; |
9606e7b9 DS |
306 | extern integer optind; |
307 | integer ch; | |
00102538 ML |
308 | |
309 | runfirst = false; | |
310 | interactive = false; | |
311 | lexdebug = false; | |
312 | tracebpts = false; | |
313 | traceexec = false; | |
314 | tracesyms = false; | |
2fd0f574 | 315 | traceblocks = false; |
0022c355 | 316 | vaddrs = false; |
9606e7b9 DS |
317 | quiet = false; |
318 | autostrip = true; | |
00102538 ML |
319 | corefile = nil; |
320 | coredump = true; | |
321 | sourcepath = list_alloc(); | |
322 | list_append(list_item("."), nil, sourcepath); | |
ef9fed8e | 323 | |
9606e7b9 | 324 | while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF) |
ef9fed8e KB |
325 | switch((char)ch) { |
326 | case 'I': | |
327 | list_append(list_item(optarg), nil, sourcepath); | |
328 | break; | |
9606e7b9 DS |
329 | case 'a': |
330 | autostrip = false; | |
331 | break; | |
ef9fed8e KB |
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; | |
9606e7b9 DS |
357 | case 'q': |
358 | quiet = true; | |
359 | break; | |
ef9fed8e KB |
360 | case 'r': /* run program before accepting commands */ |
361 | runfirst = true; | |
00102538 | 362 | coredump = false; |
ef9fed8e KB |
363 | break; |
364 | case 's': | |
365 | tracesyms = true; | |
366 | break; | |
367 | case '?': | |
368 | default: | |
369 | fatal("unknown option"); | |
00102538 | 370 | } |
ef9fed8e KB |
371 | argv += optind; |
372 | if (*argv) { | |
373 | objname = *argv; | |
ef9fed8e KB |
374 | if (*++argv && coredump) { |
375 | corename = *argv; | |
376 | corefile = fopen(*argv, "r"); | |
377 | if (corefile == nil) | |
378 | coredump = false; | |
379 | ++argv; | |
380 | } | |
00102538 | 381 | } |
9606e7b9 | 382 | if (*argv and not runfirst) { |
ef9fed8e | 383 | fatal("extraneous argument %s", *argv); |
9606e7b9 DS |
384 | } |
385 | return argv; | |
386 | } | |
387 | ||
388 | private openfiles () | |
389 | { | |
390 | File f; | |
391 | char *tmp; | |
392 | ||
393 | if (objname == nil and isatty(0)) { | |
00102538 ML |
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) { | |
0022c355 | 413 | if (vaddrs) { |
dc0e9d50 | 414 | corename = _PATH_MEM; |
ef9fed8e | 415 | corefile = fopen(corename, "r"); |
0022c355 | 416 | if (corefile == nil) { |
dc0e9d50 | 417 | panic("can't open %s", _PATH_MEM); |
0022c355 ML |
418 | } |
419 | } else { | |
0022c355 | 420 | corename = "core"; |
ef9fed8e | 421 | corefile = fopen(corename, "r"); |
0022c355 ML |
422 | if (corefile == nil) { |
423 | coredump = false; | |
424 | } | |
00102538 ML |
425 | } |
426 | } | |
00102538 ML |
427 | } |
428 | ||
39144fe1 ML |
429 | /* |
430 | * Save/restore the state of a tty. | |
431 | */ | |
432 | ||
433 | public savetty(f, t) | |
434 | File f; | |
435 | Ttyinfo *t; | |
436 | { | |
9606e7b9 DS |
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 | |
39144fe1 ML |
451 | } |
452 | ||
453 | public restoretty(f, t) | |
454 | File f; | |
455 | Ttyinfo *t; | |
456 | { | |
9606e7b9 DS |
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 | |
39144fe1 ML |
471 | } |
472 | ||
00102538 ML |
473 | /* |
474 | * Exit gracefully. | |
475 | */ | |
476 | ||
477 | public quit(r) | |
478 | Integer r; | |
479 | { | |
2fd0f574 | 480 | pterm(process); |
00102538 ML |
481 | exit(r); |
482 | } |