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