xref: /csrg-svn/old/dbx/main.c (revision 37790)
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*37790Sbostic static char sccsid[] = "@(#)main.c	5.5 (Berkeley) 05/10/89";
1521609Sdist #endif not lint
1621609Sdist 
1733322Sdonn static char rcsid[] = "$Header: main.c,v 1.4 87/07/08 21:31:27 donn 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"
2833322Sdonn #include "tree.h"
2918223Slinton #include "eval.h"
3018223Slinton #include "debug.h"
3112483Slinton #include "symbols.h"
329669Slinton #include "scanner.h"
3318223Slinton #include "keywords.h"
349669Slinton #include "process.h"
3516613Ssam #include "runtime.h"
369669Slinton #include "source.h"
379669Slinton #include "object.h"
3812483Slinton #include "mappings.h"
3918223Slinton #include "coredump.h"
40*37790Sbostic #include "pathnames.h"
419669Slinton 
429669Slinton #ifndef public
439669Slinton 
449669Slinton #define isterm(file)	(interactive or isatty(fileno(file)))
459669Slinton 
4633322Sdonn #ifdef IRIS
4733322Sdonn #   include <termio.h>
4811868Slinton 
4933322Sdonn     typedef struct termio Ttyinfo;
5033322Sdonn #else
5133322Sdonn #   include <sgtty.h>
5233322Sdonn #   include <fcntl.h>
5311868Slinton 
5433322Sdonn     typedef struct {
5533322Sdonn 	struct sgttyb sg;		/* standard sgttyb structure */
5633322Sdonn 	struct tchars tc;		/* terminal characters */
5733322Sdonn 	struct ltchars ltc;		/* local special characters */
5833322Sdonn 	integer ldisc;			/* line discipline */
5933322Sdonn 	integer local;			/* TIOCLGET */
6033322Sdonn 	integer fcflags;		/* fcntl(2) F_GETFL, F_SETFL */
6133322Sdonn     } Ttyinfo;
629669Slinton #endif
639669Slinton 
6433322Sdonn #endif
6533322Sdonn 
6618223Slinton public boolean coredump;		/* true if using a core dump */
6718223Slinton public boolean runfirst;		/* run program immediately */
6818223Slinton public boolean interactive;		/* standard input IS a terminal */
6918223Slinton public boolean lexdebug;		/* trace scanner return values */
7018223Slinton public boolean tracebpts;		/* trace create/delete breakpoints */
7118223Slinton public boolean traceexec;		/* trace execution */
7218223Slinton public boolean tracesyms;		/* print symbols are they are read */
7318223Slinton public boolean traceblocks;		/* trace blocks while reading symbols */
7418223Slinton public boolean vaddrs;			/* map addresses through page tables */
7533322Sdonn public boolean quiet;			/* don't print heading */
7633322Sdonn public boolean autostrip;		/* strip C++ prefixes */
779669Slinton 
789669Slinton public File corefile;			/* File id of core dump */
799669Slinton 
8033322Sdonn public integer versionNumber = 4;
8133322Sdonn 
829669Slinton #define FIRST_TIME 0			/* initial value setjmp returns */
839669Slinton 
849669Slinton private Boolean initdone = false;	/* true if initialization done */
859669Slinton private jmp_buf env;			/* setjmp/longjmp data */
8618223Slinton private char outbuf[BUFSIZ];		/* standard output buffer */
879669Slinton private char namebuf[512];		/* possible name of object file */
889669Slinton 
8911868Slinton private Ttyinfo ttyinfo;
9018223Slinton private String corename;		/* name of core file */
9111868Slinton 
929669Slinton private catchintr();
9333322Sdonn private char **scanargs();
949669Slinton 
959669Slinton /*
969669Slinton  * Main program.
979669Slinton  */
989669Slinton 
999669Slinton main(argc, argv)
1009669Slinton int argc;
1019669Slinton String argv[];
1029669Slinton {
10316613Ssam     extern integer versionNumber;
10431002Sbostic     char **scanargs();
1059669Slinton 
10631002Sbostic     if (!(cmdname = rindex(*argv, '/')))
10731002Sbostic 	cmdname = *argv;
10831002Sbostic     else
10931002Sbostic 	++cmdname;
11031002Sbostic 
1119669Slinton     catcherrs();
1129669Slinton     onsyserr(EINTR, nil);
11333322Sdonn     onsyserr(EADDRINUSE, nil);
11433322Sdonn     onsyserr(ENXIO, nil);
11518223Slinton     setbuf(stdout, outbuf);
11631002Sbostic     argv = scanargs(argc, argv);
11733322Sdonn     if (not runfirst and not quiet) {
11833322Sdonn 	printheading();
11933322Sdonn     }
12033322Sdonn     openfiles();
1219669Slinton     language_init();
12218223Slinton     symbols_init();
1239669Slinton     process_init();
12426328Ssam     optab_init();
1259669Slinton     if (runfirst) {
1269669Slinton 	if (setjmp(env) == FIRST_TIME) {
1279669Slinton 	    arginit();
12831002Sbostic 	    while (*argv)
12931002Sbostic 		newarg(*argv++);
1309669Slinton 	    run();
1319669Slinton 	    /* NOTREACHED */
1329669Slinton 	} else {
1339669Slinton 	    runfirst = false;
1349669Slinton 	}
1359669Slinton     } else {
1369669Slinton 	init();
1379669Slinton     }
13816613Ssam     if (setjmp(env) != FIRST_TIME) {
13916613Ssam 	restoretty(stdout, &ttyinfo);
14016613Ssam     }
1419669Slinton     signal(SIGINT, catchintr);
1429669Slinton     yyparse();
1439669Slinton     putchar('\n');
1449669Slinton     quit(0);
1459669Slinton }
1469669Slinton 
14733322Sdonn public printheading ()
14833322Sdonn {
14933322Sdonn     extern String date;
15033322Sdonn 
15133322Sdonn     printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
15233322Sdonn 	versionNumber, date
15333322Sdonn     );
15433322Sdonn     fflush(stdout);
15533322Sdonn }
15633322Sdonn 
1579669Slinton /*
1589669Slinton  * Initialize the world, including setting initial input file
1599669Slinton  * if the file exists.
1609669Slinton  */
1619669Slinton 
1629669Slinton public init()
1639669Slinton {
1649669Slinton     File f;
1659669Slinton     String home;
1669669Slinton     char buf[100];
1679669Slinton     extern String getenv();
1689669Slinton 
16911868Slinton     savetty(stdout, &ttyinfo);
1709669Slinton     enterkeywords();
1719669Slinton     scanner_init();
1729669Slinton     if (not coredump and not runfirst) {
1739669Slinton 	start(nil, nil, nil);
1749669Slinton     }
17511868Slinton     printf("reading symbolic information ...");
17611868Slinton     fflush(stdout);
1779669Slinton     readobj(objname);
17811868Slinton     printf("\n");
17911868Slinton     fflush(stdout);
18012483Slinton     if (coredump) {
18118223Slinton 	printf("[using memory image in %s]\n", corename);
18218223Slinton 	if (vaddrs) {
18318223Slinton 	    coredump_getkerinfo();
18418223Slinton 	}
18533322Sdonn 	getsrcpos();
18616613Ssam 	setcurfunc(whatblock(pc));
18712483Slinton     } else {
18816613Ssam 	setcurfunc(program);
18912483Slinton     }
1909669Slinton     bpinit();
1919669Slinton     f = fopen(initfile, "r");
1929669Slinton     if (f != nil) {
1939669Slinton 	fclose(f);
1949669Slinton 	setinput(initfile);
1959669Slinton     } else {
1969669Slinton 	home = getenv("HOME");
1979669Slinton 	if (home != nil) {
1989669Slinton 	    sprintf(buf, "%s/%s", home, initfile);
1999669Slinton 	    f = fopen(buf, "r");
2009669Slinton 	    if (f != nil) {
2019669Slinton 		fclose(f);
2029669Slinton 		setinput(strdup(buf));
2039669Slinton 	    }
2049669Slinton 	}
2059669Slinton     }
2069669Slinton     initdone = true;
2079669Slinton }
2089669Slinton 
2099669Slinton /*
2109669Slinton  * Re-initialize the world, first de-allocating all storage.
2119669Slinton  * This is necessary when the symbol information must be re-read
2129669Slinton  * from the object file when it has changed.
2139669Slinton  *
2149669Slinton  * Before "forgetting" things, we save the current tracing/breakpoint
2159669Slinton  * information to a temp file.  Then after re-creating the world,
2169669Slinton  * we read the temp file as commands.  This isn't always the right thing;
2179669Slinton  * if a procedure that was being traced is deleted, an error message
2189669Slinton  * will be generated.
2199669Slinton  *
2209669Slinton  * If the argument vector is not nil, then this is re-initialize is being
2219669Slinton  * done in preparation for running the program.  Since we want to process
2229669Slinton  * the commands in the temp file before running the program, we add the
2239669Slinton  * run command at the end of the temp file.  In this case, reinit longjmps
2249669Slinton  * back to parsing rather than returning.
2259669Slinton  */
2269669Slinton 
2279669Slinton public reinit(argv, infile, outfile)
2289669Slinton String *argv;
2299669Slinton String infile;
2309669Slinton String outfile;
2319669Slinton {
2329669Slinton     register Integer i;
2339669Slinton     String tmpfile;
2349669Slinton     extern String mktemp();
2359669Slinton 
236*37790Sbostic     tmpfile = mktemp(_PATH_TMP);
2379669Slinton     setout(tmpfile);
2389669Slinton     status();
23918223Slinton     alias(nil, nil, nil);
2409669Slinton     if (argv != nil) {
2419669Slinton 	printf("run");
2429669Slinton 	for (i = 1; argv[i] != nil; i++) {
2439669Slinton 	    printf(" %s", argv[i]);
2449669Slinton 	}
2459669Slinton 	if (infile != nil) {
2469669Slinton 	    printf(" < %s", infile);
2479669Slinton 	}
2489669Slinton 	if (outfile != nil) {
2499669Slinton 	    printf(" > %s", outfile);
2509669Slinton 	}
2519669Slinton 	putchar('\n');
2529669Slinton     }
2539669Slinton     unsetout();
2549669Slinton     bpfree();
2559669Slinton     objfree();
25618223Slinton     symbols_init();
2579669Slinton     process_init();
2589669Slinton     enterkeywords();
2599669Slinton     scanner_init();
2609669Slinton     readobj(objname);
2619669Slinton     bpinit();
2629669Slinton     fflush(stdout);
2639669Slinton     setinput(tmpfile);
2649669Slinton     unlink(tmpfile);
2659669Slinton     if (argv != nil) {
2669669Slinton 	longjmp(env, 1);
2679669Slinton 	/* NOTREACHED */
2689669Slinton     }
2699669Slinton }
2709669Slinton 
2719669Slinton /*
27218223Slinton  * After a non-fatal error we skip the rest of the current input line, and
27318223Slinton  * jump back to command parsing.
2749669Slinton  */
2759669Slinton 
2769669Slinton public erecover()
2779669Slinton {
2789669Slinton     if (initdone) {
2799669Slinton 	gobble();
2809669Slinton 	longjmp(env, 1);
2819669Slinton     }
2829669Slinton }
2839669Slinton 
2849669Slinton /*
2859669Slinton  * This routine is called when an interrupt occurs.
2869669Slinton  */
2879669Slinton 
2889669Slinton private catchintr()
2899669Slinton {
29018223Slinton     if (isredirected()) {
29118223Slinton 	fflush(stdout);
29218223Slinton 	unsetout();
29318223Slinton     }
2949669Slinton     putchar('\n');
2959669Slinton     longjmp(env, 1);
2969669Slinton }
2979669Slinton 
2989669Slinton /*
2999669Slinton  * Scan the argument list.
3009669Slinton  */
3019669Slinton 
30233322Sdonn private char **scanargs (argc, argv)
3039669Slinton int argc;
3049669Slinton String argv[];
3059669Slinton {
30631002Sbostic     extern char *optarg;
30733322Sdonn     extern integer optind;
30833322Sdonn     integer ch;
3099669Slinton 
3109669Slinton     runfirst = false;
3119669Slinton     interactive = false;
3129669Slinton     lexdebug = false;
3139669Slinton     tracebpts = false;
3149669Slinton     traceexec = false;
3159669Slinton     tracesyms = false;
31616613Ssam     traceblocks = false;
31718223Slinton     vaddrs = false;
31833322Sdonn     quiet = false;
31933322Sdonn     autostrip = true;
3209669Slinton     corefile = nil;
3219669Slinton     coredump = true;
3229669Slinton     sourcepath = list_alloc();
3239669Slinton     list_append(list_item("."), nil, sourcepath);
32431002Sbostic 
32533322Sdonn     while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF)
32631002Sbostic     switch((char)ch) {
32731002Sbostic 	case 'I':
32831002Sbostic 		list_append(list_item(optarg), nil, sourcepath);
32931002Sbostic 		break;
33033322Sdonn 	case 'a':
33133322Sdonn 		autostrip = false;
33233322Sdonn 		break;
33331002Sbostic 	case 'b':
33431002Sbostic 		tracebpts = true;
33531002Sbostic 		break;
33631002Sbostic 	case 'c':
33731002Sbostic 		initfile = optarg;
33831002Sbostic 		break;
33931002Sbostic 	case 'e':
34031002Sbostic 		traceexec = true;
34131002Sbostic 		break;
34231002Sbostic 	case 'i':
34331002Sbostic 		interactive = true;
34431002Sbostic 		break;
34531002Sbostic 	case 'k':
34631002Sbostic 		vaddrs = true;
34731002Sbostic 		break;
34831002Sbostic 	case 'l':
34931002Sbostic #ifdef LEXDEBUG
35031002Sbostic 		lexdebug = true;
35131002Sbostic #else
35231002Sbostic 		fatal("\"-l\" only applicable when compiled with LEXDEBUG");
35331002Sbostic #endif
35431002Sbostic 		break;
35531002Sbostic 	case 'n':
35631002Sbostic 		traceblocks = true;
35731002Sbostic 		break;
35833322Sdonn 	case 'q':
35933322Sdonn 		quiet = true;
36033322Sdonn 		break;
36131002Sbostic 	case 'r':	/* run program before accepting commands */
36231002Sbostic 		runfirst = true;
3639669Slinton 		coredump = false;
36431002Sbostic 		break;
36531002Sbostic 	case 's':
36631002Sbostic 		tracesyms = true;
36731002Sbostic 		break;
36831002Sbostic 	case '?':
36931002Sbostic 	default:
37031002Sbostic 		fatal("unknown option");
37131002Sbostic     }
37231002Sbostic     argv += optind;
37331002Sbostic     if (*argv) {
37431002Sbostic 	objname = *argv;
37531002Sbostic 	if (*++argv && coredump) {
37631002Sbostic 		corename = *argv;
37731002Sbostic 		corefile = fopen(*argv, "r");
37831002Sbostic 		if (corefile == nil)
37931002Sbostic 			coredump = false;
38031002Sbostic 		++argv;
3819669Slinton 	}
3829669Slinton     }
38333322Sdonn     if (*argv and not runfirst) {
38431002Sbostic 	fatal("extraneous argument %s", *argv);
38533322Sdonn     }
38633322Sdonn     return argv;
38733322Sdonn }
38833322Sdonn 
38933322Sdonn private openfiles ()
39033322Sdonn {
39133322Sdonn     File f;
39233322Sdonn     char *tmp;
39333322Sdonn 
39433322Sdonn     if (objname == nil and isatty(0)) {
3959669Slinton 	printf("enter object file name (default is `%s'): ", objname);
3969669Slinton 	fflush(stdout);
3979669Slinton 	gets(namebuf);
3989669Slinton 	if (namebuf[0] != '\0') {
3999669Slinton 	    objname = namebuf;
4009669Slinton 	}
4019669Slinton     }
4029669Slinton     f = fopen(objname, "r");
4039669Slinton     if (f == nil) {
4049669Slinton 	fatal("can't read %s", objname);
4059669Slinton     } else {
4069669Slinton 	fclose(f);
4079669Slinton     }
4089669Slinton     if (rindex(objname, '/') != nil) {
4099669Slinton 	tmp = strdup(objname);
4109669Slinton 	*(rindex(tmp, '/')) = '\0';
4119669Slinton 	list_append(list_item(tmp), nil, sourcepath);
4129669Slinton     }
4139669Slinton     if (coredump and corefile == nil) {
41418223Slinton 	if (vaddrs) {
415*37790Sbostic 	    corename = _PATH_MEM;
41631002Sbostic 	    corefile = fopen(corename, "r");
41718223Slinton 	    if (corefile == nil) {
418*37790Sbostic 		panic("can't open %s", _PATH_MEM);
41918223Slinton 	    }
42018223Slinton 	} else {
42118223Slinton 	    corename = "core";
42231002Sbostic 	    corefile = fopen(corename, "r");
42318223Slinton 	    if (corefile == nil) {
42418223Slinton 		coredump = false;
42518223Slinton 	    }
4269669Slinton 	}
4279669Slinton     }
4289669Slinton }
4299669Slinton 
4309669Slinton /*
43111868Slinton  * Save/restore the state of a tty.
43211868Slinton  */
43311868Slinton 
43411868Slinton public savetty(f, t)
43511868Slinton File f;
43611868Slinton Ttyinfo *t;
43711868Slinton {
43833322Sdonn #   ifdef IRIS
43933322Sdonn 	ioctl(fileno(f), TCGETA, t);
44033322Sdonn #   else
44133322Sdonn 	ioctl(fileno(f), TIOCGETP, &(t->sg));
44233322Sdonn 	ioctl(fileno(f), TIOCGETC, &(t->tc));
44333322Sdonn 	ioctl(fileno(f), TIOCGLTC, &(t->ltc));
44433322Sdonn 	ioctl(fileno(f), TIOCGETD, &(t->ldisc));
44533322Sdonn 	ioctl(fileno(f), TIOCLGET, &(t->local));
44633322Sdonn 	t->fcflags = fcntl(fileno(f), F_GETFL, 0);
44733322Sdonn 	if ((t->fcflags&FASYNC) != 0) {
44833322Sdonn 	    /* fprintf(stderr, "[async i/o found set -- reset]\n"); */
44933322Sdonn 	    t->fcflags &= ~FASYNC;
45033322Sdonn 	}
45133322Sdonn #   endif
45211868Slinton }
45311868Slinton 
45411868Slinton public restoretty(f, t)
45511868Slinton File f;
45611868Slinton Ttyinfo *t;
45711868Slinton {
45833322Sdonn #   ifdef IRIS
45933322Sdonn 	ioctl(fileno(f), TCSETA, t);
46033322Sdonn #   else
46133322Sdonn 	ioctl(fileno(f), TIOCSETN, &(t->sg));
46233322Sdonn 	ioctl(fileno(f), TIOCSETC, &(t->tc));
46333322Sdonn 	ioctl(fileno(f), TIOCSLTC, &(t->ltc));
46433322Sdonn 	ioctl(fileno(f), TIOCSETD, &(t->ldisc));
46533322Sdonn 	ioctl(fileno(f), TIOCLSET, &(t->local));
46633322Sdonn 	if ((t->fcflags&FASYNC) != 0) {
46733322Sdonn 	    /* fprintf(stderr, "[async i/o not set]\n"); */
46833322Sdonn 	    t->fcflags &= ~FASYNC;
46933322Sdonn 	}
47033322Sdonn 	(void) fcntl(fileno(f), F_SETFL, t->fcflags);
47133322Sdonn #   endif
47211868Slinton }
47311868Slinton 
47411868Slinton /*
4759669Slinton  * Exit gracefully.
4769669Slinton  */
4779669Slinton 
4789669Slinton public quit(r)
4799669Slinton Integer r;
4809669Slinton {
48116613Ssam     pterm(process);
4829669Slinton     exit(r);
4839669Slinton }
484