1*21609Sdist /* 2*21609Sdist * Copyright (c) 1983 Regents of the University of California. 3*21609Sdist * All rights reserved. The Berkeley software License Agreement 4*21609Sdist * specifies the terms and conditions for redistribution. 5*21609Sdist */ 69669Slinton 7*21609Sdist #ifndef lint 8*21609Sdist char copyright[] = 9*21609Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*21609Sdist All rights reserved.\n"; 11*21609Sdist #endif not lint 129669Slinton 13*21609Sdist #ifndef lint 14*21609Sdist static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 05/31/85"; 15*21609Sdist #endif not lint 16*21609Sdist 1718223Slinton static char rcsid[] = "$Header: main.c,v 1.5 84/12/26 10:40:16 linton 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" 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" 399669Slinton 409669Slinton #ifndef public 419669Slinton 429669Slinton #define isterm(file) (interactive or isatty(fileno(file))) 439669Slinton 4411868Slinton #include <sgtty.h> 4517530Sralph #include <fcntl.h> 4611868Slinton 4717530Sralph typedef struct { 4818223Slinton struct sgttyb sg; /* standard sgttyb structure */ 4918223Slinton struct tchars tc; /* terminal characters */ 5018223Slinton struct ltchars ltc; /* local special characters */ 5118223Slinton integer ldisc; /* line discipline */ 5218223Slinton integer local; /* TIOCLGET */ 5318223Slinton integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */ 5417530Sralph } Ttyinfo; 5511868Slinton 569669Slinton #endif 579669Slinton 5818223Slinton public boolean coredump; /* true if using a core dump */ 5918223Slinton public boolean runfirst; /* run program immediately */ 6018223Slinton public boolean interactive; /* standard input IS a terminal */ 6118223Slinton public boolean lexdebug; /* trace scanner return values */ 6218223Slinton public boolean tracebpts; /* trace create/delete breakpoints */ 6318223Slinton public boolean traceexec; /* trace execution */ 6418223Slinton public boolean tracesyms; /* print symbols are they are read */ 6518223Slinton public boolean traceblocks; /* trace blocks while reading symbols */ 6618223Slinton public boolean vaddrs; /* map addresses through page tables */ 679669Slinton 689669Slinton public File corefile; /* File id of core dump */ 699669Slinton 709669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */ 719669Slinton 729669Slinton private Boolean initdone = false; /* true if initialization done */ 739669Slinton private jmp_buf env; /* setjmp/longjmp data */ 7418223Slinton private char outbuf[BUFSIZ]; /* standard output buffer */ 759669Slinton private char namebuf[512]; /* possible name of object file */ 769669Slinton private int firstarg; /* first program argument (for -r) */ 779669Slinton 7811868Slinton private Ttyinfo ttyinfo; 7918223Slinton private String corename; /* name of core file */ 8011868Slinton 819669Slinton private catchintr(); 829669Slinton 839669Slinton /* 849669Slinton * Main program. 859669Slinton */ 869669Slinton 879669Slinton main(argc, argv) 889669Slinton int argc; 899669Slinton String argv[]; 909669Slinton { 9116613Ssam register integer i; 9211868Slinton extern String date; 9316613Ssam extern integer versionNumber; 949669Slinton 959669Slinton cmdname = argv[0]; 969669Slinton catcherrs(); 979669Slinton onsyserr(EINTR, nil); 9818223Slinton setbuf(stdout, outbuf); 9918223Slinton printf("dbx version 3.%d of %s.\nType 'help' for help.\n", 10016613Ssam versionNumber, date); 10111868Slinton fflush(stdout); 1029669Slinton scanargs(argc, argv); 1039669Slinton language_init(); 10418223Slinton symbols_init(); 1059669Slinton process_init(); 1069669Slinton if (runfirst) { 1079669Slinton if (setjmp(env) == FIRST_TIME) { 1089669Slinton arginit(); 1099669Slinton for (i = firstarg; i < argc; i++) { 1109669Slinton newarg(argv[i]); 1119669Slinton } 1129669Slinton run(); 1139669Slinton /* NOTREACHED */ 1149669Slinton } else { 1159669Slinton runfirst = false; 1169669Slinton } 1179669Slinton } else { 1189669Slinton init(); 1199669Slinton } 12016613Ssam if (setjmp(env) != FIRST_TIME) { 12116613Ssam restoretty(stdout, &ttyinfo); 12216613Ssam } 1239669Slinton signal(SIGINT, catchintr); 1249669Slinton yyparse(); 1259669Slinton putchar('\n'); 1269669Slinton quit(0); 1279669Slinton } 1289669Slinton 1299669Slinton /* 1309669Slinton * Initialize the world, including setting initial input file 1319669Slinton * if the file exists. 1329669Slinton */ 1339669Slinton 1349669Slinton public init() 1359669Slinton { 1369669Slinton File f; 1379669Slinton String home; 1389669Slinton char buf[100]; 1399669Slinton extern String getenv(); 1409669Slinton 14111868Slinton savetty(stdout, &ttyinfo); 1429669Slinton enterkeywords(); 1439669Slinton scanner_init(); 1449669Slinton if (not coredump and not runfirst) { 1459669Slinton start(nil, nil, nil); 1469669Slinton } 14711868Slinton printf("reading symbolic information ..."); 14811868Slinton fflush(stdout); 1499669Slinton readobj(objname); 15011868Slinton printf("\n"); 15111868Slinton fflush(stdout); 15212483Slinton if (coredump) { 15318223Slinton printf("[using memory image in %s]\n", corename); 15418223Slinton if (vaddrs) { 15518223Slinton coredump_getkerinfo(); 15618223Slinton } 15716613Ssam setcurfunc(whatblock(pc)); 15812483Slinton } else { 15916613Ssam setcurfunc(program); 16012483Slinton } 1619669Slinton bpinit(); 1629669Slinton f = fopen(initfile, "r"); 1639669Slinton if (f != nil) { 1649669Slinton fclose(f); 1659669Slinton setinput(initfile); 1669669Slinton } else { 1679669Slinton home = getenv("HOME"); 1689669Slinton if (home != nil) { 1699669Slinton sprintf(buf, "%s/%s", home, initfile); 1709669Slinton f = fopen(buf, "r"); 1719669Slinton if (f != nil) { 1729669Slinton fclose(f); 1739669Slinton setinput(strdup(buf)); 1749669Slinton } 1759669Slinton } 1769669Slinton } 1779669Slinton initdone = true; 1789669Slinton } 1799669Slinton 1809669Slinton /* 1819669Slinton * Re-initialize the world, first de-allocating all storage. 1829669Slinton * This is necessary when the symbol information must be re-read 1839669Slinton * from the object file when it has changed. 1849669Slinton * 1859669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1869669Slinton * information to a temp file. Then after re-creating the world, 1879669Slinton * we read the temp file as commands. This isn't always the right thing; 1889669Slinton * if a procedure that was being traced is deleted, an error message 1899669Slinton * will be generated. 1909669Slinton * 1919669Slinton * If the argument vector is not nil, then this is re-initialize is being 1929669Slinton * done in preparation for running the program. Since we want to process 1939669Slinton * the commands in the temp file before running the program, we add the 1949669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1959669Slinton * back to parsing rather than returning. 1969669Slinton */ 1979669Slinton 1989669Slinton public reinit(argv, infile, outfile) 1999669Slinton String *argv; 2009669Slinton String infile; 2019669Slinton String outfile; 2029669Slinton { 2039669Slinton register Integer i; 2049669Slinton String tmpfile; 2059669Slinton extern String mktemp(); 2069669Slinton 2079669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 2089669Slinton setout(tmpfile); 2099669Slinton status(); 21018223Slinton alias(nil, nil, nil); 2119669Slinton if (argv != nil) { 2129669Slinton printf("run"); 2139669Slinton for (i = 1; argv[i] != nil; i++) { 2149669Slinton printf(" %s", argv[i]); 2159669Slinton } 2169669Slinton if (infile != nil) { 2179669Slinton printf(" < %s", infile); 2189669Slinton } 2199669Slinton if (outfile != nil) { 2209669Slinton printf(" > %s", outfile); 2219669Slinton } 2229669Slinton putchar('\n'); 2239669Slinton } 2249669Slinton unsetout(); 2259669Slinton bpfree(); 2269669Slinton objfree(); 22718223Slinton symbols_init(); 2289669Slinton process_init(); 2299669Slinton enterkeywords(); 2309669Slinton scanner_init(); 2319669Slinton readobj(objname); 2329669Slinton bpinit(); 2339669Slinton fflush(stdout); 2349669Slinton setinput(tmpfile); 2359669Slinton unlink(tmpfile); 2369669Slinton if (argv != nil) { 2379669Slinton longjmp(env, 1); 2389669Slinton /* NOTREACHED */ 2399669Slinton } 2409669Slinton } 2419669Slinton 2429669Slinton /* 24318223Slinton * After a non-fatal error we skip the rest of the current input line, and 24418223Slinton * jump back to command parsing. 2459669Slinton */ 2469669Slinton 2479669Slinton public erecover() 2489669Slinton { 2499669Slinton if (initdone) { 2509669Slinton gobble(); 2519669Slinton longjmp(env, 1); 2529669Slinton } 2539669Slinton } 2549669Slinton 2559669Slinton /* 2569669Slinton * This routine is called when an interrupt occurs. 2579669Slinton */ 2589669Slinton 2599669Slinton private catchintr() 2609669Slinton { 26118223Slinton if (isredirected()) { 26218223Slinton fflush(stdout); 26318223Slinton unsetout(); 26418223Slinton } 2659669Slinton putchar('\n'); 2669669Slinton longjmp(env, 1); 2679669Slinton } 2689669Slinton 2699669Slinton /* 2709669Slinton * Scan the argument list. 2719669Slinton */ 2729669Slinton 2739669Slinton private scanargs(argc, argv) 2749669Slinton int argc; 2759669Slinton String argv[]; 2769669Slinton { 2779669Slinton register int i, j; 2789669Slinton register Boolean foundfile; 2799669Slinton register File f; 2809669Slinton char *tmp; 2819669Slinton 2829669Slinton runfirst = false; 2839669Slinton interactive = false; 2849669Slinton lexdebug = false; 2859669Slinton tracebpts = false; 2869669Slinton traceexec = false; 2879669Slinton tracesyms = false; 28816613Ssam traceblocks = false; 28918223Slinton vaddrs = false; 2909669Slinton foundfile = false; 2919669Slinton corefile = nil; 2929669Slinton coredump = true; 2939669Slinton sourcepath = list_alloc(); 2949669Slinton list_append(list_item("."), nil, sourcepath); 2959669Slinton i = 1; 29618223Slinton while (i < argc and (not foundfile or (coredump and corefile == nil))) { 2979669Slinton if (argv[i][0] == '-') { 2989669Slinton if (streq(argv[i], "-I")) { 2999669Slinton ++i; 3009669Slinton if (i >= argc) { 3019669Slinton fatal("missing directory for -I"); 3029669Slinton } 3039669Slinton list_append(list_item(argv[i]), nil, sourcepath); 30418223Slinton } else if (streq(argv[i], "-c")) { 30518223Slinton ++i; 30618223Slinton if (i >= argc) { 30718223Slinton fatal("missing command file name for -c"); 30818223Slinton } 30918223Slinton initfile = argv[i]; 3109669Slinton } else { 3119669Slinton for (j = 1; argv[i][j] != '\0'; j++) { 3129669Slinton setoption(argv[i][j]); 3139669Slinton } 3149669Slinton } 3159669Slinton } else if (not foundfile) { 3169669Slinton objname = argv[i]; 3179669Slinton foundfile = true; 3189669Slinton } else if (coredump and corefile == nil) { 3199669Slinton corefile = fopen(argv[i], "r"); 32018223Slinton corename = argv[i]; 3219669Slinton if (corefile == nil) { 3229669Slinton coredump = false; 3239669Slinton } 3249669Slinton } 3259669Slinton ++i; 3269669Slinton } 3279669Slinton if (i < argc and not runfirst) { 3289669Slinton fatal("extraneous argument %s", argv[i]); 3299669Slinton } 3309669Slinton firstarg = i; 3319669Slinton if (not foundfile and isatty(0)) { 3329669Slinton printf("enter object file name (default is `%s'): ", objname); 3339669Slinton fflush(stdout); 3349669Slinton gets(namebuf); 3359669Slinton if (namebuf[0] != '\0') { 3369669Slinton objname = namebuf; 3379669Slinton } 3389669Slinton } 3399669Slinton f = fopen(objname, "r"); 3409669Slinton if (f == nil) { 3419669Slinton fatal("can't read %s", objname); 3429669Slinton } else { 3439669Slinton fclose(f); 3449669Slinton } 3459669Slinton if (rindex(objname, '/') != nil) { 3469669Slinton tmp = strdup(objname); 3479669Slinton *(rindex(tmp, '/')) = '\0'; 3489669Slinton list_append(list_item(tmp), nil, sourcepath); 3499669Slinton } 3509669Slinton if (coredump and corefile == nil) { 35118223Slinton if (vaddrs) { 35218223Slinton corefile = fopen("/dev/mem", "r"); 35318223Slinton corename = "/dev/mem"; 35418223Slinton if (corefile == nil) { 35518223Slinton panic("can't open /dev/mem"); 35618223Slinton } 35718223Slinton } else { 35818223Slinton corefile = fopen("core", "r"); 35918223Slinton corename = "core"; 36018223Slinton if (corefile == nil) { 36118223Slinton coredump = false; 36218223Slinton } 3639669Slinton } 3649669Slinton } 3659669Slinton } 3669669Slinton 3679669Slinton /* 3689669Slinton * Take appropriate action for recognized command argument. 3699669Slinton */ 3709669Slinton 3719669Slinton private setoption(c) 3729669Slinton char c; 3739669Slinton { 3749669Slinton switch (c) { 3759669Slinton case 'r': /* run program before accepting commands */ 3769669Slinton runfirst = true; 3779669Slinton coredump = false; 3789669Slinton break; 3799669Slinton 3809669Slinton case 'i': 3819669Slinton interactive = true; 3829669Slinton break; 3839669Slinton 3849669Slinton case 'b': 3859669Slinton tracebpts = true; 3869669Slinton break; 3879669Slinton 3889669Slinton case 'e': 3899669Slinton traceexec = true; 3909669Slinton break; 3919669Slinton 3929669Slinton case 's': 3939669Slinton tracesyms = true; 3949669Slinton break; 3959669Slinton 39616613Ssam case 'n': 39716613Ssam traceblocks = true; 39816613Ssam break; 39916613Ssam 40018223Slinton case 'k': 40118223Slinton vaddrs = true; 40218223Slinton break; 40318223Slinton 4049669Slinton case 'l': 40518223Slinton # ifdef LEXDEBUG 4069669Slinton lexdebug = true; 40718223Slinton # else 40818223Slinton fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 40918223Slinton # endif 4109669Slinton break; 4119669Slinton 4129669Slinton default: 4139669Slinton fatal("unknown option '%c'", c); 4149669Slinton } 4159669Slinton } 4169669Slinton 4179669Slinton /* 41811868Slinton * Save/restore the state of a tty. 41911868Slinton */ 42011868Slinton 42111868Slinton public savetty(f, t) 42211868Slinton File f; 42311868Slinton Ttyinfo *t; 42411868Slinton { 42517530Sralph ioctl(fileno(f), TIOCGETP, &(t->sg)); 42617530Sralph ioctl(fileno(f), TIOCGETC, &(t->tc)); 42717530Sralph ioctl(fileno(f), TIOCGLTC, &(t->ltc)); 42817530Sralph ioctl(fileno(f), TIOCGETD, &(t->ldisc)); 42917530Sralph ioctl(fileno(f), TIOCLGET, &(t->local)); 43017530Sralph t->fcflags = fcntl(fileno(f), F_GETFL, 0); 43111868Slinton } 43211868Slinton 43311868Slinton public restoretty(f, t) 43411868Slinton File f; 43511868Slinton Ttyinfo *t; 43611868Slinton { 43717530Sralph ioctl(fileno(f), TIOCSETN, &(t->sg)); 43817530Sralph ioctl(fileno(f), TIOCSETC, &(t->tc)); 43917530Sralph ioctl(fileno(f), TIOCSLTC, &(t->ltc)); 44017530Sralph ioctl(fileno(f), TIOCSETD, &(t->ldisc)); 44117530Sralph ioctl(fileno(f), TIOCLSET, &(t->local)); 44217530Sralph (void) fcntl(fileno(f), F_SETFL, t->fcflags); 44311868Slinton } 44411868Slinton 44511868Slinton /* 4469669Slinton * Exit gracefully. 4479669Slinton */ 4489669Slinton 4499669Slinton public quit(r) 4509669Slinton Integer r; 4519669Slinton { 45216613Ssam pterm(process); 4539669Slinton exit(r); 4549669Slinton } 455