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*31002Sbostic static char sccsid[] = "@(#)main.c 5.3 (Berkeley) 05/01/87"; 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 7711868Slinton private Ttyinfo ttyinfo; 7818223Slinton private String corename; /* name of core file */ 7911868Slinton 809669Slinton private catchintr(); 819669Slinton 829669Slinton /* 839669Slinton * Main program. 849669Slinton */ 859669Slinton 869669Slinton main(argc, argv) 879669Slinton int argc; 889669Slinton String argv[]; 899669Slinton { 9016613Ssam register integer i; 9111868Slinton extern String date; 9216613Ssam extern integer versionNumber; 93*31002Sbostic char **scanargs(); 949669Slinton 95*31002Sbostic if (!(cmdname = rindex(*argv, '/'))) 96*31002Sbostic cmdname = *argv; 97*31002Sbostic else 98*31002Sbostic ++cmdname; 99*31002Sbostic 1009669Slinton catcherrs(); 1019669Slinton onsyserr(EINTR, nil); 10218223Slinton setbuf(stdout, outbuf); 10318223Slinton printf("dbx version 3.%d of %s.\nType 'help' for help.\n", 10416613Ssam versionNumber, date); 10511868Slinton fflush(stdout); 106*31002Sbostic argv = scanargs(argc, argv); 1079669Slinton language_init(); 10818223Slinton symbols_init(); 1099669Slinton process_init(); 11026328Ssam optab_init(); 1119669Slinton if (runfirst) { 1129669Slinton if (setjmp(env) == FIRST_TIME) { 1139669Slinton arginit(); 114*31002Sbostic while (*argv) 115*31002Sbostic newarg(*argv++); 1169669Slinton run(); 1179669Slinton /* NOTREACHED */ 1189669Slinton } else { 1199669Slinton runfirst = false; 1209669Slinton } 1219669Slinton } else { 1229669Slinton init(); 1239669Slinton } 12416613Ssam if (setjmp(env) != FIRST_TIME) { 12516613Ssam restoretty(stdout, &ttyinfo); 12616613Ssam } 1279669Slinton signal(SIGINT, catchintr); 1289669Slinton yyparse(); 1299669Slinton putchar('\n'); 1309669Slinton quit(0); 1319669Slinton } 1329669Slinton 1339669Slinton /* 1349669Slinton * Initialize the world, including setting initial input file 1359669Slinton * if the file exists. 1369669Slinton */ 1379669Slinton 1389669Slinton public init() 1399669Slinton { 1409669Slinton File f; 1419669Slinton String home; 1429669Slinton char buf[100]; 1439669Slinton extern String getenv(); 1449669Slinton 14511868Slinton savetty(stdout, &ttyinfo); 1469669Slinton enterkeywords(); 1479669Slinton scanner_init(); 1489669Slinton if (not coredump and not runfirst) { 1499669Slinton start(nil, nil, nil); 1509669Slinton } 15111868Slinton printf("reading symbolic information ..."); 15211868Slinton fflush(stdout); 1539669Slinton readobj(objname); 15411868Slinton printf("\n"); 15511868Slinton fflush(stdout); 15612483Slinton if (coredump) { 15718223Slinton printf("[using memory image in %s]\n", corename); 15818223Slinton if (vaddrs) { 15918223Slinton coredump_getkerinfo(); 16018223Slinton } 16116613Ssam setcurfunc(whatblock(pc)); 16212483Slinton } else { 16316613Ssam setcurfunc(program); 16412483Slinton } 1659669Slinton bpinit(); 1669669Slinton f = fopen(initfile, "r"); 1679669Slinton if (f != nil) { 1689669Slinton fclose(f); 1699669Slinton setinput(initfile); 1709669Slinton } else { 1719669Slinton home = getenv("HOME"); 1729669Slinton if (home != nil) { 1739669Slinton sprintf(buf, "%s/%s", home, initfile); 1749669Slinton f = fopen(buf, "r"); 1759669Slinton if (f != nil) { 1769669Slinton fclose(f); 1779669Slinton setinput(strdup(buf)); 1789669Slinton } 1799669Slinton } 1809669Slinton } 1819669Slinton initdone = true; 1829669Slinton } 1839669Slinton 1849669Slinton /* 1859669Slinton * Re-initialize the world, first de-allocating all storage. 1869669Slinton * This is necessary when the symbol information must be re-read 1879669Slinton * from the object file when it has changed. 1889669Slinton * 1899669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1909669Slinton * information to a temp file. Then after re-creating the world, 1919669Slinton * we read the temp file as commands. This isn't always the right thing; 1929669Slinton * if a procedure that was being traced is deleted, an error message 1939669Slinton * will be generated. 1949669Slinton * 1959669Slinton * If the argument vector is not nil, then this is re-initialize is being 1969669Slinton * done in preparation for running the program. Since we want to process 1979669Slinton * the commands in the temp file before running the program, we add the 1989669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1999669Slinton * back to parsing rather than returning. 2009669Slinton */ 2019669Slinton 2029669Slinton public reinit(argv, infile, outfile) 2039669Slinton String *argv; 2049669Slinton String infile; 2059669Slinton String outfile; 2069669Slinton { 2079669Slinton register Integer i; 2089669Slinton String tmpfile; 2099669Slinton extern String mktemp(); 2109669Slinton 2119669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 2129669Slinton setout(tmpfile); 2139669Slinton status(); 21418223Slinton alias(nil, nil, nil); 2159669Slinton if (argv != nil) { 2169669Slinton printf("run"); 2179669Slinton for (i = 1; argv[i] != nil; i++) { 2189669Slinton printf(" %s", argv[i]); 2199669Slinton } 2209669Slinton if (infile != nil) { 2219669Slinton printf(" < %s", infile); 2229669Slinton } 2239669Slinton if (outfile != nil) { 2249669Slinton printf(" > %s", outfile); 2259669Slinton } 2269669Slinton putchar('\n'); 2279669Slinton } 2289669Slinton unsetout(); 2299669Slinton bpfree(); 2309669Slinton objfree(); 23118223Slinton symbols_init(); 2329669Slinton process_init(); 2339669Slinton enterkeywords(); 2349669Slinton scanner_init(); 2359669Slinton readobj(objname); 2369669Slinton bpinit(); 2379669Slinton fflush(stdout); 2389669Slinton setinput(tmpfile); 2399669Slinton unlink(tmpfile); 2409669Slinton if (argv != nil) { 2419669Slinton longjmp(env, 1); 2429669Slinton /* NOTREACHED */ 2439669Slinton } 2449669Slinton } 2459669Slinton 2469669Slinton /* 24718223Slinton * After a non-fatal error we skip the rest of the current input line, and 24818223Slinton * jump back to command parsing. 2499669Slinton */ 2509669Slinton 2519669Slinton public erecover() 2529669Slinton { 2539669Slinton if (initdone) { 2549669Slinton gobble(); 2559669Slinton longjmp(env, 1); 2569669Slinton } 2579669Slinton } 2589669Slinton 2599669Slinton /* 2609669Slinton * This routine is called when an interrupt occurs. 2619669Slinton */ 2629669Slinton 2639669Slinton private catchintr() 2649669Slinton { 26518223Slinton if (isredirected()) { 26618223Slinton fflush(stdout); 26718223Slinton unsetout(); 26818223Slinton } 2699669Slinton putchar('\n'); 2709669Slinton longjmp(env, 1); 2719669Slinton } 2729669Slinton 2739669Slinton /* 2749669Slinton * Scan the argument list. 2759669Slinton */ 2769669Slinton 277*31002Sbostic private char **scanargs(argc, argv) 2789669Slinton int argc; 2799669Slinton String argv[]; 2809669Slinton { 281*31002Sbostic extern char *optarg; 282*31002Sbostic extern int optind; 2839669Slinton register int i, j; 2849669Slinton register Boolean foundfile; 2859669Slinton register File f; 286*31002Sbostic int ch; 2879669Slinton char *tmp; 2889669Slinton 2899669Slinton runfirst = false; 2909669Slinton interactive = false; 2919669Slinton lexdebug = false; 2929669Slinton tracebpts = false; 2939669Slinton traceexec = false; 2949669Slinton tracesyms = false; 29516613Ssam traceblocks = false; 29618223Slinton vaddrs = false; 2979669Slinton foundfile = false; 2989669Slinton corefile = nil; 2999669Slinton coredump = true; 3009669Slinton sourcepath = list_alloc(); 3019669Slinton list_append(list_item("."), nil, sourcepath); 302*31002Sbostic 303*31002Sbostic while ((ch = getopt(argc, argv, "I:bc:eiklnrs")) != EOF) 304*31002Sbostic switch((char)ch) { 305*31002Sbostic case 'I': 306*31002Sbostic list_append(list_item(optarg), nil, sourcepath); 307*31002Sbostic break; 308*31002Sbostic case 'b': 309*31002Sbostic tracebpts = true; 310*31002Sbostic break; 311*31002Sbostic case 'c': 312*31002Sbostic initfile = optarg; 313*31002Sbostic break; 314*31002Sbostic case 'e': 315*31002Sbostic traceexec = true; 316*31002Sbostic break; 317*31002Sbostic case 'i': 318*31002Sbostic interactive = true; 319*31002Sbostic break; 320*31002Sbostic case 'k': 321*31002Sbostic vaddrs = true; 322*31002Sbostic break; 323*31002Sbostic case 'l': 324*31002Sbostic #ifdef LEXDEBUG 325*31002Sbostic lexdebug = true; 326*31002Sbostic #else 327*31002Sbostic fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 328*31002Sbostic #endif 329*31002Sbostic break; 330*31002Sbostic case 'n': 331*31002Sbostic traceblocks = true; 332*31002Sbostic break; 333*31002Sbostic case 'r': /* run program before accepting commands */ 334*31002Sbostic runfirst = true; 3359669Slinton coredump = false; 336*31002Sbostic break; 337*31002Sbostic case 's': 338*31002Sbostic tracesyms = true; 339*31002Sbostic break; 340*31002Sbostic case '?': 341*31002Sbostic default: 342*31002Sbostic fatal("unknown option"); 343*31002Sbostic } 344*31002Sbostic argv += optind; 345*31002Sbostic if (*argv) { 346*31002Sbostic objname = *argv; 347*31002Sbostic foundfile = true; 348*31002Sbostic if (*++argv && coredump) { 349*31002Sbostic corename = *argv; 350*31002Sbostic corefile = fopen(*argv, "r"); 351*31002Sbostic if (corefile == nil) 352*31002Sbostic coredump = false; 353*31002Sbostic ++argv; 3549669Slinton } 3559669Slinton } 356*31002Sbostic if (*argv and not runfirst) 357*31002Sbostic fatal("extraneous argument %s", *argv); 3589669Slinton if (not foundfile and isatty(0)) { 3599669Slinton printf("enter object file name (default is `%s'): ", objname); 3609669Slinton fflush(stdout); 3619669Slinton gets(namebuf); 3629669Slinton if (namebuf[0] != '\0') { 3639669Slinton objname = namebuf; 3649669Slinton } 3659669Slinton } 3669669Slinton f = fopen(objname, "r"); 3679669Slinton if (f == nil) { 3689669Slinton fatal("can't read %s", objname); 3699669Slinton } else { 3709669Slinton fclose(f); 3719669Slinton } 3729669Slinton if (rindex(objname, '/') != nil) { 3739669Slinton tmp = strdup(objname); 3749669Slinton *(rindex(tmp, '/')) = '\0'; 3759669Slinton list_append(list_item(tmp), nil, sourcepath); 3769669Slinton } 3779669Slinton if (coredump and corefile == nil) { 37818223Slinton if (vaddrs) { 37918223Slinton corename = "/dev/mem"; 380*31002Sbostic corefile = fopen(corename, "r"); 38118223Slinton if (corefile == nil) { 38218223Slinton panic("can't open /dev/mem"); 38318223Slinton } 38418223Slinton } else { 38518223Slinton corename = "core"; 386*31002Sbostic corefile = fopen(corename, "r"); 38718223Slinton if (corefile == nil) { 38818223Slinton coredump = false; 38918223Slinton } 3909669Slinton } 3919669Slinton } 392*31002Sbostic return(argv); 3939669Slinton } 3949669Slinton 3959669Slinton /* 39611868Slinton * Save/restore the state of a tty. 39711868Slinton */ 39811868Slinton 39911868Slinton public savetty(f, t) 40011868Slinton File f; 40111868Slinton Ttyinfo *t; 40211868Slinton { 40317530Sralph ioctl(fileno(f), TIOCGETP, &(t->sg)); 40417530Sralph ioctl(fileno(f), TIOCGETC, &(t->tc)); 40517530Sralph ioctl(fileno(f), TIOCGLTC, &(t->ltc)); 40617530Sralph ioctl(fileno(f), TIOCGETD, &(t->ldisc)); 40717530Sralph ioctl(fileno(f), TIOCLGET, &(t->local)); 40817530Sralph t->fcflags = fcntl(fileno(f), F_GETFL, 0); 40911868Slinton } 41011868Slinton 41111868Slinton public restoretty(f, t) 41211868Slinton File f; 41311868Slinton Ttyinfo *t; 41411868Slinton { 41517530Sralph ioctl(fileno(f), TIOCSETN, &(t->sg)); 41617530Sralph ioctl(fileno(f), TIOCSETC, &(t->tc)); 41717530Sralph ioctl(fileno(f), TIOCSLTC, &(t->ltc)); 41817530Sralph ioctl(fileno(f), TIOCSETD, &(t->ldisc)); 41917530Sralph ioctl(fileno(f), TIOCLSET, &(t->local)); 42017530Sralph (void) fcntl(fileno(f), F_SETFL, t->fcflags); 42111868Slinton } 42211868Slinton 42311868Slinton /* 4249669Slinton * Exit gracefully. 4259669Slinton */ 4269669Slinton 4279669Slinton public quit(r) 4289669Slinton Integer r; 4299669Slinton { 43016613Ssam pterm(process); 4319669Slinton exit(r); 4329669Slinton } 433