|
|
1.1 ! root 1: /* ! 2: * The routines in this file make up ! 3: * a writer for the Coherent reloc.h object ! 4: * file. During code assembly all the bits get ! 5: * written to a temporary file. At the very end the ! 6: * bits get copied back to the final object file. ! 7: * The symbol table is constructed as the code is read, ! 8: * each symbol is declared when defined. References are ! 9: * tacked onto the end of the file. ! 10: * Relocation instructions for debug and symbol table entries are ! 11: * also passed through the scratch file. ! 12: */ ! 13: #ifdef vax ! 14: #include "INC$LIB:cc2.h" ! 15: #include "INC$LIB:canon.h" ! 16: #include "INC$LIB:reloc.h" ! 17: #include "INC$LIB:debug.h" ! 18: #else ! 19: #include "cc2.h" ! 20: #include <canon.h> ! 21: #include <reloc.h> ! 22: #include <debug.h> ! 23: #endif ! 24: ! 25: #if !TINY ! 26: #define dbrpt(x,y) _dbrpt(x,y) ! 27: #else ! 28: #define dbrpt(x,y) /* dbrpt(x,y) */ ! 29: #endif ! 30: #define NTXT 512 /* Text buffer size */ ! 31: #define NREL 256 /* Relocation buffer size */ ! 32: /* ! 33: * Scratch file operators. ! 34: */ ! 35: #define TTYPE 017 /* Type mask */ ! 36: #define Tflag(x) (((x)>>4)&7) /* Get flag bits */ ! 37: #define TEND 000 /* End marker */ ! 38: #define TENTER 001 /* Enter new area */ ! 39: #define TBYTE 002 /* Byte data */ ! 40: #define TWORD 003 /* Word data */ ! 41: #if 0 ! 42: #define TTRIP 004 /* Triple byte data */ ! 43: #define TLONG 005 /* Long data */ ! 44: #endif ! 45: #define TDLAB 006 /* Debug item */ ! 46: #define TDLOC 007 /* Debug location */ ! 47: #define TCODE 010 /* Code segment base */ ! 48: #define TDATA 011 /* Data segment base */ ! 49: #define TBASE 012 /* External segment base */ ! 50: ! 51: #define TPCR 020 /* PC rel flag, ored in */ ! 52: #define TSYM 040 /* Symbol based flag, ored in */ ! 53: #define locrup(x) (((x)+01)&~01) /* memory alignment */ ! 54: objhdr_t objhdr = { /* object header */ ! 55: REL_OBJ, ! 56: "i8086", ! 57: "C", ! 58: VERSMWC ! 59: }; ! 60: ! 61: summseg_t summseg = { /* Summary segment */ ! 62: SUMMARY, ! 63: sizeof (summseg.seg_off) ! 64: }; ! 65: ! 66: extern char *calloc(); ! 67: extern char *malloc(); ! 68: extern char *strcpy(); ! 69: ! 70: ADDRESS SCODE_len; /* Length of SCODE in bytes */ ! 71: char txt[NTXT]; /* Text buffer */ ! 72: char rel[NREL]; /* Relocation buffer */ ! 73: char *txtp = txt; /* Text pointer */ ! 74: char *relp = rel; /* Relocation pointer */ ! 75: int refnum = 0; /* Symbol reference number */ ! 76: static int level = 0; /* Debug brace level */ ! 77: static int dline = 0; /* Most recent line number entry */ ! 78: ! 79: /* ! 80: * This table converts a C compiler ! 81: * segment index into a relocatable object segment type. ! 82: */ ! 83: char segindex[] = { ! 84: PURCODE, /* SCODE */ ! 85: OWNCODE, /* SLINK */ ! 86: PURDATA, /* SPURE */ ! 87: STRINGS, /* SSTRN */ ! 88: OWNDATA, /* SDATA */ ! 89: BLDATA, /* SBSS */ ! 90: -1, /* SANY */ ! 91: -1, /* SSTACK */ ! 92: -1, /* SALIEN */ ! 93: DEBUG, /* SDBG */ ! 94: SYMBOLS /* SSYM */ ! 95: }; ! 96: ! 97: /* ! 98: * Output a segment switch. ! 99: */ ! 100: outseg(s) ! 101: { ! 102: bput(TENTER); ! 103: bput(s); ! 104: } ! 105: ! 106: /* ! 107: * Output an absolute byte. ! 108: */ ! 109: outab(b) ! 110: { ! 111: bput(TBYTE); ! 112: bput(b); ! 113: dot += 1; ! 114: } ! 115: ! 116: /* ! 117: * Output an absolute word. ! 118: */ ! 119: outaw(w) ! 120: { ! 121: bput(TWORD); ! 122: iput(w); ! 123: dot += 2; ! 124: } ! 125: ! 126: ! 127: #ifdef TLONG ! 128: /* ! 129: * Output an absolute long. ! 130: */ ! 131: outal(l) ! 132: long l; ! 133: { ! 134: bput(TLONG); ! 135: lput(l); ! 136: dot += 4; ! 137: } ! 138: #endif ! 139: ! 140: /* ! 141: * Output a full byte. ! 142: */ ! 143: outxb(sp, b, pcrf) ! 144: register SYM *sp; ! 145: { ! 146: register opcode; ! 147: ! 148: opcode = TBYTE; ! 149: if (sp != NULL) ! 150: opcode |= TSYM; ! 151: if (pcrf) ! 152: opcode |= TPCR; ! 153: bput(opcode); ! 154: bput(b); ! 155: if (sp != NULL) ! 156: pput(sp); ! 157: dot += 1; ! 158: } ! 159: ! 160: /* ! 161: * Output a full word. ! 162: */ ! 163: outxw(sp, w, pcrf) ! 164: register SYM *sp; ! 165: { ! 166: register opcode; ! 167: ! 168: opcode = TWORD; ! 169: if (sp != NULL) ! 170: opcode |= TSYM; ! 171: if (pcrf) ! 172: opcode |= TPCR; ! 173: bput(opcode); ! 174: iput(w); ! 175: if (sp != NULL) ! 176: pput(sp); ! 177: dot += 2; ! 178: } ! 179: ! 180: #ifdef TLONG ! 181: /* ! 182: * Output a full long. ! 183: */ ! 184: outxl(sp, l, pcrf) ! 185: register SYM *sp; ! 186: long l; ! 187: { ! 188: register opcode; ! 189: ! 190: opcode = TLONG; ! 191: if (sp != NULL) ! 192: opcode |= TSYM; ! 193: if (pcrf) ! 194: opcode |= TPCR; ! 195: bput(opcode); ! 196: lput(lR); ! 197: if (sp != NULL) ! 198: pput(sp); ! 199: dot += 4; ! 200: } ! 201: #endif ! 202: ! 203: /* ! 204: * Copy a dlabel record from ifp to ofp. ! 205: * Flag the symbol table entry if appropriate. ! 206: */ ! 207: outdlab(l,class) ! 208: { ! 209: register int val; ! 210: register SYM *sp; ! 211: int n; ! 212: ! 213: if (l == 0) ! 214: bput(TDLAB); ! 215: bput(class); ! 216: ! 217: /* Get line number. */ ! 218: iput(iget()); ! 219: ! 220: /* Get value */ ! 221: if (class < DC_AUTO) ! 222: ; ! 223: else if (class < DC_MOS) ! 224: iput(val = iget()); ! 225: else { ! 226: bput(bget()); ! 227: bput(bget()); ! 228: iput(iget()); ! 229: } ! 230: ! 231: /* Get name */ ! 232: sget(id, NCSYMB); ! 233: ! 234: /* Check for symbol table entry */ ! 235: if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) { ! 236: sp = glookup(id, 0); ! 237: sp->s_flag |= S_PUT; ! 238: } else if (class==DC_SIN) { ! 239: sp = llookup(val, 0); ! 240: sp->s_flag |= S_PUT; ! 241: } ! 242: ! 243: /* Put name */ ! 244: sput(id); ! 245: ! 246: /* Get type */ ! 247: for (;;) { ! 248: switch (bput(bget())) { ! 249: case DT_NONE: ! 250: case DT_CHAR: ! 251: case DT_UCHAR: ! 252: case DT_SHORT: ! 253: case DT_USHORT: ! 254: case DT_INT: ! 255: case DT_UINT: ! 256: case DT_LONG: ! 257: case DT_ULONG: ! 258: case DT_FLOAT: ! 259: case DT_DOUBLE: ! 260: case DT_VOID: ! 261: iput(iget()); ! 262: break; ! 263: case DT_STRUCT: ! 264: case DT_UNION: ! 265: case DT_ENUM: ! 266: case DD_PTR: ! 267: case DD_FUNC: ! 268: case DD_ARRAY: ! 269: iput(iget()); ! 270: continue; ! 271: break; ! 272: case DX_MEMBS: ! 273: bput(n = iget()); ! 274: for ( ; n > 0; n-=1) { ! 275: outdlab(1, bget()); ! 276: } ! 277: break; ! 278: case DX_NAME: ! 279: iget(); ! 280: sget(id, NCSYMB); ! 281: sput(id); ! 282: break; ! 283: default: ! 284: cbotch("outdlab: %d", n); ! 285: } ! 286: break; ! 287: } ! 288: } ! 289: ! 290: /* ! 291: * Output a debug line record. ! 292: */ ! 293: outdlin(op) ! 294: { ! 295: bput(TDLAB); ! 296: bput(DC_LINE); ! 297: iput(line); ! 298: bput(op); ! 299: bput(0); ! 300: bput(DT_NONE); ! 301: iput(0); ! 302: } ! 303: ! 304: /* ! 305: * Output a debug relocation record. ! 306: */ ! 307: outdloc(n) ! 308: { ! 309: bput(TDLOC); ! 310: iput(n); ! 311: } ! 312: ! 313: /* ! 314: * Abort illegal output. ! 315: * reloc.h doesn't handle 8087 or Large model. ! 316: */ ! 317: outbad() ! 318: { ! 319: cbotch("bad temp file object"); ! 320: } ! 321: ! 322: /* ! 323: * Output a 1 word object containing ! 324: * the base address of the current code ! 325: * segment. ! 326: */ ! 327: outcb() ! 328: { ! 329: return (outbad()); ! 330: bput(TCODE); ! 331: dot += 2; ! 332: } ! 333: ! 334: /* ! 335: * Output a 1 word object containing ! 336: * the base address of the current data ! 337: * segment. ! 338: */ ! 339: outdb() ! 340: { ! 341: return (outbad()); ! 342: bput(TDATA); ! 343: dot += 2; ! 344: } ! 345: ! 346: /* ! 347: * Output a 1 word object containing ! 348: * the base address of the external symbol ! 349: * pointed to by `sp'. ! 350: */ ! 351: outsb(sp) ! 352: SYM *sp; ! 353: { ! 354: return (outbad()); ! 355: bput(TBASE); ! 356: pput(sp); ! 357: dot += 2; ! 358: } ! 359: ! 360: /* ! 361: * Initialize the code writer. ! 362: * This routine is called before anything is written to the scratch file. ! 363: * A no op on coherent reloc.h format. ! 364: */ ! 365: outinit() ! 366: { ! 367: } ! 368: ! 369: /* ! 370: * Finish off the code writer. ! 371: * This routine is called just before the scratch file is closed. ! 372: * Write either the "end" to the output file ! 373: * if generating assembler, ! 374: * or a "TEND" code to stop the ! 375: * "copycode" routine if writing binary. ! 376: */ ! 377: outdone() ! 378: { ! 379: register SYM *sp; ! 380: register int i; ! 381: ! 382: if (isvariant(VASM)) { ! 383: return; ! 384: } ! 385: ! 386: /* ! 387: * Assign refnums to symbols. ! 388: * And make dlabel items for internally generated symbols. ! 389: */ ! 390: for (refnum = i = 0; i < NSHASH; i++) { ! 391: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) { ! 392: if ((sp->s_flag&S_GBL) != 0 ! 393: || (sp->s_flag&S_DEF) == 0) { ! 394: if ((sp->s_flag&S_LABNO) == 0) ! 395: sp->s_ref = refnum++; ! 396: if ((sp->s_flag&S_PUT) == 0) { ! 397: bput(TDLAB); ! 398: bput(DC_GREF); ! 399: iput(0); ! 400: sput(sp->s_id); ! 401: bput(DT_NONE); ! 402: iput(0); ! 403: } ! 404: } ! 405: } ! 406: } ! 407: ! 408: bput(TEND); ! 409: } ! 410: ! 411: /* ! 412: * Copy back. ! 413: * Figure out the sizes and final values ! 414: * of everything. Copy the code from the scratch ! 415: * file back to the output file. ! 416: */ ! 417: copycode() ! 418: { ! 419: int op, nd, nr; ! 420: ADDRESS data; ! 421: long addr; ! 422: fsize_t size, symsize; ! 423: unsigned char reltype, segtype; ! 424: ! 425: SCODE_len = seg[SCODE].s_dot; ! 426: ! 427: /* ! 428: * Initialize output. ! 429: */ ! 430: oheader(0); ! 431: ! 432: /* ! 433: * Copy out code. ! 434: */ ! 435: dotseg = SCODE; ! 436: dot = 0; ! 437: while ((op=bget()) != TEND) { ! 438: switch (op & TTYPE) { ! 439: ! 440: case TENTER: ! 441: oenter(bget()); ! 442: continue; ! 443: ! 444: case TBYTE: ! 445: nd = 1; ! 446: reltype = B_0; ! 447: data = bget(); ! 448: break; ! 449: ! 450: case TWORD: ! 451: nd = 2; ! 452: reltype = B_01; ! 453: data = iget(); ! 454: break; ! 455: ! 456: #ifdef TLONG ! 457: case TLONG: ! 458: nd = 4; ! 459: reltype = B_0123; ! 460: data = lget(); ! 461: break; ! 462: #endif ! 463: ! 464: case TDLAB: ! 465: getdlab(); ! 466: continue; ! 467: ! 468: case TDLOC: ! 469: getdloc(); ! 470: continue; ! 471: ! 472: default: ! 473: cbotch("copycode: op=%d", op); ! 474: ! 475: } ! 476: ! 477: switch (Tflag(op)) { ! 478: ! 479: case 0: /* Absolute */ ! 480: nr = 0; ! 481: break; ! 482: ! 483: case Tflag(TPCR|TSYM): /* Symbol based pc relative */ ! 484: data -= dot+nd; ! 485: /* Fall through */ ! 486: ! 487: case Tflag(TSYM): /* Symbol based */ ! 488: { ! 489: register SYM *sp; ! 490: ! 491: sp = pget(); ! 492: if ((sp->s_flag&S_DEF) != 0) { ! 493: nr = 6; ! 494: segtype = segindex[sp->s_seg]; ! 495: data += sp->s_value; ! 496: } else { ! 497: nr = 10; ! 498: segtype = SYMBOLS; ! 499: addr = sp->s_ref; ! 500: } ! 501: if ((op&TPCR) != 0) ! 502: segtype |= PCREL; ! 503: break; ! 504: } ! 505: ! 506: case Tflag(TPCR): /* Absolute pc relative */ ! 507: data -= dot+nd; ! 508: segtype = ABSLUTE|PCREL; ! 509: nr = 10; ! 510: addr = 0; ! 511: break; ! 512: ! 513: default: ! 514: cbotch("copycode: flags=%o", op); ! 515: } ! 516: ! 517: /* ! 518: * Write the current record. ! 519: */ ! 520: enuf(nd, nr); ! 521: if (nr != 0) { ! 522: rbbuf(reltype); ! 523: rbbuf(segtype); ! 524: rlbuf((long) dot); ! 525: if (nr == 10) ! 526: rlbuf(addr); ! 527: } ! 528: do { ! 529: bbuf((int) data); ! 530: data >>= 8; ! 531: } while (--nd > 0); ! 532: } ! 533: ! 534: if (isvariant(VLINES)) ! 535: outbrace('}'); ! 536: if (notvariant(VLIB)) ! 537: dump(); /* Dump the typedefs */ ! 538: ! 539: /* ! 540: * Flush buffers. ! 541: */ ! 542: notenuf(); ! 543: ! 544: /* ! 545: * Write symbol table. ! 546: */ ! 547: summseg.seg_off[SYMBOLS] = ftell(ofp); ! 548: segtype = SYMBOLS; ! 549: bput(segtype); ! 550: size = symsize; ! 551: cansize(size); ! 552: owrite(&size, sizeof(size)); ! 553: addr = refnum; ! 554: canuaddr(addr); ! 555: owrite(&addr, sizeof(addr)); ! 556: oglobals(); ! 557: symsize = ftell(ofp) - summseg.seg_off[SYMBOLS] - sizeof(fsize_t) - 1; ! 558: ! 559: /* ! 560: * Put end marker. ! 561: */ ! 562: segtype = LASTSEG; ! 563: bput(segtype); ! 564: ! 565: /* ! 566: * Now go back and patch the remaining holes. ! 567: */ ! 568: fseek(ofp, (fsize_t)0, 0); ! 569: oheader(1); ! 570: ! 571: /* ! 572: * Symbol segment size and count. ! 573: */ ! 574: fseek(ofp, summseg.seg_off[SYMBOLS]+1, 0); ! 575: size = symsize; ! 576: cansize(size); ! 577: owrite(&size, sizeof(size)); ! 578: addr = refnum; ! 579: canuaddr(addr); ! 580: owrite(&addr, sizeof(addr)); ! 581: } ! 582: ! 583: /* ! 584: * Switch segments. ! 585: */ ! 586: oenter(newseg) ! 587: register int newseg; ! 588: { ! 589: notenuf(); ! 590: if (dotseg != SSYM) ! 591: seg[dotseg].s_dot = dot; ! 592: dotseg = newseg; ! 593: if (dotseg != SSYM) ! 594: dot = seg[dotseg].s_dot; ! 595: else ! 596: dot = 0; ! 597: } ! 598: ! 599: /* ! 600: * This routine checks to see if ! 601: * there is enough room in the text and relocation ! 602: * buffers to hold `nt' bytes of text and `nr' bytes of ! 603: * relocation. ! 604: */ ! 605: enuf(nt, nr) ! 606: { ! 607: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL]) ! 608: notenuf(); ! 609: } ! 610: ! 611: /* ! 612: * Flush buffers. ! 613: */ ! 614: notenuf() ! 615: { ! 616: register n; ! 617: unsigned char segtype; ! 618: fsize_t size; ! 619: ! 620: if ((n=txtp-txt) != 0) { ! 621: if (dotseg != SSYM) { ! 622: segtype = segindex[dotseg]; ! 623: bput(segtype); ! 624: size = n; ! 625: cansize(size); ! 626: owrite(&size, sizeof(size)); ! 627: } ! 628: owrite(txt, n); ! 629: if ((n=relp-rel) != 0) { ! 630: segtype = RELOCN; ! 631: bput(segtype); ! 632: size = n; ! 633: cansize(size); ! 634: owrite(&size, sizeof(size)); ! 635: owrite(rel, n); ! 636: relp = rel; ! 637: } ! 638: } ! 639: txtp = txt; ! 640: } ! 641: ! 642: /* ! 643: * Write a byte or long to text or relocation buffers ! 644: * in canonical ordering. ! 645: */ ! 646: bbuf(b) ! 647: { ! 648: *txtp++ = b; ! 649: dot += 1; ! 650: } ! 651: ! 652: lbuf(l) ! 653: long l; ! 654: { ! 655: *txtp++ = l >> 16; ! 656: *txtp++ = l >> 24; ! 657: *txtp++ = l; ! 658: *txtp++ = l >> 8; ! 659: dot += 4; ! 660: } ! 661: ! 662: rbbuf(b) ! 663: { ! 664: *relp++ = b; ! 665: } ! 666: ! 667: rlbuf(l) ! 668: long l; ! 669: { ! 670: *relp++ = l >> 16; ! 671: *relp++ = l >> 24; ! 672: *relp++ = l; ! 673: *relp++ = l >> 8; ! 674: } ! 675: ! 676: /* ! 677: * Write a block of bytes to the output file. ! 678: */ ! 679: owrite(p, n) ! 680: register char *p; ! 681: register int n; ! 682: { ! 683: while (--n >= 0) ! 684: bput(*p++); ! 685: } ! 686: ! 687: /* ! 688: * Write the header and summary segment. ! 689: * Summary is complete on second call only. ! 690: */ ! 691: oheader(n) ! 692: { ! 693: fsize_t offs; ! 694: register int i; ! 695: register struct seg *segp; ! 696: ! 697: /* ! 698: * Write header. ! 699: */ ! 700: owrite(&objhdr, sizeof(objhdr)); ! 701: ! 702: /* ! 703: * Copy segment sizes into summary segment. ! 704: */ ! 705: for (segp = &seg[i=0]; i < NSEG; segp++, i++) { ! 706: if (segindex[i] < 0 || i == SSYM) continue; ! 707: offs = segp->s_dot; ! 708: if (i != SDBG) ! 709: offs = locrup(offs); ! 710: if (n == 0 || i >= SDBG) ! 711: summseg.seg_off[segindex[i]] += offs; ! 712: segp->s_dot = 0; ! 713: } ! 714: /* ! 715: * Write summary segment. ! 716: */ ! 717: bput(summseg.seg_type); ! 718: offs = summseg.seg_size; ! 719: cansize(offs); ! 720: owrite(&offs, sizeof(offs)); ! 721: for (i=0; i<SUMMARY; i+=1) { ! 722: offs = summseg.seg_off[i]; ! 723: cansize(offs); ! 724: owrite(&offs, sizeof(offs)); ! 725: } ! 726: } ! 727: ! 728: /* ! 729: * Structure to contain debug items on this pass. ! 730: */ ! 731: struct dbgt { ! 732: struct dbgt *d_dp; /* Link */ ! 733: int d_ref; /* Index number */ ! 734: unsigned char d_class; /* Storage class */ ! 735: unsigned char d_flag; /* Flags */ ! 736: unsigned char d_level; /* Bracket level */ ! 737: unsigned char d_seg; /* Segment */ ! 738: ADDRESS d_value; /* Offset in segment */ ! 739: int d_size; /* Size of d_data */ ! 740: char d_data[]; /* Name and type */ ! 741: }; ! 742: #define D_GBL 1 ! 743: #define D_LCL 2 ! 744: #define D_TAG 4 ! 745: #define D_NAM 8 ! 746: #define D_LAB 16 ! 747: #define D_ENU 32 ! 748: ! 749: struct dbgt *newdbgt(); ! 750: struct dbgt *getdbgt(); ! 751: struct dbgt *dbase; ! 752: struct dbgt *dnext; ! 753: char *getmembs(); ! 754: ! 755: /* ! 756: * Read debug table item(s) into memory. ! 757: */ ! 758: getdlab() ! 759: { ! 760: register struct dbgt *dp; ! 761: static int refnum = 0; ! 762: ! 763: dp = getdbgt(); ! 764: ! 765: /* This should be done in cc0 */ ! 766: ! 767: if (isvariant(VLIB)) { ! 768: switch (dp->d_class) { ! 769: case DC_TYPE: ! 770: case DC_STAG: ! 771: case DC_UTAG: ! 772: case DC_ETAG: ! 773: return; ! 774: } ! 775: } ! 776: if (dp->d_class == DC_LINE || dp->d_class == DC_LAB) ! 777: dp->d_ref = refnum; ! 778: ! 779: refnum += 1; ! 780: if (dbase == NULL) ! 781: dbase = dp; ! 782: if (dnext != NULL) ! 783: dnext->d_dp = dp; ! 784: dbrpt("enter", dp); ! 785: while (dp->d_dp != NULL) { ! 786: dp = dp->d_dp; ! 787: dbrpt("enter", dp); ! 788: } ! 789: dnext = dp; ! 790: if (dp->d_class == DC_FILE) ! 791: outbrace('{'); ! 792: } ! 793: ! 794: /* ! 795: * Read a debug relocation item and patch current `dot' ! 796: * into the appropriate debug/symbol table item. ! 797: * If the debug item is '}' and level 2, then dump the batch of locals. ! 798: * If the debug item is '}' and level 1, then dump the type definitions. ! 799: */ ! 800: getdloc() ! 801: { ! 802: register struct dbgt *dp; ! 803: register int ref; ! 804: ! 805: ref = iget(); ! 806: for (dp = dbase; ; dp = dp->d_dp) { ! 807: if (dp == NULL) ! 808: cbotch("getdloc: %d", ref); ! 809: if ((dp->d_flag&D_GBL) != 0) ! 810: continue; ! 811: if (dp->d_ref == ref) ! 812: break; ! 813: } ! 814: dp->d_seg = segindex[dotseg]; ! 815: dp->d_value = dot; ! 816: ! 817: dbrpt("reloc", dp); ! 818: if (dp->d_data[0] == '}' && dp->d_level <= 2) { ! 819: outbrace('}'); ! 820: level--; ! 821: dump(); ! 822: } ! 823: } ! 824: ! 825: /* ! 826: * Dump the locals and type definitions ! 827: */ ! 828: ! 829: dump() ! 830: { ! 831: register struct dbgt *dp, **dpp; ! 832: int saveseg; ! 833: ! 834: if ((saveseg = dotseg) != SDBG) ! 835: oenter(SDBG); ! 836: dpp = &dbase; ! 837: dnext = NULL; ! 838: while ((dp = *dpp) != NULL) { ! 839: if ((dp->d_flag&D_LCL) != 0) { ! 840: dbrpt("write", dp); ! 841: osymbol(dp, -1); ! 842: dp->d_flag &= ~D_LCL; ! 843: } ! 844: if ((dp->d_flag&D_GBL) == 0) { ! 845: dbrpt("free", dp); ! 846: *dpp = dp->d_dp; ! 847: free(dp); ! 848: } else { ! 849: dbrpt("save", dp); ! 850: dnext = dp; ! 851: dpp = &dp->d_dp; ! 852: } ! 853: } ! 854: if (saveseg != SDBG) ! 855: oenter(saveseg); ! 856: } ! 857: ! 858: /* ! 859: * Write out global symbol definitions and references. ! 860: */ ! 861: oglobals() ! 862: { ! 863: register struct dbgt *dp, *dp1; ! 864: extern int refnum; ! 865: ! 866: oenter(SSYM); ! 867: for (dp = dbase; dp != NULL; dp = dp1) { ! 868: dp1 = dp->d_dp; ! 869: dbrpt("write", dp); ! 870: if (dp->d_seg == TYPESYM || dp->d_seg == ABSLUTE) ! 871: osymbol(dp, refnum++); ! 872: else ! 873: osymbol(dp, dp->d_ref); ! 874: dbrpt("free", dp); ! 875: free(dp); ! 876: } ! 877: notenuf(); ! 878: } ! 879: ! 880: /* ! 881: * Write out a symbol to the symbol or debug table. ! 882: * Debug table symbols have negative refnums, ! 883: * and may require relocation. ! 884: */ ! 885: osymbol(dp, refnum) ! 886: register struct dbgt *dp; ! 887: { ! 888: register char *cp; ! 889: unsigned char segtype; ! 890: uaddr_t segaddr; ! 891: int nd, nr; ! 892: ! 893: /* Write scope/refnum or seg/value+relocation expression */ ! 894: nd = 5 + dp->d_size; ! 895: nr = 0; ! 896: if (refnum >= 0) { ! 897: if (dp->d_seg == ABSLUTE) { ! 898: segtype = MDSCOPE; ! 899: nd += 5; ! 900: } else if (dp->d_seg != LASTSEG) { ! 901: segtype = LDSCOPE; ! 902: nd += 5; ! 903: } else ! 904: segtype = RFSCOPE; ! 905: segaddr = refnum; ! 906: } else { ! 907: segtype = dp->d_seg; ! 908: segaddr = dp->d_value; ! 909: if (segtype < SUMMARY ! 910: && segtype != TYPESYM ! 911: && segtype != ABSLUTE) ! 912: nr = 6; ! 913: } ! 914: enuf(nd, nr); ! 915: bbuf(segtype); ! 916: if (nr != 0) { ! 917: rbbuf(B_2301); ! 918: rbbuf(dp->d_seg); ! 919: rlbuf((long) dot); ! 920: } ! 921: lbuf(segaddr); ! 922: ! 923: /* Write name */ ! 924: cp = dp->d_data; ! 925: nd = dp->d_size; ! 926: do { ! 927: bbuf(*cp); ! 928: nd -= 1; ! 929: } while (*cp++); ! 930: ! 931: /* Write seg/value expression */ ! 932: if (refnum >= 0 && (segtype == MDSCOPE || segtype == LDSCOPE)) { ! 933: bbuf(dp->d_seg); ! 934: lbuf((long) dp->d_value); ! 935: } ! 936: ! 937: /* Type */ ! 938: while (--nd >= 0) ! 939: bbuf(*cp++); ! 940: } ! 941: ! 942: /* ! 943: * Read in debug items translating into loader type syntax. ! 944: * Member definitions are fetched recursively. ! 945: * If a tag or type definition, the member definitions are appended to the ! 946: * node surrounded by "{" and "}" nodes. ! 947: * If not a tag definition, the member definitions are discarded. ! 948: * In either case, the member types are appended to the type of the ! 949: * parent node. ! 950: */ ! 951: #define DSZ 512 ! 952: struct dbgt * ! 953: getdbgt() ! 954: { ! 955: register int n; ! 956: register char *dptr; ! 957: struct dbgt d; ! 958: char data[DSZ]; ! 959: int value, width, offs; ! 960: int typet, subt, membs; ! 961: char *sdp; ! 962: ! 963: d.d_dp = NULL; ! 964: d.d_ref = -1; ! 965: d.d_flag = D_LCL; ! 966: d.d_level = level; ! 967: d.d_seg = LASTSEG; ! 968: d.d_value = 0; ! 969: d.d_size = 0; ! 970: width = membs = 0; ! 971: ! 972: /* ! 973: * Loop to read entire record: ! 974: * class, optional value, name, type. ! 975: */ ! 976: dptr = data; ! 977: for (typet = 0; ; typet += 1) { ! 978: ! 979: if (dptr >= data+DSZ) { ! 980: dbrpt("1", &d); ! 981: cbotch("getdbgt buffer"); ! 982: } ! 983: ! 984: n = bget(); ! 985: if (n < DX_MEMBS) ! 986: value = iget() * NBPBYTE; ! 987: else if (n < DC_SEX) ! 988: ; ! 989: else { ! 990: dline = iget(); ! 991: if (n < DC_AUTO) ! 992: ; ! 993: else if (n < DC_MOS) ! 994: value = iget(); ! 995: else { ! 996: width = bget(); ! 997: offs = bget(); ! 998: value = iget(); ! 999: } ! 1000: } ! 1001: subt = 0; ! 1002: ! 1003: switch (n) { ! 1004: ! 1005: /* ! 1006: * Classes: fetch values and set flags. ! 1007: */ ! 1008: case DC_SEX: ! 1009: d.d_flag |= D_NAM; ! 1010: goto setclass; ! 1011: ! 1012: case DC_GDEF: ! 1013: case DC_GREF: ! 1014: d.d_flag = D_GBL|D_NAM; ! 1015: goto setclass; ! 1016: ! 1017: case DC_ETAG: ! 1018: d.d_flag |= D_ENU; ! 1019: strcpy(dptr, "enum "); ! 1020: dptr += 5; ! 1021: goto tag; ! 1022: case DC_STAG: ! 1023: strcpy(dptr, "struct "); ! 1024: dptr += 7; ! 1025: goto tag; ! 1026: case DC_UTAG: ! 1027: strcpy(dptr, "union "); ! 1028: dptr += 6; ! 1029: case DC_TYPE: ! 1030: tag: ! 1031: d.d_flag = (level == 0) ? D_TAG|D_GBL : D_TAG|D_LCL; ! 1032: d.d_seg = TYPESYM; ! 1033: goto setclass; ! 1034: ! 1035: case DC_FILE: ! 1036: d.d_seg = PURCODE; ! 1037: goto setclass; ! 1038: ! 1039: case DC_AUTO: ! 1040: d.d_seg = L_STACK; ! 1041: d.d_value = value; ! 1042: goto setclass; ! 1043: ! 1044: case DC_SIN: ! 1045: d.d_flag |= D_LAB; ! 1046: goto setclass; ! 1047: ! 1048: case DC_REG: ! 1049: d.d_seg = L_REG; ! 1050: d.d_value = value; ! 1051: goto setclass; ! 1052: ! 1053: case DC_PREG: ! 1054: if (level == 0) { ! 1055: level++; ! 1056: outbrace('{'); ! 1057: } ! 1058: d.d_seg = L_REG; ! 1059: d.d_value = value; ! 1060: goto setclass; ! 1061: ! 1062: case DC_MOE: ! 1063: d.d_seg = ABSLUTE; ! 1064: d.d_value = value; ! 1065: goto setclass; ! 1066: ! 1067: case DC_PAUTO: ! 1068: if (level == 0) { ! 1069: level++; ! 1070: outbrace('{'); ! 1071: } ! 1072: d.d_seg = P_STACK; ! 1073: d.d_value = value; ! 1074: goto setclass; ! 1075: ! 1076: case DC_LAB: ! 1077: case DC_LINE: ! 1078: goto setclass; ! 1079: ! 1080: case DC_MOS: ! 1081: case DC_MOU: ! 1082: d.d_seg = FLD_OFF; ! 1083: d.d_value = value * NBPBYTE + offs; ! 1084: goto setclass; ! 1085: ! 1086: /* ! 1087: * Set the class field, read the name; ! 1088: * Lookup globals and statics. ! 1089: */ ! 1090: setclass: ! 1091: d.d_class = n; ! 1092: while (*dptr++ = bget()) ! 1093: ; ! 1094: if ((d.d_flag&(D_NAM|D_LAB)) != 0) { ! 1095: register SYM *sp; ! 1096: ! 1097: if ((d.d_flag&D_NAM) != 0) ! 1098: sp = glookup(data, 0); ! 1099: else ! 1100: sp = llookup(value, 0); ! 1101: if ((sp->s_flag&S_DEF) != 0) { ! 1102: d.d_seg = segindex[sp->s_seg]; ! 1103: d.d_value = sp->s_value; ! 1104: #if COMMON ! 1105: } else if (sp->s_value != 0) { ! 1106: d.d_seg = BLDATA|Cb; ! 1107: d.d_value = sp->s_value; ! 1108: #endif ! 1109: } ! 1110: if ((d.d_flag&D_GBL) != 0) ! 1111: d.d_ref = sp->s_ref; ! 1112: } ! 1113: continue; ! 1114: ! 1115: /* ! 1116: * Types: write type and prepare for trailing data. ! 1117: * For files and lines, write a phony type. ! 1118: */ ! 1119: case DT_NONE: ! 1120: if (d.d_class == DC_FILE) { ! 1121: register char *p; ! 1122: ! 1123: *dptr++ = STRINGt; ! 1124: p = "source file"; ! 1125: while (*dptr++ = *p++) ! 1126: ; ! 1127: } ! 1128: if (d.d_class == DC_LINE) { ! 1129: *dptr++ = 6; /* Line */ ! 1130: *dptr++ = dline; ! 1131: *dptr++ = dline >> 8; ! 1132: *dptr++ = 0; /* Column */ ! 1133: *dptr++ = 0; /* Flag */ ! 1134: *dptr++ = 0; /* Saved instruction */ ! 1135: *dptr++ = 0; ! 1136: } ! 1137: break; ! 1138: ! 1139: case DT_CHAR: ! 1140: case DT_SHORT: ! 1141: case DT_INT: ! 1142: case DT_LONG: ! 1143: n = Integer; ! 1144: goto getwidth; ! 1145: ! 1146: case DT_UCHAR: ! 1147: case DT_USHORT: ! 1148: case DT_UINT: ! 1149: case DT_ULONG: ! 1150: n = Natural; ! 1151: goto getwidth; ! 1152: ! 1153: case DT_FLOAT: ! 1154: case DT_DOUBLE: ! 1155: n = Rational; ! 1156: goto settype; ! 1157: ! 1158: case DT_VOID: ! 1159: n = Void; ! 1160: goto settype; ! 1161: ! 1162: case DT_STRUCT: ! 1163: membs = n; ! 1164: n = Record; ! 1165: sdp = dptr; ! 1166: goto settype; ! 1167: ! 1168: case DT_UNION: ! 1169: membs = n; ! 1170: n = Union; ! 1171: sdp = dptr; ! 1172: goto settype; ! 1173: ! 1174: case DT_ENUM: ! 1175: d.d_flag |= D_ENU; ! 1176: membs = n; ! 1177: n = Natural; ! 1178: sdp = dptr; ! 1179: goto settype; ! 1180: ! 1181: getwidth: ! 1182: if (width) ! 1183: value = width; ! 1184: ! 1185: settype: ! 1186: *dptr++ = 1; ! 1187: *dptr++ = n; ! 1188: if (n != Void) { ! 1189: if (value == 0) ! 1190: *dptr++ = ANYt; ! 1191: else if (value <= 0377) { ! 1192: *dptr++ = 1; ! 1193: *dptr++ = value; ! 1194: } else { ! 1195: *dptr++ = 2; ! 1196: *dptr++ = value; ! 1197: *dptr++ = value >> 8; ! 1198: } ! 1199: } ! 1200: if (subt) { ! 1201: *dptr++ = TYPEt; ! 1202: continue; ! 1203: } ! 1204: if (membs) { ! 1205: --typet; ! 1206: continue; ! 1207: } ! 1208: break; ! 1209: ! 1210: /* ! 1211: * Dimensions: as for types, but flag for subtypes. ! 1212: */ ! 1213: case DD_PTR: ! 1214: n = Pointer; ! 1215: ++subt; ! 1216: goto settype; ! 1217: ! 1218: case DD_FUNC: ! 1219: n = Proc; ! 1220: ++subt; ! 1221: goto settype; ! 1222: ! 1223: case DD_ARRAY: ! 1224: n = Array; ! 1225: ++subt; ! 1226: goto settype; ! 1227: ! 1228: /* ! 1229: * Trailing struct/union/enum data. ! 1230: */ ! 1231: case DX_NAME: ! 1232: dptr = sdp; ! 1233: *dptr++ = STRINGt; ! 1234: switch (membs) { ! 1235: case DT_STRUCT: ! 1236: strcpy(dptr, "struct "); ! 1237: dptr += 7; ! 1238: break; ! 1239: case DT_UNION: ! 1240: strcpy(dptr, "union "); ! 1241: dptr += 6; ! 1242: break; ! 1243: case DT_ENUM: ! 1244: strcpy(dptr, "enum "); ! 1245: dptr += 5; ! 1246: } ! 1247: while (*dptr++ = bget()) ! 1248: ; ! 1249: membs = 0; ! 1250: break; ! 1251: ! 1252: case DX_MEMBS: ! 1253: level += 1; ! 1254: dptr = getmembs(&d, data, dptr); ! 1255: level -= 1; ! 1256: membs = 0; ! 1257: break; ! 1258: ! 1259: default: ! 1260: cbotch("getdbgt: %d", n); ! 1261: } ! 1262: /* ! 1263: * Terminate types. ! 1264: */ ! 1265: if (dptr + typet >= data + DSZ) { ! 1266: dbrpt("2", &d); ! 1267: cbotch("getdbgt buffer"); ! 1268: } ! 1269: while (--typet >= 0) ! 1270: *dptr++ = 0; ! 1271: break; ! 1272: } ! 1273: ! 1274: /* ! 1275: * Check level change. ! 1276: */ ! 1277: if (data[0] == '{') { ! 1278: if (level++ == 0) { ! 1279: d.d_level = level++; ! 1280: outbrace('{'); ! 1281: } ! 1282: } ! 1283: else if (data[0] == '}') ! 1284: level -= 1; ! 1285: ! 1286: /* ! 1287: * Copy into dynamic storage. ! 1288: */ ! 1289: d.d_size = dptr - data; ! 1290: return (newdbgt(&d, data)); ! 1291: } ! 1292: ! 1293: /* ! 1294: * Read a list of members of a union/struct/enum. ! 1295: * If struct/union, append member types to caller's buffer. ! 1296: * If making a debug table: ! 1297: * If struct/union tag definition, bracket member definitions. ! 1298: * If enum tag, make member type into "enum tag". ! 1299: */ ! 1300: char * ! 1301: getmembs(dp0, bb, bp) ! 1302: struct dbgt *dp0; ! 1303: char *bb; ! 1304: register char *bp; ! 1305: { ! 1306: int nmembs, n, istag, isenu, isgbl, isdbg; ! 1307: char *sbp; ! 1308: register struct dbgt *dp; ! 1309: struct dbgt **dpp; ! 1310: register char *p; ! 1311: static struct dbgt dbrace = { ! 1312: NULL, /* d_dp */ ! 1313: -1, /* d_ref */ ! 1314: DT_NONE, /* d_class */ ! 1315: D_LCL, /* d_flag */ ! 1316: 0, /* d_level */ ! 1317: TYPESYM, /* d_seg */ ! 1318: 0, /* d_value */ ! 1319: 3 /* d_size */ ! 1320: }; ! 1321: ! 1322: dp = dp0; ! 1323: nmembs = bget(); ! 1324: istag = (dp->d_flag&D_TAG) != 0; ! 1325: isenu = (dp->d_flag&D_ENU) != 0; ! 1326: isgbl = (dp->d_flag&D_GBL) != 0; ! 1327: isdbg = (isvariant(VDSYMB) && isvariant(VTYPES)) != 0; ! 1328: if (isenu) { ! 1329: sbp = bp; ! 1330: isenu = strlen(bb) + 1 + 1; ! 1331: } ! 1332: if ( ! isenu) { ! 1333: *bp++ = 1; ! 1334: *bp++ = nmembs; ! 1335: } ! 1336: dpp = &dp->d_dp; ! 1337: if (istag && isdbg && ! isenu) { ! 1338: dp = *dpp = newdbgt(&dbrace, "{\0\0"); ! 1339: if (isgbl) ! 1340: dp->d_flag ^= D_GBL|D_LCL; ! 1341: dpp = &dp->d_dp; ! 1342: } ! 1343: while (--nmembs >= 0) { ! 1344: dp = *dpp = getdbgt(); ! 1345: if (isgbl) ! 1346: dp->d_flag ^= D_GBL|D_LCL; ! 1347: n = dp->d_size; ! 1348: p = dp->d_data; ! 1349: if (isenu && istag && isdbg) { ! 1350: dp->d_size += isenu; ! 1351: dp = newdbgt(dp, dp->d_data); ! 1352: bp = dp->d_data; ! 1353: while (*bp++) ! 1354: ; ! 1355: *bp++ = STRINGt; ! 1356: p = bb; ! 1357: while (*bp++ = *p++) ! 1358: ; ! 1359: *bp++ = 0; ! 1360: free(*dpp); ! 1361: *dpp = dp; ! 1362: bp = sbp; ! 1363: } ! 1364: if ( ! isenu) { ! 1365: do { ! 1366: --n; ! 1367: } while (*p++); ! 1368: *bp++ = TYPEt; ! 1369: if (bp + n >= bb + DSZ) { ! 1370: dbrpt("3", dp); ! 1371: cbotch("getdbgt buffer"); ! 1372: } ! 1373: do { ! 1374: *bp++ = *p++; ! 1375: } while (--n > 0); ! 1376: } ! 1377: if (istag && isdbg) ! 1378: dpp = &dp->d_dp; ! 1379: else ! 1380: free(*dpp); ! 1381: } ! 1382: if (istag && isdbg && ! isenu) { ! 1383: dp = *dpp = newdbgt(&dbrace, "}\0\0"); ! 1384: if (isgbl) ! 1385: dp->d_flag ^= D_GBL|D_LCL; ! 1386: dpp = &dp->d_dp; ! 1387: } ! 1388: *dpp = NULL; ! 1389: return (bp); ! 1390: } ! 1391: ! 1392: /* ! 1393: * Output a debug brace ! 1394: */ ! 1395: outbrace(c) ! 1396: char c; ! 1397: { ! 1398: struct dbgt *dp; ! 1399: ! 1400: if ((dp = (struct dbgt *)calloc(1, sizeof(struct dbgt) + 10)) == NULL) ! 1401: cnomem("outbrace"); ! 1402: dp->d_class = DC_LINE; ! 1403: dp->d_flag = D_LCL; ! 1404: dp->d_seg = segindex[SCODE]; ! 1405: dp->d_value = ( dotseg == SCODE ? dot : seg[SCODE].s_dot); ! 1406: dp->d_size = 10; ! 1407: dp->d_data[0] = c; ! 1408: *(dp->d_data + 2) = 6; ! 1409: *(dp->d_data + 3) = dline; ! 1410: *(dp->d_data + 4) = dline >> 8; ! 1411: if (dnext != NULL) ! 1412: dnext->d_dp = dp; ! 1413: dnext = dp; ! 1414: } ! 1415: ! 1416: struct dbgt * ! 1417: newdbgt(dp, cp) ! 1418: struct dbgt *dp; ! 1419: register char *cp; ! 1420: { ! 1421: register struct dbgt *ndp; ! 1422: register char *ncp; ! 1423: register int n; ! 1424: ! 1425: n = dp->d_size; ! 1426: if ((ndp = (struct dbgt *)malloc(sizeof(struct dbgt) + n)) == NULL) ! 1427: cnomem("newdbgt"); ! 1428: *ndp = *dp; ! 1429: for (ncp = ndp->d_data; --n >= 0; *ncp++ = *cp++) ! 1430: ; ! 1431: return (ndp); ! 1432: } ! 1433: ! 1434: #if !TINY ! 1435: _dbrpt(p, dp) ! 1436: char *p; ! 1437: register struct dbgt *dp; ! 1438: { ! 1439: if (xflag > 5) { ! 1440: printf("%5s: %-10s %2x %2d %2x %2x %2x %04x %2x\n", ! 1441: p, ! 1442: dp->d_data, ! 1443: dp->d_class, ! 1444: dp->d_ref, ! 1445: dp->d_flag, ! 1446: dp->d_level, ! 1447: dp->d_seg, ! 1448: dp->d_value, ! 1449: dp->d_size ! 1450: ); ! 1451: } ! 1452: } ! 1453: ! 1454: dbtyp(dp) ! 1455: struct dbgt *dp; ! 1456: { ! 1457: register int n; ! 1458: register char *p; ! 1459: ! 1460: if (xflag > 20) { ! 1461: n = dp->d_size; ! 1462: p = dp->d_data; ! 1463: do { ! 1464: --n; ! 1465: putchar(*p); ! 1466: } while (*p++); ! 1467: while (--n >= 0) { ! 1468: if (*p == STRINGt) { ! 1469: putchar(' '); ! 1470: putchar('"'); ! 1471: ++p; ! 1472: do { ! 1473: --n; ! 1474: } while (putchar(*p++)); ! 1475: putchar('"'); ! 1476: continue; ! 1477: } else if (*p == TYPEt) ! 1478: printf(" TYPEt"); ! 1479: else if (*p == ANYt) ! 1480: printf(" ANYt"); ! 1481: else ! 1482: printf(" %o", *p&0377); ! 1483: ++p; ! 1484: } ! 1485: putchar('\n'); ! 1486: } ! 1487: } ! 1488: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.