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