121609Sdist /*
238105Sbostic * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic * All rights reserved.
438105Sbostic *
5*42683Sbostic * %sccs.include.redist.c%
621609Sdist */
79669Slinton
821609Sdist #ifndef lint
921609Sdist char copyright[] =
1038105Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
1121609Sdist All rights reserved.\n";
1238105Sbostic #endif /* not lint */
139669Slinton
1421609Sdist #ifndef lint
15*42683Sbostic static char sccsid[] = "@(#)main.c 5.7 (Berkeley) 06/01/90";
1638105Sbostic #endif /* not lint */
1721609Sdist
189669Slinton /*
199669Slinton * Debugger main routine.
209669Slinton */
219669Slinton
229669Slinton #include "defs.h"
239669Slinton #include <setjmp.h>
249669Slinton #include <signal.h>
259669Slinton #include <errno.h>
269669Slinton #include "main.h"
2733322Sdonn #include "tree.h"
2818223Slinton #include "eval.h"
2918223Slinton #include "debug.h"
3012483Slinton #include "symbols.h"
319669Slinton #include "scanner.h"
3218223Slinton #include "keywords.h"
339669Slinton #include "process.h"
3416613Ssam #include "runtime.h"
359669Slinton #include "source.h"
369669Slinton #include "object.h"
3712483Slinton #include "mappings.h"
3818223Slinton #include "coredump.h"
3937790Sbostic #include "pathnames.h"
409669Slinton
419669Slinton #ifndef public
429669Slinton
439669Slinton #define isterm(file) (interactive or isatty(fileno(file)))
449669Slinton
4533322Sdonn #ifdef IRIS
4633322Sdonn # include <termio.h>
4711868Slinton
4833322Sdonn typedef struct termio Ttyinfo;
4933322Sdonn #else
5033322Sdonn # include <sgtty.h>
5133322Sdonn # include <fcntl.h>
5211868Slinton
5333322Sdonn typedef struct {
5433322Sdonn struct sgttyb sg; /* standard sgttyb structure */
5533322Sdonn struct tchars tc; /* terminal characters */
5633322Sdonn struct ltchars ltc; /* local special characters */
5733322Sdonn integer ldisc; /* line discipline */
5833322Sdonn integer local; /* TIOCLGET */
5933322Sdonn integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */
6033322Sdonn } Ttyinfo;
619669Slinton #endif
629669Slinton
6333322Sdonn #endif
6433322Sdonn
6518223Slinton public boolean coredump; /* true if using a core dump */
6618223Slinton public boolean runfirst; /* run program immediately */
6718223Slinton public boolean interactive; /* standard input IS a terminal */
6818223Slinton public boolean lexdebug; /* trace scanner return values */
6918223Slinton public boolean tracebpts; /* trace create/delete breakpoints */
7018223Slinton public boolean traceexec; /* trace execution */
7118223Slinton public boolean tracesyms; /* print symbols are they are read */
7218223Slinton public boolean traceblocks; /* trace blocks while reading symbols */
7318223Slinton public boolean vaddrs; /* map addresses through page tables */
7433322Sdonn public boolean quiet; /* don't print heading */
7533322Sdonn public boolean autostrip; /* strip C++ prefixes */
769669Slinton
779669Slinton public File corefile; /* File id of core dump */
789669Slinton
7933322Sdonn public integer versionNumber = 4;
8033322Sdonn
819669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */
829669Slinton
839669Slinton private Boolean initdone = false; /* true if initialization done */
849669Slinton private jmp_buf env; /* setjmp/longjmp data */
8518223Slinton private char outbuf[BUFSIZ]; /* standard output buffer */
869669Slinton private char namebuf[512]; /* possible name of object file */
879669Slinton
8811868Slinton private Ttyinfo ttyinfo;
8918223Slinton private String corename; /* name of core file */
9011868Slinton
919669Slinton private catchintr();
9233322Sdonn private char **scanargs();
939669Slinton
949669Slinton /*
959669Slinton * Main program.
969669Slinton */
979669Slinton
main(argc,argv)989669Slinton main(argc, argv)
999669Slinton int argc;
1009669Slinton String argv[];
1019669Slinton {
10216613Ssam extern integer versionNumber;
10331002Sbostic char **scanargs();
1049669Slinton
10531002Sbostic if (!(cmdname = rindex(*argv, '/')))
10631002Sbostic cmdname = *argv;
10731002Sbostic else
10831002Sbostic ++cmdname;
10931002Sbostic
1109669Slinton catcherrs();
1119669Slinton onsyserr(EINTR, nil);
11233322Sdonn onsyserr(EADDRINUSE, nil);
11333322Sdonn onsyserr(ENXIO, nil);
11418223Slinton setbuf(stdout, outbuf);
11531002Sbostic argv = scanargs(argc, argv);
11633322Sdonn if (not runfirst and not quiet) {
11733322Sdonn printheading();
11833322Sdonn }
11933322Sdonn openfiles();
1209669Slinton language_init();
12118223Slinton symbols_init();
1229669Slinton process_init();
12326328Ssam optab_init();
1249669Slinton if (runfirst) {
1259669Slinton if (setjmp(env) == FIRST_TIME) {
1269669Slinton arginit();
12731002Sbostic while (*argv)
12831002Sbostic newarg(*argv++);
1299669Slinton run();
1309669Slinton /* NOTREACHED */
1319669Slinton } else {
1329669Slinton runfirst = false;
1339669Slinton }
1349669Slinton } else {
1359669Slinton init();
1369669Slinton }
13716613Ssam if (setjmp(env) != FIRST_TIME) {
13816613Ssam restoretty(stdout, &ttyinfo);
13916613Ssam }
1409669Slinton signal(SIGINT, catchintr);
1419669Slinton yyparse();
1429669Slinton putchar('\n');
1439669Slinton quit(0);
1449669Slinton }
1459669Slinton
printheading()14633322Sdonn public printheading ()
14733322Sdonn {
14833322Sdonn extern String date;
14933322Sdonn
15033322Sdonn printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
15133322Sdonn versionNumber, date
15233322Sdonn );
15333322Sdonn fflush(stdout);
15433322Sdonn }
15533322Sdonn
1569669Slinton /*
1579669Slinton * Initialize the world, including setting initial input file
1589669Slinton * if the file exists.
1599669Slinton */
1609669Slinton
init()1619669Slinton public init()
1629669Slinton {
1639669Slinton File f;
1649669Slinton String home;
1659669Slinton char buf[100];
1669669Slinton extern String getenv();
1679669Slinton
16811868Slinton savetty(stdout, &ttyinfo);
1699669Slinton enterkeywords();
1709669Slinton scanner_init();
1719669Slinton if (not coredump and not runfirst) {
1729669Slinton start(nil, nil, nil);
1739669Slinton }
17411868Slinton printf("reading symbolic information ...");
17511868Slinton fflush(stdout);
1769669Slinton readobj(objname);
17711868Slinton printf("\n");
17811868Slinton fflush(stdout);
17912483Slinton if (coredump) {
18018223Slinton printf("[using memory image in %s]\n", corename);
18118223Slinton if (vaddrs) {
18218223Slinton coredump_getkerinfo();
18318223Slinton }
18433322Sdonn getsrcpos();
18516613Ssam setcurfunc(whatblock(pc));
18612483Slinton } else {
18716613Ssam setcurfunc(program);
18812483Slinton }
1899669Slinton bpinit();
1909669Slinton f = fopen(initfile, "r");
1919669Slinton if (f != nil) {
1929669Slinton fclose(f);
1939669Slinton setinput(initfile);
1949669Slinton } else {
1959669Slinton home = getenv("HOME");
1969669Slinton if (home != nil) {
1979669Slinton sprintf(buf, "%s/%s", home, initfile);
1989669Slinton f = fopen(buf, "r");
1999669Slinton if (f != nil) {
2009669Slinton fclose(f);
2019669Slinton setinput(strdup(buf));
2029669Slinton }
2039669Slinton }
2049669Slinton }
2059669Slinton initdone = true;
2069669Slinton }
2079669Slinton
2089669Slinton /*
2099669Slinton * Re-initialize the world, first de-allocating all storage.
2109669Slinton * This is necessary when the symbol information must be re-read
2119669Slinton * from the object file when it has changed.
2129669Slinton *
2139669Slinton * Before "forgetting" things, we save the current tracing/breakpoint
2149669Slinton * information to a temp file. Then after re-creating the world,
2159669Slinton * we read the temp file as commands. This isn't always the right thing;
2169669Slinton * if a procedure that was being traced is deleted, an error message
2179669Slinton * will be generated.
2189669Slinton *
2199669Slinton * If the argument vector is not nil, then this is re-initialize is being
2209669Slinton * done in preparation for running the program. Since we want to process
2219669Slinton * the commands in the temp file before running the program, we add the
2229669Slinton * run command at the end of the temp file. In this case, reinit longjmps
2239669Slinton * back to parsing rather than returning.
2249669Slinton */
2259669Slinton
reinit(argv,infile,outfile)2269669Slinton public reinit(argv, infile, outfile)
2279669Slinton String *argv;
2289669Slinton String infile;
2299669Slinton String outfile;
2309669Slinton {
2319669Slinton register Integer i;
2329669Slinton String tmpfile;
2339669Slinton extern String mktemp();
2349669Slinton
23537790Sbostic tmpfile = mktemp(_PATH_TMP);
2369669Slinton setout(tmpfile);
2379669Slinton status();
23818223Slinton alias(nil, nil, nil);
2399669Slinton if (argv != nil) {
2409669Slinton printf("run");
2419669Slinton for (i = 1; argv[i] != nil; i++) {
2429669Slinton printf(" %s", argv[i]);
2439669Slinton }
2449669Slinton if (infile != nil) {
2459669Slinton printf(" < %s", infile);
2469669Slinton }
2479669Slinton if (outfile != nil) {
2489669Slinton printf(" > %s", outfile);
2499669Slinton }
2509669Slinton putchar('\n');
2519669Slinton }
2529669Slinton unsetout();
2539669Slinton bpfree();
2549669Slinton objfree();
25518223Slinton symbols_init();
2569669Slinton process_init();
2579669Slinton enterkeywords();
2589669Slinton scanner_init();
2599669Slinton readobj(objname);
2609669Slinton bpinit();
2619669Slinton fflush(stdout);
2629669Slinton setinput(tmpfile);
2639669Slinton unlink(tmpfile);
2649669Slinton if (argv != nil) {
2659669Slinton longjmp(env, 1);
2669669Slinton /* NOTREACHED */
2679669Slinton }
2689669Slinton }
2699669Slinton
2709669Slinton /*
27118223Slinton * After a non-fatal error we skip the rest of the current input line, and
27218223Slinton * jump back to command parsing.
2739669Slinton */
2749669Slinton
erecover()2759669Slinton public erecover()
2769669Slinton {
2779669Slinton if (initdone) {
2789669Slinton gobble();
2799669Slinton longjmp(env, 1);
2809669Slinton }
2819669Slinton }
2829669Slinton
2839669Slinton /*
2849669Slinton * This routine is called when an interrupt occurs.
2859669Slinton */
2869669Slinton
catchintr()2879669Slinton private catchintr()
2889669Slinton {
28918223Slinton if (isredirected()) {
29018223Slinton fflush(stdout);
29118223Slinton unsetout();
29218223Slinton }
2939669Slinton putchar('\n');
2949669Slinton longjmp(env, 1);
2959669Slinton }
2969669Slinton
2979669Slinton /*
2989669Slinton * Scan the argument list.
2999669Slinton */
3009669Slinton
scanargs(argc,argv)30133322Sdonn private char **scanargs (argc, argv)
3029669Slinton int argc;
3039669Slinton String argv[];
3049669Slinton {
30531002Sbostic extern char *optarg;
30633322Sdonn extern integer optind;
30733322Sdonn integer ch;
3089669Slinton
3099669Slinton runfirst = false;
3109669Slinton interactive = false;
3119669Slinton lexdebug = false;
3129669Slinton tracebpts = false;
3139669Slinton traceexec = false;
3149669Slinton tracesyms = false;
31516613Ssam traceblocks = false;
31618223Slinton vaddrs = false;
31733322Sdonn quiet = false;
31833322Sdonn autostrip = true;
3199669Slinton corefile = nil;
3209669Slinton coredump = true;
3219669Slinton sourcepath = list_alloc();
3229669Slinton list_append(list_item("."), nil, sourcepath);
32331002Sbostic
32433322Sdonn while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF)
32531002Sbostic switch((char)ch) {
32631002Sbostic case 'I':
32731002Sbostic list_append(list_item(optarg), nil, sourcepath);
32831002Sbostic break;
32933322Sdonn case 'a':
33033322Sdonn autostrip = false;
33133322Sdonn break;
33231002Sbostic case 'b':
33331002Sbostic tracebpts = true;
33431002Sbostic break;
33531002Sbostic case 'c':
33631002Sbostic initfile = optarg;
33731002Sbostic break;
33831002Sbostic case 'e':
33931002Sbostic traceexec = true;
34031002Sbostic break;
34131002Sbostic case 'i':
34231002Sbostic interactive = true;
34331002Sbostic break;
34431002Sbostic case 'k':
34531002Sbostic vaddrs = true;
34631002Sbostic break;
34731002Sbostic case 'l':
34831002Sbostic #ifdef LEXDEBUG
34931002Sbostic lexdebug = true;
35031002Sbostic #else
35131002Sbostic fatal("\"-l\" only applicable when compiled with LEXDEBUG");
35231002Sbostic #endif
35331002Sbostic break;
35431002Sbostic case 'n':
35531002Sbostic traceblocks = true;
35631002Sbostic break;
35733322Sdonn case 'q':
35833322Sdonn quiet = true;
35933322Sdonn break;
36031002Sbostic case 'r': /* run program before accepting commands */
36131002Sbostic runfirst = true;
3629669Slinton coredump = false;
36331002Sbostic break;
36431002Sbostic case 's':
36531002Sbostic tracesyms = true;
36631002Sbostic break;
36731002Sbostic case '?':
36831002Sbostic default:
36931002Sbostic fatal("unknown option");
37031002Sbostic }
37131002Sbostic argv += optind;
37231002Sbostic if (*argv) {
37331002Sbostic objname = *argv;
37431002Sbostic if (*++argv && coredump) {
37531002Sbostic corename = *argv;
37631002Sbostic corefile = fopen(*argv, "r");
37731002Sbostic if (corefile == nil)
37831002Sbostic coredump = false;
37931002Sbostic ++argv;
3809669Slinton }
3819669Slinton }
38233322Sdonn if (*argv and not runfirst) {
38331002Sbostic fatal("extraneous argument %s", *argv);
38433322Sdonn }
38533322Sdonn return argv;
38633322Sdonn }
38733322Sdonn
openfiles()38833322Sdonn private openfiles ()
38933322Sdonn {
39033322Sdonn File f;
39133322Sdonn char *tmp;
39233322Sdonn
39333322Sdonn if (objname == nil and isatty(0)) {
3949669Slinton printf("enter object file name (default is `%s'): ", objname);
3959669Slinton fflush(stdout);
3969669Slinton gets(namebuf);
3979669Slinton if (namebuf[0] != '\0') {
3989669Slinton objname = namebuf;
3999669Slinton }
4009669Slinton }
4019669Slinton f = fopen(objname, "r");
4029669Slinton if (f == nil) {
4039669Slinton fatal("can't read %s", objname);
4049669Slinton } else {
4059669Slinton fclose(f);
4069669Slinton }
4079669Slinton if (rindex(objname, '/') != nil) {
4089669Slinton tmp = strdup(objname);
4099669Slinton *(rindex(tmp, '/')) = '\0';
4109669Slinton list_append(list_item(tmp), nil, sourcepath);
4119669Slinton }
4129669Slinton if (coredump and corefile == nil) {
41318223Slinton if (vaddrs) {
41437790Sbostic corename = _PATH_MEM;
41531002Sbostic corefile = fopen(corename, "r");
41618223Slinton if (corefile == nil) {
41737790Sbostic panic("can't open %s", _PATH_MEM);
41818223Slinton }
41918223Slinton } else {
42018223Slinton corename = "core";
42131002Sbostic corefile = fopen(corename, "r");
42218223Slinton if (corefile == nil) {
42318223Slinton coredump = false;
42418223Slinton }
4259669Slinton }
4269669Slinton }
4279669Slinton }
4289669Slinton
4299669Slinton /*
43011868Slinton * Save/restore the state of a tty.
43111868Slinton */
43211868Slinton
savetty(f,t)43311868Slinton public savetty(f, t)
43411868Slinton File f;
43511868Slinton Ttyinfo *t;
43611868Slinton {
43733322Sdonn # ifdef IRIS
43833322Sdonn ioctl(fileno(f), TCGETA, t);
43933322Sdonn # else
44033322Sdonn ioctl(fileno(f), TIOCGETP, &(t->sg));
44133322Sdonn ioctl(fileno(f), TIOCGETC, &(t->tc));
44233322Sdonn ioctl(fileno(f), TIOCGLTC, &(t->ltc));
44333322Sdonn ioctl(fileno(f), TIOCGETD, &(t->ldisc));
44433322Sdonn ioctl(fileno(f), TIOCLGET, &(t->local));
44533322Sdonn t->fcflags = fcntl(fileno(f), F_GETFL, 0);
44633322Sdonn if ((t->fcflags&FASYNC) != 0) {
44733322Sdonn /* fprintf(stderr, "[async i/o found set -- reset]\n"); */
44833322Sdonn t->fcflags &= ~FASYNC;
44933322Sdonn }
45033322Sdonn # endif
45111868Slinton }
45211868Slinton
restoretty(f,t)45311868Slinton public restoretty(f, t)
45411868Slinton File f;
45511868Slinton Ttyinfo *t;
45611868Slinton {
45733322Sdonn # ifdef IRIS
45833322Sdonn ioctl(fileno(f), TCSETA, t);
45933322Sdonn # else
46033322Sdonn ioctl(fileno(f), TIOCSETN, &(t->sg));
46133322Sdonn ioctl(fileno(f), TIOCSETC, &(t->tc));
46233322Sdonn ioctl(fileno(f), TIOCSLTC, &(t->ltc));
46333322Sdonn ioctl(fileno(f), TIOCSETD, &(t->ldisc));
46433322Sdonn ioctl(fileno(f), TIOCLSET, &(t->local));
46533322Sdonn if ((t->fcflags&FASYNC) != 0) {
46633322Sdonn /* fprintf(stderr, "[async i/o not set]\n"); */
46733322Sdonn t->fcflags &= ~FASYNC;
46833322Sdonn }
46933322Sdonn (void) fcntl(fileno(f), F_SETFL, t->fcflags);
47033322Sdonn # endif
47111868Slinton }
47211868Slinton
47311868Slinton /*
4749669Slinton * Exit gracefully.
4759669Slinton */
4769669Slinton
quit(r)4779669Slinton public quit(r)
4789669Slinton Integer r;
4799669Slinton {
48016613Ssam pterm(process);
4819669Slinton exit(r);
4829669Slinton }
483