xref: /csrg-svn/old/dbx/main.c (revision 18223)
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