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

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

unix.superglobalmegacorp.com

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