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