|
|
1.1 ! root 1: /* ! 2: * db/db1.c ! 3: * A debugger. ! 4: * Initialization and command line parsing. ! 5: */ ! 6: ! 7: #include <stddef.h> ! 8: #include <canon.h> ! 9: #include <signal.h> ! 10: #include <sys/core.h> ! 11: #include <sys/uproc.h> ! 12: #include "db.h" ! 13: ! 14: int ! 15: main(argc, argv) int argc; char *argv[]; ! 16: { ! 17: signal(SIGINT, &arm_sigint); ! 18: signal(SIGQUIT, SIG_IGN); ! 19: initialize(); ! 20: setup(argc, argv); ! 21: process(); ! 22: } ! 23: ! 24: /* ! 25: * Catch and flag interrupts (SIGINT). ! 26: */ ! 27: void ! 28: arm_sigint() ! 29: { ! 30: signal(SIGINT, &arm_sigint); ! 31: intflag++; ! 32: } ! 33: ! 34: /* ! 35: * Canonicalize an l.out header. ! 36: */ ! 37: void ! 38: canlout() ! 39: { ! 40: register int i; ! 41: ! 42: canint(ldh.l_magic); ! 43: canint(ldh.l_flag); ! 44: canint(ldh.l_machine); ! 45: canvaddr(ldh.l_entry); ! 46: for (i=0; i<NLSEG; i++) ! 47: cansize(ldh.l_ssize[i]); ! 48: } ! 49: ! 50: /* ! 51: * Initialize segment formats, clear the breakpoint table, ! 52: * invalidate the child process register image. ! 53: */ ! 54: void ! 55: initialize() ! 56: { ! 57: init_mch(); ! 58: strcpy(seg_format[DSEG], "w"); /* patched in set_prog() if COFF */ ! 59: strcpy(seg_format[ISEG], "i"); ! 60: strcpy(seg_format[USEG], "w"); /* patched in set_prog() if COFF */ ! 61: bpt_init(); ! 62: reg_flag = R_INVALID; ! 63: } ! 64: ! 65: /* ! 66: * Leave. ! 67: */ ! 68: void ! 69: leave() ! 70: { ! 71: killc(); ! 72: exit(0); ! 73: } ! 74: ! 75: /* ! 76: * Open the given file. ! 77: * If 'rflag' is set, the file is opened for read only. ! 78: */ ! 79: FILE * ! 80: openfile(name, rflag) char *name; int rflag; ! 81: { ! 82: register FILE *fp; ! 83: ! 84: #if __I386__ ! 85: again: ! 86: #endif ! 87: if (!rflag && (fp = fopen(name, "r+w")) != (FILE *)NULL) ! 88: return fp; ! 89: else if ((fp = fopen(name, "r")) != (FILE *)NULL) { ! 90: if (!rflag) ! 91: printr("%s: opened read only", name); ! 92: return fp; ! 93: } ! 94: #if __I386__ ! 95: if (strcmp(name, DEFLT_OBJ) == 0) { ! 96: name = DEFLT_OBJ2; /* l.out not found, try a.out */ ! 97: goto again; ! 98: } ! 99: #endif ! 100: panic("Cannot open %s", name); ! 101: } ! 102: ! 103: /* ! 104: * Set up segmentation for a core dump. ! 105: * The registers are also read. ! 106: * hal improved the core file format 4/93 for COHERENT V4.0.1r75. ! 107: * Compiling without -DOLD_CORE builds db which groks only the new format. ! 108: * Compiling with -DOLD_CORE builds db which groks both old and new formats. ! 109: * This hack should disappear when the old format becomes irrelevant. ! 110: */ ! 111: void ! 112: set_core(name) char *name; ! 113: { ! 114: struct ch_info ch_info; ! 115: long offset; ! 116: register unsigned i; ! 117: register char *cp; ! 118: register ADDR_T size; ! 119: register off_t offt; ! 120: ADDR_T regl; /* an address, int * in <sys/uproc.h> */ ! 121: int iflag, textflag; ! 122: int signo; ! 123: char ucomm[U_COMM_LEN+1]; ! 124: SR usegs[NUSEG]; ! 125: ! 126: /* Open the core file. */ ! 127: cfn = name; ! 128: cfp = openfile(name, rflag); ! 129: ! 130: /* Read the core file header and set uproc offset. */ ! 131: if (fread(&ch_info, sizeof ch_info, 1, cfp) != 1) ! 132: panic("Cannot read core file header"); ! 133: #if !OLD_CORE ! 134: if (ch_info.ch_magic != CORE_MAGIC) ! 135: panic("Not a core file"); ! 136: offset = ch_info.ch_info_len + ch_info.ch_uproc_offset; ! 137: #else ! 138: if (ch_info.ch_magic == CORE_MAGIC) ! 139: offset = ch_info.ch_info_len + ch_info.ch_uproc_offset; ! 140: else ! 141: offset = (long)U_OFFSET; ! 142: #endif ! 143: ! 144: /* Read the file name from the core file. */ ! 145: if (fseek(cfp, offset+offsetof(UPROC, u_comm[0]), SEEK_SET) != -1 ! 146: && (cp = lfn) != NULL ! 147: && fread(ucomm, sizeof(ucomm), 1, cfp) == 1) { ! 148: ! 149: /* Compare object filename to core filename. */ ! 150: while (strchr(cp, '/') != NULL) ! 151: cp = strchr(cp, '/') + 1; /* skip past '/' */ ! 152: if (strncmp(cp, ucomm, sizeof(ucomm)) != 0) { ! 153: ucomm[U_COMM_LEN] = '\0'; ! 154: printr("Core file name \"%s\" different from object file name \"%s\"", ! 155: ucomm, lfn); ! 156: } ! 157: } ! 158: ! 159: /* Read the core file segment information. */ ! 160: if (fseek(cfp, offset+offsetof(UPROC, u_segl[0]), SEEK_SET) == -1 ! 161: || fread(usegs, sizeof(usegs), 1, cfp) != 1) ! 162: panic("Bad core file"); ! 163: ! 164: /* Read the core file signal number and register pointer. */ ! 165: if (fseek(cfp, offset+offsetof(UPROC, u_signo), SEEK_SET) == -1 ! 166: || fread(&signo, sizeof(signo), 1, cfp) != 1) ! 167: panic("cannot read signo"); ! 168: dbprintf(("signo=%d\n", signo)); ! 169: if (fread(®l, sizeof(regl), 1, cfp) != 1) ! 170: panic("cannot read regl"); ! 171: regl &= (NBPC - 1); ! 172: #if OLD_CORE ! 173: if (ch_info.ch_magic == CORE_MAGIC) ! 174: regl += ch_info.ch_info_len; ! 175: #else ! 176: regl += ch_info.ch_info_len; ! 177: #endif ! 178: dbprintf(("regl=%d\n", regl)); ! 179: ! 180: #if __I386__ ! 181: /* Adjust the i386 stack segment base. */ ! 182: usegs[SISTACK].sr_base -= usegs[SISTACK].sr_size; ! 183: dbprintf(("adjust usegs[SISTACK].sr_base to %x\n", usegs[SISTACK].sr_base)); ! 184: #endif ! 185: ! 186: /* ! 187: * The new core dump format might or might not include the text segment ! 188: * but does not include a flag stating if it has been dumped (oops); ! 189: * this decides if text is present/absent by adding up segment sizes. ! 190: * Presumably it should be setting SRFDUMP flag correctly instead... ! 191: */ ! 192: textflag = 0; ! 193: #if OLD_CORE ! 194: if (ch_info.ch_magic == CORE_MAGIC) { ! 195: #endif ! 196: offt = usegs[0].sr_size + ch_info.ch_info_len; ! 197: for (i=1; i<NUSEG; i++) { ! 198: if (usegs[i].sr_segp == (SEG *)NULL) ! 199: continue; ! 200: if ((~usegs[i].sr_flag) & (SRFDUMP|SRFPMAP)) ! 201: continue; ! 202: offt += usegs[i].sr_size; ! 203: } ! 204: fseek(cfp, 0L, SEEK_END); ! 205: textflag = (ftell(cfp) != offt); ! 206: dbprintf(("cfp_len=%lx offt=%lx textflag=%d", ftell(cfp), offt, textflag)); ! 207: #if OLD_CORE ! 208: } ! 209: #endif ! 210: ! 211: /* Set up segmentation. */ ! 212: iflag = ISPACE == DSPACE; ! 213: map_set(USEG, MIN_ADDR, (ADDR_T)UPASIZE, (off_t)regl, MAP_CORE); ! 214: map_clear(DSEG, endpure); ! 215: offt = usegs[0].sr_size; ! 216: #if OLD_CORE ! 217: if (ch_info.ch_magic == CORE_MAGIC) ! 218: offt += ch_info.ch_info_len; ! 219: #else ! 220: offt += ch_info.ch_info_len; ! 221: #endif ! 222: if (textflag) { ! 223: /* Map the text segment. */ ! 224: map_clear(ISEG, NULL); ! 225: size = usegs[SISTEXT].sr_size; ! 226: map_set(ISEG, (ADDR_T)usegs[SISTEXT].sr_base, size, offt, MAP_CORE); ! 227: offt += size; ! 228: } ! 229: for (i=1; i<NUSEG; i++) { ! 230: if (usegs[i].sr_segp == (SEG *)NULL) ! 231: continue; ! 232: if ((~usegs[i].sr_flag) & (SRFDUMP|SRFPMAP)) ! 233: continue; ! 234: size = usegs[i].sr_size; ! 235: map_set(DSEG, (ADDR_T)usegs[i].sr_base, size, offt, MAP_CORE); ! 236: offt += size; ! 237: } ! 238: if (iflag) ! 239: ISPACE = DSPACE; ! 240: get_regs(R_ALL); /* read the registers */ ! 241: if (!rflag) ! 242: set_sig(signo); /* correct signal number */ ! 243: } ! 244: ! 245: /* ! 246: * Set up segmentation for an ordinary file. ! 247: * This is really easy. ! 248: */ ! 249: void ! 250: set_file(name) char *name; ! 251: { ! 252: lfp = openfile(name, rflag); ! 253: map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_PROG); ! 254: ISPACE = DSPACE; ! 255: } ! 256: ! 257: /* ! 258: * Setup object file "name". ! 259: * The flag is bit mapped: ! 260: * 1 bit read symbol table ! 261: * 2 bit read segment information ! 262: */ ! 263: void ! 264: set_prog(name, flag) char *name; int flag; ! 265: { ! 266: dbprintf(("set_prog(%s, %d)\n", name, flag)); ! 267: lfp = openfile(name, (flag&2) ? rflag : 1); ! 268: if (fread(&coff_hdr, sizeof(coff_hdr), 1, lfp) != 1) ! 269: panic("Cannot read object file header"); ! 270: if (coff_hdr.f_magic == C_386_MAGIC) { ! 271: /* The object is a COFF file. */ ! 272: dbprintf(("IS_COFF!\n")); ! 273: file_type = COFF_FILE; ! 274: addr_fmt = ADDR_FMT; ! 275: aop_size = 32; ! 276: strcpy(seg_format[DSEG], "l"); ! 277: strcpy(seg_format[USEG], "l"); ! 278: } else { ! 279: /* Not a COFF file, might be an l.out. */ ! 280: if (fseek(lfp, 0L, SEEK_SET) == -1 ! 281: || fread(&ldh, sizeof(ldh), 1, lfp) != 1) ! 282: panic("Cannot read object file"); ! 283: canlout(); ! 284: if (ldh.l_magic != L_MAGIC) ! 285: panic("Bad object file"); ! 286: ! 287: /* The object is an l.out file. */ ! 288: dbprintf(("IS_LOUT!\n")); ! 289: file_type = LOUT_FILE; ! 290: addr_fmt = ADDR16_FMT; ! 291: aop_size = 16; ! 292: } ! 293: if ((flag&1) != 0 && !sflag) { ! 294: sfp = lfp; ! 295: if (IS_LOUT) { ! 296: nsyms = ldh.l_ssize[L_SYM] / sizeof(struct ldsym); ! 297: if (nsyms != 0) ! 298: read_lout_sym((long) sizeof(ldh) ! 299: + ldh.l_ssize[L_SHRI] + ldh.l_ssize[L_PRVI] ! 300: + ldh.l_ssize[L_SHRD] + ldh.l_ssize[L_PRVD]); ! 301: } else { ! 302: if (coff_hdr.f_nsyms != 0) ! 303: read_coff_sym(); ! 304: } ! 305: } ! 306: if ((flag&2) != 0) { ! 307: lfn = name; ! 308: if (IS_LOUT) ! 309: setloutseg(); ! 310: else ! 311: setcoffseg(); ! 312: } ! 313: } ! 314: ! 315: /* ! 316: * Setup arguments. ! 317: */ ! 318: void ! 319: setup(argc, argv) int argc; char *argv[]; ! 320: { ! 321: register char *cp; ! 322: register int c; ! 323: register int t; ! 324: register int u; ! 325: register int tflag; ! 326: ! 327: t = '\0'; ! 328: tflag = 0; ! 329: ! 330: /* Process command line switches -[cdefkorstV]. */ ! 331: for (; argc > 1; argc--, argv++) { ! 332: cp = argv[1]; ! 333: if (*cp++ != '-') ! 334: break; ! 335: while ((c = *cp++) != '\0') { ! 336: switch (c) { ! 337: case 'c': ! 338: case 'd': ! 339: case 'e': ! 340: case 'f': ! 341: case 'k': ! 342: case 'o': ! 343: /* only one of [cdefko] is allowed */ ! 344: if (t != '\0') ! 345: usage(); ! 346: t = c; ! 347: continue; ! 348: case 'p': ! 349: if (argc < 3) ! 350: usage(); ! 351: --argc; ! 352: prompt = argv[2]; ! 353: ++argv; ! 354: continue; ! 355: case 'r': ! 356: rflag = 1; ! 357: continue; ! 358: case 's': ! 359: sflag = 1; ! 360: continue; ! 361: case 't': ! 362: tflag = 1; ! 363: continue; ! 364: case 'V': ! 365: fprintf(stderr, ! 366: "db: " MCHNAME " " ! 367: #if DEBUG ! 368: "DEBUG " ! 369: #endif ! 370: #ifdef NOCANON ! 371: /* "NOCANON " */ ! 372: #endif ! 373: #ifdef NOFP ! 374: "NOFP " ! 375: #endif ! 376: "V%s\n", VERSION); ! 377: continue; ! 378: default: ! 379: usage(); ! 380: } ! 381: } ! 382: } ! 383: switch (t) { ! 384: case '\0': ! 385: switch (argc) { ! 386: case 1: ! 387: set_prog(DEFLT_OBJ, 3); ! 388: set_core(DEFLT_AUX); ! 389: break; ! 390: case 2: ! 391: set_prog(argv[1], 3); ! 392: break; ! 393: case 3: ! 394: set_prog(argv[1], 3); ! 395: set_core(argv[2]); ! 396: break; ! 397: default: ! 398: usage(); ! 399: } ! 400: break; ! 401: case 'c': ! 402: switch (argc) { ! 403: case 1: ! 404: set_prog(DEFLT_OBJ, 3); ! 405: set_core(DEFLT_AUX); ! 406: break; ! 407: case 2: ! 408: set_core(argv[1]); ! 409: break; ! 410: case 3: ! 411: set_prog(argv[1], 3); ! 412: set_core(argv[2]); ! 413: break; ! 414: default: ! 415: usage(); ! 416: } ! 417: break; ! 418: case 'd': ! 419: switch (argc) { ! 420: case 1: ! 421: set_prog("/coherent", 3); ! 422: setdump("/dev/dump"); ! 423: break; ! 424: case 3: ! 425: set_prog(argv[1], 3); ! 426: setdump(argv[2]); ! 427: break; ! 428: default: ! 429: usage(); ! 430: } ! 431: break; ! 432: case 'e': ! 433: if (argc < 2) ! 434: usage(); ! 435: set_prog(argv[1], 3); ! 436: if (startc(&argv[1], NULL, NULL, 0) == 0) ! 437: leave(); ! 438: break; ! 439: case 'f': ! 440: switch (argc) { ! 441: case 2: ! 442: set_file(argv[1]); ! 443: break; ! 444: case 3: ! 445: set_prog(argv[1], 1); ! 446: set_file(argv[2]); ! 447: break; ! 448: default: ! 449: usage(); ! 450: } ! 451: break; ! 452: case 'k': ! 453: switch (argc) { ! 454: case 1: ! 455: set_prog("/coherent", 1); ! 456: setkmem("/dev/mem"); ! 457: break; ! 458: case 2: ! 459: setkmem(argv[1]); ! 460: break; ! 461: case 3: ! 462: set_prog(argv[1], 1); ! 463: setkmem(argv[2]); ! 464: break; ! 465: default: ! 466: usage(); ! 467: } ! 468: break; ! 469: case 'o': ! 470: switch (argc) { ! 471: case 1: ! 472: set_prog(DEFLT_OBJ, 3); ! 473: break; ! 474: case 2: ! 475: set_prog(argv[1], 3); ! 476: break; ! 477: case 3: ! 478: set_prog(argv[1], 1); ! 479: set_prog(argv[2], 2); ! 480: break; ! 481: default: ! 482: usage(); ! 483: } ! 484: } ! 485: if (tflag) { ! 486: if ((u=open("/dev/tty", 2)) < 0) ! 487: panic("Cannot open /dev/tty"); ! 488: dup2(u, 0); ! 489: dup2(u, 1); ! 490: dup2(u, 2); ! 491: } ! 492: } ! 493: ! 494: /* ! 495: * Check for interrupts and clear flag. ! 496: */ ! 497: int ! 498: testint() ! 499: { ! 500: register int n; ! 501: ! 502: if ((n = intflag) != 0) { ! 503: printf("Interrupted\n"); ! 504: intflag = 0; ! 505: } ! 506: return n; ! 507: } ! 508: ! 509: /* ! 510: * Generate a verbose usage message. ! 511: */ ! 512: void ! 513: usage() ! 514: { ! 515: panic( ! 516: "Usage: db [ -cdefkorst ] [ [ mapfile ] program ]\n" ! 517: "Options:\n" ! 518: "\t-c\tprogram is a core file\n" ! 519: "\t-d\tprogram is a system dump; mapfile defaults to /coherent\n" ! 520: "\t-e\tNext argument is object file and rest of command line is passed\n" ! 521: "\t\tto the child process\n" ! 522: "\t-f\tprogram is binary data (an ordinary file)\n" ! 523: "\t-k\tprogram is a kernel process; mapfile defaults to /coherent\n" ! 524: "\t-o\tprogram is an object file\n" ! 525: "\t-p str\tUse str as interactive command prompt (default: \"db: \")\n" ! 526: "\t-r\tAccess all files read-only\n" ! 527: "\t-s\tDo not load symbol table\n" ! 528: "\t-t\tPerform input and output via /dev/tty\n" ! 529: "\tmapfile defaults to a.out or l.out.\n" ! 530: "\tprogram defaults to core.\n" ! 531: "Examples:\n" ! 532: "\tdb prog\t\tExamine, patch, execute \"prog\" under db control\n" ! 533: "\tdb prog core\tExamine postmortem core dump \"core\",\n" ! 534: "\t\t\tusing symbol table from \"prog\"\n" ! 535: "\tdb -e prog *.c\tExecute \"prog\" under db control with args *.c\n" ! 536: "\tdb -f file\tExamine and patch \"file\" as stream of bytes\n" ! 537: ); ! 538: } ! 539: ! 540: /* end of db/db1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.