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

1.1       root        1: /*
                      2:  * One pass Coff Loader.
                      3:  * Acts as ld and drvld. Will be mkshrlb when the specs are done.
                      4:  *
                      5:  * By Charles Fiterman for Mark Williams 3/30/92.
                      6:  */
                      7: #include "ld.h"
                      8: #include <stdlib.h>
                      9: #include <signal.h>
                     10: #include <ctype.h>
                     11: #include <path.h>
                     12: 
                     13: flag_t reloc,  /* Combine input into a new .o not an executable */
                     14:        nosym,  /* No symbol table out. */
                     15:        watch,  /* Produce a trace */
                     16:        noilcl, /* Discard C local symbols beginning .L */
                     17:        nolcl,  /* Discard all local symbols */
                     18:        qflag,  /* No warn on commons of different length */
                     19:        Qflag,  /* Absolute silence on everything */
                     20:        debflg, /* Create debug data */
                     21:        drvld,  /* Called as drvld */
                     22:        fource = -1;    /* halt on error */
                     23: 
                     24: int    errCount;
                     25: int    nundef;
                     26: mod_t  *head,                  /* head of list of modules to load */
                     27:        *tail,                  /* tail or list of modules */
                     28:        *xhead,                 /* head of noload modules */
                     29:        *xtail;                 /* tail of noload modules */
                     30: ren_t  *rhead;                 /* rename list */
                     31: 
                     32: char *ofname = "a.out";                /* output file name */
                     33: long comnb, comns, comnl;      /* common lengths */
                     34: char *entrys;                  /* entry string */
                     35: sym_t  *symtable[NHASH];       /* hashed symbol table */
                     36: 
                     37: unsigned short osegs = NLSEG;  /* the number of output segments */
                     38: unsigned short segMap[MAXSEG] = /* All segments map to the first four */
                     39:        { S_TEXT, S_DATA, S_BSSD, S_COMM };
                     40: 
                     41: FILEHDR fileh;
                     42: AOUTHDR aouth;
                     43: SCNHDR  *secth;                /* output segments */
                     44: 
                     45: static long str_length;
                     46: static int ofd;
                     47: static long *file_value = NULL, file_first;
                     48: char *argv0;
                     49: 
                     50: /*
                     51:  * Write or die.
                     52:  */
                     53: void
                     54: xwrite(loc, size)
                     55: char *loc;
                     56: unsigned int size;
                     57: {
                     58:        if (size != write(ofd, loc, size))
                     59:                fatal("write error"); /**/
                     60: }
                     61: 
                     62: /*
                     63:  * Init segment descriptors.
                     64:  */
                     65: void
                     66: initSegs()
                     67: {
                     68:        secth = alloc(sizeof(*secth) * MAXSEG);
                     69:        strcpy(secth[S_TEXT].s_name, _TEXT);
                     70:        secth[S_TEXT].s_flags = STYP_TEXT;
                     71:        strcpy(secth[S_DATA].s_name, _DATA);
                     72:        secth[S_DATA].s_flags = STYP_DATA;
                     73:        strcpy(secth[S_BSSD].s_name, _BSS);
                     74:        secth[S_BSSD].s_flags = STYP_BSS;
                     75:        strcpy(secth[S_COMM].s_name, _COMMENT);
                     76:        secth[S_COMM].s_flags = STYP_INFO;
                     77: }
                     78: 
                     79: /*
                     80:  * Come here on interrupt.
                     81:  */
                     82: byebye()
                     83: {
                     84:        driver_fail(&aouth);
                     85:        exit(1);
                     86: }
                     87: 
                     88: /*
                     89:  * We are drvld not ld. Ask the system where to put the stuff.
                     90:  */
                     91: getsys()
                     92: {
                     93:        register int i;
                     94:        long bsz, daddr;
                     95: 
                     96:        time(&fileh.f_timdat);
                     97:        fileh.f_nscns = osegs = NLSEG;
                     98: 
                     99:        daddr = sizeof(fileh) + (sizeof(* secth) * osegs) +
                    100:                (fileh.f_opthdr = sizeof(aouth));
                    101:        
                    102:        for (i = 0; i < S_BSSD; i++) {  
                    103:                secth[i].s_scnptr = daddr;
                    104:                daddr += secth[i].s_size;
                    105:        }
                    106:        bsz = secth[S_BSSD].s_size;
                    107:        aouth.tsize = secth[S_TEXT].s_size;
                    108:        aouth.dsize = secth[S_DATA].s_size + bsz;
                    109:        signal(SIGKILL, byebye);
                    110:        if (!driver_alloc(&aouth))
                    111:                fatal("kernel interface failed");
                    112:                /* This will become more elaborite when the kernel is done */
                    113:        secth[S_TEXT].s_vaddr = secth[S_TEXT].s_paddr = aouth.text_start;
                    114:        secth[S_DATA].s_vaddr = secth[S_DATA].s_paddr = aouth.data_start;       
                    115:        secth[S_BSSD].s_vaddr = secth[S_BSSD].s_paddr = aouth.data_start + bsz;
                    116:        aouth.dsize -= aouth.bsize = bsz;
                    117: 
                    118:        if (!nosym)
                    119:                fileh.f_symptr = daddr;
                    120: }
                    121: 
                    122: /*
                    123:  * Set virtual bases in array of segments.
                    124:  */
                    125: static
                    126: baseall()
                    127: {
                    128:        register SCNHDR  *sh;
                    129:        int i;
                    130:        unsigned long daddr, vaddr, size;
                    131: 
                    132:        time(&fileh.f_timdat);
                    133: 
                    134:        /* Add extra segments to real segments */
                    135:        for (i = NLSEG; i < osegs; i++) {
                    136:                SCNHDR *oh;
                    137: 
                    138:                oh = secth + i;
                    139:                sh = secth + segMap[i];
                    140: 
                    141:                sh->s_size   += oh->s_size;
                    142:                sh->s_nreloc += oh->s_nreloc;
                    143:                sh->s_nlnno  += oh->s_nlnno;
                    144:        }
                    145: 
                    146:        /* only output S_COMM if it has something */
                    147:        fileh.f_nscns = secth[S_COMM].s_size ? NLSEG : S_COMM;
                    148: 
                    149:        size = 0;
                    150:        daddr = sizeof(fileh) + (sizeof(* secth) * fileh.f_nscns);
                    151:        if (reloc)
                    152:                vaddr = 0;
                    153:        else {
                    154:                daddr += fileh.f_opthdr = sizeof(aouth);
                    155:                if (fileh.f_flags & F_KER)      /* kernel */
                    156:                        vaddr = KERBASE;
                    157:                else                            /* executable */
                    158:                        vaddr = daddr;
                    159:        }
                    160: 
                    161:        /* set s_vaddr, s_paddr, s_size, and s_scnptr for all segments */
                    162:        for (i = 0; i < NLSEG; i++) {
                    163:                sh = secth + i;
                    164:                switch (i) {
                    165:                case S_TEXT:
                    166:                        aouth.text_start = sh->s_vaddr = vaddr;
                    167:                        aouth.tsize = size = sh->s_size;                
                    168:                        break;
                    169: 
                    170:                case S_DATA:    /* data adjustment */
                    171:                        if (!reloc) {
                    172:                                if (fileh.f_flags & F_KER)
                    173:                                        vaddr = (vaddr + 0x0fff) & ~0x0fffL;
                    174:                                else
                    175:                                        vaddr = (vaddr & 0x0fff) + DATABASE;
                    176:                        }
                    177: 
                    178:                        aouth.data_start = sh->s_vaddr = vaddr;
                    179:                        aouth.dsize = size = sh->s_size;                
                    180:                        break;
                    181: 
                    182:                case S_BSSD:
                    183:                        sh->s_paddr = sh->s_vaddr = vaddr;
                    184:                        vaddr += aouth.bsize = sh->s_size;
                    185:                        sh->s_scnptr = 0;
                    186:                        continue;
                    187: 
                    188:                default:
                    189:                        sh->s_vaddr = vaddr;
                    190:                        size = sh->s_size;
                    191:                }
                    192: 
                    193:                sh->s_paddr = sh->s_vaddr;
                    194:                sh->s_scnptr = daddr;
                    195:                daddr += size;
                    196:                vaddr += size;
                    197:        }
                    198: 
                    199:        /* fix new segments to point to right places */
                    200:        for (i = 0; i < NLSEG; i++) {
                    201:                int j;
                    202:                long vaddr, daddr;
                    203: 
                    204:                sh = secth + i;
                    205:                vaddr = sh->s_vaddr + sh->s_size;       /* mark the end */
                    206:                daddr = sh->s_scnptr + sh->s_size;
                    207: 
                    208:                for (j = osegs; --j >= NLSEG;) {
                    209:                        SCNHDR *oh;
                    210: 
                    211:                        if (segMap[j] != i)
                    212:                                continue;
                    213:                        
                    214:                        oh = secth + j;
                    215:                        oh->s_vaddr  = vaddr -= oh->s_size;
                    216:                        oh->s_scnptr = daddr -= oh->s_size;
                    217:                        w_message("set extra %.8s at %x %x",
                    218:                                  oh->s_name, vaddr, daddr);
                    219:                }
                    220:        }
                    221: 
                    222:        /* set relocations for all segments */
                    223:        for (i = 0; i < NLSEG; i++) {
                    224:                sh = secth + i;
                    225:                if (!reloc || (S_BSSD == i) || !sh->s_nreloc) {
                    226:                        sh->s_relptr = 0;
                    227:                        continue;
                    228:                }
                    229:                sh->s_relptr = daddr;
                    230:                daddr += sh->s_nreloc * RELSZ;
                    231:        }
                    232: 
                    233:        /* set line numbers for all segments */
                    234:        for (i = 0; i < NLSEG; i++) {
                    235:                sh = secth + i;
                    236:                if (!debflg || !sh->s_nlnno) {
                    237:                        sh->s_nlnno = sh->s_lnnoptr = 0;
                    238:                        continue;
                    239:                }
                    240:                sh->s_lnnoptr = daddr;
                    241:                daddr += sh->s_nlnno * LINESZ;
                    242:        }
                    243: 
                    244:        if (!nosym)
                    245:                fileh.f_symptr = daddr;
                    246: }
                    247: 
                    248: /*
                    249:  * return entry point
                    250:  */
                    251: static long
                    252: lentry(str)
                    253: char   *str;
                    254: {
                    255:        if (NULL == str)        /* not user specified */
                    256:                return(aouth.text_start);
                    257: 
                    258:        /* If an octal number use that */
                    259:        {
                    260:                register unsigned char  c, *s;
                    261:                long    oaddr = 0;
                    262: 
                    263:                /* Try to scan whole string as octal. */
                    264:                for (s = str; c = *s++;) {
                    265:                        if (('0' > c) || (c > '7'))
                    266:                                break;
                    267:                        oaddr = (oaddr * 8) + (c - '0');
                    268:                }
                    269: 
                    270:                if (!c)
                    271:                        return (oaddr);
                    272:        }
                    273: 
                    274:        /* Search for string in symbol table. */
                    275:        {
                    276:                register sym_t  *sp;
                    277:                char work[SYMNMLEN + 1];
                    278: 
                    279:                for (sp = symtable[crc16(str) % NHASH];
                    280:                     sp != NULL;
                    281:                     sp = sp->next) {
                    282:                        if ((sp->sym.n_sclass == C_EXT) &&
                    283:                            !strcmp(symName(&(sp->sym), work), str)) {
                    284:                                if (sp->sym.n_scnum != (S_TEXT + 1))
                    285:                                   message("entry point '%s' not in .text");
                    286:                                return(sp->sym.n_value);
                    287:                        }
                    288:                }
                    289: 
                    290:                message("entry point '%s' undefined", str); /**/
                    291:                return (aouth.text_start);
                    292:        }
                    293: }
                    294: 
                    295: /*
                    296:  * Define referenced special symbols.
                    297:  */
                    298: void
                    299: symBind(sn, ldrv, name, loc)
                    300: int    sn, ldrv;
                    301: char   *name;
                    302: long   loc;
                    303: {
                    304:        register SYMENT *sym;
                    305:        register sym_t *sp;
                    306:        char  work[SYMNMLEN + 1];
                    307: 
                    308:        for (sp = symtable[crc16(name) % NHASH]; sp != NULL; sp = sp->next) {
                    309:                sym = &(sp->sym);
                    310:                if ((sym->n_sclass != C_EXT) ||
                    311:                     strcmp(symName(sym, work), name))
                    312:                        continue;
                    313: 
                    314:                if (undefined(sym)) {
                    315:                        nundef--;
                    316:                        sym->n_scnum = sn + 1;
                    317:                        sym->n_value = loc;
                    318:                        sp->mod = NULL; /* not defined in any mod */
                    319:                        return;
                    320:                }
                    321: 
                    322:                if (ldrv)
                    323:                        return;
                    324:                else
                    325:                        spwarn(sp, "redefines builtin symbol");
                    326:                        /* Some symbols such as __end and __end_text
                    327:                         * are special to the linker. In general symbols
                    328:                         * beginning __ are reserved to implementors and
                    329:                         * should be avoided by users.
                    330:                         * Your definition has been used. */
                    331:        }
                    332: }
                    333: 
                    334: /*
                    335:  * Add reference to symbol table
                    336:  */
                    337: void
                    338: undef(s)
                    339: char *s;
                    340: {
                    341:        SYMENT  lds;
                    342: 
                    343:        memset(&lds, '\0', sizeof(lds));
                    344:        lds.n_offset = (long)s;         /* point symbol at our stuff */
                    345:        lds.n_sclass = C_EXTDEF;        /* mark undefined */
                    346:        addsym(&lds, NULL);             /* connect to no module */
                    347: }
                    348: 
                    349: /*
                    350:  * Show undefined symbols.
                    351:  */
                    352: void
                    353: showUndef(sp, sym)
                    354: register sym_t *sp;
                    355: register SYMENT *sym;
                    356: {
                    357:        if (undefined(sym))
                    358:                spmsg(sp, ""); /* NODOC */
                    359: }
                    360: 
                    361: /*
                    362:  * Pass all symbols through a function.
                    363:  * In a really elaborite order.
                    364:  */
                    365: void
                    366: allSym(fun)
                    367: int (*fun)();
                    368: {
                    369:        register SYMENT *sym;
                    370:        register sym_t *sp;
                    371:        register mod_t *mp;
                    372:        register i;
                    373:        SYMENT *symEnd;
                    374: 
                    375:        if (reloc) {    /* We are producing another .o */
                    376:                /*
                    377:                 * Do symbols connected to modules in module order.
                    378:                 * Only process a global symbol for it's owner.
                    379:                 */
                    380:                for (mp = head; mp != (mod_t *)NULL; mp = mp->next) {
                    381:                        sym = ((SYMENT *)(mp->f->f_symptr));
                    382:                        symEnd = sym + mp->f->f_nsyms;
                    383:                        for (; sym < symEnd; sym += sym->n_numaux + 1) {
                    384:                                if (1 == sym->n_zeroes) { /* pointer to original */
                    385:                                        sp = (sym_t *)sym->n_offset;
                    386:                                        if (sp->mod == mp)
                    387:                                                (*fun)(sp, &(sp->sym), mp, sym);
                    388:                                }
                    389:                                else
                    390:                                        (*fun)(NULL, sym, mp, sym);
                    391:                        }
                    392:                }
                    393:        }
                    394:        else {
                    395:                /*
                    396:                 * Producing an executable.
                    397:                 */
                    398:                for (mp = head; mp != (mod_t *)NULL; mp = mp->next) {
                    399:                        char showSym;
                    400: 
                    401:                        sym = ((SYMENT *)(mp->f->f_symptr));
                    402:                        symEnd = sym + mp->f->f_nsyms;
                    403: 
                    404:                        /*
                    405:                         * If first entry is not C_FILE supress 
                    406:                         * all non C_EXT entries for debug, they make
                    407:                         * Orignon barf. If not debug mode and the
                    408:                         * user wants a symbol table give him everything.
                    409:                         */
                    410:                        showSym = !debflg || C_FILE == sym->n_sclass;
                    411: 
                    412:                        for (; sym < symEnd; sym += sym->n_numaux + 1) {
                    413:                                if ((C_EXT == sym->n_sclass) && !sym->n_numaux)
                    414:                                        continue;       /* do later */
                    415: 
                    416:                                /* pointer to original */
                    417:                                if (1 == sym->n_zeroes) {
                    418:                                        sp = (sym_t *)sym->n_offset;
                    419:                                        if (sp->mod == mp)
                    420:                                                (*fun)(showSym ? sp : NULL,
                    421:                                                         &(sp->sym), mp, sym);
                    422:                                }
                    423:                                else
                    424:                                        (*fun)(NULL, sym, mp, sym);
                    425:                        }
                    426:                }
                    427: 
                    428:                /* All C_EXT entries go at the end. */
                    429:                for (mp = head; mp != (mod_t *)NULL; mp = mp->next) {
                    430:                        sym = ((SYMENT *)(mp->f->f_symptr));
                    431:                        symEnd = sym + mp->f->f_nsyms;
                    432:                        for (; sym < symEnd; sym += sym->n_numaux + 1) {
                    433:                                if (!((C_EXT == sym->n_sclass) &&
                    434:                                    !sym->n_numaux))
                    435:                                        continue;
                    436: 
                    437:                                 /* pointer to original */
                    438:                                if (1 == sym->n_zeroes) {
                    439:                                        sp = (sym_t *)sym->n_offset;
                    440:                                        if (sp->mod == mp)
                    441:                                                (*fun)(sp, &(sp->sym), mp, sym);
                    442:                                }
                    443:                                else
                    444:                                        (*fun)(NULL, sym, mp, sym);
                    445:                        }
                    446:                }
                    447:        }
                    448: 
                    449:        /*
                    450:         * Do symbols not connected to a module.
                    451:         * These are end symbols and symbols defined with -u option
                    452:         */
                    453:        for (i = 0; i < NHASH; i++)
                    454:                for (sp = symtable[i]; NULL != sp; sp = sp->next)
                    455:                        if (NULL == sp->mod)
                    456:                                (*fun)(sp, &(sp->sym), sp->mod, NULL);
                    457: }
                    458: 
                    459: /*
                    460:  * Fixup a symbol between passes.
                    461:  */
                    462: void
                    463: symFix(sp, sym, mp, auxp)
                    464: sym_t *sp;
                    465: register SYMENT *sym, *auxp;
                    466: mod_t *mp;
                    467: {
                    468:        int segn, len;
                    469: 
                    470:        segn = sym->n_scnum;
                    471:        if (debflg && NULL != auxp && C_FILE == sym->n_sclass) {
                    472:                if (NULL != file_value) /* files point in a circle */
                    473:                        *file_value = fileh.f_nsyms;
                    474:                else
                    475:                        file_first = fileh.f_nsyms;
                    476:                file_value = &(sym->n_value);
                    477:                fileh.f_nsyms += sym->n_numaux + 1;
                    478:                return;
                    479:        }
                    480:        if (!reloc && common(sym)) {
                    481:                switch ((len = sym->n_value) & 3) {
                    482:                case 2: /* 2 byte aligned */
                    483:                        sym->n_value = comns;
                    484:                        comns += len;
                    485:                        break;
                    486:                case 0: /* 4 byte aligned */
                    487:                        sym->n_value = comnl;
                    488:                        comnl += len;
                    489:                        break;
                    490:                default: /* unaligned */
                    491:                        sym->n_value = comnb;
                    492:                        comnb += len;
                    493:                }
                    494:                sym->n_scnum  = S_BSSD + 1;
                    495:        }
                    496:        else if (segn > 0)
                    497:                /*
                    498:                 * Correct the value to the output sector header.
                    499:                 * If mp == NULL then segn this is a constructed symbol
                    500:                 * and segn is relative to the output sector headers.
                    501:                 * Otherwise it is relative to the input sector headers
                    502:                 * but the connection to the output sector headers was
                    503:                 * placed in s_paddr by pass1.c/object().
                    504:                 */
                    505:                sym->n_value += secth[(NULL == mp) ? segn - 1 :
                    506:                                        mp->s[segn - 1].s_paddr].s_vaddr;
                    507: 
                    508:        if (NULL != sp && !nosym) {
                    509:                sp->symno = fileh.f_nsyms++;
                    510:                if (debflg)
                    511:                        fileh.f_nsyms += sym->n_numaux;
                    512:        }
                    513: }
                    514: 
                    515: /*
                    516:  * Do work between passes.
                    517:  */
                    518: void
                    519: betweenPass()
                    520: {
                    521:        if (reloc)
                    522:                fileh.f_flags |= F_AR32WR;
                    523:        else {
                    524:                fileh.f_flags |= F_RELFLG | F_EXEC | F_AR32WR;
                    525:                comnb += (4 - ((comnb + comns) & 3)) & 3;
                    526:                secth[S_BSSD].s_size += comnb + comns + comnl;
                    527:        }
                    528:        if (nosym)
                    529:                fileh.f_flags |= F_LSYMS;
                    530: 
                    531:        if (!debflg)
                    532:                fileh.f_flags |= F_LNNO;
                    533: 
                    534:        if (drvld)
                    535:                getsys();       /* get segment base information from system */
                    536:        else
                    537:                baseall();      /* compute segment base information */
                    538: 
                    539:        if (!reloc) {
                    540:                int i;
                    541: 
                    542:                /* define referenced end of segment symbols */
                    543:                for (i = 0; i < NLSEG; i++) {
                    544:                        char end_name[20], c, *p;
                    545: 
                    546:                        sprintf(end_name, "__end%.8s", secth[i].s_name);
                    547:                        for (p = end_name; '\0' != (c = *p); p++)
                    548:                                if (!isalnum(c))
                    549:                                        *p = '_';
                    550: 
                    551:                        symBind(i, drvld, end_name, secth[i].s_size);
                    552:                }
                    553:                /* define absolute end symbol */
                    554:                symBind(S_BSSD, drvld, "__end", secth[S_BSSD].s_size);
                    555: 
                    556:                /* get starting addresses for 1, 2 and 4 alligned commons */
                    557:                comnb = secth[S_BSSD].s_vaddr + secth[S_BSSD].s_size - comnb;
                    558:                comns = comnb - comns;
                    559:                comnl = comns - comnl;
                    560:        }
                    561: 
                    562:        if (nundef && !reloc) {
                    563:                message("the following symbols are undefined");
                    564:                errCount--;
                    565:                allSym(showUndef);
                    566:        }
                    567: 
                    568:        switch (errCount & fource) {
                    569:        case 0:
                    570:                break;
                    571:        case 1:
                    572:                fatal("pass 1, 1 error"); /* NODOC */
                    573:        default:
                    574:                fatal("pass 1, %d errors", errCount);
                    575:                /* At the end of pass 1 there were \fIn\fB errors detected.
                    576:                 * The link stopped here. */
                    577:        }
                    578: 
                    579:        /* Run through symbol table doing fixups */
                    580:        fileh.f_nsyms = 0;
                    581:        allSym(symFix);
                    582: 
                    583:        if (NULL != file_value)
                    584:                *file_value = file_first;
                    585: 
                    586:        aouth.entry = lentry(entrys);
                    587: }
                    588: 
                    589: /*
                    590:  * output symbol table.
                    591:  */
                    592: static void
                    593: outputSym(s, sm, mp, auxp)
                    594: register sym_t *s;
                    595: register SYMENT *sm;
                    596: mod_t *mp;
                    597: SYMENT *auxp;
                    598: {
                    599:        int i;
                    600:        char *name, work[SYMNMLEN + 1];
                    601:        SCNHDR *scn;
                    602:        SYMENT sym;
                    603:  
                    604:        if (NULL == (char *)s)
                    605:                return;
                    606: 
                    607:        /* build writeable copy */
                    608:        memcpy(&sym, sm, sizeof(sym));
                    609:        name = symName(sm, work);
                    610: 
                    611:        if (SYMNMLEN < (i = strlen(name))) {
                    612:                sym.n_offset = str_length;
                    613:                str_length += i + 1;
                    614:        }
                    615:        else
                    616:                memcpy(sym.n_name, name, SYMNMLEN);
                    617: 
                    618:        if (!debflg || NULL == auxp)
                    619:                sym.n_numaux = 0;
                    620:                
                    621:        if ((sym.n_scnum > 0) && (NULL != mp))
                    622:                sym.n_scnum = segMap[mp->s[sym.n_scnum - 1].s_paddr] + 1;
                    623: 
                    624:        xwrite(&sym, SYMESZ);
                    625: 
                    626:        if (sym.n_numaux) {
                    627:                int aux = 1;
                    628:                int has_fcn = 0;
                    629: 
                    630:                switch(sym.n_sclass) {
                    631:                case C_STRTAG:
                    632:                case C_UNTAG:
                    633:                case C_ENTAG:
                    634:                case C_BLOCK:
                    635:                        has_fcn = 1;
                    636:                        break;
                    637:                case C_STAT:
                    638:                case C_FILE:
                    639:                        aux = sym.n_numaux + 1; /* dont scan for ixs */
                    640:                        break;
                    641:                default:
                    642:                        if (ISFCN(sym.n_type))
                    643:                                has_fcn = 1;
                    644:                }
                    645: 
                    646:                for (; aux <= sym.n_numaux; aux++) {
                    647:                        SYMENT *s1, *s2, *s3;
                    648:                        AUXENT *a = auxp + aux;
                    649: 
                    650:                        /*
                    651:                         * Fix indices to new value.
                    652:                         */
                    653:                        if (a->ae_tagndx) {
                    654:                                s1 = ((SYMENT *)(mp->f->f_symptr)) +
                    655:                                        a->ae_tagndx;
                    656:                                s = (sym_t *)s1->n_offset;
                    657:                                a->ae_tagndx = s->symno;
                    658:                        }
                    659:                        /* ae_endndx points past an entry */
                    660:                        if (has_fcn && a->ae_endndx) {
                    661:                                s2 = ((SYMENT *)(mp->f->f_symptr));
                    662:                                /* find the entry it points past */
                    663:                                for (s1 = s2 + a->ae_endndx;
                    664:                                     (s3 = (s2 + s2->n_numaux + 1)) < s1;
                    665:                                     s2 = s3)
                    666:                                        ;
                    667:                                s = (sym_t *)s2->n_offset;
                    668:                                a->ae_endndx = s->symno + s2->n_numaux + 1;
                    669:                        }
                    670:                }
                    671:                xwrite(auxp + 1, SYMESZ * sym.n_numaux);
                    672:        }
                    673: }
                    674: 
                    675: /*
                    676:  * output long symbols.
                    677:  */
                    678: static void
                    679: longSym(s, sm)
                    680: register sym_t *s;
                    681: register SYMENT *sm;
                    682: {
                    683:        int i;
                    684:        char *name, work[SYMNMLEN + 1];
                    685: 
                    686:        if (NULL == s)
                    687:                return;
                    688: 
                    689:        name = symName(sm, work);
                    690:        if (SYMNMLEN < (i = strlen(name)))
                    691:                xwrite(name, i + 1);
                    692: }
                    693: 
                    694: 
                    695: /*
                    696:  * Scan this modules sections for a name match.
                    697:  */
                    698: SCNHDR *
                    699: findSeg(mp, segn)
                    700: register mod_t *mp;
                    701: {
                    702:        int i;
                    703:        register SCNHDR *orsp, *isgp;
                    704: 
                    705:        orsp = secth + segn;
                    706:        for (i = 0; i < mp->f->f_nscns; i++) {
                    707:                isgp = mp->s + i;
                    708:                if (strncmp(isgp->s_name, orsp->s_name, 8))
                    709:                        isgp = NULL;
                    710:                else
                    711:                        break;
                    712:        }
                    713:        return isgp;
                    714: }
                    715: 
                    716: /*
                    717:  * Do relocations
                    718:  */
                    719: static void
                    720: relocations(mp, osegn, isegn)
                    721: mod_t *  mp;
                    722: {
                    723:        register RELOC *rel;
                    724:        char    *t;     /* actual text */
                    725:        SCNHDR  *isgp, *orsp;
                    726:        unsigned i;
                    727:        long    size, told, fixr;
                    728: 
                    729:        if ((NULL == (isgp = findSeg(mp, isegn))) || !(size = isgp->s_size))
                    730:                return;
                    731: 
                    732:        orsp = secth + osegn;
                    733:        fixr = isgp->s_vaddr - orsp->s_vaddr;
                    734:        t = (char *)isgp->s_scnptr;
                    735: 
                    736:        if (watch) {
                    737:                errCount--;
                    738:                mpmsg(mp, "relocating seg#%.8s[%06lx]@%06lx to %06lx r %ld",
                    739:                        isgp->s_name,
                    740:                        size,
                    741:                        isgp->s_vaddr,
                    742:                        orsp->s_vaddr,
                    743:                        isgp->s_nreloc); /* NODOC */
                    744:                told = lseek(ofd, 0, 2);
                    745:        }
                    746:        
                    747:        for (i = 0; i < isgp->s_nreloc; i++) {
                    748:                char *ptr;
                    749:                char *mtype;
                    750:                sym_t *sp;
                    751:                SYMENT *s, *sym;
                    752:                long relf, w, at;
                    753:                int   undef;
                    754:                char work[SYMNMLEN + 1], *name;
                    755:                static char *pcrel = "pcrel";
                    756: 
                    757:                /* get reloc record */
                    758:                rel = ((RELOC *)isgp->s_relptr) + i;
                    759: 
                    760:                w = rel->r_vaddr - isgp->s_vaddr;
                    761:                if ((w < 0) || (w > size))
                    762:                        corrupt(mp);
                    763:                ptr = t + w;
                    764: 
                    765:                if ((rel->r_symndx < 0) || (rel->r_symndx > mp->f->f_nsyms))
                    766:                        corrupt(mp);
                    767:                
                    768:                s = (SYMENT *)mp->f->f_symptr + rel->r_symndx;
                    769:                if (1 == s->n_zeroes) { /* fixed elsewhere */ 
                    770:                        sp = (sym_t *)s->n_offset;
                    771:                        sym = &(sp->sym);
                    772:                } else {
                    773:                        sp = NULL;
                    774:                        sym = s;
                    775:                }
                    776:                relf = sym->n_value;
                    777:                mtype = "rel";
                    778:                undef = undefined(sym);                         
                    779: 
                    780:                if (watch) {
                    781:                        at = told + w;
                    782:                        name = symName(sym, work);
                    783:                }
                    784:                /*
                    785:                 * This wierdness is to deal with a coff wierdness.
                    786:                 * The address of a common is incremented by the
                    787:                 * length of the common as seen in that module.
                    788:                 */
                    789:                if (common(s))
                    790:                        relf -= s->n_value;
                    791:                /*
                    792:                 * If the symbol is native to this module
                    793:                 * the reference already has this modules
                    794:                 * segment address. Subtract it.
                    795:                 */
                    796:                else if (!undef && ((NULL == sp) || (sp->mod == mp)))
                    797:                        relf -= mp->s[s->n_scnum - 1].s_vaddr;
                    798: 
                    799: /* relocate what the pointer is aimed at and leave a record */
                    800: #define relocate(type) *(type *)ptr = (w = *(type *)ptr) + relf
                    801: 
                    802:                if (reloc) {
                    803:                        rel->r_vaddr = w + orsp->s_vaddr;
                    804:                        rel->r_symndx = sp->symno;
                    805: 
                    806:                        switch (rel->r_type) {
                    807:                        case R_PCRBYTE:
                    808:                                mtype = pcrel;
                    809:                                relf = fixr;
                    810: 
                    811:                        case R_DIR8:
                    812:                        case R_RELBYTE:
                    813:                                relocate(char);
                    814:                                break;
                    815: 
                    816:                        case R_PCRWORD:
                    817:                                mtype = pcrel;
                    818:                                relf = fixr;
                    819: 
                    820:                        case R_DIR16:
                    821:                        case R_RELWORD:
                    822:                                relocate(short);
                    823:                                break;
                    824: 
                    825:                        case R_PCRLONG:
                    826:                                mtype = pcrel;
                    827:                                relf = fixr;
                    828: 
                    829:                        case R_DIR32:
                    830:                        case R_RELLONG:
                    831:                                relocate(long);
                    832:                                break;
                    833: 
                    834:                        case R_NONREL:
                    835:                                mtype = "nonrel";
                    836:                                w = *(long *)ptr;
                    837:                                relf = 0;
                    838:                                break;
                    839: 
                    840:                        default:
                    841:                        mpmsg(mp, "unknown r_type %d in segment %.8s record %d",
                    842:                                rel->r_type, isgp->s_name, i);
                    843:                        /* Unknown type on COFF relocation record. */
                    844:                        }
                    845: 
                    846:                        if ((sym->n_scnum > 0) && (mtype != pcrel))
                    847:                                rel->r_symndx = sym->n_scnum - 1;
                    848: 
                    849:                        if (!undef && (sym->n_scnum < 0))
                    850:                                rel->r_type = R_NONREL;
                    851: 
                    852:                        w_message("%lx '%s'(%d %lx %lx) %lx = '%s'(%lx) + %lx",
                    853:                                at,
                    854:                                mtype,
                    855:                                rel->r_type,
                    856:                                rel->r_vaddr,
                    857:                                rel->r_symndx,
                    858:                                relf + w,
                    859:                                name,
                    860:                                sym->n_value,
                    861:                                w);
                    862:                }
                    863:                else {
                    864:                        switch (rel->r_type) {
                    865:                        case R_PCRBYTE:
                    866:                                mtype = pcrel;
                    867:                                relf -= orsp->s_vaddr;
                    868:                        case R_DIR8:
                    869:                        case R_RELBYTE:
                    870:                                relocate(char);
                    871:                                break;
                    872:                        case R_PCRWORD:
                    873:                                mtype = pcrel;
                    874:                                relf -= orsp->s_vaddr;
                    875:                        case R_RELWORD:
                    876:                        case R_DIR16:
                    877:                                relocate(short);
                    878:                                break;
                    879:                        case R_PCRLONG:
                    880:                                mtype = pcrel;
                    881:                                relf -= orsp->s_vaddr;
                    882:                        case R_RELLONG:
                    883:                        case R_DIR32:
                    884:                                relocate(long);
                    885:                                break;
                    886:                        case R_NONREL:
                    887:                                mtype = "nonrel";
                    888:                                w = *(long *)ptr;
                    889:                                relf = 0;
                    890:                                break;
                    891:                        default:
                    892:                        mpmsg(mp, "unknown r_type %d in segment %.8s record %d",
                    893:                                rel->r_type, isgp->s_name, i);
                    894:                        /* NODOC */
                    895:                        }
                    896:                        w_message("%lx '%s'(%d) %lx = '%s'(%lx) + %lx",
                    897:                                at,
                    898:                                mtype,
                    899:                                rel->r_type,
                    900:                                relf + w,
                    901:                                name,
                    902:                                sym->n_value,
                    903:                                w);
                    904:                }
                    905:        }
                    906: #undef relocate
                    907: 
                    908:        orsp->s_vaddr += size;
                    909:        xwrite(t, (int)size);
                    910: }
                    911: 
                    912: /*
                    913:  * Write line records for a segment.
                    914:  */
                    915: writeLine(mp, segn)
                    916: mod_t *mp;
                    917: {
                    918:        int j;
                    919:        long fptr;
                    920:        AUXENT *a;
                    921:        SYMENT *sym;
                    922:        LINENO *l;
                    923:        SCNHDR *scn;
                    924: 
                    925:        if (NULL == (scn = findSeg(mp, segn)) || (!scn->s_nlnno))
                    926:                return;
                    927: 
                    928:        /*
                    929:         * set up n_lnnoptr in symbol table to point
                    930:         * to line records
                    931:         */
                    932:        l = (LINENO *)scn->s_lnnoptr;
                    933:        fptr = lseek(ofd, 0L, 1);       /* where I am */
                    934:        for (j = 0; j < scn->s_nlnno; j++, l++) {
                    935:                if (!l->l_lnno) {
                    936:                        sym = ((SYMENT *)(mp->f->f_symptr)) +
                    937:                                l->l_addr.l_symndx;
                    938:                        if (sym->n_numaux) {
                    939:                                a = (AUXENT *)sym + 1;
                    940:                                a->ae_lnnoptr = fptr;
                    941:                                if (1 == sym->n_zeroes) {
                    942:                                    sym_t *sp;
                    943:                                    sp = (sym_t *)sym->n_offset;
                    944:                                    l->l_addr.l_symndx = sp->symno;
                    945:                                }
                    946:                        }
                    947:                }
                    948:                fptr += LINESZ;
                    949:        }
                    950:        xwrite(scn->s_lnnoptr, LINESZ * scn->s_nlnno);
                    951: }
                    952: 
                    953: /*
                    954:  * Output all data.
                    955:  */
                    956: outputAll()
                    957: {
                    958:        register mod_t *mp;
                    959:        register SCNHDR *scn;
                    960:        int i, j;
                    961:        struct stat statbuf;
                    962: 
                    963:        /* Open output file */
                    964:        ofd = qopen(ofname, 1);
                    965: 
                    966:        /* write header */
                    967:        xwrite(&fileh, sizeof(fileh));
                    968: 
                    969:        if (!reloc) {   /* if executable set bits and write opt header */
                    970:                stat(ofname, &statbuf);
                    971:                chmod(ofname,
                    972:                        statbuf.st_mode | S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
                    973: 
                    974:                aouth.magic = Z_MAGIC;
                    975:                xwrite(&aouth, sizeof(aouth));
                    976:        }
                    977: 
                    978:        /* write sector headers */
                    979:        xwrite(secth, sizeof(* secth) * fileh.f_nscns);
                    980: 
                    981:        /* write corrected text segments */
                    982:        for (i = 0; i < NLSEG; i++) {
                    983:                if (i == S_BSSD)
                    984:                        continue;
                    985:                for (j = 0; j < osegs; j++) {
                    986:                        if (segMap[j] == i)
                    987:                                for (mp = head; mp != NULL; mp = mp->next)
                    988:                                        relocations(mp, i, j);
                    989:                }
                    990:        }
                    991: 
                    992:        /* write relocation if required */
                    993:        for (i = (reloc ? 0 : S_BSSD); i < S_BSSD; i++) {
                    994:                for (j = 0; j < osegs; j++) {
                    995:                        if (segMap[j] != i)
                    996:                                continue;
                    997: 
                    998:                        for (mp = head; mp != NULL; mp = mp->next) {
                    999:                                if ((NULL == (scn = findSeg(mp, j))) ||
                   1000:                                     !scn->s_nreloc)
                   1001:                                        continue;
                   1002:                                xwrite(scn->s_relptr,
                   1003:                                        RELSZ * (int)scn->s_nreloc);
                   1004:                        }
                   1005:                }
                   1006:        }
                   1007: 
                   1008:        /* write lines if required */
                   1009:        for (i = (debflg ? 0 : NLSEG); i < NLSEG; i++) {
                   1010:                for (j = 0; j < osegs; j++) {
                   1011:                        if (segMap[j] != i)
                   1012:                                continue;
                   1013: 
                   1014:                        for (mp = head; mp != NULL; mp = mp->next)
                   1015:                                writeLine(mp, j);
                   1016:                }
                   1017:        }
                   1018: 
                   1019:        if (!nosym) {
                   1020:                str_length = 4;
                   1021: 
                   1022:                allSym(outputSym);
                   1023:                if (4 != str_length) {
                   1024:                        xwrite(&str_length, sizeof(str_length));
                   1025:                        allSym(longSym);
                   1026:                }
                   1027:        }
                   1028: 
                   1029:        close(ofd);
                   1030: }
                   1031: 
                   1032: /*
                   1033:  * Process arguements, and call other work.
                   1034:  */
                   1035: main(argc, argv)
                   1036: char *argv[];
                   1037: {
                   1038:        int     c;
                   1039:        char    *specialList = NULL;
                   1040:        char    *argString = "?ge:finKl:L:o:A:O:rsu:wXxZ:qQ";
                   1041:        char    *env;
                   1042: 
                   1043:        /* find program name */
                   1044:        if (NULL == (argv0 = strrchr(argv[0], '/')))
                   1045:                argv0 = argv[0];
                   1046:        else
                   1047:                argv0++;
                   1048: 
                   1049:        env = getenv("LIBPATH");
                   1050:        /*
                   1051:         * drvld is an alternative name for ld.
                   1052:         * In this mode ld will load the kernel's symbol table, so
                   1053:         * that the loadable driver can link directly to kernel services.
                   1054:         * After pass1 we call driver_alloc() to tell the kernel the
                   1055:         * sizes of the driver segments, the kernel replys with locations
                   1056:         * for them. Then we output the driver to a tmp file and execl()
                   1057:         */
                   1058:        if (!strcmp(argv0, "drvld")) {
                   1059: #if 0
                   1060:                ofname = tmpnam(NULL);
                   1061: #endif
                   1062:                argString = "?ge:l:L:u:wdq";
                   1063:                fileh.f_flags |= F_KER;
                   1064:                drvld = 1;
                   1065:                /* read kernel for symbol table but don't load */
                   1066:                readFile(kernelName(), 0, NULL);
                   1067:                _addargs("DRVLD", &argc, &argv);        
                   1068:        }
                   1069:        else
                   1070:                _addargs("LD", &argc, &argv);   
                   1071: 
                   1072:        initSegs();
                   1073: 
                   1074:        while (EOF != (c = getargs(argc, argv, argString))) {
                   1075:                switch (c) {
                   1076:                case 0:         /* Not an option, read a file for load */
                   1077:                        readFile(optarg, 1, NULL);
                   1078:                        continue;
                   1079: 
                   1080:                case 'A': /* Read a file as an archive regardless of name */
                   1081:                        readFile(optarg, 1, ".a");
                   1082:                        continue;
                   1083: 
                   1084:                case 'O': /* Read a file as an object regardless of name */
                   1085:                        readFile(optarg, 1, ".o");
                   1086:                        continue;
                   1087: 
                   1088:                case 'f':       /* attempt link even if errors */
                   1089:                        fource = 0;
                   1090:                        continue;
                   1091: 
                   1092:                case 'g':       /* save extra segments and aux symbols */
                   1093:                        debflg ^= 1;
                   1094:                        continue;
                   1095: 
                   1096:                case 'e':
                   1097:                        entrys = optarg;
                   1098: 
                   1099:                case 'Z':       /* use and erase after */
                   1100:                case 'i':       /* obselete options */
                   1101:                case 'n':
                   1102:                        continue;
                   1103: 
                   1104:                case 'K':       /* recompile of Kernel */
                   1105:                        fileh.f_flags |= F_KER;
                   1106:                        continue;
                   1107: 
                   1108:                case 'L':
                   1109:                        /*
                   1110:                         * Special filelist for lookup.
                   1111:                         */
                   1112:                        {
                   1113:                                char *new;
                   1114: 
                   1115:                                if (NULL == specialList) {
                   1116:                                        new = alloc(strlen(optarg) + 2);
                   1117:                                        sprintf(new, "%c%s", LISTSEP, optarg);
                   1118:                                }
                   1119:                                else {
                   1120:                                        new = alloc(
                   1121:                                         strlen(specialList)+strlen(optarg)+2);
                   1122:                                        sprintf(new, "%s%c%s",
                   1123:                                         specialList, LISTSEP, optarg);
                   1124:                                        free(specialList);
                   1125:                                }
                   1126:                                specialList = new;
                   1127:                                continue;
                   1128:                        }
                   1129: 
                   1130:                case 'l':
                   1131:                        /* -l<lib>: use standard lib */
                   1132:                        {
                   1133:                                char *xp, *lp;
                   1134: 
                   1135:                                xp = alloc(strlen(optarg) + 6);
                   1136:                                sprintf(xp, "lib%s.a", optarg);
                   1137:                                lp = NULL;
                   1138:                                if (NULL != specialList)
                   1139:                                        lp = path(specialList, xp, AREAD);
                   1140:                                if (NULL == lp && NULL != env)
                   1141:                                        lp = path(env, xp, AREAD);
                   1142:                                if (NULL == lp)
                   1143:                                        lp = path(DEFLIBPATH, xp, AREAD);
                   1144:                                if (NULL == lp)
                   1145:                                   fatal("can't find '%s'", xp);
                   1146:                                   /* Can't locate requested library. */
                   1147: 
                   1148:                                readFile(lp, 1, NULL);
                   1149:                                free(xp);
                   1150:                                continue;
                   1151:                        }
                   1152: 
                   1153:                case 'o':
                   1154:                        ofname = optarg;
                   1155:                        continue;
                   1156: 
                   1157:                case 'r':
                   1158:                        reloc ^= 1;     /* retain relocation information */
                   1159:                        continue;
                   1160: 
                   1161:                case 's':
                   1162:                        nosym ^= 1;
                   1163:                        continue;
                   1164: 
                   1165:                case 'u':
                   1166:                        undef(optarg);
                   1167:                        continue;
                   1168: 
                   1169:                case 'Q':
                   1170:                        Qflag = 1;
                   1171: 
                   1172:                case 'q':
                   1173:                        qflag = 1;
                   1174:                        continue;
                   1175: 
                   1176:                case 'w':
                   1177:                        watch ^= 1;
                   1178:                        continue;
                   1179: 
                   1180:                case 'X':
                   1181:                        noilcl ^= 1;
                   1182:                        continue;
                   1183: 
                   1184:                case 'x':
                   1185:                        nolcl ^= 1;
                   1186:                        continue;
                   1187: 
                   1188:                case '?':
                   1189:                        help();         /* non returning */
                   1190: 
                   1191:                default:
                   1192:                        usage();        /* non returning */
                   1193:                }
                   1194:        }
                   1195:        if (nosym)
                   1196:                nolcl = 1;
                   1197: 
                   1198:        if (reloc || debflg)
                   1199:                nosym = nolcl = noilcl = 0;
                   1200: 
                   1201:        if (!fileh.f_magic)
                   1202:                fatal("No work");
                   1203:        /* There were no object files loaded. */
                   1204: 
                   1205:        betweenPass();  /* between passes */
                   1206:        outputAll();    /* output all data */
                   1207: 
                   1208:        /* repass argument list to erase any -Z files */
                   1209:        for (optix = 1; EOF != (c = getargs(argc, argv, argString));)
                   1210:                if ('Z' == c)
                   1211:                        unlink(optarg);
                   1212: 
                   1213: #if 0
                   1214:        if (drvld) {
                   1215:                execl(ofname, ofname, NULL); /* should never return */
                   1216:                fatal("Cannot execute loadable driver '%s'.", ofname); /**/
                   1217:        }
                   1218: #endif
                   1219:        return (0);
                   1220: }

unix.superglobalmegacorp.com

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