19669Slinton /* Copyright (c) 1982 Regents of the University of California */ 29669Slinton 3*18223Slinton static char sccsid[] = "@(#)main.c 1.11 (Berkeley) 03/01/85"; 49669Slinton 5*18223Slinton static char rcsid[] = "$Header: main.c,v 1.5 84/12/26 10:40:16 linton Exp $"; 6*18223Slinton 79669Slinton /* 89669Slinton * Debugger main routine. 99669Slinton */ 109669Slinton 119669Slinton #include "defs.h" 129669Slinton #include <setjmp.h> 139669Slinton #include <signal.h> 149669Slinton #include <errno.h> 159669Slinton #include "main.h" 16*18223Slinton #include "eval.h" 17*18223Slinton #include "debug.h" 1812483Slinton #include "symbols.h" 199669Slinton #include "scanner.h" 20*18223Slinton #include "keywords.h" 219669Slinton #include "process.h" 2216613Ssam #include "runtime.h" 239669Slinton #include "source.h" 249669Slinton #include "object.h" 2512483Slinton #include "mappings.h" 26*18223Slinton #include "coredump.h" 279669Slinton 289669Slinton #ifndef public 299669Slinton 309669Slinton #define isterm(file) (interactive or isatty(fileno(file))) 319669Slinton 3211868Slinton #include <sgtty.h> 3317530Sralph #include <fcntl.h> 3411868Slinton 3517530Sralph typedef struct { 36*18223Slinton struct sgttyb sg; /* standard sgttyb structure */ 37*18223Slinton struct tchars tc; /* terminal characters */ 38*18223Slinton struct ltchars ltc; /* local special characters */ 39*18223Slinton integer ldisc; /* line discipline */ 40*18223Slinton integer local; /* TIOCLGET */ 41*18223Slinton integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */ 4217530Sralph } Ttyinfo; 4311868Slinton 449669Slinton #endif 459669Slinton 46*18223Slinton public boolean coredump; /* true if using a core dump */ 47*18223Slinton public boolean runfirst; /* run program immediately */ 48*18223Slinton public boolean interactive; /* standard input IS a terminal */ 49*18223Slinton public boolean lexdebug; /* trace scanner return values */ 50*18223Slinton public boolean tracebpts; /* trace create/delete breakpoints */ 51*18223Slinton public boolean traceexec; /* trace execution */ 52*18223Slinton public boolean tracesyms; /* print symbols are they are read */ 53*18223Slinton public boolean traceblocks; /* trace blocks while reading symbols */ 54*18223Slinton public boolean vaddrs; /* map addresses through page tables */ 559669Slinton 569669Slinton public File corefile; /* File id of core dump */ 579669Slinton 589669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */ 599669Slinton 609669Slinton private Boolean initdone = false; /* true if initialization done */ 619669Slinton private jmp_buf env; /* setjmp/longjmp data */ 62*18223Slinton private char outbuf[BUFSIZ]; /* standard output buffer */ 639669Slinton private char namebuf[512]; /* possible name of object file */ 649669Slinton private int firstarg; /* first program argument (for -r) */ 659669Slinton 6611868Slinton private Ttyinfo ttyinfo; 67*18223Slinton private String corename; /* name of core file */ 6811868Slinton 699669Slinton private catchintr(); 709669Slinton 719669Slinton /* 729669Slinton * Main program. 739669Slinton */ 749669Slinton 759669Slinton main(argc, argv) 769669Slinton int argc; 779669Slinton String argv[]; 789669Slinton { 7916613Ssam register integer i; 8011868Slinton extern String date; 8116613Ssam extern integer versionNumber; 829669Slinton 839669Slinton cmdname = argv[0]; 849669Slinton catcherrs(); 859669Slinton onsyserr(EINTR, nil); 86*18223Slinton setbuf(stdout, outbuf); 87*18223Slinton printf("dbx version 3.%d of %s.\nType 'help' for help.\n", 8816613Ssam versionNumber, date); 8911868Slinton fflush(stdout); 909669Slinton scanargs(argc, argv); 919669Slinton language_init(); 92*18223Slinton symbols_init(); 939669Slinton process_init(); 949669Slinton if (runfirst) { 959669Slinton if (setjmp(env) == FIRST_TIME) { 969669Slinton arginit(); 979669Slinton for (i = firstarg; i < argc; i++) { 989669Slinton newarg(argv[i]); 999669Slinton } 1009669Slinton run(); 1019669Slinton /* NOTREACHED */ 1029669Slinton } else { 1039669Slinton runfirst = false; 1049669Slinton } 1059669Slinton } else { 1069669Slinton init(); 1079669Slinton } 10816613Ssam if (setjmp(env) != FIRST_TIME) { 10916613Ssam restoretty(stdout, &ttyinfo); 11016613Ssam } 1119669Slinton signal(SIGINT, catchintr); 1129669Slinton yyparse(); 1139669Slinton putchar('\n'); 1149669Slinton quit(0); 1159669Slinton } 1169669Slinton 1179669Slinton /* 1189669Slinton * Initialize the world, including setting initial input file 1199669Slinton * if the file exists. 1209669Slinton */ 1219669Slinton 1229669Slinton public init() 1239669Slinton { 1249669Slinton File f; 1259669Slinton String home; 1269669Slinton char buf[100]; 1279669Slinton extern String getenv(); 1289669Slinton 12911868Slinton savetty(stdout, &ttyinfo); 1309669Slinton enterkeywords(); 1319669Slinton scanner_init(); 1329669Slinton if (not coredump and not runfirst) { 1339669Slinton start(nil, nil, nil); 1349669Slinton } 13511868Slinton printf("reading symbolic information ..."); 13611868Slinton fflush(stdout); 1379669Slinton readobj(objname); 13811868Slinton printf("\n"); 13911868Slinton fflush(stdout); 14012483Slinton if (coredump) { 141*18223Slinton printf("[using memory image in %s]\n", corename); 142*18223Slinton if (vaddrs) { 143*18223Slinton coredump_getkerinfo(); 144*18223Slinton } 14516613Ssam setcurfunc(whatblock(pc)); 14612483Slinton } else { 14716613Ssam setcurfunc(program); 14812483Slinton } 1499669Slinton bpinit(); 1509669Slinton f = fopen(initfile, "r"); 1519669Slinton if (f != nil) { 1529669Slinton fclose(f); 1539669Slinton setinput(initfile); 1549669Slinton } else { 1559669Slinton home = getenv("HOME"); 1569669Slinton if (home != nil) { 1579669Slinton sprintf(buf, "%s/%s", home, initfile); 1589669Slinton f = fopen(buf, "r"); 1599669Slinton if (f != nil) { 1609669Slinton fclose(f); 1619669Slinton setinput(strdup(buf)); 1629669Slinton } 1639669Slinton } 1649669Slinton } 1659669Slinton initdone = true; 1669669Slinton } 1679669Slinton 1689669Slinton /* 1699669Slinton * Re-initialize the world, first de-allocating all storage. 1709669Slinton * This is necessary when the symbol information must be re-read 1719669Slinton * from the object file when it has changed. 1729669Slinton * 1739669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1749669Slinton * information to a temp file. Then after re-creating the world, 1759669Slinton * we read the temp file as commands. This isn't always the right thing; 1769669Slinton * if a procedure that was being traced is deleted, an error message 1779669Slinton * will be generated. 1789669Slinton * 1799669Slinton * If the argument vector is not nil, then this is re-initialize is being 1809669Slinton * done in preparation for running the program. Since we want to process 1819669Slinton * the commands in the temp file before running the program, we add the 1829669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1839669Slinton * back to parsing rather than returning. 1849669Slinton */ 1859669Slinton 1869669Slinton public reinit(argv, infile, outfile) 1879669Slinton String *argv; 1889669Slinton String infile; 1899669Slinton String outfile; 1909669Slinton { 1919669Slinton register Integer i; 1929669Slinton String tmpfile; 1939669Slinton extern String mktemp(); 1949669Slinton 1959669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 1969669Slinton setout(tmpfile); 1979669Slinton status(); 198*18223Slinton alias(nil, nil, nil); 1999669Slinton if (argv != nil) { 2009669Slinton printf("run"); 2019669Slinton for (i = 1; argv[i] != nil; i++) { 2029669Slinton printf(" %s", argv[i]); 2039669Slinton } 2049669Slinton if (infile != nil) { 2059669Slinton printf(" < %s", infile); 2069669Slinton } 2079669Slinton if (outfile != nil) { 2089669Slinton printf(" > %s", outfile); 2099669Slinton } 2109669Slinton putchar('\n'); 2119669Slinton } 2129669Slinton unsetout(); 2139669Slinton bpfree(); 2149669Slinton objfree(); 215*18223Slinton symbols_init(); 2169669Slinton process_init(); 2179669Slinton enterkeywords(); 2189669Slinton scanner_init(); 2199669Slinton readobj(objname); 2209669Slinton bpinit(); 2219669Slinton fflush(stdout); 2229669Slinton setinput(tmpfile); 2239669Slinton unlink(tmpfile); 2249669Slinton if (argv != nil) { 2259669Slinton longjmp(env, 1); 2269669Slinton /* NOTREACHED */ 2279669Slinton } 2289669Slinton } 2299669Slinton 2309669Slinton /* 231*18223Slinton * After a non-fatal error we skip the rest of the current input line, and 232*18223Slinton * jump back to command parsing. 2339669Slinton */ 2349669Slinton 2359669Slinton public erecover() 2369669Slinton { 2379669Slinton if (initdone) { 2389669Slinton gobble(); 2399669Slinton longjmp(env, 1); 2409669Slinton } 2419669Slinton } 2429669Slinton 2439669Slinton /* 2449669Slinton * This routine is called when an interrupt occurs. 2459669Slinton */ 2469669Slinton 2479669Slinton private catchintr() 2489669Slinton { 249*18223Slinton if (isredirected()) { 250*18223Slinton fflush(stdout); 251*18223Slinton unsetout(); 252*18223Slinton } 2539669Slinton putchar('\n'); 2549669Slinton longjmp(env, 1); 2559669Slinton } 2569669Slinton 2579669Slinton /* 2589669Slinton * Scan the argument list. 2599669Slinton */ 2609669Slinton 2619669Slinton private scanargs(argc, argv) 2629669Slinton int argc; 2639669Slinton String argv[]; 2649669Slinton { 2659669Slinton register int i, j; 2669669Slinton register Boolean foundfile; 2679669Slinton register File f; 2689669Slinton char *tmp; 2699669Slinton 2709669Slinton runfirst = false; 2719669Slinton interactive = false; 2729669Slinton lexdebug = false; 2739669Slinton tracebpts = false; 2749669Slinton traceexec = false; 2759669Slinton tracesyms = false; 27616613Ssam traceblocks = false; 277*18223Slinton vaddrs = false; 2789669Slinton foundfile = false; 2799669Slinton corefile = nil; 2809669Slinton coredump = true; 2819669Slinton sourcepath = list_alloc(); 2829669Slinton list_append(list_item("."), nil, sourcepath); 2839669Slinton i = 1; 284*18223Slinton while (i < argc and (not foundfile or (coredump and corefile == nil))) { 2859669Slinton if (argv[i][0] == '-') { 2869669Slinton if (streq(argv[i], "-I")) { 2879669Slinton ++i; 2889669Slinton if (i >= argc) { 2899669Slinton fatal("missing directory for -I"); 2909669Slinton } 2919669Slinton list_append(list_item(argv[i]), nil, sourcepath); 292*18223Slinton } else if (streq(argv[i], "-c")) { 293*18223Slinton ++i; 294*18223Slinton if (i >= argc) { 295*18223Slinton fatal("missing command file name for -c"); 296*18223Slinton } 297*18223Slinton initfile = argv[i]; 2989669Slinton } else { 2999669Slinton for (j = 1; argv[i][j] != '\0'; j++) { 3009669Slinton setoption(argv[i][j]); 3019669Slinton } 3029669Slinton } 3039669Slinton } else if (not foundfile) { 3049669Slinton objname = argv[i]; 3059669Slinton foundfile = true; 3069669Slinton } else if (coredump and corefile == nil) { 3079669Slinton corefile = fopen(argv[i], "r"); 308*18223Slinton corename = argv[i]; 3099669Slinton if (corefile == nil) { 3109669Slinton coredump = false; 3119669Slinton } 3129669Slinton } 3139669Slinton ++i; 3149669Slinton } 3159669Slinton if (i < argc and not runfirst) { 3169669Slinton fatal("extraneous argument %s", argv[i]); 3179669Slinton } 3189669Slinton firstarg = i; 3199669Slinton if (not foundfile and isatty(0)) { 3209669Slinton printf("enter object file name (default is `%s'): ", objname); 3219669Slinton fflush(stdout); 3229669Slinton gets(namebuf); 3239669Slinton if (namebuf[0] != '\0') { 3249669Slinton objname = namebuf; 3259669Slinton } 3269669Slinton } 3279669Slinton f = fopen(objname, "r"); 3289669Slinton if (f == nil) { 3299669Slinton fatal("can't read %s", objname); 3309669Slinton } else { 3319669Slinton fclose(f); 3329669Slinton } 3339669Slinton if (rindex(objname, '/') != nil) { 3349669Slinton tmp = strdup(objname); 3359669Slinton *(rindex(tmp, '/')) = '\0'; 3369669Slinton list_append(list_item(tmp), nil, sourcepath); 3379669Slinton } 3389669Slinton if (coredump and corefile == nil) { 339*18223Slinton if (vaddrs) { 340*18223Slinton corefile = fopen("/dev/mem", "r"); 341*18223Slinton corename = "/dev/mem"; 342*18223Slinton if (corefile == nil) { 343*18223Slinton panic("can't open /dev/mem"); 344*18223Slinton } 345*18223Slinton } else { 346*18223Slinton corefile = fopen("core", "r"); 347*18223Slinton corename = "core"; 348*18223Slinton if (corefile == nil) { 349*18223Slinton coredump = false; 350*18223Slinton } 3519669Slinton } 3529669Slinton } 3539669Slinton } 3549669Slinton 3559669Slinton /* 3569669Slinton * Take appropriate action for recognized command argument. 3579669Slinton */ 3589669Slinton 3599669Slinton private setoption(c) 3609669Slinton char c; 3619669Slinton { 3629669Slinton switch (c) { 3639669Slinton case 'r': /* run program before accepting commands */ 3649669Slinton runfirst = true; 3659669Slinton coredump = false; 3669669Slinton break; 3679669Slinton 3689669Slinton case 'i': 3699669Slinton interactive = true; 3709669Slinton break; 3719669Slinton 3729669Slinton case 'b': 3739669Slinton tracebpts = true; 3749669Slinton break; 3759669Slinton 3769669Slinton case 'e': 3779669Slinton traceexec = true; 3789669Slinton break; 3799669Slinton 3809669Slinton case 's': 3819669Slinton tracesyms = true; 3829669Slinton break; 3839669Slinton 38416613Ssam case 'n': 38516613Ssam traceblocks = true; 38616613Ssam break; 38716613Ssam 388*18223Slinton case 'k': 389*18223Slinton vaddrs = true; 390*18223Slinton break; 391*18223Slinton 3929669Slinton case 'l': 393*18223Slinton # ifdef LEXDEBUG 3949669Slinton lexdebug = true; 395*18223Slinton # else 396*18223Slinton fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 397*18223Slinton # endif 3989669Slinton break; 3999669Slinton 4009669Slinton default: 4019669Slinton fatal("unknown option '%c'", c); 4029669Slinton } 4039669Slinton } 4049669Slinton 4059669Slinton /* 40611868Slinton * Save/restore the state of a tty. 40711868Slinton */ 40811868Slinton 40911868Slinton public savetty(f, t) 41011868Slinton File f; 41111868Slinton Ttyinfo *t; 41211868Slinton { 41317530Sralph ioctl(fileno(f), TIOCGETP, &(t->sg)); 41417530Sralph ioctl(fileno(f), TIOCGETC, &(t->tc)); 41517530Sralph ioctl(fileno(f), TIOCGLTC, &(t->ltc)); 41617530Sralph ioctl(fileno(f), TIOCGETD, &(t->ldisc)); 41717530Sralph ioctl(fileno(f), TIOCLGET, &(t->local)); 41817530Sralph t->fcflags = fcntl(fileno(f), F_GETFL, 0); 41911868Slinton } 42011868Slinton 42111868Slinton public restoretty(f, t) 42211868Slinton File f; 42311868Slinton Ttyinfo *t; 42411868Slinton { 42517530Sralph ioctl(fileno(f), TIOCSETN, &(t->sg)); 42617530Sralph ioctl(fileno(f), TIOCSETC, &(t->tc)); 42717530Sralph ioctl(fileno(f), TIOCSLTC, &(t->ltc)); 42817530Sralph ioctl(fileno(f), TIOCSETD, &(t->ldisc)); 42917530Sralph ioctl(fileno(f), TIOCLSET, &(t->local)); 43017530Sralph (void) fcntl(fileno(f), F_SETFL, t->fcflags); 43111868Slinton } 43211868Slinton 43311868Slinton /* 4349669Slinton * Exit gracefully. 4359669Slinton */ 4369669Slinton 4379669Slinton public quit(r) 4389669Slinton Integer r; 4399669Slinton { 44016613Ssam pterm(process); 4419669Slinton exit(r); 4429669Slinton } 443