|
|
1.1 ! root 1: /* ! 2: * n2/i8086/outcoff.c ! 3: * 8/29/91 ! 4: * C compiler COFF output writer. ! 5: * The first pass writes to a temp file. ! 6: * After the first pass, the compiler knows the sizes of the internal segments. ! 7: * The compiler then maps the internal segments to the actual output segments. ! 8: * The second pass reads the temp file and writes the actual output bits. ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <time.h> ! 13: #include <string.h> ! 14: #include "cc2.h" ! 15: #include "coff.h" ! 16: ! 17: #define NTXT 256 /* Text buffer size */ ! 18: #define NREL 256 /* Relocation buffer size */ ! 19: ! 20: #define RUP(n) (((n)+1)&(~1)) /* Round n up to word boundary */ ! 21: ! 22: /* Debugging output. */ ! 23: #if DEBUG ! 24: #define dbprintf(args) printf args ! 25: #else ! 26: #define dbprintf(args) ! 27: #endif ! 28: ! 29: /* ! 30: * COFF output. ! 31: * The structure of the COFF output file is presently as follows: ! 32: * file header ! 33: * [optional header: absent] ! 34: * section headers 1 through n ! 35: * data for sections 1 through n ! 36: * relocs for sections 1 through n ! 37: * [line numbers: absent] ! 38: * symbol table [segment names, then symbols] ! 39: * string table ! 40: * These definitions correspond to the header definitions in scn_hdr[] below. ! 41: * These are used as array indices and as indices into COFF symbol table. ! 42: * Add 1 to get the COFF segment number. ! 43: * They will have to change when full debug info is desired. ! 44: */ ! 45: #define C_CODE_SEG 0 /* Code segment index */ ! 46: #define C_DATA_SEG 1 /* Data segment index */ ! 47: #define C_BSS_SEG 2 /* BSS segment index */ ! 48: #define C_NSEGS 3 /* Number of segments */ ! 49: #define C_UNDEF 0 /* Undefined segment */ ! 50: ! 51: /* ! 52: * Scratch file. ! 53: */ ! 54: #define TTYPE 0x07 /* Type */ ! 55: #define TPCR 0x08 /* PC rel flag, or'ed in */ ! 56: #define TSYM 0x10 /* Symbol based flag, or'ed in */ ! 57: ! 58: #define TEND 0x00 /* End marker */ ! 59: #define TENTER 0x01 /* Enter new segment */ ! 60: #define TBYTE 0x02 /* Byte data */ ! 61: #define TWORD 0x03 /* Word data */ ! 62: #define TBASE 0x04 /* External segment base */ ! 63: ! 64: /* ! 65: * Output writer globals. ! 66: */ ! 67: FILEHDR coff_hdr; /* Header buffer */ ! 68: int coff_seg; /* Current COFF segment */ ! 69: char rel[NREL]; /* Relocation buffer */ ! 70: ADDRESS reldot[C_NSEGS]; /* Relocation offsets */ ! 71: char *relp; /* Relocation pointer */ ! 72: SCNHDR scn_hdr[C_NSEGS] = { /* Section headers */ ! 73: { ".text", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_TEXT }, ! 74: { ".data", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_DATA }, ! 75: { ".bss", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_BSS } ! 76: }; ! 77: char txt[NTXT]; /* Text buffer */ ! 78: ADDRESS txtdot; /* Text offset */ ! 79: char *txtp; /* Text pointer */ ! 80: ! 81: /* ! 82: * Map C compiler internal segment into a COFF output segment. ! 83: * The SSTRN entry gets patched by outinit() if -VROM. ! 84: */ ! 85: char segindex[] = { ! 86: C_CODE_SEG, /* SCODE */ ! 87: C_CODE_SEG, /* SLINK */ ! 88: C_CODE_SEG, /* SPURE */ ! 89: C_DATA_SEG, /* possibly patched */ /* SSTRN */ ! 90: C_DATA_SEG, /* SDATA */ ! 91: C_BSS_SEG /* SBSS */ ! 92: }; ! 93: ! 94: /* First pass routines. */ ! 95: /* ! 96: * Initialize the code writer. ! 97: */ ! 98: outinit() ! 99: { ! 100: if (isvariant(VROM)) ! 101: segindex[SSTRN] = C_CODE_SEG; ! 102: } ! 103: ! 104: /* ! 105: * Output an absolute byte. ! 106: */ ! 107: outab(b) int b; ! 108: { ! 109: bput(TBYTE); ! 110: bput(b); ! 111: ++dot; ! 112: } ! 113: ! 114: /* ! 115: * Output an absolute word. ! 116: */ ! 117: outaw(w) int w; ! 118: { ! 119: bput(TWORD); ! 120: iput(w); ! 121: dot += 2; ! 122: } ! 123: ! 124: /* ! 125: * Output a 1 word object containing the base address ! 126: * of the external symbol pointed to by sp. ! 127: */ ! 128: outsb(sp) SYM *sp; ! 129: { ! 130: bput(TBASE); ! 131: pput(sp); ! 132: dot += 2; ! 133: } ! 134: ! 135: /* ! 136: * Output a full byte. ! 137: */ ! 138: outxb(sp, b, pcrf) register SYM *sp; int b, pcrf; ! 139: { ! 140: register int opcode; ! 141: ! 142: opcode = TBYTE; ! 143: if (sp != NULL) { ! 144: opcode |= TSYM; ! 145: scn_hdr[coff_seg].s_nreloc++; ! 146: } ! 147: if (pcrf) ! 148: opcode |= TPCR; ! 149: bput(opcode); ! 150: bput(b); ! 151: if (sp != NULL) ! 152: pput(sp); ! 153: ++dot; ! 154: } ! 155: ! 156: /* ! 157: * Output a full word. ! 158: */ ! 159: outxw(sp, w, pcrf) register SYM *sp; int w, pcrf; ! 160: { ! 161: register int opcode; ! 162: ! 163: opcode = TWORD; ! 164: if (sp != NULL) { ! 165: opcode |= TSYM; ! 166: scn_hdr[coff_seg].s_nreloc++; ! 167: } ! 168: if (pcrf) ! 169: opcode |= TPCR; ! 170: bput(opcode); ! 171: iput(w); ! 172: if (sp != NULL) ! 173: pput(sp); ! 174: dot += 2; ! 175: } ! 176: ! 177: /* ! 178: * Output a segment switch. ! 179: */ ! 180: outseg(s) register int s; ! 181: { ! 182: bput(TENTER); ! 183: bput(s); ! 184: coff_seg = segindex[s]; ! 185: } ! 186: ! 187: /* ! 188: * Copy a dlabel record from ifp to nowhere. ! 189: */ ! 190: outdlab(i, n) ! 191: int i; /* Indentation */ ! 192: register int n; /* Class initially */ ! 193: { ! 194: /* Get line number */ ! 195: iget(); ! 196: ! 197: /* Get value */ ! 198: if (n < DC_AUTO) ! 199: ; ! 200: else if (n < DC_MOS) ! 201: iget(); ! 202: else { ! 203: bget(); /* Width */ ! 204: bget(); /* Offset */ ! 205: iget(); /* Value */ ! 206: } ! 207: ! 208: /* Get name */ ! 209: sget(id, NCSYMB); ! 210: ! 211: /* Get type */ ! 212: for (;;) { ! 213: n = bget(); ! 214: if (n < DC_SEX) { ! 215: if (n < DX_MEMBS) ! 216: iget(); ! 217: if (n == DX_MEMBS) { ! 218: ++i; ! 219: n = iget(); ! 220: for ( ; n > 0; n-=1) { ! 221: outdlab(i, bget()); ! 222: } ! 223: --i; ! 224: break; ! 225: } else if (n == DX_NAME) { ! 226: iget(); ! 227: sget(id, NCSYMB); ! 228: break; ! 229: } else if (n < DT_STRUCT) ! 230: break; ! 231: } else ! 232: cbotch("unrecognized type byte: %d", n); ! 233: } ! 234: ! 235: /* Done */ ! 236: } ! 237: ! 238: /* ! 239: * Forget a debug relocation record. ! 240: */ ! 241: outdloc(n) int n; ! 242: { ! 243: } ! 244: ! 245: /* ! 246: * Finish up. ! 247: */ ! 248: outdone() ! 249: { ! 250: if (notvariant(VASM)) ! 251: bput(TEND); ! 252: } ! 253: ! 254: /* Second pass. */ ! 255: copycode() ! 256: { ! 257: register int op, i; ! 258: register SEG *segp; ! 259: register SYM *sp; ! 260: register long dseek, sseek, ssize; ! 261: register ADDRESS mseek, segsize; ! 262: int symnum, nd, data, len, isbyte, issym, ispcr; ! 263: SCNHDR *shp; ! 264: SYMENT sym; ! 265: RELOC *rp; ! 266: ! 267: /* Assign segment base addresses. */ ! 268: coff_seg = -1; ! 269: dseek = sizeof(FILEHDR) + C_NSEGS * sizeof(SCNHDR); ! 270: mseek = 0; ! 271: for (i = SCODE, segp = &seg[SCODE]; i <= SBSS; ++i, ++segp) { ! 272: segsize = RUP(segp->s_dot); ! 273: segp->s_dot = 0; ! 274: if (segindex[i] != coff_seg) { ! 275: /* Begin new COFF segment. */ ! 276: coff_seg = segindex[i]; ! 277: dbprintf(("COFF segment %d\n", coff_seg)); ! 278: shp = &scn_hdr[coff_seg]; ! 279: shp->s_paddr = shp->s_vaddr = mseek; ! 280: if (i != C_BSS_SEG) ! 281: shp->s_scnptr = dseek; ! 282: } ! 283: dbprintf(("segment %d: size=%d dseek=%ld mseek=%ld\n", i, segsize, dseek, mseek)); ! 284: segp->s_dseek = dseek; /* set compiler seg disk seek */ ! 285: segp->s_mseek = mseek; /* and memory seek */ ! 286: scn_hdr[coff_seg].s_size += segsize; /* bump COFF seg size */ ! 287: dseek += segsize; /* bump seek pointer */ ! 288: mseek += segsize; /* bump memory seek */ ! 289: } ! 290: ! 291: /* Fix reloc offsets. */ ! 292: for (shp = &scn_hdr[C_CODE_SEG]; shp < &scn_hdr[C_NSEGS]; ++shp) { ! 293: if (shp->s_nreloc != 0) { ! 294: shp->s_relptr = dseek; ! 295: dseek += shp->s_nreloc * sizeof(RELOC); ! 296: } ! 297: } ! 298: ! 299: /* Write symbols. */ ! 300: coff_hdr.f_symptr = dseek; /* symbol secton base */ ! 301: oseek(dseek); /* seek to symbol section */ ! 302: sym.n_type = 0; /* ignore type */ ! 303: sym.n_numaux = 0; /* no aux entries */ ! 304: for (i = C_CODE_SEG, shp = &scn_hdr[i]; i < C_NSEGS; ++i, ++shp) { ! 305: /* Write segment name symbols. */ ! 306: memset(sym.n_name, 0, sizeof(sym.n_name)); ! 307: strcpy(sym.n_name, shp->s_name); ! 308: sym.n_value = shp->s_vaddr; ! 309: sym.n_scnum = i; ! 310: sym.n_sclass = C_STAT; ! 311: owrite((char *)&sym, sizeof(sym)); ! 312: } ! 313: /* Count symbols so symbol section length is known. */ ! 314: symnum = C_NSEGS; ! 315: for (i=0; i < NSHASH; ++i) { ! 316: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) { ! 317: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) ! 318: sp->s_ref = symnum++; ! 319: } ! 320: } ! 321: coff_hdr.f_nsyms = symnum; /* symbol count */ ! 322: ssize = sizeof(long); /* string segment size */ ! 323: sseek = dseek + symnum * sizeof(sym) + ssize; /* first string seek */ ! 324: symnum = C_NSEGS; ! 325: for (i=0; i < NSHASH; ++i) { ! 326: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) { ! 327: if ((sp->s_flag&S_DEF) != 0) ! 328: sp->s_value += seg[sp->s_seg].s_mseek; ! 329: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) { ! 330: /* Write global or external symbol. */ ! 331: sp->s_ref = symnum++; ! 332: len = strlen(sp->s_id); ! 333: if (len <= SYMNMLEN) ! 334: strncpy(sym.n_name, sp->s_id, SYMNMLEN); ! 335: else { ! 336: /* Spill long name to string table. */ ! 337: dseek = ftell(ofp); ! 338: sym.n_zeroes = 0L; ! 339: sym.n_offset = ssize; ! 340: oseek(sseek); ! 341: sput(sp->s_id); ! 342: sseek += len + 1; ! 343: ssize += len + 1; ! 344: oseek(dseek); ! 345: } ! 346: sym.n_value = sp->s_value; ! 347: if ((sp->s_flag&S_DEF) != 0) { ! 348: sym.n_scnum = segindex[sp->s_seg] + 1; ! 349: sym.n_sclass = C_STAT; ! 350: } else { ! 351: sym.n_scnum = C_UNDEF; ! 352: sym.n_sclass = C_EXT; ! 353: } ! 354: owrite((char *)&sym, sizeof(sym)); ! 355: } ! 356: } ! 357: } ! 358: /* Write string table size if nonempty. */ ! 359: if (ssize != sizeof(long)) ! 360: owrite((char *)&ssize, sizeof(ssize)); ! 361: ! 362: /* Copy out code. */ ! 363: dotseg = SCODE; ! 364: coff_seg = segindex[dotseg]; ! 365: txtdot = dot = 0; ! 366: txtp = &txt[0]; ! 367: relp = &rel[0]; ! 368: while ((op = bget()) != TEND) { ! 369: if (op == TENTER) { ! 370: notenuf(); ! 371: seg[dotseg].s_dot = dot; ! 372: dotseg = bget(); ! 373: coff_seg = segindex[dotseg]; ! 374: txtdot = dot = seg[dotseg].s_dot; ! 375: continue; ! 376: } ! 377: enuf(2, sizeof(RELOC)); /* leave space for next op */ ! 378: if (isbyte = ((op & TTYPE) == TBYTE)) { ! 379: nd = 1; ! 380: data = bget(); ! 381: } else { ! 382: nd = 2; ! 383: data = iget(); ! 384: } ! 385: if (issym = ((op & TSYM) != 0)) { ! 386: sp = pget(); ! 387: if ((sp->s_flag&S_DEF) != 0) ! 388: data += sp->s_value; ! 389: } ! 390: if (ispcr = ((op & TPCR) != 0)) ! 391: data -= dot + nd; ! 392: ! 393: /* Write text. */ ! 394: *txtp++ = data; ! 395: if (nd != 1) ! 396: *txtp++ = data >> 8; ! 397: ! 398: if (issym || ispcr) { ! 399: /* Write relocation item. */ ! 400: rp = (RELOC *)relp; ! 401: rp->r_vaddr = dot + seg[dotseg].s_mseek; ! 402: rp->r_symndx = (issym) ? sp->s_ref : coff_seg; ! 403: if (ispcr) ! 404: rp->r_type = (isbyte) ? R_PCRBYTE : R_PCRWORD; ! 405: else ! 406: rp->r_type = (isbyte) ? R_DIR8 : R_DIR16; ! 407: relp += sizeof(RELOC); ! 408: } ! 409: dot += nd; ! 410: } ! 411: ! 412: /* Flush buffers. */ ! 413: notenuf(); ! 414: ! 415: /* Write COFF header. */ ! 416: coff_hdr.f_magic = C_386_MAGIC; ! 417: coff_hdr.f_nscns = C_NSEGS; ! 418: coff_hdr.f_timdat = time(NULL); ! 419: coff_hdr.f_opthdr = 0; ! 420: coff_hdr.f_flags = F_AR32WR | F_LLNO | L_SYMS; ! 421: oseek(0L); ! 422: owrite((char *)&coff_hdr, sizeof(coff_hdr)); ! 423: ! 424: /* Write section headers. */ ! 425: for (shp = &scn_hdr[C_CODE_SEG]; shp < &scn_hdr[C_NSEGS]; ++shp) ! 426: owrite((char *)shp, sizeof(*shp)); ! 427: } ! 428: ! 429: /* Buffering and output writing routines. */ ! 430: /* ! 431: * Make sure there is enough room in the text and relocation buffers ! 432: * for nt bytes of text and nr bytes of relocation. ! 433: */ ! 434: enuf(nt, nr) ! 435: { ! 436: if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) ! 437: notenuf(); ! 438: } ! 439: ! 440: /* ! 441: * Flush the text and relocation buffers. ! 442: * Look at the segment table to figure out the exact location ! 443: * of the data in the file, and compute the correct seek ! 444: * address in the image by adding the base address of ! 445: * the text record "txtdot" to that base. ! 446: */ ! 447: notenuf() ! 448: { ! 449: register int n; ! 450: ! 451: if ((n = txtp-txt) != 0) { ! 452: dbprintf(("notenuf: %d text bytes\n", n)); ! 453: dbprintf(("seek to txtdot=%d + seg[%d].s_dseek=%ld\n", txtdot, dotseg, seg[dotseg].s_dseek)); ! 454: oseek(txtdot + seg[dotseg].s_dseek); ! 455: owrite(txt, n); ! 456: if ((n = relp-rel) != 0) { ! 457: dbprintf(("notenuf: %d reloc bytes\n", n)); ! 458: dbprintf(("seek to reldot[%d]=%d + relptr=%ld\n", coff_seg, reldot[coff_seg], scn_hdr[coff_seg].s_relptr)); ! 459: oseek(reldot[coff_seg] + scn_hdr[coff_seg].s_relptr); ! 460: owrite(rel, n); ! 461: reldot[coff_seg] += n; ! 462: relp = rel; ! 463: } ! 464: } ! 465: txtp = txt; ! 466: txtdot = dot; ! 467: } ! 468: ! 469: /* ! 470: * Seek output file, checking for seek error. ! 471: */ ! 472: oseek(l) long l; ! 473: { ! 474: if (fseek(ofp, l, SEEK_SET) == -1L) ! 475: cfatal("seek to %ld failed", l); ! 476: } ! 477: ! 478: /* ! 479: * Write a block of n bytes from p to the output file, ! 480: * checking for write errors. ! 481: */ ! 482: owrite(p, n) char *p; ! 483: { ! 484: if (fwrite(p, sizeof(char), n, ofp) != n) ! 485: cfatal("output write error"); ! 486: } ! 487: ! 488: /* end of outcoff.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.