Annotation of coherent/b/bin/c/n2/i8086/outcoff.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.