xref: /csrg-svn/old/dbx/main.c (revision 38105)
121609Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621609Sdist  */
179669Slinton 
1821609Sdist #ifndef lint
1921609Sdist char copyright[] =
20*38105Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
2121609Sdist  All rights reserved.\n";
22*38105Sbostic #endif /* not lint */
239669Slinton 
2421609Sdist #ifndef lint
25*38105Sbostic static char sccsid[] = "@(#)main.c	5.6 (Berkeley) 05/23/89";
26*38105Sbostic #endif /* not lint */
2721609Sdist 
289669Slinton /*
299669Slinton  * Debugger main routine.
309669Slinton  */
319669Slinton 
329669Slinton #include "defs.h"
339669Slinton #include <setjmp.h>
349669Slinton #include <signal.h>
359669Slinton #include <errno.h>
369669Slinton #include "main.h"
3733322Sdonn #include "tree.h"
3818223Slinton #include "eval.h"
3918223Slinton #include "debug.h"
4012483Slinton #include "symbols.h"
419669Slinton #include "scanner.h"
4218223Slinton #include "keywords.h"
439669Slinton #include "process.h"
4416613Ssam #include "runtime.h"
459669Slinton #include "source.h"
469669Slinton #include "object.h"
4712483Slinton #include "mappings.h"
4818223Slinton #include "coredump.h"
4937790Sbostic #include "pathnames.h"
509669Slinton 
519669Slinton #ifndef public
529669Slinton 
539669Slinton #define isterm(file)	(interactive or isatty(fileno(file)))
549669Slinton 
5533322Sdonn #ifdef IRIS
5633322Sdonn #   include <termio.h>
5711868Slinton 
5833322Sdonn     typedef struct termio Ttyinfo;
5933322Sdonn #else
6033322Sdonn #   include <sgtty.h>
6133322Sdonn #   include <fcntl.h>
6211868Slinton 
6333322Sdonn     typedef struct {
6433322Sdonn 	struct sgttyb sg;		/* standard sgttyb structure */
6533322Sdonn 	struct tchars tc;		/* terminal characters */
6633322Sdonn 	struct ltchars ltc;		/* local special characters */
6733322Sdonn 	integer ldisc;			/* line discipline */
6833322Sdonn 	integer local;			/* TIOCLGET */
6933322Sdonn 	integer fcflags;		/* fcntl(2) F_GETFL, F_SETFL */
7033322Sdonn     } Ttyinfo;
719669Slinton #endif
729669Slinton 
7333322Sdonn #endif
7433322Sdonn 
7518223Slinton public boolean coredump;		/* true if using a core dump */
7618223Slinton public boolean runfirst;		/* run program immediately */
7718223Slinton public boolean interactive;		/* standard input IS a terminal */
7818223Slinton public boolean lexdebug;		/* trace scanner return values */
7918223Slinton public boolean tracebpts;		/* trace create/delete breakpoints */
8018223Slinton public boolean traceexec;		/* trace execution */
8118223Slinton public boolean tracesyms;		/* print symbols are they are read */
8218223Slinton public boolean traceblocks;		/* trace blocks while reading symbols */
8318223Slinton public boolean vaddrs;			/* map addresses through page tables */
8433322Sdonn public boolean quiet;			/* don't print heading */
8533322Sdonn public boolean autostrip;		/* strip C++ prefixes */
869669Slinton 
879669Slinton public File corefile;			/* File id of core dump */
889669Slinton 
8933322Sdonn public integer versionNumber = 4;
9033322Sdonn 
919669Slinton #define FIRST_TIME 0			/* initial value setjmp returns */
929669Slinton 
939669Slinton private Boolean initdone = false;	/* true if initialization done */
949669Slinton private jmp_buf env;			/* setjmp/longjmp data */
9518223Slinton private char outbuf[BUFSIZ];		/* standard output buffer */
969669Slinton private char namebuf[512];		/* possible name of object file */
979669Slinton 
9811868Slinton private Ttyinfo ttyinfo;
9918223Slinton private String corename;		/* name of core file */
10011868Slinton 
1019669Slinton private catchintr();
10233322Sdonn private char **scanargs();
1039669Slinton 
1049669Slinton /*
1059669Slinton  * Main program.
1069669Slinton  */
1079669Slinton 
1089669Slinton main(argc, argv)
1099669Slinton int argc;
1109669Slinton String argv[];
1119669Slinton {
11216613Ssam     extern integer versionNumber;
11331002Sbostic     char **scanargs();
1149669Slinton 
11531002Sbostic     if (!(cmdname = rindex(*argv, '/')))
11631002Sbostic 	cmdname = *argv;
11731002Sbostic     else
11831002Sbostic 	++cmdname;
11931002Sbostic 
1209669Slinton     catcherrs();
1219669Slinton     onsyserr(EINTR, nil);
12233322Sdonn     onsyserr(EADDRINUSE, nil);
12333322Sdonn     onsyserr(ENXIO, nil);
12418223Slinton     setbuf(stdout, outbuf);
12531002Sbostic     argv = scanargs(argc, argv);
12633322Sdonn     if (not runfirst and not quiet) {
12733322Sdonn 	printheading();
12833322Sdonn     }
12933322Sdonn     openfiles();
1309669Slinton     language_init();
13118223Slinton     symbols_init();
1329669Slinton     process_init();
13326328Ssam     optab_init();
1349669Slinton     if (runfirst) {
1359669Slinton 	if (setjmp(env) == FIRST_TIME) {
1369669Slinton 	    arginit();
13731002Sbostic 	    while (*argv)
13831002Sbostic 		newarg(*argv++);
1399669Slinton 	    run();
1409669Slinton 	    /* NOTREACHED */
1419669Slinton 	} else {
1429669Slinton 	    runfirst = false;
1439669Slinton 	}
1449669Slinton     } else {
1459669Slinton 	init();
1469669Slinton     }
14716613Ssam     if (setjmp(env) != FIRST_TIME) {
14816613Ssam 	restoretty(stdout, &ttyinfo);
14916613Ssam     }
1509669Slinton     signal(SIGINT, catchintr);
1519669Slinton     yyparse();
1529669Slinton     putchar('\n');
1539669Slinton     quit(0);
1549669Slinton }
1559669Slinton 
15633322Sdonn public printheading ()
15733322Sdonn {
15833322Sdonn     extern String date;
15933322Sdonn 
16033322Sdonn     printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
16133322Sdonn 	versionNumber, date
16233322Sdonn     );
16333322Sdonn     fflush(stdout);
16433322Sdonn }
16533322Sdonn 
1669669Slinton /*
1679669Slinton  * Initialize the world, including setting initial input file
1689669Slinton  * if the file exists.
1699669Slinton  */
1709669Slinton 
1719669Slinton public init()
1729669Slinton {
1739669Slinton     File f;
1749669Slinton     String home;
1759669Slinton     char buf[100];
1769669Slinton     extern String getenv();
1779669Slinton 
17811868Slinton     savetty(stdout, &ttyinfo);
1799669Slinton     enterkeywords();
1809669Slinton     scanner_init();
1819669Slinton     if (not coredump and not runfirst) {
1829669Slinton 	start(nil, nil, nil);
1839669Slinton     }
18411868Slinton     printf("reading symbolic information ...");
18511868Slinton     fflush(stdout);
1869669Slinton     readobj(objname);
18711868Slinton     printf("\n");
18811868Slinton     fflush(stdout);
18912483Slinton     if (coredump) {
19018223Slinton 	printf("[using memory image in %s]\n", corename);
19118223Slinton 	if (vaddrs) {
19218223Slinton 	    coredump_getkerinfo();
19318223Slinton 	}
19433322Sdonn 	getsrcpos();
19516613Ssam 	setcurfunc(whatblock(pc));
19612483Slinton     } else {
19716613Ssam 	setcurfunc(program);
19812483Slinton     }
1999669Slinton     bpinit();
2009669Slinton     f = fopen(initfile, "r");
2019669Slinton     if (f != nil) {
2029669Slinton 	fclose(f);
2039669Slinton 	setinput(initfile);
2049669Slinton     } else {
2059669Slinton 	home = getenv("HOME");
2069669Slinton 	if (home != nil) {
2079669Slinton 	    sprintf(buf, "%s/%s", home, initfile);
2089669Slinton 	    f = fopen(buf, "r");
2099669Slinton 	    if (f != nil) {
2109669Slinton 		fclose(f);
2119669Slinton 		setinput(strdup(buf));
2129669Slinton 	    }
2139669Slinton 	}
2149669Slinton     }
2159669Slinton     initdone = true;
2169669Slinton }
2179669Slinton 
2189669Slinton /*
2199669Slinton  * Re-initialize the world, first de-allocating all storage.
2209669Slinton  * This is necessary when the symbol information must be re-read
2219669Slinton  * from the object file when it has changed.
2229669Slinton  *
2239669Slinton  * Before "forgetting" things, we save the current tracing/breakpoint
2249669Slinton  * information to a temp file.  Then after re-creating the world,
2259669Slinton  * we read the temp file as commands.  This isn't always the right thing;
2269669Slinton  * if a procedure that was being traced is deleted, an error message
2279669Slinton  * will be generated.
2289669Slinton  *
2299669Slinton  * If the argument vector is not nil, then this is re-initialize is being
2309669Slinton  * done in preparation for running the program.  Since we want to process
2319669Slinton  * the commands in the temp file before running the program, we add the
2329669Slinton  * run command at the end of the temp file.  In this case, reinit longjmps
2339669Slinton  * back to parsing rather than returning.
2349669Slinton  */
2359669Slinton 
2369669Slinton public reinit(argv, infile, outfile)
2379669Slinton String *argv;
2389669Slinton String infile;
2399669Slinton String outfile;
2409669Slinton {
2419669Slinton     register Integer i;
2429669Slinton     String tmpfile;
2439669Slinton     extern String mktemp();
2449669Slinton 
24537790Sbostic     tmpfile = mktemp(_PATH_TMP);
2469669Slinton     setout(tmpfile);
2479669Slinton     status();
24818223Slinton     alias(nil, nil, nil);
2499669Slinton     if (argv != nil) {
2509669Slinton 	printf("run");
2519669Slinton 	for (i = 1; argv[i] != nil; i++) {
2529669Slinton 	    printf(" %s", argv[i]);
2539669Slinton 	}
2549669Slinton 	if (infile != nil) {
2559669Slinton 	    printf(" < %s", infile);
2569669Slinton 	}
2579669Slinton 	if (outfile != nil) {
2589669Slinton 	    printf(" > %s", outfile);
2599669Slinton 	}
2609669Slinton 	putchar('\n');
2619669Slinton     }
2629669Slinton     unsetout();
2639669Slinton     bpfree();
2649669Slinton     objfree();
26518223Slinton     symbols_init();
2669669Slinton     process_init();
2679669Slinton     enterkeywords();
2689669Slinton     scanner_init();
2699669Slinton     readobj(objname);
2709669Slinton     bpinit();
2719669Slinton     fflush(stdout);
2729669Slinton     setinput(tmpfile);
2739669Slinton     unlink(tmpfile);
2749669Slinton     if (argv != nil) {
2759669Slinton 	longjmp(env, 1);
2769669Slinton 	/* NOTREACHED */
2779669Slinton     }
2789669Slinton }
2799669Slinton 
2809669Slinton /*
28118223Slinton  * After a non-fatal error we skip the rest of the current input line, and
28218223Slinton  * jump back to command parsing.
2839669Slinton  */
2849669Slinton 
2859669Slinton public erecover()
2869669Slinton {
2879669Slinton     if (initdone) {
2889669Slinton 	gobble();
2899669Slinton 	longjmp(env, 1);
2909669Slinton     }
2919669Slinton }
2929669Slinton 
2939669Slinton /*
2949669Slinton  * This routine is called when an interrupt occurs.
2959669Slinton  */
2969669Slinton 
2979669Slinton private catchintr()
2989669Slinton {
29918223Slinton     if (isredirected()) {
30018223Slinton 	fflush(stdout);
30118223Slinton 	unsetout();
30218223Slinton     }
3039669Slinton     putchar('\n');
3049669Slinton     longjmp(env, 1);
3059669Slinton }
3069669Slinton 
3079669Slinton /*
3089669Slinton  * Scan the argument list.
3099669Slinton  */
3109669Slinton 
31133322Sdonn private char **scanargs (argc, argv)
3129669Slinton int argc;
3139669Slinton String argv[];
3149669Slinton {
31531002Sbostic     extern char *optarg;
31633322Sdonn     extern integer optind;
31733322Sdonn     integer ch;
3189669Slinton 
3199669Slinton     runfirst = false;
3209669Slinton     interactive = false;
3219669Slinton     lexdebug = false;
3229669Slinton     tracebpts = false;
3239669Slinton     traceexec = false;
3249669Slinton     tracesyms = false;
32516613Ssam     traceblocks = false;
32618223Slinton     vaddrs = false;
32733322Sdonn     quiet = false;
32833322Sdonn     autostrip = true;
3299669Slinton     corefile = nil;
3309669Slinton     coredump = true;
3319669Slinton     sourcepath = list_alloc();
3329669Slinton     list_append(list_item("."), nil, sourcepath);
33331002Sbostic 
33433322Sdonn     while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF)
33531002Sbostic     switch((char)ch) {
33631002Sbostic 	case 'I':
33731002Sbostic 		list_append(list_item(optarg), nil, sourcepath);
33831002Sbostic 		break;
33933322Sdonn 	case 'a':
34033322Sdonn 		autostrip = false;
34133322Sdonn 		break;
34231002Sbostic 	case 'b':
34331002Sbostic 		tracebpts = true;
34431002Sbostic 		break;
34531002Sbostic 	case 'c':
34631002Sbostic 		initfile = optarg;
34731002Sbostic 		break;
34831002Sbostic 	case 'e':
34931002Sbostic 		traceexec = true;
35031002Sbostic 		break;
35131002Sbostic 	case 'i':
35231002Sbostic 		interactive = true;
35331002Sbostic 		break;
35431002Sbostic 	case 'k':
35531002Sbostic 		vaddrs = true;
35631002Sbostic 		break;
35731002Sbostic 	case 'l':
35831002Sbostic #ifdef LEXDEBUG
35931002Sbostic 		lexdebug = true;
36031002Sbostic #else
36131002Sbostic 		fatal("\"-l\" only applicable when compiled with LEXDEBUG");
36231002Sbostic #endif
36331002Sbostic 		break;
36431002Sbostic 	case 'n':
36531002Sbostic 		traceblocks = true;
36631002Sbostic 		break;
36733322Sdonn 	case 'q':
36833322Sdonn 		quiet = true;
36933322Sdonn 		break;
37031002Sbostic 	case 'r':	/* run program before accepting commands */
37131002Sbostic 		runfirst = true;
3729669Slinton 		coredump = false;
37331002Sbostic 		break;
37431002Sbostic 	case 's':
37531002Sbostic 		tracesyms = true;
37631002Sbostic 		break;
37731002Sbostic 	case '?':
37831002Sbostic 	default:
37931002Sbostic 		fatal("unknown option");
38031002Sbostic     }
38131002Sbostic     argv += optind;
38231002Sbostic     if (*argv) {
38331002Sbostic 	objname = *argv;
38431002Sbostic 	if (*++argv && coredump) {
38531002Sbostic 		corename = *argv;
38631002Sbostic 		corefile = fopen(*argv, "r");
38731002Sbostic 		if (corefile == nil)
38831002Sbostic 			coredump = false;
38931002Sbostic 		++argv;
3909669Slinton 	}
3919669Slinton     }
39233322Sdonn     if (*argv and not runfirst) {
39331002Sbostic 	fatal("extraneous argument %s", *argv);
39433322Sdonn     }
39533322Sdonn     return argv;
39633322Sdonn }
39733322Sdonn 
39833322Sdonn private openfiles ()
39933322Sdonn {
40033322Sdonn     File f;
40133322Sdonn     char *tmp;
40233322Sdonn 
40333322Sdonn     if (objname == nil and isatty(0)) {
4049669Slinton 	printf("enter object file name (default is `%s'): ", objname);
4059669Slinton 	fflush(stdout);
4069669Slinton 	gets(namebuf);
4079669Slinton 	if (namebuf[0] != '\0') {
4089669Slinton 	    objname = namebuf;
4099669Slinton 	}
4109669Slinton     }
4119669Slinton     f = fopen(objname, "r");
4129669Slinton     if (f == nil) {
4139669Slinton 	fatal("can't read %s", objname);
4149669Slinton     } else {
4159669Slinton 	fclose(f);
4169669Slinton     }
4179669Slinton     if (rindex(objname, '/') != nil) {
4189669Slinton 	tmp = strdup(objname);
4199669Slinton 	*(rindex(tmp, '/')) = '\0';
4209669Slinton 	list_append(list_item(tmp), nil, sourcepath);
4219669Slinton     }
4229669Slinton     if (coredump and corefile == nil) {
42318223Slinton 	if (vaddrs) {
42437790Sbostic 	    corename = _PATH_MEM;
42531002Sbostic 	    corefile = fopen(corename, "r");
42618223Slinton 	    if (corefile == nil) {
42737790Sbostic 		panic("can't open %s", _PATH_MEM);
42818223Slinton 	    }
42918223Slinton 	} else {
43018223Slinton 	    corename = "core";
43131002Sbostic 	    corefile = fopen(corename, "r");
43218223Slinton 	    if (corefile == nil) {
43318223Slinton 		coredump = false;
43418223Slinton 	    }
4359669Slinton 	}
4369669Slinton     }
4379669Slinton }
4389669Slinton 
4399669Slinton /*
44011868Slinton  * Save/restore the state of a tty.
44111868Slinton  */
44211868Slinton 
44311868Slinton public savetty(f, t)
44411868Slinton File f;
44511868Slinton Ttyinfo *t;
44611868Slinton {
44733322Sdonn #   ifdef IRIS
44833322Sdonn 	ioctl(fileno(f), TCGETA, t);
44933322Sdonn #   else
45033322Sdonn 	ioctl(fileno(f), TIOCGETP, &(t->sg));
45133322Sdonn 	ioctl(fileno(f), TIOCGETC, &(t->tc));
45233322Sdonn 	ioctl(fileno(f), TIOCGLTC, &(t->ltc));
45333322Sdonn 	ioctl(fileno(f), TIOCGETD, &(t->ldisc));
45433322Sdonn 	ioctl(fileno(f), TIOCLGET, &(t->local));
45533322Sdonn 	t->fcflags = fcntl(fileno(f), F_GETFL, 0);
45633322Sdonn 	if ((t->fcflags&FASYNC) != 0) {
45733322Sdonn 	    /* fprintf(stderr, "[async i/o found set -- reset]\n"); */
45833322Sdonn 	    t->fcflags &= ~FASYNC;
45933322Sdonn 	}
46033322Sdonn #   endif
46111868Slinton }
46211868Slinton 
46311868Slinton public restoretty(f, t)
46411868Slinton File f;
46511868Slinton Ttyinfo *t;
46611868Slinton {
46733322Sdonn #   ifdef IRIS
46833322Sdonn 	ioctl(fileno(f), TCSETA, t);
46933322Sdonn #   else
47033322Sdonn 	ioctl(fileno(f), TIOCSETN, &(t->sg));
47133322Sdonn 	ioctl(fileno(f), TIOCSETC, &(t->tc));
47233322Sdonn 	ioctl(fileno(f), TIOCSLTC, &(t->ltc));
47333322Sdonn 	ioctl(fileno(f), TIOCSETD, &(t->ldisc));
47433322Sdonn 	ioctl(fileno(f), TIOCLSET, &(t->local));
47533322Sdonn 	if ((t->fcflags&FASYNC) != 0) {
47633322Sdonn 	    /* fprintf(stderr, "[async i/o not set]\n"); */
47733322Sdonn 	    t->fcflags &= ~FASYNC;
47833322Sdonn 	}
47933322Sdonn 	(void) fcntl(fileno(f), F_SETFL, t->fcflags);
48033322Sdonn #   endif
48111868Slinton }
48211868Slinton 
48311868Slinton /*
4849669Slinton  * Exit gracefully.
4859669Slinton  */
4869669Slinton 
4879669Slinton public quit(r)
4889669Slinton Integer r;
4899669Slinton {
49016613Ssam     pterm(process);
4919669Slinton     exit(r);
4929669Slinton }
493