121609Sdist /* 221609Sdist * Copyright (c) 1983 Regents of the University of California. 321609Sdist * All rights reserved. The Berkeley software License Agreement 421609Sdist * specifies the terms and conditions for redistribution. 521609Sdist */ 69669Slinton 721609Sdist #ifndef lint 821609Sdist char copyright[] = 921609Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021609Sdist All rights reserved.\n"; 1121609Sdist #endif not lint 129669Slinton 1321609Sdist #ifndef lint 14*37790Sbostic static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 05/10/89"; 1521609Sdist #endif not lint 1621609Sdist 1733322Sdonn static char rcsid[] = "$Header: main.c,v 1.4 87/07/08 21:31:27 donn Exp $"; 1818223Slinton 199669Slinton /* 209669Slinton * Debugger main routine. 219669Slinton */ 229669Slinton 239669Slinton #include "defs.h" 249669Slinton #include <setjmp.h> 259669Slinton #include <signal.h> 269669Slinton #include <errno.h> 279669Slinton #include "main.h" 2833322Sdonn #include "tree.h" 2918223Slinton #include "eval.h" 3018223Slinton #include "debug.h" 3112483Slinton #include "symbols.h" 329669Slinton #include "scanner.h" 3318223Slinton #include "keywords.h" 349669Slinton #include "process.h" 3516613Ssam #include "runtime.h" 369669Slinton #include "source.h" 379669Slinton #include "object.h" 3812483Slinton #include "mappings.h" 3918223Slinton #include "coredump.h" 40*37790Sbostic #include "pathnames.h" 419669Slinton 429669Slinton #ifndef public 439669Slinton 449669Slinton #define isterm(file) (interactive or isatty(fileno(file))) 459669Slinton 4633322Sdonn #ifdef IRIS 4733322Sdonn # include <termio.h> 4811868Slinton 4933322Sdonn typedef struct termio Ttyinfo; 5033322Sdonn #else 5133322Sdonn # include <sgtty.h> 5233322Sdonn # include <fcntl.h> 5311868Slinton 5433322Sdonn typedef struct { 5533322Sdonn struct sgttyb sg; /* standard sgttyb structure */ 5633322Sdonn struct tchars tc; /* terminal characters */ 5733322Sdonn struct ltchars ltc; /* local special characters */ 5833322Sdonn integer ldisc; /* line discipline */ 5933322Sdonn integer local; /* TIOCLGET */ 6033322Sdonn integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */ 6133322Sdonn } Ttyinfo; 629669Slinton #endif 639669Slinton 6433322Sdonn #endif 6533322Sdonn 6618223Slinton public boolean coredump; /* true if using a core dump */ 6718223Slinton public boolean runfirst; /* run program immediately */ 6818223Slinton public boolean interactive; /* standard input IS a terminal */ 6918223Slinton public boolean lexdebug; /* trace scanner return values */ 7018223Slinton public boolean tracebpts; /* trace create/delete breakpoints */ 7118223Slinton public boolean traceexec; /* trace execution */ 7218223Slinton public boolean tracesyms; /* print symbols are they are read */ 7318223Slinton public boolean traceblocks; /* trace blocks while reading symbols */ 7418223Slinton public boolean vaddrs; /* map addresses through page tables */ 7533322Sdonn public boolean quiet; /* don't print heading */ 7633322Sdonn public boolean autostrip; /* strip C++ prefixes */ 779669Slinton 789669Slinton public File corefile; /* File id of core dump */ 799669Slinton 8033322Sdonn public integer versionNumber = 4; 8133322Sdonn 829669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */ 839669Slinton 849669Slinton private Boolean initdone = false; /* true if initialization done */ 859669Slinton private jmp_buf env; /* setjmp/longjmp data */ 8618223Slinton private char outbuf[BUFSIZ]; /* standard output buffer */ 879669Slinton private char namebuf[512]; /* possible name of object file */ 889669Slinton 8911868Slinton private Ttyinfo ttyinfo; 9018223Slinton private String corename; /* name of core file */ 9111868Slinton 929669Slinton private catchintr(); 9333322Sdonn private char **scanargs(); 949669Slinton 959669Slinton /* 969669Slinton * Main program. 979669Slinton */ 989669Slinton 999669Slinton main(argc, argv) 1009669Slinton int argc; 1019669Slinton String argv[]; 1029669Slinton { 10316613Ssam extern integer versionNumber; 10431002Sbostic char **scanargs(); 1059669Slinton 10631002Sbostic if (!(cmdname = rindex(*argv, '/'))) 10731002Sbostic cmdname = *argv; 10831002Sbostic else 10931002Sbostic ++cmdname; 11031002Sbostic 1119669Slinton catcherrs(); 1129669Slinton onsyserr(EINTR, nil); 11333322Sdonn onsyserr(EADDRINUSE, nil); 11433322Sdonn onsyserr(ENXIO, nil); 11518223Slinton setbuf(stdout, outbuf); 11631002Sbostic argv = scanargs(argc, argv); 11733322Sdonn if (not runfirst and not quiet) { 11833322Sdonn printheading(); 11933322Sdonn } 12033322Sdonn openfiles(); 1219669Slinton language_init(); 12218223Slinton symbols_init(); 1239669Slinton process_init(); 12426328Ssam optab_init(); 1259669Slinton if (runfirst) { 1269669Slinton if (setjmp(env) == FIRST_TIME) { 1279669Slinton arginit(); 12831002Sbostic while (*argv) 12931002Sbostic newarg(*argv++); 1309669Slinton run(); 1319669Slinton /* NOTREACHED */ 1329669Slinton } else { 1339669Slinton runfirst = false; 1349669Slinton } 1359669Slinton } else { 1369669Slinton init(); 1379669Slinton } 13816613Ssam if (setjmp(env) != FIRST_TIME) { 13916613Ssam restoretty(stdout, &ttyinfo); 14016613Ssam } 1419669Slinton signal(SIGINT, catchintr); 1429669Slinton yyparse(); 1439669Slinton putchar('\n'); 1449669Slinton quit(0); 1459669Slinton } 1469669Slinton 14733322Sdonn public printheading () 14833322Sdonn { 14933322Sdonn extern String date; 15033322Sdonn 15133322Sdonn printf("dbx version 3.%d of %s.\nType 'help' for help.\n", 15233322Sdonn versionNumber, date 15333322Sdonn ); 15433322Sdonn fflush(stdout); 15533322Sdonn } 15633322Sdonn 1579669Slinton /* 1589669Slinton * Initialize the world, including setting initial input file 1599669Slinton * if the file exists. 1609669Slinton */ 1619669Slinton 1629669Slinton public init() 1639669Slinton { 1649669Slinton File f; 1659669Slinton String home; 1669669Slinton char buf[100]; 1679669Slinton extern String getenv(); 1689669Slinton 16911868Slinton savetty(stdout, &ttyinfo); 1709669Slinton enterkeywords(); 1719669Slinton scanner_init(); 1729669Slinton if (not coredump and not runfirst) { 1739669Slinton start(nil, nil, nil); 1749669Slinton } 17511868Slinton printf("reading symbolic information ..."); 17611868Slinton fflush(stdout); 1779669Slinton readobj(objname); 17811868Slinton printf("\n"); 17911868Slinton fflush(stdout); 18012483Slinton if (coredump) { 18118223Slinton printf("[using memory image in %s]\n", corename); 18218223Slinton if (vaddrs) { 18318223Slinton coredump_getkerinfo(); 18418223Slinton } 18533322Sdonn getsrcpos(); 18616613Ssam setcurfunc(whatblock(pc)); 18712483Slinton } else { 18816613Ssam setcurfunc(program); 18912483Slinton } 1909669Slinton bpinit(); 1919669Slinton f = fopen(initfile, "r"); 1929669Slinton if (f != nil) { 1939669Slinton fclose(f); 1949669Slinton setinput(initfile); 1959669Slinton } else { 1969669Slinton home = getenv("HOME"); 1979669Slinton if (home != nil) { 1989669Slinton sprintf(buf, "%s/%s", home, initfile); 1999669Slinton f = fopen(buf, "r"); 2009669Slinton if (f != nil) { 2019669Slinton fclose(f); 2029669Slinton setinput(strdup(buf)); 2039669Slinton } 2049669Slinton } 2059669Slinton } 2069669Slinton initdone = true; 2079669Slinton } 2089669Slinton 2099669Slinton /* 2109669Slinton * Re-initialize the world, first de-allocating all storage. 2119669Slinton * This is necessary when the symbol information must be re-read 2129669Slinton * from the object file when it has changed. 2139669Slinton * 2149669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 2159669Slinton * information to a temp file. Then after re-creating the world, 2169669Slinton * we read the temp file as commands. This isn't always the right thing; 2179669Slinton * if a procedure that was being traced is deleted, an error message 2189669Slinton * will be generated. 2199669Slinton * 2209669Slinton * If the argument vector is not nil, then this is re-initialize is being 2219669Slinton * done in preparation for running the program. Since we want to process 2229669Slinton * the commands in the temp file before running the program, we add the 2239669Slinton * run command at the end of the temp file. In this case, reinit longjmps 2249669Slinton * back to parsing rather than returning. 2259669Slinton */ 2269669Slinton 2279669Slinton public reinit(argv, infile, outfile) 2289669Slinton String *argv; 2299669Slinton String infile; 2309669Slinton String outfile; 2319669Slinton { 2329669Slinton register Integer i; 2339669Slinton String tmpfile; 2349669Slinton extern String mktemp(); 2359669Slinton 236*37790Sbostic tmpfile = mktemp(_PATH_TMP); 2379669Slinton setout(tmpfile); 2389669Slinton status(); 23918223Slinton alias(nil, nil, nil); 2409669Slinton if (argv != nil) { 2419669Slinton printf("run"); 2429669Slinton for (i = 1; argv[i] != nil; i++) { 2439669Slinton printf(" %s", argv[i]); 2449669Slinton } 2459669Slinton if (infile != nil) { 2469669Slinton printf(" < %s", infile); 2479669Slinton } 2489669Slinton if (outfile != nil) { 2499669Slinton printf(" > %s", outfile); 2509669Slinton } 2519669Slinton putchar('\n'); 2529669Slinton } 2539669Slinton unsetout(); 2549669Slinton bpfree(); 2559669Slinton objfree(); 25618223Slinton symbols_init(); 2579669Slinton process_init(); 2589669Slinton enterkeywords(); 2599669Slinton scanner_init(); 2609669Slinton readobj(objname); 2619669Slinton bpinit(); 2629669Slinton fflush(stdout); 2639669Slinton setinput(tmpfile); 2649669Slinton unlink(tmpfile); 2659669Slinton if (argv != nil) { 2669669Slinton longjmp(env, 1); 2679669Slinton /* NOTREACHED */ 2689669Slinton } 2699669Slinton } 2709669Slinton 2719669Slinton /* 27218223Slinton * After a non-fatal error we skip the rest of the current input line, and 27318223Slinton * jump back to command parsing. 2749669Slinton */ 2759669Slinton 2769669Slinton public erecover() 2779669Slinton { 2789669Slinton if (initdone) { 2799669Slinton gobble(); 2809669Slinton longjmp(env, 1); 2819669Slinton } 2829669Slinton } 2839669Slinton 2849669Slinton /* 2859669Slinton * This routine is called when an interrupt occurs. 2869669Slinton */ 2879669Slinton 2889669Slinton private catchintr() 2899669Slinton { 29018223Slinton if (isredirected()) { 29118223Slinton fflush(stdout); 29218223Slinton unsetout(); 29318223Slinton } 2949669Slinton putchar('\n'); 2959669Slinton longjmp(env, 1); 2969669Slinton } 2979669Slinton 2989669Slinton /* 2999669Slinton * Scan the argument list. 3009669Slinton */ 3019669Slinton 30233322Sdonn private char **scanargs (argc, argv) 3039669Slinton int argc; 3049669Slinton String argv[]; 3059669Slinton { 30631002Sbostic extern char *optarg; 30733322Sdonn extern integer optind; 30833322Sdonn integer ch; 3099669Slinton 3109669Slinton runfirst = false; 3119669Slinton interactive = false; 3129669Slinton lexdebug = false; 3139669Slinton tracebpts = false; 3149669Slinton traceexec = false; 3159669Slinton tracesyms = false; 31616613Ssam traceblocks = false; 31718223Slinton vaddrs = false; 31833322Sdonn quiet = false; 31933322Sdonn autostrip = true; 3209669Slinton corefile = nil; 3219669Slinton coredump = true; 3229669Slinton sourcepath = list_alloc(); 3239669Slinton list_append(list_item("."), nil, sourcepath); 32431002Sbostic 32533322Sdonn while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF) 32631002Sbostic switch((char)ch) { 32731002Sbostic case 'I': 32831002Sbostic list_append(list_item(optarg), nil, sourcepath); 32931002Sbostic break; 33033322Sdonn case 'a': 33133322Sdonn autostrip = false; 33233322Sdonn break; 33331002Sbostic case 'b': 33431002Sbostic tracebpts = true; 33531002Sbostic break; 33631002Sbostic case 'c': 33731002Sbostic initfile = optarg; 33831002Sbostic break; 33931002Sbostic case 'e': 34031002Sbostic traceexec = true; 34131002Sbostic break; 34231002Sbostic case 'i': 34331002Sbostic interactive = true; 34431002Sbostic break; 34531002Sbostic case 'k': 34631002Sbostic vaddrs = true; 34731002Sbostic break; 34831002Sbostic case 'l': 34931002Sbostic #ifdef LEXDEBUG 35031002Sbostic lexdebug = true; 35131002Sbostic #else 35231002Sbostic fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 35331002Sbostic #endif 35431002Sbostic break; 35531002Sbostic case 'n': 35631002Sbostic traceblocks = true; 35731002Sbostic break; 35833322Sdonn case 'q': 35933322Sdonn quiet = true; 36033322Sdonn break; 36131002Sbostic case 'r': /* run program before accepting commands */ 36231002Sbostic runfirst = true; 3639669Slinton coredump = false; 36431002Sbostic break; 36531002Sbostic case 's': 36631002Sbostic tracesyms = true; 36731002Sbostic break; 36831002Sbostic case '?': 36931002Sbostic default: 37031002Sbostic fatal("unknown option"); 37131002Sbostic } 37231002Sbostic argv += optind; 37331002Sbostic if (*argv) { 37431002Sbostic objname = *argv; 37531002Sbostic if (*++argv && coredump) { 37631002Sbostic corename = *argv; 37731002Sbostic corefile = fopen(*argv, "r"); 37831002Sbostic if (corefile == nil) 37931002Sbostic coredump = false; 38031002Sbostic ++argv; 3819669Slinton } 3829669Slinton } 38333322Sdonn if (*argv and not runfirst) { 38431002Sbostic fatal("extraneous argument %s", *argv); 38533322Sdonn } 38633322Sdonn return argv; 38733322Sdonn } 38833322Sdonn 38933322Sdonn private openfiles () 39033322Sdonn { 39133322Sdonn File f; 39233322Sdonn char *tmp; 39333322Sdonn 39433322Sdonn if (objname == nil and isatty(0)) { 3959669Slinton printf("enter object file name (default is `%s'): ", objname); 3969669Slinton fflush(stdout); 3979669Slinton gets(namebuf); 3989669Slinton if (namebuf[0] != '\0') { 3999669Slinton objname = namebuf; 4009669Slinton } 4019669Slinton } 4029669Slinton f = fopen(objname, "r"); 4039669Slinton if (f == nil) { 4049669Slinton fatal("can't read %s", objname); 4059669Slinton } else { 4069669Slinton fclose(f); 4079669Slinton } 4089669Slinton if (rindex(objname, '/') != nil) { 4099669Slinton tmp = strdup(objname); 4109669Slinton *(rindex(tmp, '/')) = '\0'; 4119669Slinton list_append(list_item(tmp), nil, sourcepath); 4129669Slinton } 4139669Slinton if (coredump and corefile == nil) { 41418223Slinton if (vaddrs) { 415*37790Sbostic corename = _PATH_MEM; 41631002Sbostic corefile = fopen(corename, "r"); 41718223Slinton if (corefile == nil) { 418*37790Sbostic panic("can't open %s", _PATH_MEM); 41918223Slinton } 42018223Slinton } else { 42118223Slinton corename = "core"; 42231002Sbostic corefile = fopen(corename, "r"); 42318223Slinton if (corefile == nil) { 42418223Slinton coredump = false; 42518223Slinton } 4269669Slinton } 4279669Slinton } 4289669Slinton } 4299669Slinton 4309669Slinton /* 43111868Slinton * Save/restore the state of a tty. 43211868Slinton */ 43311868Slinton 43411868Slinton public savetty(f, t) 43511868Slinton File f; 43611868Slinton Ttyinfo *t; 43711868Slinton { 43833322Sdonn # ifdef IRIS 43933322Sdonn ioctl(fileno(f), TCGETA, t); 44033322Sdonn # else 44133322Sdonn ioctl(fileno(f), TIOCGETP, &(t->sg)); 44233322Sdonn ioctl(fileno(f), TIOCGETC, &(t->tc)); 44333322Sdonn ioctl(fileno(f), TIOCGLTC, &(t->ltc)); 44433322Sdonn ioctl(fileno(f), TIOCGETD, &(t->ldisc)); 44533322Sdonn ioctl(fileno(f), TIOCLGET, &(t->local)); 44633322Sdonn t->fcflags = fcntl(fileno(f), F_GETFL, 0); 44733322Sdonn if ((t->fcflags&FASYNC) != 0) { 44833322Sdonn /* fprintf(stderr, "[async i/o found set -- reset]\n"); */ 44933322Sdonn t->fcflags &= ~FASYNC; 45033322Sdonn } 45133322Sdonn # endif 45211868Slinton } 45311868Slinton 45411868Slinton public restoretty(f, t) 45511868Slinton File f; 45611868Slinton Ttyinfo *t; 45711868Slinton { 45833322Sdonn # ifdef IRIS 45933322Sdonn ioctl(fileno(f), TCSETA, t); 46033322Sdonn # else 46133322Sdonn ioctl(fileno(f), TIOCSETN, &(t->sg)); 46233322Sdonn ioctl(fileno(f), TIOCSETC, &(t->tc)); 46333322Sdonn ioctl(fileno(f), TIOCSLTC, &(t->ltc)); 46433322Sdonn ioctl(fileno(f), TIOCSETD, &(t->ldisc)); 46533322Sdonn ioctl(fileno(f), TIOCLSET, &(t->local)); 46633322Sdonn if ((t->fcflags&FASYNC) != 0) { 46733322Sdonn /* fprintf(stderr, "[async i/o not set]\n"); */ 46833322Sdonn t->fcflags &= ~FASYNC; 46933322Sdonn } 47033322Sdonn (void) fcntl(fileno(f), F_SETFL, t->fcflags); 47133322Sdonn # endif 47211868Slinton } 47311868Slinton 47411868Slinton /* 4759669Slinton * Exit gracefully. 4769669Slinton */ 4779669Slinton 4789669Slinton public quit(r) 4799669Slinton Integer r; 4809669Slinton { 48116613Ssam pterm(process); 4829669Slinton exit(r); 4839669Slinton } 484