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