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