|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)main.c 5.4 (Berkeley) 1/12/88"; ! 15: #endif not lint ! 16: ! 17: static char rcsid[] = "$Header: main.c,v 1.4 87/07/08 21:31:27 donn Exp $"; ! 18: ! 19: /* ! 20: * Debugger main routine. ! 21: */ ! 22: ! 23: #include "defs.h" ! 24: #include <setjmp.h> ! 25: #include <signal.h> ! 26: #include <errno.h> ! 27: #include "main.h" ! 28: #include "tree.h" ! 29: #include "eval.h" ! 30: #include "debug.h" ! 31: #include "symbols.h" ! 32: #include "scanner.h" ! 33: #include "keywords.h" ! 34: #include "process.h" ! 35: #include "runtime.h" ! 36: #include "source.h" ! 37: #include "object.h" ! 38: #include "mappings.h" ! 39: #include "coredump.h" ! 40: ! 41: #ifndef public ! 42: ! 43: #define isterm(file) (interactive or isatty(fileno(file))) ! 44: ! 45: #ifdef IRIS ! 46: # include <termio.h> ! 47: ! 48: typedef struct termio Ttyinfo; ! 49: #else ! 50: # include <sgtty.h> ! 51: # include <fcntl.h> ! 52: ! 53: typedef struct { ! 54: struct sgttyb sg; /* standard sgttyb structure */ ! 55: struct tchars tc; /* terminal characters */ ! 56: struct ltchars ltc; /* local special characters */ ! 57: integer ldisc; /* line discipline */ ! 58: integer local; /* TIOCLGET */ ! 59: integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */ ! 60: } Ttyinfo; ! 61: #endif ! 62: ! 63: #endif ! 64: ! 65: public boolean coredump; /* true if using a core dump */ ! 66: public boolean runfirst; /* run program immediately */ ! 67: public boolean interactive; /* standard input IS a terminal */ ! 68: public boolean lexdebug; /* trace scanner return values */ ! 69: public boolean tracebpts; /* trace create/delete breakpoints */ ! 70: public boolean traceexec; /* trace execution */ ! 71: public boolean tracesyms; /* print symbols are they are read */ ! 72: public boolean traceblocks; /* trace blocks while reading symbols */ ! 73: public boolean vaddrs; /* map addresses through page tables */ ! 74: public boolean quiet; /* don't print heading */ ! 75: public boolean autostrip; /* strip C++ prefixes */ ! 76: ! 77: public File corefile; /* File id of core dump */ ! 78: ! 79: public integer versionNumber = 4; ! 80: ! 81: #define FIRST_TIME 0 /* initial value setjmp returns */ ! 82: ! 83: private Boolean initdone = false; /* true if initialization done */ ! 84: private jmp_buf env; /* setjmp/longjmp data */ ! 85: private char outbuf[BUFSIZ]; /* standard output buffer */ ! 86: private char namebuf[512]; /* possible name of object file */ ! 87: ! 88: private Ttyinfo ttyinfo; ! 89: private String corename; /* name of core file */ ! 90: ! 91: private catchintr(); ! 92: private char **scanargs(); ! 93: ! 94: /* ! 95: * Main program. ! 96: */ ! 97: ! 98: main(argc, argv) ! 99: int argc; ! 100: String argv[]; ! 101: { ! 102: extern integer versionNumber; ! 103: char **scanargs(); ! 104: ! 105: if (!(cmdname = rindex(*argv, '/'))) ! 106: cmdname = *argv; ! 107: else ! 108: ++cmdname; ! 109: ! 110: catcherrs(); ! 111: onsyserr(EINTR, nil); ! 112: onsyserr(EADDRINUSE, nil); ! 113: onsyserr(ENXIO, nil); ! 114: setbuf(stdout, outbuf); ! 115: argv = scanargs(argc, argv); ! 116: if (not runfirst and not quiet) { ! 117: printheading(); ! 118: } ! 119: openfiles(); ! 120: language_init(); ! 121: symbols_init(); ! 122: process_init(); ! 123: optab_init(); ! 124: if (runfirst) { ! 125: if (setjmp(env) == FIRST_TIME) { ! 126: arginit(); ! 127: while (*argv) ! 128: newarg(*argv++); ! 129: run(); ! 130: /* NOTREACHED */ ! 131: } else { ! 132: runfirst = false; ! 133: } ! 134: } else { ! 135: init(); ! 136: } ! 137: if (setjmp(env) != FIRST_TIME) { ! 138: restoretty(stdout, &ttyinfo); ! 139: } ! 140: signal(SIGINT, catchintr); ! 141: yyparse(); ! 142: putchar('\n'); ! 143: quit(0); ! 144: } ! 145: ! 146: public printheading () ! 147: { ! 148: extern String date; ! 149: ! 150: printf("dbx version 3.%d of %s.\nType 'help' for help.\n", ! 151: versionNumber, date ! 152: ); ! 153: fflush(stdout); ! 154: } ! 155: ! 156: /* ! 157: * Initialize the world, including setting initial input file ! 158: * if the file exists. ! 159: */ ! 160: ! 161: public init() ! 162: { ! 163: File f; ! 164: String home; ! 165: char buf[100]; ! 166: extern String getenv(); ! 167: ! 168: savetty(stdout, &ttyinfo); ! 169: enterkeywords(); ! 170: scanner_init(); ! 171: if (not coredump and not runfirst) { ! 172: start(nil, nil, nil); ! 173: } ! 174: printf("reading symbolic information ..."); ! 175: fflush(stdout); ! 176: readobj(objname); ! 177: printf("\n"); ! 178: fflush(stdout); ! 179: if (coredump) { ! 180: printf("[using memory image in %s]\n", corename); ! 181: if (vaddrs) { ! 182: coredump_getkerinfo(); ! 183: } ! 184: getsrcpos(); ! 185: setcurfunc(whatblock(pc)); ! 186: } else { ! 187: setcurfunc(program); ! 188: } ! 189: bpinit(); ! 190: f = fopen(initfile, "r"); ! 191: if (f != nil) { ! 192: fclose(f); ! 193: setinput(initfile); ! 194: } else { ! 195: home = getenv("HOME"); ! 196: if (home != nil) { ! 197: sprintf(buf, "%s/%s", home, initfile); ! 198: f = fopen(buf, "r"); ! 199: if (f != nil) { ! 200: fclose(f); ! 201: setinput(strdup(buf)); ! 202: } ! 203: } ! 204: } ! 205: initdone = true; ! 206: } ! 207: ! 208: /* ! 209: * Re-initialize the world, first de-allocating all storage. ! 210: * This is necessary when the symbol information must be re-read ! 211: * from the object file when it has changed. ! 212: * ! 213: * Before "forgetting" things, we save the current tracing/breakpoint ! 214: * information to a temp file. Then after re-creating the world, ! 215: * we read the temp file as commands. This isn't always the right thing; ! 216: * if a procedure that was being traced is deleted, an error message ! 217: * will be generated. ! 218: * ! 219: * If the argument vector is not nil, then this is re-initialize is being ! 220: * done in preparation for running the program. Since we want to process ! 221: * the commands in the temp file before running the program, we add the ! 222: * run command at the end of the temp file. In this case, reinit longjmps ! 223: * back to parsing rather than returning. ! 224: */ ! 225: ! 226: public reinit(argv, infile, outfile) ! 227: String *argv; ! 228: String infile; ! 229: String outfile; ! 230: { ! 231: register Integer i; ! 232: String tmpfile; ! 233: extern String mktemp(); ! 234: ! 235: tmpfile = mktemp("/tmp/dbxXXXX"); ! 236: setout(tmpfile); ! 237: status(); ! 238: alias(nil, nil, nil); ! 239: if (argv != nil) { ! 240: printf("run"); ! 241: for (i = 1; argv[i] != nil; i++) { ! 242: printf(" %s", argv[i]); ! 243: } ! 244: if (infile != nil) { ! 245: printf(" < %s", infile); ! 246: } ! 247: if (outfile != nil) { ! 248: printf(" > %s", outfile); ! 249: } ! 250: putchar('\n'); ! 251: } ! 252: unsetout(); ! 253: bpfree(); ! 254: objfree(); ! 255: symbols_init(); ! 256: process_init(); ! 257: enterkeywords(); ! 258: scanner_init(); ! 259: readobj(objname); ! 260: bpinit(); ! 261: fflush(stdout); ! 262: setinput(tmpfile); ! 263: unlink(tmpfile); ! 264: if (argv != nil) { ! 265: longjmp(env, 1); ! 266: /* NOTREACHED */ ! 267: } ! 268: } ! 269: ! 270: /* ! 271: * After a non-fatal error we skip the rest of the current input line, and ! 272: * jump back to command parsing. ! 273: */ ! 274: ! 275: public erecover() ! 276: { ! 277: if (initdone) { ! 278: gobble(); ! 279: longjmp(env, 1); ! 280: } ! 281: } ! 282: ! 283: /* ! 284: * This routine is called when an interrupt occurs. ! 285: */ ! 286: ! 287: private catchintr() ! 288: { ! 289: if (isredirected()) { ! 290: fflush(stdout); ! 291: unsetout(); ! 292: } ! 293: putchar('\n'); ! 294: longjmp(env, 1); ! 295: } ! 296: ! 297: /* ! 298: * Scan the argument list. ! 299: */ ! 300: ! 301: private char **scanargs (argc, argv) ! 302: int argc; ! 303: String argv[]; ! 304: { ! 305: extern char *optarg; ! 306: extern integer optind; ! 307: integer ch; ! 308: ! 309: runfirst = false; ! 310: interactive = false; ! 311: lexdebug = false; ! 312: tracebpts = false; ! 313: traceexec = false; ! 314: tracesyms = false; ! 315: traceblocks = false; ! 316: vaddrs = false; ! 317: quiet = false; ! 318: autostrip = true; ! 319: corefile = nil; ! 320: coredump = true; ! 321: sourcepath = list_alloc(); ! 322: list_append(list_item("."), nil, sourcepath); ! 323: ! 324: while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF) ! 325: switch((char)ch) { ! 326: case 'I': ! 327: list_append(list_item(optarg), nil, sourcepath); ! 328: break; ! 329: case 'a': ! 330: autostrip = false; ! 331: break; ! 332: case 'b': ! 333: tracebpts = true; ! 334: break; ! 335: case 'c': ! 336: initfile = optarg; ! 337: break; ! 338: case 'e': ! 339: traceexec = true; ! 340: break; ! 341: case 'i': ! 342: interactive = true; ! 343: break; ! 344: case 'k': ! 345: vaddrs = true; ! 346: break; ! 347: case 'l': ! 348: #ifdef LEXDEBUG ! 349: lexdebug = true; ! 350: #else ! 351: fatal("\"-l\" only applicable when compiled with LEXDEBUG"); ! 352: #endif ! 353: break; ! 354: case 'n': ! 355: traceblocks = true; ! 356: break; ! 357: case 'q': ! 358: quiet = true; ! 359: break; ! 360: case 'r': /* run program before accepting commands */ ! 361: runfirst = true; ! 362: coredump = false; ! 363: break; ! 364: case 's': ! 365: tracesyms = true; ! 366: break; ! 367: case '?': ! 368: default: ! 369: fatal("unknown option"); ! 370: } ! 371: argv += optind; ! 372: if (*argv) { ! 373: objname = *argv; ! 374: if (*++argv && coredump) { ! 375: corename = *argv; ! 376: corefile = fopen(*argv, "r"); ! 377: if (corefile == nil) ! 378: coredump = false; ! 379: ++argv; ! 380: } ! 381: } ! 382: if (*argv and not runfirst) { ! 383: fatal("extraneous argument %s", *argv); ! 384: } ! 385: return argv; ! 386: } ! 387: ! 388: private openfiles () ! 389: { ! 390: File f; ! 391: char *tmp; ! 392: ! 393: if (objname == nil and isatty(0)) { ! 394: printf("enter object file name (default is `%s'): ", objname); ! 395: fflush(stdout); ! 396: gets(namebuf); ! 397: if (namebuf[0] != '\0') { ! 398: objname = namebuf; ! 399: } ! 400: } ! 401: f = fopen(objname, "r"); ! 402: if (f == nil) { ! 403: fatal("can't read %s", objname); ! 404: } else { ! 405: fclose(f); ! 406: } ! 407: if (rindex(objname, '/') != nil) { ! 408: tmp = strdup(objname); ! 409: *(rindex(tmp, '/')) = '\0'; ! 410: list_append(list_item(tmp), nil, sourcepath); ! 411: } ! 412: if (coredump and corefile == nil) { ! 413: if (vaddrs) { ! 414: corename = "/dev/mem"; ! 415: corefile = fopen(corename, "r"); ! 416: if (corefile == nil) { ! 417: panic("can't open /dev/mem"); ! 418: } ! 419: } else { ! 420: corename = "core"; ! 421: corefile = fopen(corename, "r"); ! 422: if (corefile == nil) { ! 423: coredump = false; ! 424: } ! 425: } ! 426: } ! 427: } ! 428: ! 429: /* ! 430: * Save/restore the state of a tty. ! 431: */ ! 432: ! 433: public savetty(f, t) ! 434: File f; ! 435: Ttyinfo *t; ! 436: { ! 437: # ifdef IRIS ! 438: ioctl(fileno(f), TCGETA, t); ! 439: # else ! 440: ioctl(fileno(f), TIOCGETP, &(t->sg)); ! 441: ioctl(fileno(f), TIOCGETC, &(t->tc)); ! 442: ioctl(fileno(f), TIOCGLTC, &(t->ltc)); ! 443: ioctl(fileno(f), TIOCGETD, &(t->ldisc)); ! 444: ioctl(fileno(f), TIOCLGET, &(t->local)); ! 445: t->fcflags = fcntl(fileno(f), F_GETFL, 0); ! 446: if ((t->fcflags&FASYNC) != 0) { ! 447: /* fprintf(stderr, "[async i/o found set -- reset]\n"); */ ! 448: t->fcflags &= ~FASYNC; ! 449: } ! 450: # endif ! 451: } ! 452: ! 453: public restoretty(f, t) ! 454: File f; ! 455: Ttyinfo *t; ! 456: { ! 457: # ifdef IRIS ! 458: ioctl(fileno(f), TCSETA, t); ! 459: # else ! 460: ioctl(fileno(f), TIOCSETN, &(t->sg)); ! 461: ioctl(fileno(f), TIOCSETC, &(t->tc)); ! 462: ioctl(fileno(f), TIOCSLTC, &(t->ltc)); ! 463: ioctl(fileno(f), TIOCSETD, &(t->ldisc)); ! 464: ioctl(fileno(f), TIOCLSET, &(t->local)); ! 465: if ((t->fcflags&FASYNC) != 0) { ! 466: /* fprintf(stderr, "[async i/o not set]\n"); */ ! 467: t->fcflags &= ~FASYNC; ! 468: } ! 469: (void) fcntl(fileno(f), F_SETFL, t->fcflags); ! 470: # endif ! 471: } ! 472: ! 473: /* ! 474: * Exit gracefully. ! 475: */ ! 476: ! 477: public quit(r) ! 478: Integer r; ! 479: { ! 480: pterm(process); ! 481: exit(r); ! 482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.