Annotation of coherent/b/bin/ld386/pass1.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ld/pass1.c
                      3:  *
                      4:  * One Pass Coff Loader.
                      5:  * By Charles Fiterman 3/31/92 for Mark Williams.
                      6:  */ 
                      7: #include "ld.h"
                      8: 
                      9: mod_t *sysHead;
                     10: static int  ifd;
                     11: static char *fname;
                     12: 
                     13: /*
                     14:  * Reverse bytes on the 80386 for archive pointers.
                     15:  */
                     16: #ifdef GEMDOS
                     17: #include <osbind.h>
                     18: #define flipbytes(x)
                     19: #else
                     20: flipbytes(c)
                     21: register char *c;
                     22: {
                     23:        register char t;
                     24: 
                     25:        t = c[0]; c[0] = c[3]; c[3] = t;
                     26:        t = c[1]; c[1] = c[2]; c[2] = t;
                     27: }
                     28: #endif
                     29: 
                     30: /*
                     31:  * Symbol name.
                     32:  */
                     33: char *
                     34: symName(sym, work)
                     35: register SYMENT *sym;
                     36: register char *work;
                     37: {
                     38:        if (1 == sym->n_zeroes) {       /* pointer to table record */
                     39:                sym_t *s;
                     40: 
                     41:                s = (sym_t *)sym->n_offset;
                     42:                sym = &(s->sym);
                     43:        }
                     44: 
                     45:        if (!sym->n_zeroes)             /* pointer to long symbol */
                     46:                return ((char *)sym->n_offset);
                     47: 
                     48:        /*
                     49:         * Name in record may need terminator.
                     50:         * Profiling shows this gets used a lot so do it quick
                     51:         * even at the cost of some readability.
                     52:         */
                     53:        ((long *)work)[0] = sym->n_zeroes;
                     54:        ((long *)work)[1] = sym->n_offset;
                     55: /*     memcpy(work, sym->n_name, SYMNMLEN); */
                     56:        work[SYMNMLEN] = '\0';
                     57:        return (work);
                     58: }
                     59: 
                     60: /*
                     61:  * complain about redefined symbol
                     62:  */
                     63: void
                     64: symredef(sp, mp)
                     65: sym_t  *sp;
                     66: mod_t  *mp;
                     67: {
                     68:        /*
                     69:         * Simple module.
                     70:         */
                     71:        if (mp->mname[0] == '\0')
                     72:                spmsg(sp, "redefined in file '%s'", mp->fname);
                     73:        /* A symbol is defined in incompatible ways in different files. */
                     74: 
                     75:        else
                     76:                spmsg(sp, "redefined in file '%s': module '%.*s'",
                     77:                        mp->fname, DIRSIZ, mp->mname );
                     78:        /* A symbol is defined in incompatible ways in different files. */
                     79: }
                     80: 
                     81: /*
                     82:  * Return undefined reference to given symbol if any.
                     83:  */
                     84: sym_t *
                     85: symref(name)
                     86: char *name;
                     87: {
                     88:        char work[SYMNMLEN + 1];
                     89:        register sym_t  *sp;
                     90:        register SYMENT *sym;
                     91: 
                     92:        /* Scan internal symbol table for undefined reference. */
                     93:        for (sp=symtable[crc16(name) % NHASH]; sp != NULL; sp=sp->next) {
                     94:                sym = &(sp->sym);
                     95:                if (undefined(sym) && !strcmp(symName(sym, work), name))
                     96:                        break;
                     97:        }
                     98:        return(sp); /* Return reference, or NULL. */
                     99: }
                    100: 
                    101: /*
                    102:  * Read input files.
                    103:  */
                    104: readFile(fn, loadsw, p)
                    105: char *fn;      /* file name */
                    106: int  loadsw;   /* 1 = load this file, 0 = use its symbol table */
                    107: register char *p;
                    108: {
                    109:        struct stat st;
                    110: 
                    111:        fname = fn;
                    112: 
                    113:        if (NULL == p) {        /* not forced */
                    114:                /*
                    115:                 * Look for rename entrys.
                    116:                 * con=atcon
                    117:                 * is not a filename with an =
                    118:                 * it means rename con to atcon.
                    119:                 * This is a drvld requirment.
                    120:                 */
                    121:                if (NULL != (p = strchr(fname, '='))) {
                    122:                        ren_t   *new;
                    123:        
                    124:                        new = alloc(sizeof(*new));
                    125:                        new->next = rhead;
                    126:                        rhead = new;
                    127:                        new->from = fname;
                    128:                        *p = '\0';
                    129:                        new->to = p + 1;
                    130:                        return;
                    131:                }
                    132: 
                    133:                /* all names must be *.[ao] */
                    134:                if (NULL == (p = strrchr(fname, '.')) || p[2])
                    135:                        p = ".?";
                    136:                if (!loadsw)    /* drvld's read of the system */
                    137:                        p = "_s.o" + 2;
                    138: #if    0
                    139: /* This is bogus, e.g. it suppresses the ld of a_s.o in "cc a_s.o". */
                    140:                /* shared libs have names like libc_s.a */
                    141:                if ((p[-2] == '_') && (p[-1] == 's'))
                    142:                        loadsw = 0;
                    143: #endif
                    144:        }
                    145: #ifdef GEMDOS
                    146:        stat(fname, &st);
                    147:        ifd = qopen(fname, 0);
                    148: #else
                    149:        ifd = qopen(fname, 0);
                    150:        fstat(ifd, &st);
                    151: #endif
                    152:        switch(p[1]) {
                    153:        case 'a':
                    154:                archive(loadsw);
                    155:                break;
                    156:        case 'o':
                    157:                object("", st.st_size, loadsw);
                    158:                break;
                    159:        default:
                    160:                message("unlikely input file name '%s'", fname);
                    161:                /* Input file names must end \fB.o\fR for object or \fB.a\fR
                    162:                 * for archive. */
                    163:        }
                    164:        close(ifd);
                    165: }
                    166: 
                    167: /*
                    168:  * Add item to correct common
                    169:  */
                    170: static void
                    171: addComm(v)
                    172: long v;
                    173: {
                    174:        switch ((int)v & 3) {
                    175:        case 0:
                    176:                comnl += v;     /* Long aligned commons */
                    177:                break;
                    178:        case 2:
                    179:                comns += v;     /* Short aligned commons */
                    180:                break;
                    181:        default:
                    182:                comnb += v;     /* Byte aligned commons */
                    183:        }
                    184: }
                    185: 
                    186: /*
                    187:  * add a symbol to the symbol table.
                    188:  */
                    189: addsym(s, mp)
                    190: register SYMENT *s;
                    191: mod_t *mp;
                    192: {
                    193:        register sym_t *sp;
                    194:        ren_t *ren;
                    195:        enum state {
                    196:                local, gdef, gref, comm
                    197:        } new, old;
                    198:        int h, sec;
                    199:        char has_fsize, has_fcn, nodata;
                    200:        char *name;
                    201:        char w1[SYMNMLEN + 1], w2[SYMNMLEN + 1];
                    202: 
                    203:        sec = s->n_scnum;
                    204:        switch (s->n_sclass) {
                    205:        case C_EXTDEF:
                    206:                s->n_sclass = C_EXT;
                    207:                sec = s->n_value = s->n_scnum = 0;
                    208:        case C_EXT:
                    209:                if (sec)
                    210:                        new = gdef;
                    211:                else if (s->n_value)
                    212:                        new = comm;
                    213:                else
                    214:                        new = gref;
                    215:                break;
                    216:        case C_STAT:
                    217:                new = local;
                    218:                break;
                    219:        default:
                    220:                if (!debflg)
                    221:                        return;
                    222:                new = local;
                    223:        }
                    224: 
                    225:        name = symName(s, w1);
                    226: 
                    227:        /* check rename entrys */
                    228:        for (ren = rhead; NULL != ren; ren = ren->next) {
                    229:                if (!strcmp(ren->from, name)) {
                    230:                        s->n_zeroes = 0;
                    231:                        name = ren->to;
                    232:                        s->n_offset = (long)name;
                    233:                        break;
                    234:                }
                    235:        }
                    236:        h = crc16(name) % NHASH;
                    237: 
                    238:        /* Make symbols segment relative, if mp == NULL than sec == 0 */
                    239:        if (sec > 0)
                    240:                s->n_value += secth[sec - 1].s_size - mp->s[sec - 1].s_vaddr;
                    241:                                
                    242:        if (local == new && 
                    243:            (nolcl ||
                    244:             (noilcl && (name[0] == '.') && (name[1] == 'L'))))
                    245:                return;
                    246: 
                    247:        for (sp = ((local == new) ? NULL : symtable[h]);
                    248:             sp != NULL;
                    249:             sp = sp->next) {
                    250:                if ((sp->sym.n_sclass != C_EXT) ||
                    251:                    (strcmp(symName(&(sp->sym), w2), name)))
                    252:                        continue;
                    253:        
                    254:                if (sp->sym.n_scnum)
                    255:                        old = gdef;
                    256:                else if (sp->sym.n_value)
                    257:                        old = comm;
                    258:                else
                    259:                        old = gref;
                    260: 
                    261:                switch (new) {
                    262:                /* case local: can't get here */
                    263: 
                    264:                case gref:
                    265:                        s->n_offset = (long)sp;
                    266:                        s->n_zeroes = 1;
                    267:                        return;
                    268: 
                    269:                case gdef:
                    270:                        switch (old) {
                    271:                        case comm:
                    272:                                spwarn(sp,
                    273:                        "symbol defined as a common then a global");
                    274:                        /* A symbol was defined as a common and a globl, eg
                    275:                         * .DM
                    276:                         *      int x;          // a common in one module
                    277:                         *      int x = 5;      // a globl in another module
                    278:                         * .DE
                    279:                         * Read your code and think about variable usage.
                    280:                         * We redefined the common as an external to match
                    281:                         * the UNIX linker, which fails to flag this.
                    282:                         */
                    283:                                addComm(- sp->sym.n_value); /* zonk common */
                    284:                                memcpy(&(sp->sym), s, sizeof(*s));
                    285:                                sp->mod = mp;
                    286:                                s->n_offset = (long)sp;
                    287:                                s->n_zeroes = 1;
                    288:                                return;
                    289: 
                    290:                        case gref:
                    291:                                nundef--;
                    292:                                memcpy(&(sp->sym), s, sizeof(*s));
                    293:                                sp->mod = mp;
                    294:                                s->n_offset = (long)sp;
                    295:                                s->n_zeroes = 1;
                    296:                                return;
                    297: 
                    298:                        default:
                    299:                                symredef(sp, mp);
                    300:                                return;
                    301:                        }
                    302: 
                    303:                case comm:
                    304:                        switch (old) {
                    305:                        case comm:
                    306:                                s->n_offset = (long)sp;
                    307:                                s->n_zeroes = 1;
                    308: 
                    309:                                if (sp->sym.n_value == s->n_value)
                    310:                                        return;
                    311: 
                    312:                                spwarn(sp,  "defined with lengths %ld and %ld",
                    313:                                        sp->sym.n_value,
                    314:                                        s->n_value);
                    315:                                /* A common was defined with different lengths,
                    316:                                 * while this is legal it is very unusual in
                    317:                                 * C programs. This warning may be turned off
                    318:                                 * with the -q flag */
                    319: 
                    320:                                addComm(- sp->sym.n_value);
                    321:                                if (sp->sym.n_value < s->n_value) {
                    322:                                        sp->sym.n_value = s->n_value;
                    323:                                        sp->mod = mp;
                    324:                                }
                    325:                                sp->sym.n_value += 3;
                    326:                                sp->sym.n_value &= ~3L;
                    327:                                addComm(sp->sym.n_value);
                    328:                                return;
                    329: 
                    330:                        case gref:
                    331:                                addComm(s->n_value);
                    332:                                nundef--;
                    333:                                memcpy(&(sp->sym), s, sizeof(*s));
                    334:                                sp->mod = mp;
                    335:                                s->n_offset = (long)sp;
                    336:                                s->n_zeroes = 1;
                    337:                                return;
                    338: 
                    339:                        case gdef:
                    340:                                spwarn(sp, "Defined as a global then a common");
                    341:                                        /* NODOC */
                    342:                                s->n_offset = (long)sp;
                    343:                                s->n_zeroes = 1;
                    344:                                return;
                    345:                        }
                    346:                }
                    347:        }
                    348: 
                    349:        /* symbol local or not found */
                    350:        sp = alloc(sizeof(*sp));
                    351:        memcpy(&(sp->sym), s, sizeof(*s));
                    352:        sp->next = symtable[h];
                    353:        symtable[h] = sp;
                    354: 
                    355:        switch (new) {
                    356:        case comm:
                    357:                addComm(s->n_value);
                    358:        case local:
                    359:                break;
                    360:        case gref:
                    361:                nundef++;
                    362:        }
                    363:        
                    364:        sp->mod = mp;
                    365:        s->n_offset = (long)sp;
                    366:        s->n_zeroes = 1;
                    367: }
                    368: 
                    369: /*
                    370:  * Read input file.
                    371:  */
                    372: static void
                    373: xread(loc, size)
                    374: char *loc;
                    375: unsigned size;
                    376: {
                    377:        if (size != read(ifd, loc, size))
                    378:                fatal("error reading '%s'", fname); /**/
                    379: }
                    380: 
                    381: /*
                    382:  * Inhale object file.
                    383:  */
                    384: object(mname, size, loadsw)
                    385: char *mname;
                    386: long size;
                    387: {
                    388:        register SYMENT *sym;
                    389:        register SCNHDR *s;
                    390:        SYMENT *endSym;
                    391:        mod_t *mp;
                    392:        char *endmod;
                    393:        long i, j, k;
                    394: 
                    395:        if (watch) {
                    396:                errCount--;
                    397:                modmsg(fname, mname, "adding"); /* NODOC */
                    398:        }
                    399:        if (size < sizeof(FILEHDR)) {
                    400:                modmsg(fname, mname, "not an object file - length %d", size);
                    401:                /* This cannot be an object file */
                    402:                exit(1);
                    403:        }
                    404:        mp    = alloc(sizeof(*mp));     /* allocate our header */
                    405:        mp->f = alloc((int)size);       /* allocate space for file */
                    406:        endmod = mp->f + size;          /* end of space for file */
                    407:        xread(mp->f, (int)size);        /* inhale file */
                    408: 
                    409:        if (mp->f->f_magic != C_386_MAGIC) {
                    410:                modmsg(fname, mname, "not an object file - header starts %x", mp->f->f_magic);
                    411:                /* Coff headers are expected to start 0x14C,
                    412:                 * which is called the magic number.
                    413:                 * This started with the stated hex number. */
                    414:                exit(1);
                    415:        }
                    416: 
                    417:        mp->fname = newcpy(fname);
                    418:        if (*mname)
                    419:                mp->mname = newcpy(mname);
                    420:        else
                    421:                mp->mname = "";
                    422: 
                    423:        if (loadsw) {   /* put modules on load list */
                    424:                if (head == NULL)
                    425:                        head = mp;
                    426:                else
                    427:                        tail->next = mp;
                    428:                tail = mp;
                    429:                fileh.f_magic = C_386_MAGIC;
                    430:        }
                    431:        else {          /* put modules on linkto list */
                    432:                if (xhead == NULL)
                    433:                        xhead = mp;
                    434:                else
                    435:                        xtail->next = mp;
                    436:                xtail = mp;
                    437:        }
                    438: 
                    439:        /*
                    440:         * Turn disk pointers into ram pointers.
                    441:         */
                    442:        j = ((long)(mp->f));
                    443:        mp->s = (SCNHDR *)(sizeof(FILEHDR) + j + mp->f->f_opthdr);
                    444:        mp->f->f_symptr += j;
                    445:        mp->l = (char *)(mp->f->f_symptr + (mp->f->f_nsyms * sizeof(SYMENT)));
                    446:        if ((mp->f->f_symptr > (long)endmod) ||
                    447:            (mp->l > endmod) ||
                    448:            (mp->f->f_nsyms < 0))
                    449:                corrupt(mp);
                    450: 
                    451:        /* Setup all sections */
                    452:        for (i = 0; i < mp->f->f_nscns; i++) {
                    453:                s = mp->s + i;
                    454: 
                    455:                if (nosym && (STYP_INFO == s->s_flags))
                    456:                        continue;       /* -s strips comments */
                    457: 
                    458:                /* Test disk pointers for sanity and make them char pointers */
                    459: #define tst(x) if ((s->x > size) || (s->x < 0)) corrupt(mp); s->x += j;
                    460:                tst(s_scnptr);
                    461:                tst(s_relptr);
                    462:                tst(s_lnnoptr);
                    463: #undef tst
                    464: 
                    465:                for (k = 0; k < osegs; k++) {
                    466:                        if (!strncmp(secth[k].s_name, s->s_name, 8)) {
                    467:                                s->s_paddr = k; /* remember outseg number */
                    468:                                break;
                    469:                        }
                    470:                }
                    471: 
                    472:                if ((k == osegs) && loadsw) {   /* New segment */
                    473:                        if (++osegs == MAXSEG)
                    474:                           fatal("Max segment limit of %s exceeded", MAXSEG);
                    475:                        w_message("adding segment '%s'", s->s_name);
                    476:                        memcpy(secth + k, s, sizeof(*s));
                    477:                        s->s_paddr = k;
                    478:                        secth[k].s_size = secth[k].s_nreloc = 0;
                    479: 
                    480:                        /* extra segments go to four places */
                    481:                        switch(s->s_flags) {
                    482:                        case STYP_TEXT:
                    483:                                segMap[k] = S_TEXT;
                    484:                                break;
                    485:                        case STYP_DATA:
                    486:                                segMap[k] = S_DATA;
                    487:                                break;
                    488:                        case STYP_BSS:
                    489:                                segMap[k] = S_BSSD;
                    490:                                break;
                    491:                        case STYP_INFO:
                    492:                                segMap[k] = S_COMM;
                    493:                                break;
                    494:                        default:
                    495:                                segMap[k] = S_COMM;
                    496:                                fprintf(stderr, 
                    497:                        "warning: segment '%s' treated as comment\n",
                    498:                                        s->s_name);
                    499:                        }
                    500:                }
                    501:        }
                    502: 
                    503:        /* Do all symbols */
                    504:        sym = (SYMENT *)mp->f->f_symptr;
                    505:        endSym =  sym + mp->f->f_nsyms;
                    506:        for (; sym < endSym; sym += sym->n_numaux + 1) {
                    507:                if (sym->n_numaux < 0)
                    508:                        corrupt(mp);
                    509:                if (!sym->n_zeroes)
                    510:                        sym->n_offset += (long)(mp->l);
                    511:                addsym(sym, mp);
                    512:        }
                    513: 
                    514:        if (loadsw) {
                    515:                /* Add to all sections */
                    516:                for (i = 0; i < mp->f->f_nscns; i++) {
                    517:                        s = mp->s + i;
                    518: 
                    519:                        if (nosym && (STYP_INFO == s->s_flags))
                    520:                                continue;       /* -s strips comments */
                    521: 
                    522:                        for (k = 0; k < osegs; k++)
                    523:                                if (!strncmp(secth[k].s_name, s->s_name, 8))
                    524:                                        break;
                    525: 
                    526:                        secth[k].s_size  += s->s_size;
                    527:                        secth[k].s_nlnno += s->s_nlnno;
                    528:                        if (reloc)
                    529:                                secth[k].s_nreloc += s->s_nreloc;
                    530:                }
                    531:        }
                    532: }
                    533: 
                    534: /*
                    535:  * Read archive.
                    536:  */
                    537: archive(loadsw)
                    538: {
                    539:        struct old_hdr {
                    540:                char    ar_name[DIRSIZ];        /* Member name */
                    541:                time_t  ar_date;                /* Time inserted */
                    542:                short   ar_gid;                 /* Group id */
                    543:                short   ar_uid;                 /* User id */
                    544:                short   ar_mode;                /* Mode */
                    545:                fsize_t ar_size;                /* File size */
                    546:        } arh;
                    547: 
                    548:        struct  ar_hdr in_arh;
                    549:        fsize_t count, size, *ptrs;
                    550:        char    magic[SARMAG], *p;
                    551:        int     found;
                    552:        unsigned i;
                    553:        char    *names, *name;
                    554: 
                    555:        xread(magic, sizeof(magic));    /* read archive magic string */
                    556: 
                    557:        if (memcmp(ARMAG, magic, SARMAG))
                    558:                fatal("'%s' is not a COFF archive", fname);
                    559:                /* All files ending \fB.a\fR should be COFF archives. */
                    560: 
                    561:        xread(&in_arh, sizeof(in_arh)); /* read archive header */
                    562: 
                    563:        memset(&arh, '\0', sizeof(arh));
                    564:        memcpy(arh.ar_name, in_arh.ar_name, DIRSIZ);
                    565:        if (NULL != (p = strchr(arh.ar_name, '/')))
                    566:                *p = '\0';
                    567: 
                    568:        sscanf(in_arh.ar_date, "%ld %d %d %o %ld",
                    569:                &arh.ar_date, &arh.ar_uid,
                    570:                &arh.ar_gid, &arh.ar_mode, &arh.ar_size);
                    571: 
                    572:        if (arh.ar_name[0])
                    573:                fatal("Library must be created with ar -s option");
                    574:                /* The \fBar \-s\fR option gives libraries a symbol table
                    575:                 * for the use of \fBld\fR. */
                    576: 
                    577:        /*
                    578:         * read random libraries symbol table.
                    579:         */
                    580:        xread(&count, sizeof(count));   /* read pointer count */
                    581:        flipbytes(&count);
                    582: 
                    583:        /* read file pointers */
                    584:        i = size = count * sizeof(count);
                    585:        if (i != size)
                    586:                fatal("archive '%s' is corrupt", fname);
                    587:                /* This file makes no sense as a COFF archive. */
                    588:        ptrs = alloca(i);
                    589:        xread(ptrs, i);
                    590: 
                    591:        /* read symbol names corresponding to pointers */
                    592:        i = size = arh.ar_size - size - sizeof(count);
                    593:        if (i != size)
                    594:                fatal("archive '%s' is corrupt", fname); /* NODOC */
                    595:        names = alloca(i);
                    596:        xread(names, i);
                    597: 
                    598:        w_message("reading archive '%s' nundef %d", fname, nundef);
                    599: 
                    600:        /* search symbol table unitl nothing found */
                    601:        do {
                    602:                for (found = i = 0, name = names;
                    603:                     (i < count) && nundef;
                    604:                     i++, name = strchr(name, '\0') + 1) {
                    605:                        if(!ptrs[i] || symref(name, 0) == NULL)
                    606:                                continue;
                    607: 
                    608:                        found = 1;      /* found something this pass */
                    609:                        flipbytes(ptrs + i);
                    610:                        lseek(ifd, ptrs[i], 0);
                    611:                        xread(&in_arh, sizeof(in_arh));
                    612: 
                    613:                        sscanf(in_arh.ar_date,
                    614:                                "%ld %d %d %o %ld",
                    615:                                &arh.ar_date, &arh.ar_uid,
                    616:                                &arh.ar_gid, &arh.ar_mode,
                    617:                                &arh.ar_size);
                    618: 
                    619:                        in_arh.ar_date[0] = '\0';
                    620:                        if (NULL != (p = strchr(in_arh.ar_name,'/')))
                    621:                                *p = '\0';
                    622: 
                    623:                        object(in_arh.ar_name, arh.ar_size, loadsw);
                    624: 
                    625:                        ptrs[i] = 0;    /* don't find this again */
                    626:                }
                    627:        } while (found);
                    628: }

unix.superglobalmegacorp.com

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