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