|
|
1.1 ! root 1: /* ! 2: * The routines in this file make up ! 3: * a writer for the Coherent style l.out 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: * This uses the newest compiler base (the one ! 8: * that does "readonly" and has the segment names ! 9: * rearranged). ! 10: */ ! 11: #ifdef vax ! 12: #include "INC$LIB:cc2.h" ! 13: #include "INC$LIB:canon.h" ! 14: #include "INC$LIB:lout.h" ! 15: #else ! 16: #include "cc2.h" ! 17: #include "canon.h" ! 18: #include "l.out.h" ! 19: #endif ! 20: ! 21: #define NTXT 256 /* Text buffer size */ ! 22: #define NREL 256 /* Relocation buffer size */ ! 23: ! 24: /* ! 25: * Scratch file. ! 26: */ ! 27: #define TTYPE 07 /* Type */ ! 28: #define TTYPE 07 /* Type */ ! 29: #define TPCR 010 /* PC rel flag, ored in */ ! 30: #define TSYM 020 /* Symbol based flag, ored in */ ! 31: #define T8087 0340 /* 8087 flags */ ! 32: ! 33: #define TEND 00 /* End marker */ ! 34: #define TENTER 01 /* Enter new area */ ! 35: #define TBYTE 02 /* Byte data */ ! 36: #define TWORD 03 /* Word data */ ! 37: #define TCODE 04 /* Code segment base */ ! 38: #define TDATA 05 /* Data segment base */ ! 39: #define TBASE 06 /* External segment base */ ! 40: ! 41: #define TWT 0040 /* M:_WT */ ! 42: #define TWST 0100 /* M:_WST */ ! 43: #define TWES 0140 /* M:_WES */ ! 44: #define TWCS 0200 /* M:_WCS */ ! 45: #define TWSS 0240 /* M:_WSS */ ! 46: #define TWDS 0300 /* M:_WDS */ ! 47: ! 48: struct ldheader ldh; /* Header buffer */ ! 49: long crseek; /* Current relocation seek address */ ! 50: ADDRESS txtla; /* Load address */ ! 51: char txt[NTXT]; /* Text buffer */ ! 52: char rel[NREL]; /* Relocation buffer */ ! 53: char *txtp; /* Text pointer */ ! 54: char *relp; /* Relocation pointer */ ! 55: ! 56: /* ! 57: * Convert a C compiler segment into ! 58: * an "l.out" segment. This is no longer a ! 59: * one to one mapping. ! 60: */ ! 61: char segindex[] = { ! 62: L_SHRI, /* SCODE */ ! 63: L_SHRI, /* SLINK */ ! 64: L_SHRD, /* SPURE */ ! 65: 0, /* SSTRN (Patched) */ ! 66: L_PRVD, /* SDATA */ ! 67: L_BSSD /* SBSS */ ! 68: }; ! 69: ! 70: /* ! 71: * Output a segment switch. ! 72: */ ! 73: outseg(s) ! 74: { ! 75: bput(TENTER); ! 76: bput(s); ! 77: } ! 78: ! 79: /* ! 80: * Output an absolute byte. ! 81: */ ! 82: outab(b) ! 83: { ! 84: bput(TBYTE); ! 85: bput(b); ! 86: ++dot; ! 87: } ! 88: ! 89: /* ! 90: * Output an absolute word. ! 91: */ ! 92: outaw(w) ! 93: { ! 94: bput(TWORD); ! 95: iput(w); ! 96: dot += 2; ! 97: } ! 98: ! 99: /* ! 100: * Output a full byte. ! 101: */ ! 102: outxb(sp, b, pcrf) ! 103: register SYM *sp; ! 104: { ! 105: register int opcode; ! 106: ! 107: opcode = TBYTE; ! 108: if (sp != NULL) ! 109: opcode |= TSYM; ! 110: if (pcrf) ! 111: opcode |= TPCR; ! 112: bput(opcode); ! 113: bput(b); ! 114: if (sp != NULL) ! 115: pput(sp); ! 116: ++dot; ! 117: } ! 118: ! 119: /* ! 120: * Output a full word. ! 121: */ ! 122: outxw(sp, w, pcrf) ! 123: register SYM *sp; ! 124: { ! 125: register int opcode; ! 126: ! 127: opcode = TWORD; ! 128: if (sp != NULL) ! 129: opcode |= TSYM; ! 130: if (pcrf) ! 131: opcode |= TPCR; ! 132: bput(opcode); ! 133: iput(w); ! 134: if (sp != NULL) ! 135: pput(sp); ! 136: dot += 2; ! 137: } ! 138: ! 139: /* ! 140: * Output a 1 word object containing ! 141: * the base address of the current code ! 142: * segment. ! 143: */ ! 144: outcb() ! 145: { ! 146: bput(TCODE); ! 147: dot += 2; ! 148: } ! 149: ! 150: /* ! 151: * Output a 1 word object containing ! 152: * the base address of the current data ! 153: * segment. ! 154: */ ! 155: outdb() ! 156: { ! 157: bput(TDATA); ! 158: dot += 2; ! 159: } ! 160: ! 161: /* ! 162: * Output a 1 word object containing ! 163: * the base address of the external symbol ! 164: * pointed to by `sp'. ! 165: */ ! 166: outsb(sp) ! 167: SYM *sp; ! 168: { ! 169: bput(TBASE); ! 170: pput(sp); ! 171: dot += 2; ! 172: } ! 173: ! 174: /* ! 175: * Copy a dlabel record from ifp to nowhere. ! 176: */ ! 177: outdlab(i, n) ! 178: int i; /* Indentation */ ! 179: register int n; /* Class initially */ ! 180: { ! 181: /* Get line number */ ! 182: iget(); ! 183: ! 184: /* Get value */ ! 185: if (n < DC_AUTO) ! 186: ; ! 187: else if (n < DC_MOS) ! 188: iget(); ! 189: else { ! 190: bget(); /* Width */ ! 191: bget(); /* Offset */ ! 192: iget(); /* Value */ ! 193: } ! 194: ! 195: /* Get name */ ! 196: sget(id, NCSYMB); ! 197: ! 198: /* Get type */ ! 199: for (;;) { ! 200: n = bget(); ! 201: if (n < DC_SEX) { ! 202: if (n < DX_MEMBS) ! 203: iget(); ! 204: if (n == DX_MEMBS) { ! 205: ++i; ! 206: n = iget(); ! 207: for ( ; n > 0; n-=1) { ! 208: outdlab(i, bget()); ! 209: } ! 210: --i; ! 211: break; ! 212: } else if (n == DX_NAME) { ! 213: iget(); ! 214: sget(id, NCSYMB); ! 215: break; ! 216: } else if (n < DT_STRUCT) ! 217: break; ! 218: } else ! 219: cbotch("unrecognized type byte: %d", n); ! 220: } ! 221: ! 222: /* Done */ ! 223: } ! 224: ! 225: /* ! 226: * Forget a debug line record. ! 227: */ ! 228: outdlin(op) ! 229: { ! 230: } ! 231: ! 232: /* ! 233: * Forget a debug relocation record. ! 234: */ ! 235: outdloc(n) ! 236: { ! 237: } ! 238: ! 239: /* ! 240: * Initialize the code writer. ! 241: */ ! 242: outinit() ! 243: { ! 244: txtp = &txt[0]; ! 245: relp = &rel[0]; ! 246: } ! 247: ! 248: /* ! 249: * Finish up. ! 250: */ ! 251: outdone() ! 252: { ! 253: if (notvariant(VASM)) ! 254: bput(TEND); ! 255: } ! 256: ! 257: /* ! 258: * Copy back. ! 259: * Figure out the sizes and final values ! 260: * of everything. Copy the code from the scratch ! 261: * file back to the output file. ! 262: */ ! 263: copycode() ! 264: { ! 265: register SYM *sp; ! 266: register SEG *segp; ! 267: register int op; ! 268: register int data; ! 269: register ADDRESS mseek; ! 270: register long dseek; ! 271: register int nd; ! 272: register int nr; ! 273: register int index; ! 274: register ADDRESS segsize; ! 275: register ADDRESS auxsize; ! 276: register ADDRESS reldot; ! 277: register int refnum; ! 278: register int i; ! 279: register int rop; ! 280: struct ldsym lds; ! 281: ! 282: /* ! 283: * Make sure that the "segindex" ! 284: * table is set up correctly for the string ! 285: * mapping, based on the ROM flags. ! 286: */ ! 287: if (isvariant(VROM)) ! 288: segindex[SSTRN] = L_SHRD; ! 289: else ! 290: segindex[SSTRN] = L_PRVD; ! 291: /* ! 292: * Sweep through the segment table and ! 293: * assign the memory and disc seek addresses to each ! 294: * entry. Two sections (SLINK and SSTRN) are done in ! 295: * a magic way, because they live in another segment. ! 296: */ ! 297: mseek = 0; ! 298: index = 0; ! 299: dseek = sizeof(ldh); ! 300: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp) { ! 301: if (segp!=&seg[SLINK] && segp!=&seg[SSTRN]) { ! 302: segp->s_mseek = mseek; ! 303: segsize = rup(segp->s_dot); ! 304: mseek += segsize; ! 305: if (segp != &seg[SBSS]) { ! 306: segp->s_dseek = dseek; ! 307: dseek += segsize; ! 308: } ! 309: if (segp == &seg[SCODE]) { ! 310: seg[SLINK].s_mseek = mseek; ! 311: auxsize = rup(seg[SLINK].s_dot); ! 312: mseek += auxsize; ! 313: seg[SLINK].s_dseek = dseek; ! 314: dseek += auxsize; ! 315: segsize += auxsize; ! 316: } ! 317: if (isvariant(VROM) && segp==&seg[SPURE] ! 318: || notvariant(VROM) && segp==&seg[SDATA]) { ! 319: seg[SSTRN].s_mseek = mseek; ! 320: auxsize = rup(seg[SSTRN].s_dot); ! 321: mseek += auxsize; ! 322: seg[SSTRN].s_dseek = dseek; ! 323: dseek += auxsize; ! 324: segsize += auxsize; ! 325: } ! 326: ldh.l_ssize[segindex[index]] = segsize; ! 327: } ! 328: ++index; ! 329: } ! 330: /* ! 331: * Seek to the start of the symbol table and ! 332: * write out all of the global symbols. All symbols get ! 333: * relocated to their final values here. Reference numbers ! 334: * are assigned to every symbol. ! 335: */ ! 336: fseek(ofp, dseek, 0); ! 337: ldh.l_ssize[L_SYM] = 0; ! 338: refnum = 0; ! 339: for (i=0; i<NSHASH; ++i) { ! 340: sp = hash2[i]; ! 341: while (sp != NULL) { ! 342: if ((sp->s_flag&S_DEF) != 0) ! 343: sp->s_value += seg[sp->s_seg].s_mseek; ! 344: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) { ! 345: sp->s_ref = refnum++; ! 346: ldscopy(lds.ls_id, sp->s_id); ! 347: lds.ls_type = L_REF; ! 348: if ((sp->s_flag&S_DEF) != 0) ! 349: lds.ls_type = segindex[sp->s_seg]; ! 350: lds.ls_type |= L_GLOBAL; ! 351: lds.ls_addr = sp->s_value; ! 352: canint(lds.ls_type); ! 353: canvaddr(lds.ls_addr); ! 354: owrite((char *) &lds, sizeof(lds)); ! 355: ldh.l_ssize[L_SYM] += sizeof(lds); ! 356: } ! 357: sp = sp->s_fp; ! 358: } ! 359: } ! 360: /* ! 361: * Copy out code. ! 362: */ ! 363: crseek = ftell(ofp); ! 364: ldh.l_ssize[L_REL] = 0; ! 365: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp) ! 366: segp->s_dot = 0; ! 367: dotseg = SCODE; ! 368: dot = 0; ! 369: while ((op = bget()) != TEND) { ! 370: if (op==TCODE || op==TDATA || op==TBASE) ! 371: cbotch("large item"); ! 372: if ((op&T8087) != 0) ! 373: cbotch("8087 item"); ! 374: if (op == TENTER) { ! 375: notenuf(); ! 376: seg[dotseg].s_dot = dot; ! 377: dotseg = bget(); ! 378: dot = seg[dotseg].s_dot; ! 379: continue; ! 380: } ! 381: if ((op&TTYPE) == TBYTE) { ! 382: nd = 1; ! 383: data = bget(); ! 384: } else { ! 385: nd = 2; ! 386: data = iget(); ! 387: } ! 388: if ((op&TPCR) != 0) ! 389: data -= dot+nd; ! 390: /* ! 391: * Absolute. ! 392: */ ! 393: if ((op&(TSYM|TPCR)) == 0) { ! 394: enuf(nd, 0); ! 395: *txtp++ = data; ! 396: if (nd != 1) ! 397: *txtp++ = data>>8; ! 398: dot += nd; ! 399: continue; ! 400: } ! 401: /* ! 402: * Not symbol based. ! 403: * Must be absolute and PC rel. ! 404: */ ! 405: reldot = dot + seg[dotseg].s_mseek; ! 406: if ((op&TSYM) == 0) { ! 407: enuf(nd, 3); ! 408: rop = LR_BYTE|L_ABS|LR_PCR; ! 409: *txtp++ = data; ! 410: if (nd != 1) { ! 411: rop = LR_WORD|L_ABS|LR_PCR; ! 412: *txtp++ = data>>8; ! 413: } ! 414: *relp++ = rop; ! 415: *relp++ = reldot; ! 416: *relp++ = reldot>>8; ! 417: dot += nd; ! 418: continue; ! 419: } ! 420: /* ! 421: * Symbol based. ! 422: * Might be PC rel. ! 423: */ ! 424: nr = 5; ! 425: sp = pget(); ! 426: if ((sp->s_flag&S_DEF) != 0) { ! 427: nr = 3; ! 428: data += sp->s_value; ! 429: } ! 430: enuf(nd, nr); ! 431: rop = LR_BYTE; ! 432: *txtp++ = data; ! 433: if (nd != 1) { ! 434: rop = LR_WORD; ! 435: *txtp++ = data>>8; ! 436: } ! 437: if ((op&TPCR) != 0) ! 438: rop |= LR_PCR; ! 439: if (nr == 3) ! 440: rop |= segindex[sp->s_seg]; ! 441: else ! 442: rop |= L_SYM; ! 443: *relp++ = rop; ! 444: *relp++ = reldot; ! 445: *relp++ = reldot>>8; ! 446: if (nr == 5) { ! 447: *relp++ = sp->s_ref; ! 448: *relp++ = sp->s_ref>>8; ! 449: } ! 450: dot += nd; ! 451: } ! 452: /* ! 453: * Flush buffers. ! 454: * Write out the l.out header, since we ! 455: * now know the size of the relocation section. ! 456: */ ! 457: notenuf(); ! 458: ldh.l_magic = L_MAGIC; ! 459: canint(ldh.l_magic); ! 460: ldh.l_flag = 0; ! 461: canint(ldh.l_flag); ! 462: ldh.l_machine = M_8086; ! 463: canint(ldh.l_machine); ! 464: ldh.l_entry = 0; ! 465: canvaddr(ldh.l_entry); ! 466: for (i=L_SHRI; i<=L_REL; ++i) ! 467: cansize(ldh.l_ssize[i]); ! 468: fseek(ofp, (long)0, 0); ! 469: owrite((char *) &ldh, sizeof(ldh)); ! 470: } ! 471: ! 472: /* ! 473: * Copy a NUL terminated name into ! 474: * a loader symbol. Pad the symbol out with ! 475: * 0 bytes. ! 476: */ ! 477: ldscopy(p1, p2) ! 478: register char *p1; ! 479: register char *p2; ! 480: { ! 481: register int n; ! 482: ! 483: n = NCPLN; ! 484: while (*p2!=0 && n!=0) { ! 485: *p1++ = *p2++; ! 486: --n; ! 487: } ! 488: while (n != 0) { ! 489: *p1++ = 0; ! 490: --n; ! 491: } ! 492: } ! 493: ! 494: /* ! 495: * This routine checks to see if ! 496: * there is enough room in the text and relocation ! 497: * buffers to hold `nt' bytes of text and `nr' bytes of ! 498: * relocation. ! 499: */ ! 500: enuf(nt, nr) ! 501: { ! 502: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL]) ! 503: notenuf(); ! 504: if (txtp == txt) ! 505: txtla = dot; ! 506: } ! 507: ! 508: /* ! 509: * Flush the text and relocation buffers. Look ! 510: * at the segment table to figure out the exact location ! 511: * of the data in the file, and compute the correct seek ! 512: * address in the image by adding the base address of ! 513: * the text record "txtla" to that base. ! 514: */ ! 515: notenuf() ! 516: { ! 517: register int n; ! 518: ! 519: if ((n=txtp-txt) != 0) { ! 520: fseek(ofp, txtla+seg[dotseg].s_dseek, 0); ! 521: owrite(txt, n); ! 522: if ((n=relp-rel) != 0) { ! 523: fseek(ofp, crseek, 0); ! 524: owrite(rel, n); ! 525: crseek += n; ! 526: ldh.l_ssize[L_REL] += n; ! 527: relp = rel; ! 528: } ! 529: } ! 530: txtp = txt; ! 531: } ! 532: ! 533: /* ! 534: * Write a block of bytes to the output file, ! 535: * looking at the return status and checking for any ! 536: * write errors. ! 537: */ ! 538: owrite(p, n) ! 539: char *p; ! 540: { ! 541: if (fwrite(p, sizeof(char), n, ofp) != n) ! 542: cfatal("output write error"); ! 543: } ! 544: ! 545: /* ! 546: * Round up a size to the next ! 547: * even boundry. ! 548: */ ! 549: rup(a) ! 550: { ! 551: return ((a+01)&~01); ! 552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.