Annotation of coherent/b/bin/c/n2/i386/outcoff.c, 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 <coff.h>
        !            15: #include "cc2.h"
        !            16: 
        !            17: #define        CC_ID   "COHERENT i386 cc "     /* .comment contains CC_ID VERSMWC */
        !            18: 
        !            19: #define        NTXT    256                     /* Text buffer size             */
        !            20: #define        NREL    256                     /* Relocation buffer size       */
        !            21: 
        !            22: #define        RUP(n)  (((n)+3)&(~3))          /* Round n up to dword boundary */
        !            23: 
        !            24: /* SYM flag tests. */
        !            25: #define        is_bss(sp)      ((sp)->s_seg==SBSS)
        !            26: #define        is_def(sp)      (((sp)->s_flag&S_DEF)!=0)
        !            27: #define        is_global(sp)   (((sp)->s_flag&S_GBL)!=0)
        !            28: #define        is_label(sp)    (((sp)->s_flag&S_LABNO)!=0)
        !            29: 
        !            30: /* Debugging output. */
        !            31: #if    DEBUG
        !            32: #define        dbprintf(args)  printf args
        !            33: #else
        !            34: #define        dbprintf(args)
        !            35: #endif
        !            36: 
        !            37: /*
        !            38:  * COFF output.
        !            39:  * .text is section 1, .data is section 2, .bss is section 3.
        !            40:  * Section 4 is .comment, containing a translator ID and version number;
        !            41:  * this currently gets written only if debug.
        !            42:  * The structure of the COFF output file is presently as follows:
        !            43:  *     file header
        !            44:  *     [optional header: absent]
        !            45:  *     section headers 1 through 3 [4 if debug]
        !            46:  *     data for sections 1 through 3 [4 if debug]
        !            47:  *     relocs for sections 1 through 3
        !            48:  *     line numbers for section 1 [absent if not debug]
        !            49:  *     symbol table [seg names, then symbols]
        !            50:  *     string table [absent if no long names]
        !            51:  */
        !            52: 
        !            53: /*
        !            54:  * The definitions below are indices for the header definitions in scn_hdr[].
        !            55:  * If not debug, they are also the symbol indices for .text, .data, .bss.
        !            56:  * Add 1 to covert to COFF section number.
        !            57:  */
        !            58: #define        C_TEXT_SEG      0                       /* .text section index  */
        !            59: #define        C_DATA_SEG      1                       /* .data section index  */
        !            60: #define        C_BSS_SEG       2                       /* .bss section index   */
        !            61: #define        C_CMT_SEG       3                       /* .comment section index */
        !            62: #define        C_NSECS         4                       /* Number of sections   */
        !            63: 
        !            64: /* Symbol indices for .text, .data and .bss if debug. */
        !            65: /* Symbol 0 is .file with 1 aux entry, each section also has 1 aux entry. */
        !            66: #define        C_TEXT_DB       2
        !            67: #define        C_DATA_DB       4
        !            68: #define        C_BSS_DB        6
        !            69: 
        !            70: /*
        !            71:  * Debug information.
        !            72:  * Each DBSYM represents one symbol entry or aux entry
        !            73:  * in the object symbol table.
        !            74:  * The DBSYM contains the proto entry itself, plus
        !            75:  * enough additional information for the second pass to correct the
        !            76:  * actual entry by adjusting long names and adding segment bases.
        !            77:  */
        !            78: typedef        struct  dbsym   {
        !            79:        struct  dbsym   *db_next;       /* Link, must be first  */
        !            80:        int             db_ref;         /* Index number         */
        !            81:        union   {
        !            82:                SYMENT  db_use;         /* Symbol entry         */
        !            83:                AUXENT  db_uae;         /* Aux entry            */
        !            84:        } db_u;
        !            85:        unsigned short  db_level;       /* Lexical level        */
        !            86:        char            db_seg;         /* C segment            */
        !            87:        char            db_flags;       /* Flags                */
        !            88:        char            db_name[];      /* NUL or name if > 8   */
        !            89: } DBSYM;
        !            90: #define        db_se   db_u.db_use
        !            91: #define        db_ae   db_u.db_uae
        !            92: #define        DB_AUX          0x01            /* AUXENT, not SYMENT   */
        !            93: #define        DB_LNAME        0x02            /* Name is in db_name   */
        !            94: #define        is_aux(dp)      (((dp)->db_flags & DB_AUX) != 0)
        !            95: #define        is_lname(dp)    (((dp)->db_flags & DB_LNAME) != 0)
        !            96: 
        !            97: /* The output writer generates a LNNUM for each line number entry. */
        !            98: typedef        struct  lnnum   {
        !            99:        struct  lnnum   *ln_next;       /* Link                 */
        !           100:        DBSYM           *ln_dp;         /* Symbol needing value */
        !           101:        AUXENT          *ln_ap;         /* Function aux entry   */
        !           102:        unsigned short  ln_lnnum;       /* Line number, 0 for fn */
        !           103:        unsigned short  ln_val;         /* Refnum or fn syminx  */
        !           104:        ADDRESS         ln_addr;        /* Address              */
        !           105:        char            ln_flag;        /* LN_FUNC or LN_LINE   */
        !           106: } LNNUM;
        !           107: #define        LN_FUNC 0
        !           108: #define        LN_LINE 1
        !           109: 
        !           110: /* Linked list of symbols, used for .bb and tag lists. */
        !           111: typedef        struct  symlist {
        !           112:        struct  symlist *sl_next;       /* Link                 */
        !           113:        DBSYM           *sl_dp;         /* Symbol pointer       */
        !           114: } SYMLIST;
        !           115: 
        !           116: /* Tag patch list for forward tag references. */
        !           117: typedef        struct  tagfix  {
        !           118:        struct  tagfix  *tf_next;       /* Link                 */
        !           119:        SYMLIST         *tf_sp;         /* DBSYMs to fix        */
        !           120:        char            tf_name[];      /* Name                 */
        !           121: } TAGFIX;
        !           122: 
        !           123: extern DBSYM   *new_db();
        !           124: extern DBSYM   *new_sym();
        !           125: extern AUXENT  *new_aux();
        !           126: extern LNNUM   *new_ln();
        !           127: 
        !           128: /*
        !           129:  * Scratch file.
        !           130:  */
        !           131: #define        TTYPE   0x07                    /* Type mask                    */
        !           132: #define        TPCR    0x08                    /* PC rel flag, or'ed in        */
        !           133: #define        TSYM    0x10                    /* Symbol based flag, or'ed in  */
        !           134: 
        !           135: #define        TEND    0x00                    /* End marker                   */
        !           136: #define        TENTER  0x01                    /* Enter new segment            */
        !           137: #define        TBYTE   0x02                    /* Byte data                    */
        !           138: #define        TWORD   0x03                    /* Word data                    */
        !           139: #define        TLONG   0x04                    /* Dword data                   */
        !           140: 
        !           141: /*
        !           142:  * Output writer globals.
        !           143:  */
        !           144: SYMLIST        *blockp;                        /* Open .bb block list  */
        !           145: FILEHDR        coff_hdr;                       /* Header buffer        */
        !           146: DBSYM  *db_list;                       /* Debug symbol list    */
        !           147: DBSYM  **db_lastp = &db_list;          /* Last db_list pointer */
        !           148: int    dot_sec;                        /* Current COFF section */
        !           149: DBSYM  *fn_dp;                         /* Current fn entry     */
        !           150: int    level;                          /* Lexical level        */
        !           151: LNNUM  *ln_list;                       /* Line number list     */
        !           152: LNNUM  **ln_lastp = &ln_list;          /* Last ln_list pointer */
        !           153: int    refnum = -1;                    /* Debug item refnum    */
        !           154: char   rel[NREL];                      /* Relocation buffer    */
        !           155: ADDRESS        reldot[C_NSECS];                /* Relocation offsets   */
        !           156: char   *relp;                          /* Relocation pointer   */
        !           157: SCNHDR scn_hdr[C_NSECS] = {            /* Section headers      */
        !           158:        { _TEXT,        0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_TEXT },
        !           159:        { _DATA,        0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_DATA },
        !           160:        { _BSS,         0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_BSS },
        !           161:        { _COMMENT,     0L, 0L, 0L, 0L, 0L, 0L, 0, 0, STYP_INFO }
        !           162: };
        !           163: long   str_seek;                       /* Seek to string table */
        !           164: long   str_size;                       /* Size of string table */
        !           165: char   symindex[C_NSECS];              /* Section symbol indices */
        !           166: SYMLIST        *tag_list;                      /* Defined tags         */
        !           167: TAGFIX *tag_fix;                       /* Forward tag refs     */
        !           168: char   txt[NTXT];                      /* Text buffer          */
        !           169: ADDRESS        txtdot;                         /* Text offset          */
        !           170: char   *txtp;                          /* Text pointer         */
        !           171: 
        !           172: /*
        !           173:  * Map C compiler internal segment into a COFF output section.
        !           174:  * The SSTRN entry gets patched by outinit() if not -VPSTR.
        !           175:  */
        !           176: char   sec_index[] = {
        !           177:        C_TEXT_SEG,                             /* SCODE */
        !           178:        C_TEXT_SEG,                             /* SLINK */
        !           179:        C_TEXT_SEG,                             /* SPURE */
        !           180:        C_TEXT_SEG,     /* possibly patched */  /* SSTRN */
        !           181:        C_DATA_SEG,                             /* SDATA */
        !           182:        C_BSS_SEG                               /* SBSS  */
        !           183: };
        !           184: 
        !           185: /*
        !           186:  * Map C debug scalar types to COFF types.
        !           187:  * Indexed by type as defined in h/ops.h.
        !           188:  * COFF has no direct representation for "void" type,
        !           189:  * it uses <DT_FCN T_NULL> for a void function.
        !           190:  */
        !           191: char   coff_type[] = {
        !           192:        T_NULL,                         /* DT_NONE      */
        !           193:        T_CHAR,                         /* DT_CHAR      */
        !           194:        T_UCHAR,                        /* DT_UCHAR     */
        !           195:        T_SHORT,                        /* DT_SHORT     */
        !           196:        T_USHORT,                       /* DT_USHORT    */
        !           197:        T_INT,                          /* DT_INT       */
        !           198:        T_UINT,                         /* DT_UINT      */
        !           199:        T_LONG,                         /* DT_LONG      */
        !           200:        T_ULONG,                        /* DT_ULONG     */
        !           201:        T_FLOAT,                        /* DT_FLOAT     */
        !           202:        T_DOUBLE,                       /* DT_DOUBLE    */
        !           203:        T_NULL,                         /* DT_VOID      */
        !           204:        T_STRUCT,                       /* DT_STRUCT    */
        !           205:        T_UNION,                        /* DT_UNION     */
        !           206:        T_ENUM,                         /* DT_ENUM      */
        !           207:        DT_PTR,                         /* DD_PTR       */
        !           208:        DT_FCN,                         /* DD_FUNC      */
        !           209:        DT_ARY                          /* DD_ARRAY     */
        !           210: };
        !           211: 
        !           212: /*
        !           213:  * Map C debug storage class to COFF storage class.
        !           214:  * Indexed by class-DC_SEX, as defined in h/ops.h.
        !           215:  * DC_CALL is defined in ops.h but not used anywhere.
        !           216:  * DC_LINE items generate COFF line number items,
        !           217:  * they have no COFF storage class.
        !           218:  */
        !           219: char   coff_class[] = {
        !           220:        C_STAT,                         /* DC_SEX       */
        !           221:        C_EXT,                          /* DC_GDEF      */
        !           222:        C_EXT,                          /* DC_GREF      */
        !           223:        C_TPDEF,                        /* DC_TYPE      */
        !           224:        C_STRTAG,                       /* DC_STAG      */
        !           225:        C_UNTAG,                        /* DC_UTAG      */
        !           226:        C_ENTAG,                        /* DC_ETAG      */
        !           227:        C_FILE,                         /* DC_FILE      */
        !           228:        C_NULL,                         /* DC_LINE      */
        !           229:        C_LABEL,                        /* DC_LAB       */
        !           230:        C_AUTO,                         /* DC_AUTO      */
        !           231:        C_ARG,                          /* DC_PAUTO     */
        !           232:        C_REG,                          /* DC_REG       */
        !           233:        C_REGPARM,                      /* DC_PREG      */
        !           234:        C_STAT,                         /* DC_SIN       */
        !           235:        C_MOE,                          /* DC_MOE       */
        !           236:        C_NULL,         /* unused */    /* DC_CALL      */
        !           237:        C_MOS,                          /* DC_MOS       */
        !           238:        C_MOU                           /* DC_MOU       */
        !           239: };
        !           240: 
        !           241: /*
        !           242:  * Map C debug storage class to COFF section number.
        !           243:  * Indexed by class-DC_SEX, as defined in h/ops.h.
        !           244:  * DC_CALL is defined in ops.h but not used anywhere.
        !           245:  * DC_LINE items generate COFF line number items, they have no COFF section.
        !           246:  */
        !           247: #define        N_ANY   127     /* maps to .code, .text or .data using sec_index[] */
        !           248: char   coff_sec[] = {
        !           249:        N_ANY,                          /* DC_SEX       */
        !           250:        N_ANY,                          /* DC_GDEF      */
        !           251:        N_UNDEF,                        /* DC_GREF      */
        !           252:        N_DEBUG,                        /* DC_TYPE      */
        !           253:        N_DEBUG,                        /* DC_STAG      */
        !           254:        N_DEBUG,                        /* DC_UTAG      */
        !           255:        N_DEBUG,                        /* DC_ETAG      */
        !           256:        N_DEBUG,                        /* DC_FILE      */
        !           257:        N_DEBUG,                        /* DC_LINE      */
        !           258:        N_ANY,                          /* DC_LAB       */
        !           259:        N_ABS,                          /* DC_AUTO      */
        !           260:        N_ABS,                          /* DC_PAUTO     */
        !           261:        N_ABS,                          /* DC_REG       */
        !           262:        N_ABS,                          /* DC_PREG      */
        !           263:        N_ANY,                          /* DC_SIN       */
        !           264:        N_ABS,                          /* DC_MOE       */
        !           265:        N_ANY,          /* unused */    /* DC_CALL      */
        !           266:        N_ABS,                          /* DC_MOS       */
        !           267:        N_ABS                           /* DC_MOU       */
        !           268: };
        !           269: 
        !           270: /* First pass routines. */
        !           271: /*
        !           272:  * Initialize the code writer.
        !           273:  */
        !           274: outinit()
        !           275: {
        !           276: #if    MONOLITHIC
        !           277:        /* Reinitialize the coff_hdr. */
        !           278:        memset(&coff_hdr, 0, sizeof coff_hdr);
        !           279:        dot_sec = 0;
        !           280:        memset(reldot, 0, sizeof reldot);
        !           281:        memset(scn_hdr, 0, sizeof scn_hdr);
        !           282:        strcpy(scn_hdr[C_TEXT_SEG].s_name, _TEXT);
        !           283:        scn_hdr[C_TEXT_SEG].s_flags = STYP_TEXT;
        !           284:        strcpy(scn_hdr[C_DATA_SEG].s_name, _DATA);
        !           285:        scn_hdr[C_DATA_SEG].s_flags = STYP_DATA;
        !           286:        strcpy(scn_hdr[C_BSS_SEG].s_name, _BSS);
        !           287:        scn_hdr[C_BSS_SEG].s_flags = STYP_BSS;
        !           288:        strcpy(scn_hdr[C_CMT_SEG].s_name, _COMMENT);
        !           289:        scn_hdr[C_CMT_SEG].s_flags = STYP_INFO;
        !           290: 
        !           291:        /* Reinitialize other globals. */
        !           292:        level = 0;
        !           293:        db_lastp = &db_list;
        !           294:        ln_lastp = &ln_list;
        !           295:        refnum = -1;
        !           296:        tag_fix = tag_list = NULL;
        !           297: #endif
        !           298:        if (notvariant(VPSTR))
        !           299:                sec_index[SSTRN] = C_DATA_SEG;
        !           300: }
        !           301: 
        !           302: /*
        !           303:  * Output an absolute byte.
        !           304:  */
        !           305: outab(b) int b;
        !           306: {
        !           307:        bput(TBYTE);
        !           308:        bput(b);
        !           309:        ++dot;
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * Output an absolute word.
        !           314:  */
        !           315: outaw(w) int w;
        !           316: {
        !           317:        bput(TWORD);
        !           318:        iput((ival_t)w);
        !           319:        dot += 2;
        !           320: }
        !           321: 
        !           322: /*
        !           323:  * Output an absolute dword.
        !           324:  */
        !           325: outal(i) ival_t i;
        !           326: {
        !           327:        bput(TLONG);
        !           328:        iput(i);
        !           329:        dot += 4;
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * Output a full byte.
        !           334:  */
        !           335: outxb(sp, b, pcrf) register SYM        *sp; ADDRESS b; int pcrf;
        !           336: {
        !           337:        register int    opcode;
        !           338: 
        !           339:        opcode = TBYTE;
        !           340:        if (sp != NULL) {
        !           341:                opcode |= TSYM;
        !           342:                scn_hdr[dot_sec].s_nreloc++;
        !           343:        }
        !           344:        if (pcrf)
        !           345:                opcode |= TPCR;
        !           346:        bput(opcode);
        !           347:        bput(b);
        !           348:        if (sp != NULL)
        !           349:                pput(sp);
        !           350:        ++dot;
        !           351: }
        !           352: 
        !           353: /*
        !           354:  * Output a full word.
        !           355:  */
        !           356: outxw(sp, w, pcrf) register SYM *sp; ADDRESS w; int pcrf;
        !           357: {
        !           358:        register int    opcode;
        !           359: 
        !           360:        opcode = TWORD;
        !           361:        if (sp != NULL) {
        !           362:                opcode |= TSYM;
        !           363:                scn_hdr[dot_sec].s_nreloc++;
        !           364:        }
        !           365:        if (pcrf)
        !           366:                opcode |= TPCR;
        !           367:        bput(opcode);
        !           368:        iput((ival_t)w);
        !           369:        if (sp != NULL)
        !           370:                pput(sp);
        !           371:        dot += 2;
        !           372: }
        !           373: 
        !           374: /*
        !           375:  * Output a full dword.
        !           376:  */
        !           377: outxl(sp, i, pcrf) register SYM *sp; ADDRESS i; int pcrf;
        !           378: {
        !           379:        register int    opcode;
        !           380: 
        !           381:        opcode = TLONG;
        !           382:        if (sp != NULL) {
        !           383:                opcode |= TSYM;
        !           384:                scn_hdr[dot_sec].s_nreloc++;
        !           385:        }
        !           386:        if (pcrf)
        !           387:                opcode |= TPCR;
        !           388:        bput(opcode);
        !           389:        iput(i);
        !           390:        if (sp != NULL)
        !           391:                pput(sp);
        !           392:        dot += 4;
        !           393: }
        !           394: 
        !           395: /*
        !           396:  * Output a segment switch.
        !           397:  */
        !           398: outseg(s) register int s;
        !           399: {
        !           400:        bput(TENTER);
        !           401:        bput(s);
        !           402:        dot_sec = sec_index[s];
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * Output n zero bytes.
        !           407:  * If flag is true, generate NOPs instead.
        !           408:  */
        !           409: outnzb(n, flag) register sizeof_t n; int flag;
        !           410: {
        !           411:        register int i, val;
        !           412: 
        !           413:        val = (flag) ? 0x90 : 0;        /* xchg %eax, %eax or 0 */
        !           414:        for (i = 1; i <= n; ++i) {
        !           415:                bput(TBYTE);
        !           416:                bput(val);
        !           417:        }
        !           418:        dot += n;
        !           419: }
        !           420: 
        !           421: /*
        !           422:  * Process a dlabel record.
        !           423:  * Do the work on pass 1 so that the number of symbols in the table is known.
        !           424:  * 'i' is the level of indentation, 'class' is the initial storage class.
        !           425:  * A lot of grunge.
        !           426:  */
        !           427: outdlab(i, class) int i; register int class;
        !           428: {
        !           429:        register int line, type, n;
        !           430:        int csec, ctype, cclass, tagn;
        !           431:        ival_t size, value, cvalue, array_size, last_size, sue_size;
        !           432:        int seg, width, derived, dims, suppress;
        !           433:        static int enumtype = DT_INT;
        !           434:        unsigned short dim[DIMNUM];
        !           435:        SYM *sp;
        !           436:        DBSYM *dp, *tagdp;
        !           437:        AUXENT *ap, *endap, *arrayap;
        !           438: 
        !           439:        ++refnum;                                       /* compiler db refnum */
        !           440: 
        !           441:        /* Initialize locals. */
        !           442:        seg = -1;
        !           443:        suppress = tagn = ctype = derived = dims = 0;
        !           444:        last_size = array_size = sue_size = (ival_t)0;
        !           445:        ap = endap = arrayap = tagdp = sp = NULL;
        !           446: 
        !           447:        /*
        !           448:         * Map C segment and storage class to COFF section and storage class.
        !           449:         * The COFF info may get adjusted later.
        !           450:         */
        !           451:        if (class >= DC_SEX && class <= DC_MOU) {
        !           452:                csec = coff_sec[class - DC_SEX];
        !           453:                cclass = coff_class[class - DC_SEX];
        !           454:                if (cclass == C_NULL && class != DC_LINE)
        !           455:                        cbotch("unrecognized class=%d", class);
        !           456:        } else
        !           457:                cbotch("unrecognized class=%d", class);
        !           458:        dbprintf(("outdlab(%d, %d)\t", i, class));
        !           459:        dbprintf(("#%d\t", refnum));
        !           460:        dbprintf(("cclass=%d\t", cclass));
        !           461: 
        !           462:        /* Get line number. */
        !           463:        line = iget();
        !           464:        dbprintf(("line=%d\t", line));
        !           465: 
        !           466:        /* Get value. */
        !           467:        if (class < DC_AUTO)
        !           468:                value = 0;              /* Name string only */
        !           469:        else if (class < DC_MOS)
        !           470:                value = iget();         /* Value */
        !           471:        else {                          /* DC_MOS or DC_MOU */
        !           472:                width = bget();         /* Width */
        !           473:                n = bget();             /* Offset */
        !           474:                value = iget();         /* Value */
        !           475:                if (width != 0) {
        !           476:                        value = value * 8 + n;          /* bitfield offset */
        !           477:                        cclass = C_FIELD;               /* and class */
        !           478:                }
        !           479:        }
        !           480:        cvalue = value;                 /* COFF value, may be modified below */
        !           481:        if (class == DC_REG || class == DC_PREG) {
        !           482:                /* Map compiler register to machine register number. */
        !           483:                switch(value) {
        !           484:                case EBX:       cvalue = MEBX;          break;
        !           485:                case EDI:       cvalue = MEDI;          break;
        !           486:                case ESI:       cvalue = MESI;          break;
        !           487:                default:        cbotch("unexpected register %d", value);
        !           488:                }
        !           489:        }
        !           490: 
        !           491:        /* Get name. */
        !           492:        sget(id, NCSYMB);
        !           493:        dbprintf(("id=%s\t", id));
        !           494: 
        !           495:        if (class == DC_SEX || class == DC_GDEF || class == DC_GREF) {
        !           496: 
        !           497:                /* Check for global symbol table entry. */
        !           498:                sp = glookup(id, 0);
        !           499:                if (sp == NULL)
        !           500:                        cbotch("global %s not found", id);
        !           501:                seg = sp->s_seg;
        !           502:                /* Grab section and value; cvalue gets patched later for commons. */
        !           503:                if (is_def(sp)) {
        !           504:                        csec = sec_index[seg] + 1;
        !           505:                        value = cvalue = sp->s_value;
        !           506:                } else {
        !           507:                        /*
        !           508:                         * Extern: seg != SANY changed to seg -1;
        !           509:                         * common: seg SANY.
        !           510:                         */
        !           511:                        csec = N_UNDEF;
        !           512:                        if (seg != SANY)
        !           513:                                seg = -1;
        !           514:                }
        !           515:                /* Suppress redefinitions of globals. */
        !           516:                for (dp = db_list; dp != NULL; dp = dp->db_next) {
        !           517:                        if (!is_aux(dp)
        !           518:                         && dp->db_level == 0
        !           519:                         && db_strcmp(dp, id) == 0) {
        !           520:                                ++suppress;
        !           521: #if    0
        !           522:                                if (is_def(sp)) {
        !           523:                                        /* Symbol may be defined since previous ref. */
        !           524:                                        dp->db_se.n_value = cvalue;
        !           525:                                        dp->db_se.n_scnum = csec;
        !           526:                                }
        !           527: #endif
        !           528:                                break;
        !           529:                        }
        !           530:                }
        !           531:        } else if (class == DC_SIN) {
        !           532:                /* Find location of static internal items. */
        !           533:                sp = llookup(value, 0);
        !           534:                if (sp == NULL)
        !           535:                        cbotch("local %d not found", value);
        !           536:                seg = sp->s_seg;
        !           537:                csec = sec_index[seg] + 1;
        !           538:                value = cvalue = sp->s_value;
        !           539:        } else if (class == DC_LAB)
        !           540:                csec = C_TEXT_SEG + 1;
        !           541: 
        !           542:        /* Get type. */
        !           543:        for (;;) {
        !           544:                type = bget();                          /* type */
        !           545:                if (class == DC_MOE)
        !           546:                        type = enumtype;                /* fudge DT_NONE */
        !           547:                dbprintf(("type=%d ", type));
        !           548: 
        !           549:                if (type < DC_SEX) {
        !           550:                        size = iget();                  /* size */
        !           551:                        if (csec == N_UNDEF && seg != SANY)
        !           552:                                cvalue = size;          /* cvalue means size for commons */
        !           553:                        if (last_size != 0) {
        !           554:                                /* Compute array dim from last/current size. */
        !           555:                                if (dims <= DIMNUM)
        !           556:                                        dim[dims-1] = (unsigned short)(last_size/size);
        !           557:                                last_size = 0;
        !           558:                        }
        !           559:                        dbprintf(("size=%d\t", size));
        !           560: 
        !           561:                        /* Compute COFF type. */
        !           562:                        if (type <= DT_ENUM)
        !           563:                                ctype |= coff_type[type];       /* basic COFF type */
        !           564:                        else if (type <= DD_ARRAY) {
        !           565:                                /* Derived types DD_PTR, DD_FUNC, DD_ARRAY. */
        !           566:                                ctype |= (coff_type[type] << N_BTSHFT) << (derived++ * N_TSHIFT);
        !           567:                                if (type == DD_ARRAY
        !           568:                                 && (csec != N_UNDEF || seg != SANY)) {
        !           569:                                        /* Reconstruct array dim from current/next size. */
        !           570:                                        if (dims++ == 0) {
        !           571:                                                array_size = size;
        !           572:                                                for (n = 0; n < DIMNUM; n++)
        !           573:                                                        dim[n] = 0;
        !           574:                                        }
        !           575:                                        last_size = size;
        !           576:                                }
        !           577:                        }
        !           578:                        dbprintf(("ctype=%x\t", ctype));
        !           579: 
        !           580:                        if (type < DT_STRUCT) {
        !           581:                                /*
        !           582:                                 * Simple types.
        !           583:                                 * An aux entry is needed for fields, functions,
        !           584:                                 * nested autos and arrays.
        !           585:                                 */
        !           586:                                if (class == DC_LINE || class == DC_LAB) {
        !           587:                                        dbprintf(("\n"));
        !           588:                                        db_line(line);
        !           589:                                        return;
        !           590:                                } else if (class == DC_FILE) {
        !           591:                                        dbprintf(("\n"));
        !           592:                                        db_file();
        !           593:                                        return;
        !           594:                                }
        !           595:                                if (suppress)
        !           596:                                        break;
        !           597:                                if (csec == N_UNDEF && dims > 0)
        !           598:                                        cvalue = array_size;
        !           599:                                dp = new_sym(id, cvalue, csec, ctype, cclass);
        !           600:                                dp->db_seg = seg;
        !           601:                                if (cclass == C_FIELD) {
        !           602:                                        /* Bitfield. */
        !           603:                                        ap = new_aux();
        !           604:                                        ap->ae_size = width;
        !           605:                                } else if (ISFCN(ctype) && csec != N_UNDEF) {
        !           606:                                        /* Non-extern function. */
        !           607:                                        ap = new_aux();
        !           608:                                        db_func(dp);
        !           609:                                } else if (cclass == C_AUTO && level > 1) {
        !           610:                                        /* Auto in nested block. */
        !           611:                                        if (blockp == NULL)
        !           612:                                                cbotch("no blockp");
        !           613:                                        ap = new_aux();
        !           614:                                        ap->ae_lnno = blockp->sl_dp->db_ae.ae_lnno;
        !           615:                                }
        !           616:                                if (dims != 0) {
        !           617:                                        /* Array. */
        !           618:                                        if (ap == NULL)
        !           619:                                                ap = new_aux();
        !           620:                                        arrayap = ap;
        !           621:                                        arrayap->ae_size = array_size;
        !           622:                                }
        !           623:                                break;
        !           624:                        } else if (type <= DT_ENUM) {
        !           625:                                /*
        !           626:                                 * DT_STRUCT, DT_UNION, DT_ENUM types.
        !           627:                                 * An aux entry is always generated, although in
        !           628:                                 * rare cases (unresolved tags) it remains empty.
        !           629:                                 */
        !           630:                                sue_size = size;
        !           631:                                if (suppress)
        !           632:                                        ap = &(dp->db_ae);
        !           633:                                else {
        !           634:                                        if (csec == N_UNDEF && dims > 0)
        !           635:                                                cvalue = array_size;
        !           636:                                        dp = new_sym(id, cvalue, csec, ctype, cclass);
        !           637:                                        ap = new_aux();
        !           638:                                        ap->ae_size = size;
        !           639:                                }
        !           640:                                tagn = dp->db_ref;              /* tag index */
        !           641:                                tagdp = dp->db_next;            /* tag aux dp */
        !           642:                                if (ISTAG(cclass)) {
        !           643:                                        /* Tag definition. */
        !           644:                                        tag_def(dp);
        !           645:                                        endap = ap;
        !           646:                                        ap->ae_size = size;
        !           647:                                        if (cclass == C_ENTAG)
        !           648:                                                enumtype = (size == 1) ? DT_UCHAR : DT_INT;
        !           649:                                } else if (ISFCN(ctype))
        !           650:                                        db_func(dp);
        !           651:                                if (dims != 0) {
        !           652:                                        arrayap = ap;
        !           653:                                        arrayap->ae_size = array_size;
        !           654:                                }
        !           655:                                continue;       /* to process tag, member list */
        !           656:                        } else if (type == DX_MEMBS) {
        !           657:                                /* Process member list recursively. */
        !           658:                                ++level;
        !           659:                                for ( ; size > 0; --size) {
        !           660:                                        dbprintf(("\n"));
        !           661:                                        /*
        !           662:                                         * Leave refnum unchanged to keep
        !           663:                                         * it in sync with the outdloc()
        !           664:                                         * reference numbers, for local structs.
        !           665:                                         * It gets bumped in outdlab().
        !           666:                                         */
        !           667:                                        --refnum;
        !           668:                                        outdlab(i+1, bget());   /* overwrites id */
        !           669:                                }
        !           670:                                --level;
        !           671:                                dp = new_sym(".eos", sue_size, N_ABS, T_NULL, C_EOS);
        !           672:                                ap = new_aux();
        !           673:                                ap->ae_size = sue_size;
        !           674:                                ap->ae_tagndx = tagn;
        !           675:                                break;
        !           676:                        } else if (type == DX_NAME) {
        !           677:                                /* Named type. */
        !           678:                                sget(id, NCSYMB);               /* overwrites id */
        !           679:                                tag_ref(id, tagdp);
        !           680:                                dbprintf(("tag=%s", id));
        !           681:                                break;
        !           682:                        }
        !           683:                } else
        !           684:                        cbotch("unrecognized type %d", type);
        !           685:        }
        !           686:        if (endap != NULL)
        !           687:                endap->ae_endndx = coff_hdr.f_nsyms;    /* patch end index */
        !           688:        if (arrayap != NULL)
        !           689:                for (n = 0; n < DIMNUM; n++)
        !           690:                        arrayap->ae_dimen[n] = dim[n];  /* patch array dims */
        !           691:        if (dims > DIMNUM)
        !           692:                cwarn("line %d: array type too complex, debug information lost", line);
        !           693:        if (derived > 6)
        !           694:                cwarn("line %d: type too complex, debug information lost", line);
        !           695:        dbprintf(("\n"));
        !           696: }
        !           697: 
        !           698: /*
        !           699:  * Handle function debug information.
        !           700:  * This generates the .bf when the function name is seen
        !           701:  * rather than when the '{' is seen,
        !           702:  * because the .bb symbol must precede the function parameter symbols.
        !           703:  * The function size and endindex are patched when the .ef gets generated.
        !           704:  */
        !           705: db_func(dp) register DBSYM *dp;
        !           706: {
        !           707:        register LNNUM *lp;
        !           708: 
        !           709:        lp = new_ln(LN_FUNC);
        !           710:        lp->ln_val = dp->db_ref;
        !           711:        fn_dp = dp;
        !           712:        dp = new_sym(".bf", (ival_t)0, C_TEXT_SEG+1, T_NULL, C_FCN);
        !           713:        new_aux();
        !           714: }
        !           715: 
        !           716: /*
        !           717:  * Process DC_LINE ('{', ';' and '}') and DC_LAB items.
        !           718:  * Each generates a line number entry, some generate additional symbol entries.
        !           719:  * The screwy line numbers for .bb/.eb are as in Unix, might be wrong.
        !           720:  */
        !           721: db_line(line) register int line;
        !           722: {
        !           723:        static  int     fn_line;        /* First lnnum of fn            */
        !           724:        register LNNUM *lp;
        !           725:        register DBSYM *dp;
        !           726:        register AUXENT *ap;
        !           727:        SYMLIST *bp;
        !           728:        char *name;
        !           729: 
        !           730:        dbprintf(("db_line(%d): %c\n", line, id[0]));
        !           731:        dp = NULL;
        !           732:        switch(id[0]) {
        !           733:        case '{':
        !           734:                /* .bf got generated by db_func(), patch its value and line. */
        !           735:                if (level == 0) {
        !           736:                        if (fn_dp == NULL)
        !           737:                                cfatal("incomplete function debug information");
        !           738:                        dp = fn_dp->db_next->db_next;           /* .bf entry */
        !           739:                        fn_line = dp->db_next->db_ae.ae_lnno = line;
        !           740:                } else {
        !           741:                        /* Generate a .bb entry. */
        !           742:                        dp = new_sym(".bb", (ival_t)0, C_TEXT_SEG+1, T_NULL, C_BLOCK);
        !           743:                        ap = new_aux();
        !           744:                        ap->ae_lnno = line - fn_line + 2;       /* huh? */
        !           745: 
        !           746:                        /* Link the .bb onto the blockp list. */
        !           747:                        bp = (SYMLIST *)malloc(sizeof(SYMLIST));
        !           748:                        if (bp == NULL)
        !           749:                                cnomem("db_line");
        !           750:                        bp->sl_next = blockp;
        !           751:                        bp->sl_dp = dp->db_next;
        !           752:                        blockp = bp;
        !           753:                }
        !           754:                level++;
        !           755:                break;
        !           756:        case ';':
        !           757:                /* Generate a line number entry only. */
        !           758:                break;
        !           759:        case '}':
        !           760:                /* Generate a .ef or .eb entry. */
        !           761:                level--;
        !           762:                name = (level == 0) ? ".ef" : ".eb";
        !           763:                dp = new_sym(name, (ival_t)0, C_TEXT_SEG+1, T_NULL,
        !           764:                        (level == 0) ? C_FCN : C_BLOCK);
        !           765:                ap = new_aux();
        !           766:                ap->ae_lnno = (level==0) ? line - fn_line + 1
        !           767:                                         : line - fn_line + 2;  /* huh? */
        !           768:                if (level == 0) {
        !           769:                        /* End of function, patch its length and end. */
        !           770:                        ap = &(fn_dp->db_next->db_ae);
        !           771:                        ap->ae_fsize = -(fn_dp->db_se.n_value); /* -start */
        !           772:                        ap->ae_endndx = coff_hdr.f_nsyms;
        !           773:                } else {
        !           774:                        /* Close nested block, popping blockp entry. */
        !           775:                        if ((bp = blockp) == NULL)
        !           776:                                cbotch("db_line");
        !           777:                        blockp = bp->sl_next;
        !           778:                        bp->sl_dp->db_ae.ae_endndx = coff_hdr.f_nsyms;
        !           779:                        free(bp);
        !           780:                }
        !           781:                break;
        !           782:        default:
        !           783:                /* Generate a label entry. */
        !           784:                dp = new_sym(id, (ival_t)0, C_TEXT_SEG+1,
        !           785:                        T_NULL,         /* icc uses <DT_ARY T_INT>, dunno why */
        !           786:                        C_LABEL);
        !           787:                break;
        !           788:        }
        !           789: 
        !           790:        /* Generate a new line number item. */
        !           791:        lp = new_ln(LN_LINE);
        !           792:        lp->ln_dp = dp;         /* adjust value of DBSYM when addr is known */
        !           793:        lp->ln_lnnum = line - fn_line + 1;
        !           794:        lp->ln_val = refnum;
        !           795:        if (id[0] == '}' && level == 0)
        !           796:                lp->ln_ap = ap; /* adjust fn size when addr is known */
        !           797: }
        !           798: 
        !           799: /*
        !           800:  * Create symbol table entries for a DC_FILE.
        !           801:  */
        !           802: db_file()
        !           803: {
        !           804:        register DBSYM *dp;
        !           805:        register AUXENT *ap;
        !           806:        register char *cp;
        !           807: 
        !           808:        if (refnum != 0)
        !           809:                cbotch("db_file");      /* DC_FILE must be first entry */
        !           810:        dp = new_sym(".file", (ival_t)0, N_DEBUG, T_NULL, C_FILE);
        !           811:        ap = new_aux();                 /* aux entry */
        !           812:        if ((cp = strrchr(id, '/')) == NULL)    /* ignore pathname if present */
        !           813:                cp = id;
        !           814:        strncpy(ap->ae_fname, cp, FILNMLEN);
        !           815:        coff_hdr.f_nsyms += 2 * C_NSECS;        /* section symbols with aux entries */
        !           816: }
        !           817: 
        !           818: /*
        !           819:  * Allocate a new DBSYM item, initialize it to 0 and link it into the list.
        !           820:  * If name is non-NULL, initialize its name field.
        !           821:  */
        !           822: DBSYM *
        !           823: new_db(name) register char *name;
        !           824: {
        !           825:        register DBSYM *dp;
        !           826:        register int size, len;
        !           827: 
        !           828:        size = sizeof(*dp);
        !           829:        if (name != NULL && (len = strlen(name)) > 8)
        !           830:                size += len + 1;
        !           831:        dp = (DBSYM *)malloc(size);
        !           832:        if (dp == NULL)
        !           833:                cnomem("new_db");
        !           834:        memset(dp, 0, size);
        !           835:        *db_lastp = dp;
        !           836:        db_lastp = &(dp->db_next);
        !           837:        if (name != NULL) {
        !           838:                if (len <= 8)
        !           839:                        strncpy(dp->db_se.n_name, name, 8);
        !           840:                else {
        !           841:                        strcpy(dp->db_name, name);
        !           842:                        dp->db_flags = DB_LNAME;
        !           843:                }
        !           844:        }
        !           845:        dp->db_seg = -1;
        !           846:        dp->db_level = level;
        !           847:        dp->db_ref = coff_hdr.f_nsyms++;
        !           848:        return dp;
        !           849: }
        !           850: 
        !           851: /*
        !           852:  * Allocate a new DBSYM item and initialize it.
        !           853:  */
        !           854: DBSYM *
        !           855: new_sym(name, value, sec, type, class)
        !           856: char *name;
        !           857: ival_t value;
        !           858: int sec, type, class;
        !           859: {
        !           860:        register DBSYM *dp;
        !           861:        register SYMENT *sp;
        !           862: 
        !           863:        dp = new_db(name);
        !           864:        dbprintf(("new_sym(%s) val=%ld sec=%d type=%d cl=%d @%x\n", name, value, sec,type, class, dp));
        !           865:        sp = &(dp->db_se);
        !           866:        sp->n_value = value;
        !           867:        sp->n_scnum = sec;
        !           868:        sp->n_type = type;
        !           869:        sp->n_sclass = class;
        !           870:        sp->n_numaux = 0;
        !           871:        return dp;
        !           872: }
        !           873: 
        !           874: /*
        !           875:  * Allocate a new AUXENT and return a pointer to it.
        !           876:  */
        !           877: AUXENT *
        !           878: new_aux()
        !           879: {
        !           880:        register DBSYM *dp;
        !           881: 
        !           882:        ++(((DBSYM *)db_lastp)->db_se.n_numaux);        /* bump aux entry count */
        !           883:        dp = new_db(NULL);
        !           884:        dp->db_flags |= DB_AUX;
        !           885:        return &(dp->db_ae);
        !           886: }
        !           887: 
        !           888: /*
        !           889:  * Allocate a new LNNUM item, initialize it to 0 and link it into the list.
        !           890:  */
        !           891: LNNUM *
        !           892: new_ln(flag) int flag;
        !           893: {
        !           894:        register LNNUM *lp;
        !           895: 
        !           896:        lp = (LNNUM *)malloc(sizeof(*lp));
        !           897:        if (lp == NULL)
        !           898:                cnomem("new_ln");
        !           899:        memset(lp, 0, sizeof(*lp));
        !           900:        *ln_lastp = lp;
        !           901:        ln_lastp = &(lp->ln_next);
        !           902:        ++scn_hdr[C_TEXT_SEG].s_nlnno;
        !           903:        lp->ln_flag = flag;
        !           904:        return lp;
        !           905: }
        !           906: 
        !           907: /* Tag handling. */
        !           908: /*
        !           909:  * Define a tag with symbol table entry dp.
        !           910:  * Previous forward references are left unresolved until tag_resolve().
        !           911:  */
        !           912: tag_def(dp) DBSYM *dp;
        !           913: {
        !           914:        register SYMLIST *sp;
        !           915: 
        !           916:        sp = (SYMLIST *)malloc(sizeof(*sp));
        !           917:        if (sp == NULL)
        !           918:                cnomem("tag_def");
        !           919:        sp->sl_next = tag_list;
        !           920:        sp->sl_dp = dp;
        !           921:        tag_list = sp;
        !           922: }
        !           923: 
        !           924: /*
        !           925:  * Look up a tag name in the list of defined tags.
        !           926:  * Return a nonnegative symbol reference number or -1 if not found.
        !           927:  */
        !           928: int
        !           929: tag_lookup(name) register char *name;
        !           930: {
        !           931:        register SYMLIST *sp;
        !           932: 
        !           933:        for (sp = tag_list; sp != NULL; sp = sp->sl_next)
        !           934:                if (db_strcmp(sp->sl_dp, name) == 0)
        !           935:                        return sp->sl_dp->db_ref;
        !           936:        return -1;
        !           937: }
        !           938: 
        !           939: /*
        !           940:  * Reference a tag.
        !           941:  * If defined, store the symbol reference number in the aux entry at dp.
        !           942:  * If not, add an entry to the TAGFIX list so it gets fixed up later.
        !           943:  */
        !           944: tag_ref(name, dp) char *name; DBSYM *dp;
        !           945: {
        !           946:        register SYMLIST *sp;
        !           947:        register TAGFIX *tp;
        !           948:        register int n;
        !           949: 
        !           950:        dbprintf(("tag_ref(%s, %d):\n", name, dp->db_ref));
        !           951:        if (dp == NULL)
        !           952:                cbotch("NULL aux pointer in tag_ref");
        !           953:        if ((n = tag_lookup(name)) != -1) {
        !           954:                /* The tag is defined already. */
        !           955:                dp->db_ae.ae_tagndx = n;                /* store index */
        !           956:                return;
        !           957:        }
        !           958: 
        !           959:        /*
        !           960:         * The tag is not defined.
        !           961:         * Search for an existing tag_fix entry.
        !           962:         */
        !           963:        for (tp = tag_fix; tp != NULL; tp = tp->tf_next)
        !           964:                if (strcmp(name, tp->tf_name) == 0)
        !           965:                        break;
        !           966:        if (tp == NULL) {
        !           967:                /* Build a new TAGFIX entry on first forward reference. */
        !           968:                tp = (TAGFIX *)malloc(sizeof(*tp) + strlen(name) + 1);
        !           969:                if (tp == NULL)
        !           970:                        cnomem("tag_ref");
        !           971:                tp->tf_next = tag_fix;
        !           972:                tp->tf_sp = NULL;
        !           973:                strcpy(tp->tf_name, name);
        !           974:                tag_fix = tp;
        !           975:        }
        !           976: 
        !           977:        /* Add dp to the list of fixes. */
        !           978:        sp = (SYMLIST *)malloc(sizeof(*sp));
        !           979:        if (sp == NULL)
        !           980:                cnomem("tag_ref");
        !           981:        sp->sl_next = tp->tf_sp;
        !           982:        sp->sl_dp = dp;
        !           983:        tp->tf_sp = sp;
        !           984: }
        !           985: 
        !           986: /*
        !           987:  * Resolve forward tag references and free the tag lists.
        !           988:  * Forward references which remain unresolved could be handled in several ways,
        !           989:  * this just leaves the aux entry (rather than deleting it) and leaves its
        !           990:  * tag member index zeroed.
        !           991:  */
        !           992: tag_resolve()
        !           993: {
        !           994:        register TAGFIX *tp;
        !           995:        register SYMLIST *sp;
        !           996:        int n;
        !           997:        SYMLIST *sp2;
        !           998: 
        !           999:        while ((tp = tag_fix) != NULL) {
        !          1000:                if ((n = tag_lookup(tp->tf_name)) != -1) {
        !          1001:                        /* Tag is defined. */
        !          1002:                        for (sp = tp->tf_sp; sp != NULL; ) {
        !          1003:                                sp->sl_dp->db_ae.ae_tagndx = n;
        !          1004:                                sp2 = sp;
        !          1005:                                sp = sp->sl_next;
        !          1006:                                free(sp2);
        !          1007:                        }
        !          1008:                } else {
        !          1009:                        /* Tag is not defined. */
        !          1010:                        dbprintf(("tag %s: unresolved forward references\n", tp->tf_name));
        !          1011:                        for (sp = tp->tf_sp; sp != NULL; ) {
        !          1012:                                /* Do nothing; there are alternatives... */
        !          1013:                                sp2 = sp;
        !          1014:                                sp = sp->sl_next;
        !          1015:                                free(sp2);
        !          1016:                        }
        !          1017:                }
        !          1018:                tag_fix = tp->tf_next;
        !          1019:                free(tp);
        !          1020:        }
        !          1021: 
        !          1022:        /* Free the tag list. */
        !          1023:        while (tag_list != NULL) {
        !          1024:                sp = tag_list;
        !          1025:                tag_list = sp->sl_next;
        !          1026:                free(sp);
        !          1027:        }
        !          1028: }
        !          1029: 
        !          1030: /*
        !          1031:  * Process a debug relocation record.
        !          1032:  * n is the debug item reference number.
        !          1033:  */
        !          1034: outdloc(n) register int n;
        !          1035: {
        !          1036:        register LNNUM *lp;
        !          1037:        register DBSYM *dp;
        !          1038:        register AUXENT *ap;
        !          1039: 
        !          1040:        dbprintf(("outdloc(%d): dot=%d\n", n, dot));
        !          1041: 
        !          1042:        /* Find matching refnum in line number list. */
        !          1043:        for (lp = ln_list; lp != NULL; lp = lp->ln_next) {
        !          1044:                if (lp->ln_flag == LN_LINE && lp->ln_val == n)
        !          1045:                        break;
        !          1046:        }
        !          1047:        if (lp == NULL)
        !          1048:                cbotch("outdloc refnum=%d", n);
        !          1049:        if (dotseg != SCODE)
        !          1050:                cbotch("outdloc seg=%d", seg);
        !          1051:        lp->ln_addr = dot;                      /* patch address */
        !          1052:        if ((dp = lp->ln_dp) != NULL)
        !          1053:                dp->db_se.n_value = dot;        /* patch symbol entry address */
        !          1054: 
        !          1055:        /*
        !          1056:         * The function size patch below is wrong because the actual
        !          1057:         * function size includes the epilog.
        !          1058:         * The "dot + 2" adds in the "leave; ret" bytes,
        !          1059:         * but there may be from 0 to 3 additional "pop" bytes for EBX, ESI, EDI.
        !          1060:         */
        !          1061:        if ((ap = lp->ln_ap) != NULL)
        !          1062:                ap->ae_fsize += dot + 2;        /* patch function length */
        !          1063: }
        !          1064: 
        !          1065: /*
        !          1066:  * Finish up.
        !          1067:  */
        !          1068: outdone()
        !          1069: {
        !          1070:        if (notvariant(VASM))
        !          1071:                bput(TEND);
        !          1072:        tag_resolve();
        !          1073: }
        !          1074: 
        !          1075: /* Second pass. */
        !          1076: copycode()
        !          1077: {
        !          1078:        register int op, i, flags;
        !          1079:        register SEG *segp;
        !          1080:        register SYM *sp;
        !          1081:        register long dseek;
        !          1082:        register ADDRESS mseek, segsize;
        !          1083:        int nsecs, nd, isbyte, isword, issym, ispcr;
        !          1084:        ival_t data;
        !          1085:        RELOC *rp;
        !          1086:        SCNHDR *shp;
        !          1087: 
        !          1088:        /* Assign symbol table indices for sections, different if debug. */
        !          1089:        flags = 0;              /* COFF header flags */
        !          1090:        nsecs = C_NSECS;        /* number of sections, including .comment */
        !          1091:        if (refnum != -1) {
        !          1092:                symindex[C_TEXT_SEG] = C_TEXT_DB;
        !          1093:                symindex[C_DATA_SEG] = C_DATA_DB;
        !          1094:                symindex[C_BSS_SEG] = C_BSS_DB;
        !          1095:        } else {
        !          1096:                flags |= F_LSYMS;               /* no local symbols */
        !          1097:                symindex[C_TEXT_SEG] = C_TEXT_SEG;
        !          1098:                symindex[C_DATA_SEG] = C_DATA_SEG;
        !          1099:                symindex[C_BSS_SEG] = C_BSS_SEG;
        !          1100:                --nsecs;                        /* do not write .comment section */
        !          1101:        }
        !          1102: 
        !          1103:        /* Assign segment base addresses. */
        !          1104:        dot_sec = -1;
        !          1105:        dseek = sizeof(FILEHDR) + nsecs * sizeof(SCNHDR);
        !          1106:        mseek = 0;
        !          1107:        for (i = SCODE, segp = &seg[SCODE]; i <= SBSS; ++i, ++segp) {
        !          1108:                segsize = RUP(segp->s_dot);
        !          1109:                segp->s_dot = 0;
        !          1110:                if (sec_index[i] != dot_sec) {
        !          1111:                        /* Begin new COFF section. */
        !          1112:                        dot_sec = sec_index[i];
        !          1113:                        dbprintf(("COFF section %d\n", dot_sec));
        !          1114:                        shp = &scn_hdr[dot_sec];
        !          1115:                        shp->s_paddr = shp->s_vaddr = mseek;
        !          1116:                        if (i != C_BSS_SEG)
        !          1117:                                shp->s_scnptr = dseek;
        !          1118:                }
        !          1119:                dbprintf(("segment %d: size=%d dseek=%ld mseek=%ld\n", i, segsize, dseek, mseek));
        !          1120:                segp->s_dseek = dseek;          /* set compiler seg disk seek */
        !          1121:                segp->s_mseek = mseek;          /* and memory seek */
        !          1122:                scn_hdr[dot_sec].s_size += segsize;     /* bump COFF seg size */
        !          1123:                dseek += segsize;               /* bump seek pointer */
        !          1124:                mseek += segsize;               /* bump memory seek */
        !          1125:        }
        !          1126: 
        !          1127:        /* Write the .comment section: translator id and version number. */
        !          1128:        if (refnum != -1) {
        !          1129:                shp = &scn_hdr[C_CMT_SEG];
        !          1130:                segsize = RUP(strlen(CC_ID) + strlen(VERSMWC) + 1);
        !          1131:                shp->s_paddr = mseek;
        !          1132:                shp->s_vaddr = mseek;
        !          1133:                shp->s_size = segsize;
        !          1134:                shp->s_scnptr = dseek;
        !          1135:                oseek(dseek);
        !          1136:                owrite(CC_ID, sizeof(CC_ID) - 1);       /* no NUL */
        !          1137:                owrite(VERSMWC, sizeof(VERSMWC));       /* with NUL */
        !          1138:                dseek += segsize;                       /* bump seek pointer */
        !          1139:                mseek += segsize;                       /* bump memory seek */
        !          1140:        }
        !          1141: 
        !          1142:        /* Fix reloc offsets. */
        !          1143:        for (shp = &scn_hdr[C_TEXT_SEG]; shp < &scn_hdr[nsecs]; ++shp) {
        !          1144:                if (shp->s_nreloc != 0) {
        !          1145:                        shp->s_relptr = dseek;
        !          1146:                        dseek += shp->s_nreloc * sizeof(RELOC);
        !          1147:                }
        !          1148:        }
        !          1149: 
        !          1150:        /* Write line number information, .text section only. */
        !          1151:        shp = &scn_hdr[C_TEXT_SEG];
        !          1152:        if (shp->s_nlnno != 0) {
        !          1153:                shp->s_lnnoptr = dseek;
        !          1154:                oseek(dseek);
        !          1155:                write_lnnums();
        !          1156:                dseek += scn_hdr[C_TEXT_SEG].s_nlnno * sizeof(LINENO);
        !          1157:        } else
        !          1158:                flags |= F_LNNO;                /* no line numbers */
        !          1159: 
        !          1160:        /* Write symbols. */
        !          1161:        write_symbols(dseek);
        !          1162: 
        !          1163:        /* Copy out code. */
        !          1164:        dotseg = SCODE;
        !          1165:        dot_sec = sec_index[dotseg];
        !          1166:        txtdot = dot = 0;
        !          1167:        txtp = &txt[0];
        !          1168:        relp = &rel[0];
        !          1169:        while ((op = bget()) != TEND) {
        !          1170:                if (op == TENTER) {
        !          1171:                        notenuf();
        !          1172:                        seg[dotseg].s_dot = dot;
        !          1173:                        dotseg = bget();
        !          1174:                        dot_sec = sec_index[dotseg];
        !          1175:                        txtdot = dot = seg[dotseg].s_dot;
        !          1176:                        continue;
        !          1177:                }
        !          1178:                enuf(4, sizeof(RELOC));         /* leave space for next op */
        !          1179:                if (isbyte = ((op & TTYPE) == TBYTE)) {
        !          1180:                        nd = 1;
        !          1181:                        data = bget();
        !          1182:                } else if (isword = ((op & TTYPE) == TWORD)) {
        !          1183:                        nd = 2;
        !          1184:                        data = iget();
        !          1185:                } else if ((op & TTYPE) == TLONG) {
        !          1186:                        nd = 4;
        !          1187:                        data = iget();
        !          1188:                } else
        !          1189:                        cbotch("unrecognized op byte: %d", op);
        !          1190:                if (issym = ((op & TSYM) != 0)) {
        !          1191:                        sp = pget();
        !          1192:                        if (is_def(sp) || is_label(sp) || is_bss(sp))
        !          1193:                                data += sp->s_value;
        !          1194:                }
        !          1195:                if (ispcr = ((op & TPCR) != 0))
        !          1196:                        data -= dot + nd;
        !          1197: 
        !          1198:                /* Write text. */
        !          1199:                for (i = 1; i <= nd; i++) {
        !          1200:                        *txtp++ = data;
        !          1201:                        data >>= 8;
        !          1202:                }
        !          1203: 
        !          1204:                /* Write relocation item if required. */
        !          1205:                if (issym || ispcr) {
        !          1206:                        rp = (RELOC *)relp;
        !          1207:                        rp->r_vaddr = dot + seg[dotseg].s_mseek;
        !          1208:                        if (issym) {
        !          1209:                                if (is_def(sp) || is_label(sp))
        !          1210:                                        rp->r_symndx = symindex[sec_index[sp->s_seg]];
        !          1211:                                else
        !          1212:                                        rp->r_symndx = sp->s_ref;
        !          1213:                        } else
        !          1214:                                rp->r_symndx = symindex[dot_sec];
        !          1215:                        if (ispcr)
        !          1216:                                rp->r_type = (isbyte) ? R_PCRBYTE
        !          1217:                                           : (isword) ? R_PCRWORD : R_PCRLONG;
        !          1218:                        else
        !          1219:                                rp->r_type = (isbyte) ? R_DIR8
        !          1220:                                           : (isword) ? R_DIR16 : R_DIR32;
        !          1221:                        relp += sizeof(RELOC);
        !          1222:                }
        !          1223:                dot += nd;
        !          1224:        }
        !          1225: 
        !          1226:        /* Flush buffers. */
        !          1227:        notenuf();
        !          1228: 
        !          1229:        /* Write COFF header. */
        !          1230:        coff_hdr.f_magic = C_386_MAGIC;
        !          1231:        coff_hdr.f_nscns = nsecs;
        !          1232:        coff_hdr.f_timdat = time(NULL);
        !          1233:        coff_hdr.f_opthdr = 0;
        !          1234:        coff_hdr.f_flags = F_AR32WR | flags;
        !          1235:        oseek(0L);
        !          1236:        owrite((char *)&coff_hdr, sizeof(coff_hdr));
        !          1237: 
        !          1238:        /* Write section headers. */
        !          1239:        for (shp = &scn_hdr[C_TEXT_SEG]; shp < &scn_hdr[nsecs]; ++shp)
        !          1240:                owrite((char *)shp, sizeof(*shp));
        !          1241: }
        !          1242: 
        !          1243: /*
        !          1244:  * Write the COFF symbol table.
        !          1245:  * Spill long symbol names to the strings section.
        !          1246:  * If debug, there is a DBSYM entry for each symbol table entry,
        !          1247:  * except that the section names and their aux entries are implicit.
        !          1248:  * If not debug, generate COFF symbol table from the compiler symbol table.
        !          1249:  */
        !          1250: write_symbols(dseek) register long dseek;
        !          1251: {
        !          1252:        register int i;
        !          1253:        register SYM *sp;
        !          1254:        int db_flag, nsecs;
        !          1255:        SYMENT sym;
        !          1256:        AUXENT aux;
        !          1257:        SCNHDR *shp;
        !          1258: 
        !          1259:        db_flag = (refnum != -1);
        !          1260:        nsecs = C_NSECS;
        !          1261:        coff_hdr.f_symptr = dseek;              /* symbol secton base */
        !          1262:        oseek(dseek);                           /* seek to symbol section */
        !          1263:        if (db_flag) {
        !          1264:                /* Write .file symbol and its aux entry. */
        !          1265:                write_dbsym();                  /* .file */
        !          1266:                write_dbsym();                  /* .file aux entry */
        !          1267:        } else
        !          1268:                coff_hdr.f_nsyms = --nsecs;     /* .text, .data, .bss symbols */
        !          1269: 
        !          1270:        /* Set reference numbers and adjust offsets in symbol table. */
        !          1271:        for (i = 0; i < NSHASH; ++i) {
        !          1272:                for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) {
        !          1273:                        /* Adjust symbol offsets for segment bases. */
        !          1274:                        if (is_def(sp) || is_label(sp))
        !          1275:                                sp->s_value += seg[sp->s_seg].s_mseek;
        !          1276:                        /* Set reference numbers. */
        !          1277:                        if (is_global(sp) || (!is_label(sp) && !is_def(sp))) {
        !          1278:                                if (db_flag)
        !          1279:                                        setrefnum(sp);
        !          1280:                                else
        !          1281:                                        sp->s_ref = coff_hdr.f_nsyms++;
        !          1282:                        } else if (isvariant(VXSTAT) && !is_global(sp)
        !          1283:                                && !is_label(sp) && is_def(sp))
        !          1284:                                        sp->s_ref = coff_hdr.f_nsyms++;
        !          1285:                }
        !          1286:        }
        !          1287: 
        !          1288:        /* Write section name symbols. */
        !          1289:        for (i = C_TEXT_SEG, shp = &scn_hdr[i]; i < nsecs; ++i, ++shp) {
        !          1290:                memset(sym.n_name, 0, sizeof(sym.n_name));
        !          1291:                strcpy(sym.n_name, shp->s_name);
        !          1292:                sym.n_value = shp->s_vaddr;
        !          1293:                sym.n_scnum = i + 1;
        !          1294:                sym.n_type = T_NULL;                    /* no type */
        !          1295:                sym.n_sclass = C_STAT;
        !          1296:                sym.n_numaux = (db_flag) ? 1 : 0;       /* aux entries */
        !          1297:                owrite((char *)&sym, sizeof(sym));
        !          1298:                if (db_flag) {
        !          1299:                        /* Write aux entries for sections if debug. */
        !          1300:                        memset(&aux, 0, sizeof(aux));
        !          1301:                        aux.ae_scnlen = shp->s_size;
        !          1302:                        aux.ae_nreloc = shp->s_nreloc;
        !          1303:                        aux.ae_nlinno = shp->s_nlnno;
        !          1304:                        owrite((char *)&aux, sizeof(aux));
        !          1305:                }
        !          1306:        }
        !          1307: 
        !          1308:        /* Write remaining symbols. */
        !          1309:        str_size = sizeof(long);                /* initial string section size */
        !          1310:        str_seek = dseek + coff_hdr.f_nsyms * sizeof(sym) + str_size;   /* first string seek */
        !          1311:        if (db_flag) {
        !          1312:                while (db_list != NULL)
        !          1313:                        write_dbsym();
        !          1314:        } else {
        !          1315:            /* Scan the C symbol table again and dump the appropriate symbols. */
        !          1316:            for (i = 0; i < NSHASH; ++i) {
        !          1317:                for (sp = hash2[i]; sp != NULL; sp = sp->s_fp) {
        !          1318:                        if (is_global(sp) || (!is_label(sp) && !is_def(sp)))
        !          1319:                                write_sym(sp, C_EXT);
        !          1320:                        else if (isvariant(VXSTAT) && !is_global(sp)
        !          1321:                                && !is_label(sp) && is_def(sp))
        !          1322:                                write_sym(sp, C_STAT);
        !          1323:                }
        !          1324:            }
        !          1325:        }
        !          1326:        /* Write string table size if nonempty. */
        !          1327:        if (str_size != sizeof(long))
        !          1328:                owrite((char *)&str_size, sizeof(str_size));    
        !          1329: }
        !          1330: 
        !          1331: /*
        !          1332:  * Write a symbol.
        !          1333:  */
        !          1334: write_sym(sp, class) register SYM *sp;
        !          1335: {
        !          1336:        register int len;
        !          1337:        SYMENT sym;
        !          1338: 
        !          1339:        len = strlen(sp->s_id);
        !          1340:        if (len <= SYMNMLEN)
        !          1341:                strncpy(sym.n_name, sp->s_id, SYMNMLEN);
        !          1342:        else {
        !          1343:                /* Spill long name to string table. */
        !          1344:                write_string(&sym, sp->s_id);
        !          1345:        }
        !          1346:        sym.n_value = sp->s_value;
        !          1347:        if (is_def(sp))
        !          1348:                sym.n_scnum = sec_index[sp->s_seg] + 1;
        !          1349:        else
        !          1350:                sym.n_scnum = N_UNDEF;
        !          1351:        sym.n_type = T_NULL;                    /* no type */
        !          1352:        sym.n_sclass = class;
        !          1353:        sym.n_numaux = 0;                       /* no aux entries */
        !          1354:        owrite((char *)&sym, sizeof(sym));
        !          1355: }
        !          1356: 
        !          1357: /*
        !          1358:  * Write a long string name to the string section.
        !          1359:  */
        !          1360: write_string(sp, id) SYMENT *sp; register char *id;
        !          1361: {
        !          1362:        register long seek;
        !          1363:        register int len;
        !          1364: 
        !          1365:        sp->n_zeroes = 0L;
        !          1366:        sp->n_offset = str_size;
        !          1367:        len = strlen(id) + 1;
        !          1368:        seek = ftell(ofp);
        !          1369:        oseek(str_seek);
        !          1370:        sput(id);
        !          1371:        str_seek += len;
        !          1372:        str_size += len;
        !          1373:        oseek(seek);
        !          1374: }
        !          1375: 
        !          1376: /*
        !          1377:  * Write the line number entries.
        !          1378:  */
        !          1379: write_lnnums()
        !          1380: {
        !          1381:        register LNNUM *lp;
        !          1382:        LINENO lineno;
        !          1383: 
        !          1384:        while ((lp = ln_list) != NULL) {
        !          1385:                lineno.l_lnno = lp->ln_lnnum;
        !          1386:                if (lp->ln_flag == LN_FUNC)             /* function index */
        !          1387:                        lineno.l_addr.l_symndx = lp->ln_val;
        !          1388:                else if (lp->ln_flag == LN_LINE)        /* line physical address */
        !          1389:                        lineno.l_addr.l_paddr = lp->ln_addr;
        !          1390:                else
        !          1391:                        cbotch("write_lnnums");
        !          1392:                owrite(&lineno, sizeof lineno);
        !          1393:                ln_list = lp->ln_next;
        !          1394:                free(lp);               
        !          1395:        }
        !          1396: }
        !          1397: 
        !          1398: /*
        !          1399:  * Write a single DBSYM item to the symbol table.
        !          1400:  * Free the item from the list.
        !          1401:  */
        !          1402: write_dbsym()
        !          1403: {
        !          1404:        register DBSYM *dp;
        !          1405:        register SYMENT *sp;
        !          1406:        register int n;
        !          1407: 
        !          1408:        if ((dp = db_list) == NULL)
        !          1409:                cfatal("incomplete debug information");
        !          1410:        sp = &(dp->db_se);
        !          1411: 
        !          1412:        /* Adjust .data and .bss locations by section base. */
        !          1413:        n = sp->n_scnum - 1;
        !          1414:        if (dp->db_seg != -1)
        !          1415:                sp->n_value += seg[dp->db_seg].s_mseek;
        !          1416: 
        !          1417:        /* Spill long name to the string table. */
        !          1418:        if (is_lname(dp))
        !          1419:                write_string(sp, dp->db_name);
        !          1420:        
        !          1421:        /* Write the symbol entry. */
        !          1422:        owrite(sp, sizeof *sp);
        !          1423: 
        !          1424:        /* Free the entry. */
        !          1425:        db_list = dp->db_next;
        !          1426:        free(dp);
        !          1427: }
        !          1428: 
        !          1429: /*
        !          1430:  * Set reference number of symbol sp by searching the debug symbol list,
        !          1431:  * so that fixups targeting it get the right symbol number.
        !          1432:  * This is used only if debug.
        !          1433:  */
        !          1434: setrefnum(sp) register SYM *sp;
        !          1435: {
        !          1436:        static int ignore = -1;
        !          1437:        register DBSYM *dp;
        !          1438:        register char *name;
        !          1439: 
        !          1440:        /* If the user specifies -VTPROF but not -g, ignore the debug info. */
        !          1441:        if (ignore == -1)                               /* set it first time */
        !          1442:                ignore = (isvariant(VTPROF) && notvariant(VLINES)
        !          1443:                         && notvariant(VTYPES) && notvariant(VDSYMB));
        !          1444:        if (ignore)
        !          1445:                return;
        !          1446: 
        !          1447:        name = sp->s_id;
        !          1448:        for (dp = db_list; dp != NULL; dp = dp->db_next)
        !          1449:                if (!is_aux(dp)                         /* SYMENT not AUXENT */
        !          1450:                 && dp->db_level == 0                   /* global */
        !          1451:                 && db_strcmp(dp, name) == 0)           /* matching name */
        !          1452:                        break;                          /* gotcha */
        !          1453:        if (dp == NULL) {
        !          1454:                /*
        !          1455:                 * Function calls generated by the compiler (e.g. "memcpy"
        !          1456:                 * for structure assignment) may have no associated debug item,
        !          1457:                 * so create an appropriate External entry as required.
        !          1458:                 */
        !          1459:                if (sp->s_seg != SANY)
        !          1460:                        cfatal("incomplete debug information (%s)", sp->s_id);
        !          1461:                dp = new_sym(sp->s_id, sp->s_value, N_UNDEF, T_NULL, C_EXT);
        !          1462:        }
        !          1463:        sp->s_ref = dp->db_ref;
        !          1464: }
        !          1465: 
        !          1466: /*
        !          1467:  * Compare two names like strcmp() does, but the first arg is a DBSYM *.
        !          1468:  */
        !          1469: int
        !          1470: db_strcmp(dp, s) register DBSYM *dp; register char *s;
        !          1471: {
        !          1472:        register int status;
        !          1473: 
        !          1474:        if (is_lname(dp))
        !          1475:                return strcmp(dp->db_name, s);          /* compare long db name */
        !          1476:        status = strncmp(dp->db_se.n_name, s, 8);       /* compare short db name */
        !          1477:        if (status != 0)
        !          1478:                return status;                          /* mismatch */
        !          1479:        return (strlen(s) <= 8) ? status : 1;           /* first 8 match */
        !          1480: }
        !          1481: 
        !          1482: /* Buffering and output writing routines. */
        !          1483: /*
        !          1484:  * Make sure there is enough room in the text and relocation buffers
        !          1485:  * for nt bytes of text and nr bytes of relocation.
        !          1486:  */
        !          1487: enuf(nt, nr) int nt, nr;
        !          1488: {
        !          1489:        if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL])
        !          1490:                notenuf();
        !          1491: }
        !          1492: 
        !          1493: /*
        !          1494:  * Flush the text and relocation buffers.
        !          1495:  * Look at the segment table to figure out the exact location
        !          1496:  * of the data in the file, and compute the correct seek
        !          1497:  * address in the image by adding the base address of
        !          1498:  * the text record "txtdot" to that base.
        !          1499:  */
        !          1500: notenuf()
        !          1501: {
        !          1502:        register int n;
        !          1503: 
        !          1504:        if ((n = txtp-txt) != 0) {
        !          1505:                dbprintf(("notenuf: %d text bytes\n", n));
        !          1506:                dbprintf(("seek to txtdot=%d + seg[%d].s_dseek=%ld\n", txtdot, dotseg, seg[dotseg].s_dseek));
        !          1507:                oseek(txtdot + seg[dotseg].s_dseek);
        !          1508:                owrite(txt, n);
        !          1509:                if ((n = relp-rel) != 0) {
        !          1510:                        dbprintf(("notenuf: %d reloc bytes\n", n));
        !          1511:                        dbprintf(("seek to reldot[%d]=%d + relptr=%ld\n", dot_sec, reldot[dot_sec], scn_hdr[dot_sec].s_relptr));
        !          1512:                        oseek(reldot[dot_sec] + scn_hdr[dot_sec].s_relptr);
        !          1513:                        owrite(rel, n);
        !          1514:                        reldot[dot_sec] += n;
        !          1515:                        relp = rel;
        !          1516:                }
        !          1517:        }
        !          1518:        txtp = txt;
        !          1519:        txtdot = dot;
        !          1520: }
        !          1521: 
        !          1522: /*
        !          1523:  * Seek output file, checking for seek error.
        !          1524:  */
        !          1525: oseek(l) long l;
        !          1526: {
        !          1527:        if (fseek(ofp, l, SEEK_SET) == -1L)
        !          1528:                cfatal("seek to %ld failed", l);
        !          1529: }
        !          1530: 
        !          1531: /*
        !          1532:  * Write a block of n bytes from p to the output file,
        !          1533:  * checking for write errors.
        !          1534:  */
        !          1535: owrite(p, n) char *p; register int n;
        !          1536: {
        !          1537:        if (fwrite(p, sizeof(char), n, ofp) != n)
        !          1538:                cfatal("output write error");
        !          1539: }
        !          1540: 
        !          1541: /* 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.