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

1.1       root        1: /*
                      2:  * n2/i386/outcoff.c
                      3:  * C compiler COFF output writer.
                      4:  * The first pass writes to a temp file.
                      5:  * After the first pass, the compiler knows the sizes of the internal segments.
                      6:  * The compiler then maps the internal segments to the actual output segments.
                      7:  * The second pass reads the temp file and writes the actual output bits.
                      8:  * i386.
                      9:  */
                     10: 
                     11: #include <stdio.h>
                     12: #include <time.h>
                     13: #include <string.h>
                     14: #include <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.