Annotation of coherent/b/bin/c/n2/i8086/outcoff.c, revision 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.