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*26328Ssam static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 02/22/86"; 1521609Sdist #endif not lint 1621609Sdist 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(); 106*26328Ssam optab_init(); 1079669Slinton if (runfirst) { 1089669Slinton if (setjmp(env) == FIRST_TIME) { 1099669Slinton arginit(); 1109669Slinton for (i = firstarg; i < argc; i++) { 1119669Slinton newarg(argv[i]); 1129669Slinton } 1139669Slinton run(); 1149669Slinton /* NOTREACHED */ 1159669Slinton } else { 1169669Slinton runfirst = false; 1179669Slinton } 1189669Slinton } else { 1199669Slinton init(); 1209669Slinton } 12116613Ssam if (setjmp(env) != FIRST_TIME) { 12216613Ssam restoretty(stdout, &ttyinfo); 12316613Ssam } 1249669Slinton signal(SIGINT, catchintr); 1259669Slinton yyparse(); 1269669Slinton putchar('\n'); 1279669Slinton quit(0); 1289669Slinton } 1299669Slinton 1309669Slinton /* 1319669Slinton * Initialize the world, including setting initial input file 1329669Slinton * if the file exists. 1339669Slinton */ 1349669Slinton 1359669Slinton public init() 1369669Slinton { 1379669Slinton File f; 1389669Slinton String home; 1399669Slinton char buf[100]; 1409669Slinton extern String getenv(); 1419669Slinton 14211868Slinton savetty(stdout, &ttyinfo); 1439669Slinton enterkeywords(); 1449669Slinton scanner_init(); 1459669Slinton if (not coredump and not runfirst) { 1469669Slinton start(nil, nil, nil); 1479669Slinton } 14811868Slinton printf("reading symbolic information ..."); 14911868Slinton fflush(stdout); 1509669Slinton readobj(objname); 15111868Slinton printf("\n"); 15211868Slinton fflush(stdout); 15312483Slinton if (coredump) { 15418223Slinton printf("[using memory image in %s]\n", corename); 15518223Slinton if (vaddrs) { 15618223Slinton coredump_getkerinfo(); 15718223Slinton } 15816613Ssam setcurfunc(whatblock(pc)); 15912483Slinton } else { 16016613Ssam setcurfunc(program); 16112483Slinton } 1629669Slinton bpinit(); 1639669Slinton f = fopen(initfile, "r"); 1649669Slinton if (f != nil) { 1659669Slinton fclose(f); 1669669Slinton setinput(initfile); 1679669Slinton } else { 1689669Slinton home = getenv("HOME"); 1699669Slinton if (home != nil) { 1709669Slinton sprintf(buf, "%s/%s", home, initfile); 1719669Slinton f = fopen(buf, "r"); 1729669Slinton if (f != nil) { 1739669Slinton fclose(f); 1749669Slinton setinput(strdup(buf)); 1759669Slinton } 1769669Slinton } 1779669Slinton } 1789669Slinton initdone = true; 1799669Slinton } 1809669Slinton 1819669Slinton /* 1829669Slinton * Re-initialize the world, first de-allocating all storage. 1839669Slinton * This is necessary when the symbol information must be re-read 1849669Slinton * from the object file when it has changed. 1859669Slinton * 1869669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1879669Slinton * information to a temp file. Then after re-creating the world, 1889669Slinton * we read the temp file as commands. This isn't always the right thing; 1899669Slinton * if a procedure that was being traced is deleted, an error message 1909669Slinton * will be generated. 1919669Slinton * 1929669Slinton * If the argument vector is not nil, then this is re-initialize is being 1939669Slinton * done in preparation for running the program. Since we want to process 1949669Slinton * the commands in the temp file before running the program, we add the 1959669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1969669Slinton * back to parsing rather than returning. 1979669Slinton */ 1989669Slinton 1999669Slinton public reinit(argv, infile, outfile) 2009669Slinton String *argv; 2019669Slinton String infile; 2029669Slinton String outfile; 2039669Slinton { 2049669Slinton register Integer i; 2059669Slinton String tmpfile; 2069669Slinton extern String mktemp(); 2079669Slinton 2089669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 2099669Slinton setout(tmpfile); 2109669Slinton status(); 21118223Slinton alias(nil, nil, nil); 2129669Slinton if (argv != nil) { 2139669Slinton printf("run"); 2149669Slinton for (i = 1; argv[i] != nil; i++) { 2159669Slinton printf(" %s", argv[i]); 2169669Slinton } 2179669Slinton if (infile != nil) { 2189669Slinton printf(" < %s", infile); 2199669Slinton } 2209669Slinton if (outfile != nil) { 2219669Slinton printf(" > %s", outfile); 2229669Slinton } 2239669Slinton putchar('\n'); 2249669Slinton } 2259669Slinton unsetout(); 2269669Slinton bpfree(); 2279669Slinton objfree(); 22818223Slinton symbols_init(); 2299669Slinton process_init(); 2309669Slinton enterkeywords(); 2319669Slinton scanner_init(); 2329669Slinton readobj(objname); 2339669Slinton bpinit(); 2349669Slinton fflush(stdout); 2359669Slinton setinput(tmpfile); 2369669Slinton unlink(tmpfile); 2379669Slinton if (argv != nil) { 2389669Slinton longjmp(env, 1); 2399669Slinton /* NOTREACHED */ 2409669Slinton } 2419669Slinton } 2429669Slinton 2439669Slinton /* 24418223Slinton * After a non-fatal error we skip the rest of the current input line, and 24518223Slinton * jump back to command parsing. 2469669Slinton */ 2479669Slinton 2489669Slinton public erecover() 2499669Slinton { 2509669Slinton if (initdone) { 2519669Slinton gobble(); 2529669Slinton longjmp(env, 1); 2539669Slinton } 2549669Slinton } 2559669Slinton 2569669Slinton /* 2579669Slinton * This routine is called when an interrupt occurs. 2589669Slinton */ 2599669Slinton 2609669Slinton private catchintr() 2619669Slinton { 26218223Slinton if (isredirected()) { 26318223Slinton fflush(stdout); 26418223Slinton unsetout(); 26518223Slinton } 2669669Slinton putchar('\n'); 2679669Slinton longjmp(env, 1); 2689669Slinton } 2699669Slinton 2709669Slinton /* 2719669Slinton * Scan the argument list. 2729669Slinton */ 2739669Slinton 2749669Slinton private scanargs(argc, argv) 2759669Slinton int argc; 2769669Slinton String argv[]; 2779669Slinton { 2789669Slinton register int i, j; 2799669Slinton register Boolean foundfile; 2809669Slinton register File f; 2819669Slinton char *tmp; 2829669Slinton 2839669Slinton runfirst = false; 2849669Slinton interactive = false; 2859669Slinton lexdebug = false; 2869669Slinton tracebpts = false; 2879669Slinton traceexec = false; 2889669Slinton tracesyms = false; 28916613Ssam traceblocks = false; 29018223Slinton vaddrs = false; 2919669Slinton foundfile = false; 2929669Slinton corefile = nil; 2939669Slinton coredump = true; 2949669Slinton sourcepath = list_alloc(); 2959669Slinton list_append(list_item("."), nil, sourcepath); 2969669Slinton i = 1; 29718223Slinton while (i < argc and (not foundfile or (coredump and corefile == nil))) { 2989669Slinton if (argv[i][0] == '-') { 2999669Slinton if (streq(argv[i], "-I")) { 3009669Slinton ++i; 3019669Slinton if (i >= argc) { 3029669Slinton fatal("missing directory for -I"); 3039669Slinton } 3049669Slinton list_append(list_item(argv[i]), nil, sourcepath); 30518223Slinton } else if (streq(argv[i], "-c")) { 30618223Slinton ++i; 30718223Slinton if (i >= argc) { 30818223Slinton fatal("missing command file name for -c"); 30918223Slinton } 31018223Slinton initfile = argv[i]; 3119669Slinton } else { 3129669Slinton for (j = 1; argv[i][j] != '\0'; j++) { 3139669Slinton setoption(argv[i][j]); 3149669Slinton } 3159669Slinton } 3169669Slinton } else if (not foundfile) { 3179669Slinton objname = argv[i]; 3189669Slinton foundfile = true; 3199669Slinton } else if (coredump and corefile == nil) { 3209669Slinton corefile = fopen(argv[i], "r"); 32118223Slinton corename = argv[i]; 3229669Slinton if (corefile == nil) { 3239669Slinton coredump = false; 3249669Slinton } 3259669Slinton } 3269669Slinton ++i; 3279669Slinton } 3289669Slinton if (i < argc and not runfirst) { 3299669Slinton fatal("extraneous argument %s", argv[i]); 3309669Slinton } 3319669Slinton firstarg = i; 3329669Slinton if (not foundfile and isatty(0)) { 3339669Slinton printf("enter object file name (default is `%s'): ", objname); 3349669Slinton fflush(stdout); 3359669Slinton gets(namebuf); 3369669Slinton if (namebuf[0] != '\0') { 3379669Slinton objname = namebuf; 3389669Slinton } 3399669Slinton } 3409669Slinton f = fopen(objname, "r"); 3419669Slinton if (f == nil) { 3429669Slinton fatal("can't read %s", objname); 3439669Slinton } else { 3449669Slinton fclose(f); 3459669Slinton } 3469669Slinton if (rindex(objname, '/') != nil) { 3479669Slinton tmp = strdup(objname); 3489669Slinton *(rindex(tmp, '/')) = '\0'; 3499669Slinton list_append(list_item(tmp), nil, sourcepath); 3509669Slinton } 3519669Slinton if (coredump and corefile == nil) { 35218223Slinton if (vaddrs) { 35318223Slinton corefile = fopen("/dev/mem", "r"); 35418223Slinton corename = "/dev/mem"; 35518223Slinton if (corefile == nil) { 35618223Slinton panic("can't open /dev/mem"); 35718223Slinton } 35818223Slinton } else { 35918223Slinton corefile = fopen("core", "r"); 36018223Slinton corename = "core"; 36118223Slinton if (corefile == nil) { 36218223Slinton coredump = false; 36318223Slinton } 3649669Slinton } 3659669Slinton } 3669669Slinton } 3679669Slinton 3689669Slinton /* 3699669Slinton * Take appropriate action for recognized command argument. 3709669Slinton */ 3719669Slinton 3729669Slinton private setoption(c) 3739669Slinton char c; 3749669Slinton { 3759669Slinton switch (c) { 3769669Slinton case 'r': /* run program before accepting commands */ 3779669Slinton runfirst = true; 3789669Slinton coredump = false; 3799669Slinton break; 3809669Slinton 3819669Slinton case 'i': 3829669Slinton interactive = true; 3839669Slinton break; 3849669Slinton 3859669Slinton case 'b': 3869669Slinton tracebpts = true; 3879669Slinton break; 3889669Slinton 3899669Slinton case 'e': 3909669Slinton traceexec = true; 3919669Slinton break; 3929669Slinton 3939669Slinton case 's': 3949669Slinton tracesyms = true; 3959669Slinton break; 3969669Slinton 39716613Ssam case 'n': 39816613Ssam traceblocks = true; 39916613Ssam break; 40016613Ssam 40118223Slinton case 'k': 40218223Slinton vaddrs = true; 40318223Slinton break; 40418223Slinton 4059669Slinton case 'l': 40618223Slinton # ifdef LEXDEBUG 4079669Slinton lexdebug = true; 40818223Slinton # else 40918223Slinton fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 41018223Slinton # endif 4119669Slinton break; 4129669Slinton 4139669Slinton default: 4149669Slinton fatal("unknown option '%c'", c); 4159669Slinton } 4169669Slinton } 4179669Slinton 4189669Slinton /* 41911868Slinton * Save/restore the state of a tty. 42011868Slinton */ 42111868Slinton 42211868Slinton public savetty(f, t) 42311868Slinton File f; 42411868Slinton Ttyinfo *t; 42511868Slinton { 42617530Sralph ioctl(fileno(f), TIOCGETP, &(t->sg)); 42717530Sralph ioctl(fileno(f), TIOCGETC, &(t->tc)); 42817530Sralph ioctl(fileno(f), TIOCGLTC, &(t->ltc)); 42917530Sralph ioctl(fileno(f), TIOCGETD, &(t->ldisc)); 43017530Sralph ioctl(fileno(f), TIOCLGET, &(t->local)); 43117530Sralph t->fcflags = fcntl(fileno(f), F_GETFL, 0); 43211868Slinton } 43311868Slinton 43411868Slinton public restoretty(f, t) 43511868Slinton File f; 43611868Slinton Ttyinfo *t; 43711868Slinton { 43817530Sralph ioctl(fileno(f), TIOCSETN, &(t->sg)); 43917530Sralph ioctl(fileno(f), TIOCSETC, &(t->tc)); 44017530Sralph ioctl(fileno(f), TIOCSLTC, &(t->ltc)); 44117530Sralph ioctl(fileno(f), TIOCSETD, &(t->ldisc)); 44217530Sralph ioctl(fileno(f), TIOCLSET, &(t->local)); 44317530Sralph (void) fcntl(fileno(f), F_SETFL, t->fcflags); 44411868Slinton } 44511868Slinton 44611868Slinton /* 4479669Slinton * Exit gracefully. 4489669Slinton */ 4499669Slinton 4509669Slinton public quit(r) 4519669Slinton Integer r; 4529669Slinton { 45316613Ssam pterm(process); 4549669Slinton exit(r); 4559669Slinton } 456