Annotation of researchv9/cmd/sun/ld/ld.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)ld.c 1.1 86/02/03 SMI"; /* from UCB 4.9 83/07/01 */
                      3: #endif
                      4: 
                      5: /*
                      6:  * ld - string table version
                      7:  */
                      8: 
                      9: #include <sys/types.h>
                     10: #include <signal.h>
                     11: #include <stdio.h>
                     12: #include <ctype.h>
                     13: #include <ar.h>
                     14: #include <a.out.h>
                     15: #include <ranlib.h>
                     16: #include <sys/stat.h>
                     17: #include <stab.h>
                     18: #include <sys/dir.h>
                     19: 
                     20: int nsymwrite;
                     21: char *rindex();
                     22: 
                     23: 
                     24: /*
                     25:  * Basic strategy:
                     26:  *
                     27:  * The loader takes a number of files and libraries as arguments.
                     28:  * A first pass examines each file in turn.  Normal files are
                     29:  * unconditionally loaded, and the (external) symbols they define and require
                     30:  * are noted in the symbol table.   Libraries are searched, and the
                     31:  * library members which define needed symbols are remembered
                     32:  * in a special data structure so they can be selected on the second
                     33:  * pass.  Symbols defined and required by library members are also
                     34:  * recorded.
                     35:  *
                     36:  * After the first pass, the loader knows the size of the basic text
                     37:  * data, and bss segments from the sum of the sizes of the modules which
                     38:  * were required.  It has computed, for each ``common'' symbol, the
                     39:  * maximum size of any reference to it, and these symbols are then assigned
                     40:  * storage locations after their sizes are appropriately rounded.
                     41:  * The loader now knows all sizes for the eventual output file, and
                     42:  * can determine the final locations of external symbols before it
                     43:  * begins a second pass.
                     44:  *
                     45:  * On the second pass each normal file and required library member
                     46:  * is processed again.  The symbol table for each such file is
                     47:  * reread and relevant parts of it are placed in the output.  The offsets
                     48:  * in the local symbol table for externally defined symbols are recorded
                     49:  * since relocation information refers to symbols in this way.
                     50:  * Armed with all necessary information, the text and data segments
                     51:  * are relocated and the result is placed in the output file, which
                     52:  * is pasted together, ``in place'', by writing to it in several
                     53:  * different places concurrently.
                     54:  */
                     55: 
                     56: /*
                     57:  * Internal data structures
                     58:  *
                     59:  * All internal data structures are segmented and dynamically extended.
                     60:  * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT)
                     61:  * referenced library members, and 100 (NSYMPR) private (local) symbols
                     62:  * per object module.  For large programs and/or modules, these structures
                     63:  * expand to be up to 40 (NSEG) times as large as this as necessary.
                     64:  */
                     65: #define        NSEG    40              /* Number of segments, each data structure */
                     66: #define        NSYM    1103            /* Number of symbols per segment */
                     67: #define        NROUT   250             /* Number of library references per segment */
                     68: #define        NSYMPR  100             /* Number of private symbols per segment */
                     69: 
                     70: /*
                     71:  * Structure describing each symbol table segment.
                     72:  * Each segment has its own hash table.  We record the first
                     73:  * address in and first address beyond both the symbol and hash
                     74:  * tables, for use in the routine symx and the lookup routine respectively.
                     75:  * The symfree routine also understands this structure well as it used
                     76:  * to back out symbols from modules we decide that we don't need in pass 1.
                     77:  *
                     78:  * Csymseg points to the current symbol table segment;
                     79:  * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated,
                     80:  * (unless csymseg->sy_used == NSYM in which case we will allocate another
                     81:  * symbol table segment first.)
                     82:  */
                     83: struct symseg {
                     84:        struct  nlist *sy_first;        /* base of this alloc'ed segment */
                     85:        struct  nlist *sy_last;         /* end of this segment, for n_strx */
                     86:        int     sy_used;                /* symbols used in this seg */
                     87:        struct  nlist **sy_hfirst;      /* base of hash table, this seg */
                     88:        struct  nlist **sy_hlast;       /* end of hash table, this seg */
                     89: } symseg[NSEG], *csymseg;
                     90: 
                     91: /*
                     92:  * The lookup routine uses quadratic rehash.  Since a quadratic rehash
                     93:  * only probes 1/2 of the buckets in the table, and since the hash
                     94:  * table is segmented the same way the symbol table is, we make the
                     95:  * hash table have twice as many buckets as there are symbol table slots
                     96:  * in the segment.  This guarantees that the quadratic rehash will never
                     97:  * fail to find an empty bucket if the segment is not full and the
                     98:  * symbol is not there.
                     99:  */
                    100: #define        HSIZE   (NSYM*2)
                    101: 
                    102: #ifndef n_hash
                    103: #define        n_hash  n_desc
                    104: #endif n_hash
                    105: 
                    106: /*
                    107:  * Xsym converts symbol table indices (ala x) into symbol table pointers.
                    108:  * Symx (harder, but never used in loops) inverts pointers into the symbol
                    109:  * table into indices using the symseg[] structure.
                    110:  */
                    111: #define        xsym(x) (symseg[(x)/NSYM].sy_first+((x)%NSYM))
                    112: /* symx() is a function, defined below */
                    113: 
                    114: struct nlist cursym;           /* current symbol */
                    115: struct nlist *lastsym;         /* last symbol entered */
                    116: struct nlist *nextsym;         /* next available symbol table entry */
                    117: struct nlist *addsym;          /* first sym defined during incr load */
                    118: int    nsym;                   /* pass2: number of local symbols in a.out */
                    119: /* nsym + symx(nextsym) is the symbol table size during pass2 */
                    120: 
                    121: struct nlist **lookup(), **slookup();
                    122: struct nlist *p_etext, *p_edata, *p_end, *entrypt;
                    123: 
                    124: /*
                    125:  * Definitions of segmentation for library member table.
                    126:  * For each library we encounter on pass 1 we record pointers to all
                    127:  * members which we will load on pass 2.  These are recorded as offsets
                    128:  * into the archive in the library member table.  Libraries are
                    129:  * separated in the table by the special offset value -1.
                    130:  */
                    131: off_t  li_init[NROUT];
                    132: struct libseg {
                    133:        off_t   *li_first;
                    134:        int     li_used;
                    135:        int     li_used2;
                    136: } libseg[NSEG] = {
                    137:        li_init, 0, 0,
                    138: }, *clibseg = libseg;
                    139: 
                    140: /*
                    141:  * In processing each module on pass 2 we must relocate references
                    142:  * relative to external symbols.  These references are recorded
                    143:  * in the relocation information as relative to local symbol numbers
                    144:  * assigned to the external symbols when the module was created.
                    145:  * Thus before relocating the module in pass 2 we create a table
                    146:  * which maps these internal numbers to symbol table entries.
                    147:  * A hash table is constructed, based on the local symbol table indices,
                    148:  * for quick lookup of these symbols.
                    149:  */
                    150: #define        LHSIZ   31
                    151: struct local {
                    152:        int     l_index;                /* index to symbol in file */
                    153:        struct  nlist *l_symbol;        /* ptr to symbol table */
                    154:        struct  local *l_link;          /* hash link */
                    155: } *lochash[LHSIZ], lhinit[NSYMPR];
                    156: struct locseg {
                    157:        struct  local *lo_first;
                    158:        int     lo_used;
                    159: } locseg[NSEG] = {
                    160:        lhinit, 0
                    161: }, *clocseg;
                    162: 
                    163: /*
                    164:  * Libraries are typically built with a table of contents,
                    165:  * which is the first member of a library with special file
                    166:  * name __.SYMDEF and contains a list of symbol names
                    167:  * and with each symbol the offset of the library member which defines
                    168:  * it.  The loader uses this table to quickly tell which library members
                    169:  * are (potentially) useful.  The alternative, examining the symbol
                    170:  * table of each library member, is painfully slow for large archives.
                    171:  *
                    172:  * See <ranlib.h> for the definition of the ranlib structure and an
                    173:  * explanation of the __.SYMDEF file format.
                    174:  */
                    175: int    tnum;           /* number of symbols in table of contents */
                    176: int    ssiz;           /* size of string table for table of contents */
                    177: struct ranlib *tab;    /* the table of contents (dynamically allocated) */
                    178: char   *tabstr;        /* string table for table of contents */
                    179: 
                    180: /*
                    181:  * We open each input file or library only once, but in pass2 we
                    182:  * (historically) read from such a file at 2 different places at the
                    183:  * same time.  These structures are remnants from those days,
                    184:  * and now serve only to catch ``Premature EOF''.
                    185:  * In order to make I/O more efficient, we provide routines which
                    186:  * work in hardware page sizes. The associated constants are defined 
                    187:  * as BLKSIZE, BLKSHIFT, and BLKMASK.
                    188:  */
                    189: #define BLKSIZE 1024
                    190: #define BLKSHIFT 10
                    191: #define BLKMASK (BLKSIZE - 1)
                    192: typedef struct {
                    193:        short   *fakeptr;
                    194:        int     bno;
                    195:        int     nibuf;
                    196:        int     nuser;
                    197:        char    buff[BLKSIZE];
                    198: } PAGE;
                    199: 
                    200: PAGE   page[2];
                    201: 
                    202: struct {
                    203:        short   *fakeptr;
                    204:        int     bno;
                    205:        int     nibuf;
                    206:        int     nuser;
                    207: } fpage;
                    208: 
                    209: typedef struct {
                    210:        char    *ptr;
                    211:        int     bno;
                    212:        int     nibuf;
                    213:        long    size;
                    214:        long    pos;
                    215:        PAGE    *pno;
                    216: } STREAM;
                    217: 
                    218: STREAM text;
                    219: STREAM reloc;
                    220: 
                    221: /*
                    222:  * Header from the a.out and the archive it is from (if any).
                    223:  */
                    224: struct exec filhdr;
                    225: struct  exec outfilhdr;
                    226: struct ar_hdr archdr;
                    227: #define        OARMAG 0177545
                    228: 
                    229: /*
                    230:  * Options.
                    231:  */
                    232: int    trace;
                    233: int    xflag;          /* discard local symbols */
                    234: int    Xflag;          /* discard locals starting with 'L' */
                    235: int    Sflag;          /* discard all except locals and globals*/
                    236: int    rflag;          /* preserve relocation bits, don't define common */
                    237: int    arflag;         /* original copy of rflag */
                    238: int    sflag;          /* discard all symbols */
                    239: int    Mflag;          /* print rudimentary load map */
                    240: int    nflag;          /* pure procedure */
                    241: int    dflag;          /* define common even with rflag */
                    242: int    zflag;          /* demand paged  */
                    243: long   hsize;          /* size of hole at beginning of data to be squashed */
                    244: int    Aflag;          /* doing incremental load */
                    245: int    Tflag = 0;
                    246: int    Nflag;          /* want impure a.out */
                    247: int    funding;        /* reading fundamental file for incremental load */
                    248: int    yflag;          /* number of symbols to be traced */
                    249: char   **ytab;         /* the symbols */
                    250: 
                    251: #ifdef sun3
                    252: int    use68020;       /* 68020-specific instructions used */
                    253: #endif sun3
                    254: 
                    255: /*
                    256:  * These are the cumulative sizes, set in pass 1, which
                    257:  * appear in the a.out header when the loader is finished.
                    258:  */
                    259: off_t  tsize, dsize, bsize, trsize, drsize, ssize;
                    260: 
                    261: /*
                    262:  * Symbol relocation: c?rel is a scale factor which is
                    263:  * added to an old relocation to convert it to new units;
                    264:  * i.e. it is the difference between segment origins.
                    265:  * (Thus if we are loading from a data segment which began at location
                    266:  * 4 in a .o file into an a.out where it will be loaded starting at
                    267:  * 1024, cdrel will be 1020.)
                    268:  */
                    269: long   ctrel, cdrel, cbrel;
                    270: 
                    271: /*
                    272:  * Textbase is the start address of all text, given by textreloc()
                    273:  * unless specified by -T, or unless we are still relocating (-r), in
                    274:  * which case it is 0.  Database is the base of all data, computed
                    275:  * before and used during pass2.
                    276:  */
                    277: long   textbase = -1, database = -1;
                    278: 
                    279: #ifdef vax
                    280: #define        textreloc() 0
                    281: #define pagesize() sys_pagesize
                    282: #define segsize() sys_pagesize
                    283: #endif vax
                    284: 
                    285: #ifdef sun
                    286: #      ifdef   sun3
                    287: #              define textreloc() (zflag ? PAGSIZ+sizeof(struct exec): PAGSIZ)
                    288: #              define pagesize() PAGSIZ
                    289: #              define segsize()  SEGSIZ
                    290: #      else    !sun3
                    291: #              define textreloc() OLD_SEGSIZ
                    292: #              define pagesize() OLD_PAGSIZ
                    293: #              define segsize() OLD_SEGSIZ
                    294: #      endif   !sun3
                    295: #endif sun
                    296: 
                    297: /*
                    298:  * Origins of the text and data segments can be regulated by command-
                    299:  * line flags -Ttext & -Tdata (just -T will be interpreted as -Ttext).
                    300:  */
                    301: struct origopts{
                    302:     char       *optname;
                    303:     char       *whatbase;
                    304:     int                *flagptr;
                    305:     int                *whatsize;
                    306: } origopts[] = {
                    307:        "T",            "text", &textbase,      &tsize,
                    308:        "Ttext",        "text", &textbase,      &tsize,
                    309:        "Tdata",        "data", &database,      &dsize,
                    310:        (char *)0 ,
                    311: };
                    312: 
                    313: /*
                    314:  * changes for Sun-3 and subsequent architectures:
                    315:  *
                    316:  *   1.        (magic numbers) Magic numbers are 16 bits and are preceded by
                    317:  *     a 16-bit machine type field, which is 0 for Sun-2 and earlier
                    318:  *     architectures.  Sun-3 has a machine type of 1.
                    319:  *
                    320:  *   2.        (segment relocation bases) Changed from Sun-2:
                    321:  *
                    322:  *     text(old):      0x8000
                    323:  *     text(new):      0x2000 + sizeof(struct exec)
                    324:  *     data(old):      begins at a multiple of 0x8000
                    325:  *     data(new):      begins at a multiple of 0x20000
                    326:  *
                    327:  *   3. (location of a.out header) In all Sun-3 object file formats,
                    328:  *     the exec structure is at the beginning of the text segment.
                    329:  *     In demand-paged (0413) files, this saves about a page of
                    330:  *     disk space.
                    331:  */
                    332: 
                    333: /*
                    334:  * The base addresses for the loaded text, data and bss from the
                    335:  * current module during pass2 are given by torigin, dorigin and borigin.
                    336:  */
                    337: long   torigin, dorigin, borigin;
                    338: 
                    339: /*
                    340:  * Errlev is nonzero when errors have occured.
                    341:  * Delarg is an implicit argument to the routine delexit
                    342:  * which is called on error.  We do ``delarg = errlev'' before normal
                    343:  * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the
                    344:  * result file executable.
                    345:  */
                    346: int    errlev;
                    347: int    delarg  = 4;
                    348: 
                    349: /*
                    350:  * The biobuf structure and associated routines are used to write
                    351:  * into one file at several places concurrently.  Calling bopen
                    352:  * with a biobuf structure sets it up to write ``biofd'' starting
                    353:  * at the specified offset.  You can then use ``bwrite'' and/or ``bputc''
                    354:  * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
                    355:  * Calling bflush drains all the buffers and MUST be done before exit.
                    356:  */
                    357: struct biobuf {
                    358:        short   b_nleft;                /* Number free spaces left in b_buf */
                    359: /* Initialize to be less than BUFSIZ initially, to boundary align in file */
                    360:        char    *b_ptr;                 /* Next place to stuff characters */
                    361:        char    b_buf[BUFSIZ];          /* The buffer itself */
                    362:        off_t   b_off;                  /* Current file offset */
                    363:        struct  biobuf *b_link;         /* Link in chain for bflush() */
                    364: } *biobufs;
                    365: #define        bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
                    366:                       : bflushc(b, c))
                    367: int    biofd;
                    368: off_t  boffset;
                    369: struct biobuf *tout, *dout, *trout, *drout, *sout, *strout;
                    370: 
                    371: /*
                    372:  * Offset is the current offset in the string file.
                    373:  * Its initial value reflects the fact that we will
                    374:  * eventually stuff the size of the string table at the
                    375:  * beginning of the string table (i.e. offset itself!).
                    376:  */
                    377: off_t  offset = sizeof (off_t);
                    378: 
                    379: char   *aoutname = "a.out";    /* name of resultant file: -o argument or a.out */
                    380: char   ofilename[DIRSIZ+1];
                    381: int    ofilemode;              /* respect umask even for unsucessful ld's */
                    382: int    infil;                  /* current input file descriptor */
                    383: char   *filname;               /* and its name */
                    384: int    header_num;             /* ordinal # of header file (for dbx) */
                    385: 
                    386: /*
                    387:  * Base of the string table of the current module (pass1 and pass2).
                    388:  */
                    389: char   *curstr;
                    390: 
                    391: /*
                    392:  * System software page size
                    393:  */
                    394: 
                    395: /* int sys_pagesize;*/
                    396: 
                    397: char   get();
                    398: int    delexit();
                    399: char   *savestr();
                    400: 
                    401: main(argc, argv)
                    402:        int argc;
                    403:        char **argv;
                    404: {
                    405:        register int c, i; 
                    406:        int num;
                    407:        register char *ap, **p;
                    408:        char save;
                    409: 
                    410:        if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
                    411:                signal(SIGINT, delexit);
                    412:                signal(SIGTERM, delexit);
                    413:        }
                    414:        if (argc == 1)
                    415:                exit(4);
                    416:        p = argv+1;
                    417:        alloc_inclstack();
                    418: /*     sys_pagesize = getpagesize(); */
                    419: 
                    420:        /*
                    421:         * Scan arguments to determine the correct setting of
                    422:         * zflag.  The text relocation base depends on it, and
                    423:         * cannot change after the first file is processed.
                    424:         */
                    425:        zflag = 1;      /* default: on */
                    426:        for (c=1; c<argc; c++) {
                    427:                ap = argv[c];
                    428:                if (ap[0] != '-') {
                    429:                        /* not an option string */
                    430:                        continue;
                    431:                }
                    432:                for (i=1; ap[i]; i++) {
                    433:                        switch (ap[i]) {
                    434:                        case 'o':
                    435:                        case 'u':
                    436:                        case 'e':
                    437:                        case 'H':
                    438:                        case 'D':
                    439:                                /*
                    440:                                 * skip the next argument string --
                    441:                                 * but look at the rest of the flags
                    442:                                 * in the current one (bletch)
                    443:                                 */
                    444:                                c++;
                    445:                                continue;
                    446:                        case 'A':
                    447:                                c++;
                    448:                                zflag = 0;
                    449:                                continue;
                    450:                        case 'T':
                    451:                                /*
                    452:                                 * skip the next argument string,
                    453:                                 * discard the rest of the current one,
                    454:                                 * and cancel zflag
                    455:                                 */
                    456:                                c++;
                    457:                                zflag = 0;
                    458:                                Tflag = 1;
                    459:                                goto nextarg;
                    460:                        case 'l':
                    461:                        case 'y':
                    462:                                /*
                    463:                                 * discard the rest of the current argument
                    464:                                 * string
                    465:                                 */
                    466:                                goto nextarg;
                    467:                        case 'r':
                    468:                        case 'n':
                    469:                        case 'N':
                    470:                                /*
                    471:                                 * the whole point of this silly loop:
                    472:                                 * cancel zflag
                    473:                                 */
                    474:                                zflag = 0;
                    475:                                continue;
                    476:                        default:
                    477:                                continue;
                    478:                        }
                    479:                }
                    480: nextarg:
                    481:                continue;
                    482:        }
                    483: 
                    484:        /*
                    485:         * Scan files once to find where symbols are defined.
                    486:         */
                    487:        for (c=1; c<argc; c++) {
                    488:                if (trace)
                    489:                        printf("%s:\n", *p);
                    490:                filname = 0;
                    491:                ap = *p++;
                    492:                if (*ap != '-') {
                    493:                        load1arg(ap);
                    494:                        continue;
                    495:                }
                    496:                for (i=1; ap[i]; i++) switch (ap[i]) {
                    497: 
                    498:                case 'o':
                    499:                        if (++c >= argc)
                    500:                                error(1, "-o where?");
                    501:                        aoutname = *p++;
                    502:                        continue;
                    503:                case 'u':
                    504:                case 'e':
                    505:                        if (++c >= argc)
                    506:                                error(1, "-u or -c: arg missing");
                    507:                        enter(slookup(*p++));
                    508:                        if (ap[i]=='e')
                    509:                                entrypt = lastsym;
                    510:                        continue;
                    511:                case 'H':
                    512:                        if (++c >= argc)
                    513:                                error(1, "-H: arg missing");
                    514:                        if (tsize!=0)
                    515:                                error(1, "-H: too late, some text already loaded");
                    516:                        hsize = atoi(*p++);
                    517:                        continue;
                    518:                case 'A':
                    519:                        if (++c >= argc)
                    520:                                error(1, "-A: arg missing");
                    521:                        if (Aflag) 
                    522:                                error(1, "-A: only one base file allowed");
                    523:                        Aflag = 1;
                    524:                        nflag = 0;
                    525:                        funding = 1;
                    526:                        load1arg(*p++);
                    527:                        trsize = drsize = tsize = dsize = bsize = 0;
                    528:                        ctrel = cdrel = cbrel = 0;
                    529:                        funding = 0;
                    530:                        addsym = nextsym;
                    531:                        continue;
                    532:                case 'D':
                    533:                        if (++c >= argc)
                    534:                                error(1, "-D: arg missing");
                    535:                        num = htoi(*p++);
                    536:                        if (dsize > num)
                    537:                                error(1, "-D: too small");
                    538:                        dsize = num;
                    539:                        continue;
                    540:                case 'T':
                    541:                        {
                    542:                        struct origopts *t;
                    543:                        for (t = origopts; t->optname; t++){
                    544:                            if (!strcmp( &ap[i] ,t->optname))
                    545:                                break;
                    546:                        }
                    547:                        if (t->optname==NULL)
                    548:                                error(1, "-%s option unrecognized", &ap[i] );
                    549:                        if (++c >= argc)
                    550:                                error(1, "-%s: arg missing", t->optname);
                    551:                        if (*(t->whatsize)!=0)
                    552:                                error(1, "-%s: too late, some %s already loaded",
                    553:                                        t->optname,  t->whatbase);
                    554:                        if (*(t->flagptr)>=0 && !Aflag)
                    555:                                error(-1, "-%s: %s base already given: old value overridden",
                    556:                                        t->optname,  t->whatbase);
                    557:                        *(t->flagptr) = htoi(*p++);
                    558:                        }
                    559:                        goto next;
                    560:                case 'l':
                    561:                        save = ap[--i]; 
                    562:                        ap[i]='-';
                    563:                        load1arg(&ap[i]); 
                    564:                        ap[i]=save;
                    565:                        goto next;
                    566:                case 'M':
                    567:                        Mflag++;
                    568:                        continue;
                    569:                case 'x':
                    570:                        xflag++;
                    571:                        continue;
                    572:                case 'X':
                    573:                        Xflag++;
                    574:                        continue;
                    575:                case 'S':
                    576:                        Sflag++; 
                    577:                        continue;
                    578:                case 'r':
                    579:                        rflag++;
                    580:                        arflag++;
                    581:                        /* We don't want to relocate the text. */
                    582:                        if (textbase != 0 && textbase != -1){
                    583:                                if (tsize!=0)
                    584:                                        error(1, "-r: too late, some text already loaded");
                    585:                                else
                    586:                                        error(0, "-T & -r are mutually exclusive");
                    587:                        }
                    588:                        textbase = 0;
                    589:                        continue;
                    590:                case 's':
                    591:                        sflag++;
                    592:                        xflag++;
                    593:                        continue;
                    594:                case 'd':
                    595:                        dflag++;
                    596:                        continue;
                    597:                case 'i':
                    598:                        printf("ld: -i ignored\n");
                    599:                        continue;
                    600:                case 't':
                    601:                        trace++;
                    602:                        continue;
                    603:                case 'y':
                    604:                        if (ap[i+1] == 0)
                    605:                                error(1, "-y: symbol name missing");
                    606:                        if (yflag == 0) {
                    607:                                ytab = (char **)calloc(argc, sizeof (char **));
                    608:                                if (ytab == 0)
                    609:                                        error(1, "ran out of memory (-y)");
                    610:                        }
                    611:                        ytab[yflag++] = &ap[i+1];
                    612:                        goto next;
                    613:                case 'N':
                    614:                        Nflag++;
                    615:                        nflag = zflag = 0;
                    616:                        continue;
                    617:                case 'n':
                    618:                        nflag++;
                    619:                        Nflag = zflag = 0;
                    620:                        continue;
                    621:                case 'z':
                    622:                        zflag++;
                    623:                        Nflag = nflag = 0;
                    624:                        continue;
                    625:                default:
                    626:                        filname = savestr("-x");        /* kludge */
                    627:                        filname[1] = ap[i];             /* kludge */
                    628:                        archdr.ar_name[0] = 0;          /* kludge */
                    629:                        error(1, "bad flag");
                    630:                }
                    631: next:
                    632:                ;
                    633:        }
                    634:        ap = rindex( aoutname, '/' );
                    635:        if ( ap != 0 ){
                    636:            strncpy( ofilename, aoutname, ap-aoutname+1 );
                    637:        }
                    638:        strcat( ofilename, "l.outXXXXXX");
                    639:        mktemp( ofilename );
                    640: 
                    641:        header_num = 0;
                    642:        merge_headers();
                    643:        endload(argc, argv);
                    644:        exit(0);
                    645: }
                    646: 
                    647: /*
                    648:  * Convert a ascii string which is a hex number.
                    649:  * Used by -T and -D options.
                    650:  */
                    651: htoi(p)
                    652:        register char *p;
                    653: {
                    654:        register int c, n;
                    655: 
                    656:        n = 0;
                    657:        while (c = *p++) {
                    658:                n <<= 4;
                    659:                if (isdigit(c))
                    660:                        n += c - '0';
                    661:                else if (c >= 'a' && c <= 'f')
                    662:                        n += 10 + (c - 'a');
                    663:                else if (c >= 'A' && c <= 'F')
                    664:                        n += 10 + (c - 'A');
                    665:                else
                    666:                        error(1, "badly formed hex number");
                    667:        }
                    668:        return (n);
                    669: }
                    670: 
                    671: delexit()
                    672: {
                    673:        struct stat stbuf;
                    674:        long size;
                    675:        char c = 0;
                    676: 
                    677:        bflush();
                    678:        unlink(ofilename);
                    679:        if (delarg==0 && Aflag==0)
                    680:                chmod(aoutname, ofilemode);
                    681:        /*
                    682:         * We have to insure that the last block of the data segment
                    683:         * is allocated a full size page. If the underlying
                    684:         * file system allocates frags that are smaller than pagesize,
                    685:         * a full zero filled block needs to be allocated so 
                    686:         * that when it is demand paged, the paged in block will be 
                    687:         * appropriately filled with zeros.
                    688:         */
                    689:        fstat(biofd, &stbuf);
                    690:        size = round(stbuf.st_size, pagesize());
                    691:        if (!rflag && zflag && size > stbuf.st_size) {
                    692:                lseek(biofd, size - 1, 0);
                    693:                write(biofd, &c, 1);
                    694:        }
                    695:        exit (delarg);
                    696: }
                    697: 
                    698: endload(argc, argv)
                    699:        int argc; 
                    700:        char **argv;
                    701: {
                    702:        register int c, i; 
                    703:        long dnum;
                    704:        register char *ap, **p;
                    705: 
                    706:        clibseg = libseg;
                    707:        filname = 0;
                    708:        middle();
                    709:        setupout();
                    710:        p = argv+1;
                    711:        for (c=1; c<argc; c++) {
                    712:                ap = *p++;
                    713:                if (trace)
                    714:                        printf("%s:\n", ap);
                    715:                if (*ap != '-') {
                    716:                        load2arg(ap);
                    717:                        continue;
                    718:                }
                    719:                for (i=1; ap[i]; i++) switch (ap[i]) {
                    720: 
                    721:                case 'D':
                    722:                        dnum = htoi(*p);
                    723:                        if (dorigin < dnum)
                    724:                                while (dorigin < dnum)
                    725:                                        bputc(0, dout), dorigin++;
                    726:                        /* fall into ... */
                    727:                case 'u':
                    728:                case 'e':
                    729:                case 'o':
                    730:                case 'H':
                    731:                        ++c; 
                    732:                        ++p;
                    733:                        /* fall into ... */
                    734:                default:
                    735:                        continue;
                    736:                case 'A':
                    737:                        funding = 1;
                    738:                        load2arg(*p++);
                    739:                        funding = 0;
                    740:                        c++;
                    741:                        continue;
                    742:                case 'T':
                    743:                        ++c; 
                    744:                        ++p;
                    745:                        /* fall into ... */
                    746:                case 'y':
                    747:                        goto next;
                    748:                case 'l':
                    749:                        ap[--i]='-'; 
                    750:                        load2arg(&ap[i]);
                    751:                        goto next;
                    752:                }
                    753: next:
                    754:                ;
                    755:        }
                    756:        finishout();
                    757: }
                    758: 
                    759: 
                    760: /*
                    761:  * Scan file to find defined symbols.
                    762:  */
                    763: load1arg(cp)
                    764:        register char *cp;
                    765: {
                    766:        register struct ranlib *tp;
                    767:        off_t nloc;
                    768:        int kind;
                    769: 
                    770:        /* 
                    771:         * If the user hasn't somehow specified a textbase (by -T or -r)
                    772:         * take the default.
                    773:         */
                    774:        if (textbase == -1 && !Aflag)
                    775:                textbase = textreloc();
                    776:        kind = getfile(cp);
                    777:        if (Mflag)
                    778:                printf("%s\n", filname);
                    779:        switch (kind) {
                    780: 
                    781:        /*
                    782:         * Plain file.
                    783:         */
                    784:        case 0:
                    785:                load1(0, 0L);
                    786:                break;
                    787: 
                    788:        /*
                    789:         * Archive without table of contents.
                    790:         * (Slowly) process each member.
                    791:         */
                    792:        case 1:
                    793:                error(-1,
                    794: "warning: archive has no table of contents; add one using ranlib(1)");
                    795:                nloc = SARMAG;
                    796:                while (step(nloc))
                    797:                        nloc += sizeof(archdr) +
                    798:                            round(atol(archdr.ar_size), sizeof (short));
                    799:                break;
                    800: 
                    801:        /*
                    802:         * Archive with table of contents.
                    803:         * Read the table of contents and its associated string table.
                    804:         * Pass through the library resolving symbols until nothing changes
                    805:         * for an entire pass (i.e. you can get away with backward references
                    806:         * when there is a table of contents!)
                    807:         */
                    808:        case 2:
                    809:                nloc = SARMAG + sizeof (archdr);
                    810:                dseek(&text, nloc, sizeof (tnum));
                    811:                mget((char *)&tnum, sizeof (tnum), &text);
                    812:                nloc += sizeof (tnum);
                    813:                tab = (struct ranlib *)malloc(tnum);
                    814:                if (tab == 0)
                    815:                        error(1, "ran out of memory (toc)");
                    816:                dseek(&text, nloc, tnum);
                    817:                mget((char *)tab, tnum, &text);
                    818:                nloc += tnum;
                    819:                tnum /= sizeof (struct ranlib);
                    820:                dseek(&text, nloc, sizeof (ssiz));
                    821:                mget((char *)&ssiz, sizeof (ssiz), &text);
                    822:                nloc += sizeof (ssiz);
                    823:                tabstr = (char *)malloc(ssiz);
                    824:                if (tabstr == 0)
                    825:                        error(1, "ran out of memory (tocstr)");
                    826:                dseek(&text, nloc, ssiz);
                    827:                mget((char *)tabstr, ssiz, &text);
                    828:                for (tp = &tab[tnum]; --tp >= tab;) {
                    829:                        if (tp->ran_un.ran_strx < 0 ||
                    830:                            tp->ran_un.ran_strx >= ssiz)
                    831:                                error(1, "mangled archive table of contents");
                    832:                        tp->ran_un.ran_name = tabstr + tp->ran_un.ran_strx;
                    833:                }
                    834:                while (ldrand())
                    835:                        continue;
                    836:                cfree((char *)tab);
                    837:                cfree(tabstr);
                    838:                nextlibp(-1);
                    839:                break;
                    840: 
                    841:        /*
                    842:         * Table of contents is out of date, so search
                    843:         * as a normal library (but skip the __.SYMDEF file).
                    844:         */
                    845:        case 3:
                    846:                error(-1,
                    847: "warning: table of contents for archive is out of date; rerun ranlib(1)");
                    848:                nloc = SARMAG;
                    849:                do
                    850:                        nloc += sizeof(archdr) +
                    851:                            round(atol(archdr.ar_size), sizeof(short));
                    852:                while (step(nloc));
                    853:                break;
                    854:        }
                    855:        close(infil);
                    856: }
                    857: 
                    858: /*
                    859:  * Advance to the next archive member, which
                    860:  * is at offset nloc in the archive.  If the member
                    861:  * is useful, record its location in the liblist structure
                    862:  * for use in pass2.  Mark the end of the archive in libilst with a -1.
                    863:  */
                    864: step(nloc)
                    865:        off_t nloc;
                    866: {
                    867: 
                    868:        dseek(&text, nloc, (long) sizeof archdr);
                    869:        if (text.size <= 0) {
                    870:                nextlibp(-1);
                    871:                return (0);
                    872:        }
                    873:        getarhdr();
                    874:        if (load1(1, nloc + (sizeof archdr)))
                    875:                nextlibp(nloc);
                    876:        return (1);
                    877: }
                    878: 
                    879: /*
                    880:  * Record the location of a useful archive member.
                    881:  * Recording -1 marks the end of files from an archive.
                    882:  * The liblist data structure is dynamically extended here.
                    883:  */
                    884: nextlibp(val)
                    885:        off_t val;
                    886: {
                    887: 
                    888:        if (clibseg->li_used == NROUT) {
                    889:                if (++clibseg == &libseg[NSEG])
                    890:                        error(1, "too many files loaded from libraries");
                    891:                clibseg->li_first = (off_t *)malloc(NROUT * sizeof (off_t));
                    892:                if (clibseg->li_first == 0)
                    893:                        error(1, "ran out of memory (nextlibp)");
                    894:        }
                    895:        clibseg->li_first[clibseg->li_used++] = val;
                    896:        if (val != -1 && Mflag)
                    897:                printf("\t%s\n", archdr.ar_name);
                    898: }
                    899: 
                    900: /*
                    901:  * One pass over an archive with a table of contents.
                    902:  * Remember the number of symbols currently defined,
                    903:  * then call step on members which look promising (i.e.
                    904:  * that define a symbol which is currently externally undefined).
                    905:  * Indicate to our caller whether this process netted any more symbols.
                    906:  */
                    907: ldrand()
                    908: {
                    909:        register struct nlist *sp, **hp;
                    910:        register struct ranlib *tp, *tplast;
                    911:        off_t loc;
                    912:        int nsymt = symx(nextsym);
                    913: 
                    914:        tplast = &tab[tnum-1];
                    915:        for (tp = tab; tp <= tplast; tp++) {
                    916:                if ((hp = slookup(tp->ran_un.ran_name)) == 0)
                    917:                        continue;
                    918:                if ((sp = *hp) == NULL)
                    919:                        continue;
                    920:                if (sp->n_type != N_EXT+N_UNDF)
                    921:                        continue;
                    922:                step(tp->ran_off);
                    923:                loc = tp->ran_off;
                    924:                while (tp < tplast && (tp+1)->ran_off == loc)
                    925:                        tp++;
                    926:        }
                    927:        return (symx(nextsym) != nsymt);
                    928: }
                    929: 
                    930: /*
                    931:  * Examine a single file or archive member on pass 1.
                    932:  */
                    933: load1(libflg, loc)
                    934:        off_t loc;
                    935: {
                    936:        register struct nlist *sp;
                    937:        struct nlist *savnext;
                    938:        int ndef, nlocal, type, size, nsymt;
                    939:        register int i;
                    940:        off_t maxoff;
                    941:        struct stat stb;
                    942: 
                    943:        new_obj1();
                    944:        readhdr(loc);
                    945:        if (filhdr.a_syms == 0) {
                    946:                if (filhdr.a_text+filhdr.a_data == 0) {
                    947:                        if (libflg == 0) {
                    948:                                ssize += sizeof(cursym);
                    949:                        }
                    950:                        return(0);
                    951:                }
                    952:                error(1, "no namelist");
                    953:        }
                    954:        if (libflg)
                    955:                maxoff = atol(archdr.ar_size);
                    956:        else {
                    957:                fstat(infil, &stb);
                    958:                maxoff = stb.st_size;
                    959:        }
                    960:        if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff)
                    961:                error(1, "too small (old format .o?)");
                    962:        ctrel = tsize; cdrel += dsize; cbrel += bsize;
                    963:        ndef = 0;
                    964:        nlocal = sizeof(cursym);
                    965:        savnext = nextsym;
                    966:        loc += N_SYMOFF(filhdr);
                    967:        dseek(&text, loc, filhdr.a_syms);
                    968:        dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t));
                    969:        mget(&size, sizeof (size), &reloc);
                    970:        dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t));
                    971:        curstr = (char *)malloc(size);
                    972:        if (curstr == NULL)
                    973:                error(1, "no space for string table");
                    974:        mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc);
                    975:        while (text.size > 0) {
                    976:                mget((char *)&cursym, sizeof(struct nlist), &text);
                    977:                if (cursym.n_un.n_strx) {
                    978:                        if (cursym.n_un.n_strx<sizeof(size) ||
                    979:                            cursym.n_un.n_strx>=size)
                    980:                                error(1, "bad string table index (pass 1)");
                    981:                        cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
                    982:                }
                    983:                type = cursym.n_type;
                    984:                if (type & N_STAB) {
                    985:                        if (type == N_BINCL) {
                    986:                                start_incl1(&cursym, header_num);
                    987:                                header_num++;
                    988:                        } else if (type == N_EINCL) {
                    989:                                end_incl1();
                    990:                        } else {
                    991:                                stab1(&cursym);
                    992:                        }
                    993:                }
                    994:                if ((type&N_EXT)==0) {
                    995:                        if (Xflag==0 || type & N_STAB ||
                    996:                            cursym.n_un.n_name[0]!='L' )
                    997:                                nlocal += sizeof cursym;
                    998:                        continue;
                    999:                }
                   1000:                symreloc();
                   1001:                if (enter(lookup()))
                   1002:                        continue;
                   1003:                if ((sp = lastsym)->n_type != N_EXT+N_UNDF)
                   1004:                        continue;
                   1005:                if (cursym.n_type == N_EXT+N_UNDF) {
                   1006:                        if (cursym.n_value > sp->n_value)
                   1007:                                sp->n_value = cursym.n_value;
                   1008:                        continue;
                   1009:                }
                   1010:                if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT)
                   1011:                        continue;
                   1012:                ndef++;
                   1013:                sp->n_type = cursym.n_type;
                   1014:                sp->n_value = cursym.n_value;
                   1015:        }
                   1016:        if (libflg==0 || ndef) {
                   1017:                tsize += filhdr.a_text;
                   1018:                dsize += round(filhdr.a_data, sizeof (long));
                   1019:                bsize += round(filhdr.a_bss, sizeof (long));
                   1020:                ssize += nlocal;
                   1021:                trsize += filhdr.a_trsize;
                   1022:                drsize += filhdr.a_drsize;
                   1023:                if (funding) {
                   1024:                        if (textbase == -1 && Tflag == 0) {
                   1025:                                if ((*slookup("_end")) == 0) {
                   1026:                                        error(1, "base address is not provided, use option \"-T\" or link the fundamental file with option \"-u _end\"");
                   1027:                                }
                   1028:                                textbase = (*slookup("_end"))->n_value;
                   1029:                        } 
                   1030:                }
                   1031:                nsymt = symx(nextsym);
                   1032:                for (i = symx(savnext); i < nsymt; i++) {
                   1033:                        sp = xsym(i);
                   1034:                        if (sp->n_un.n_name)
                   1035:                                sp->n_un.n_name = savestr(sp->n_un.n_name);
                   1036:                }
                   1037:                free(curstr);
                   1038:                return (1);
                   1039:        }
                   1040:        /*
                   1041:         * No symbols defined by this library member.
                   1042:         * Rip out the hash table entries and reset the symbol table.
                   1043:         */
                   1044:        incl_free();
                   1045:        symfree(savnext);
                   1046:        free(curstr);
                   1047:        return(0);
                   1048: }
                   1049: 
                   1050: middle()
                   1051: {
                   1052:        register struct nlist *sp;
                   1053:        long csize, t, corigin, ocsize;
                   1054:        int nund, rnd;
                   1055:        char s;
                   1056:        register int i;
                   1057:        int nsymt;
                   1058: 
                   1059:        torigin = 0; 
                   1060:        dorigin = 0; 
                   1061:        borigin = 0;
                   1062: 
                   1063:        p_etext = *slookup("_etext");
                   1064:        p_edata = *slookup("_edata");
                   1065:        p_end = *slookup("_end");
                   1066:        /*
                   1067:         * If there are any undefined symbols, save the relocation bits.
                   1068:         */
                   1069:        nsymt = symx(nextsym);
                   1070:        if (rflag==0) {
                   1071:                for (i = 0; i < nsymt; i++) {
                   1072:                        sp = xsym(i);
                   1073:                        if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 &&
                   1074:                            sp!=p_end && sp!=p_edata && sp!=p_etext) {
                   1075:                                rflag++;
                   1076:                                dflag = 0;
                   1077:                                break;
                   1078:                        }
                   1079:                }
                   1080:        }
                   1081:        if (rflag) 
                   1082:                sflag = zflag = 0;
                   1083:        /*
                   1084:         * Assign common locations.
                   1085:         */
                   1086:        csize = 0;
                   1087:        if (!Aflag)
                   1088:                addsym = symseg[0].sy_first;
                   1089: #ifdef sun3
                   1090:        if (zflag) {
                   1091:                /*
                   1092:                 * in sun-3 demand-paged programs,
                   1093:                 * the exec structure is in text space
                   1094:                 */
                   1095:                tsize += sizeof(struct exec);
                   1096:        }
                   1097: #endif sun3
                   1098: #ifdef mc68000
                   1099:        /*
                   1100:         * prevent programs from ending exactly on a page boundary;
                   1101:         * if they do, they will coredump as they prefetch the last
                   1102:         * "unlk a6; rts" instruction sequence (bug in unlk instruction)
                   1103:         */
                   1104:        if (tsize > 0 && tsize % pagesize() == 0) {
                   1105:                tsize += sizeof(long);
                   1106:        }
                   1107: #endif mc68000
                   1108:        if (database == -1 ){
                   1109:                /* compute normal, default data base */
                   1110:                database = round(tsize+textbase,
                   1111:                    (nflag||zflag ? segsize() : sizeof (long)));
                   1112:                database += hsize;
                   1113:        }
                   1114:        if (dflag || rflag==0) {
                   1115:                ldrsym(p_etext, tsize, N_EXT+N_TEXT);
                   1116:                ldrsym(p_edata, dsize, N_EXT+N_DATA);
                   1117:                ldrsym(p_end, bsize, N_EXT+N_BSS);
                   1118:                for (i = symx(addsym); i < nsymt; i++) {
                   1119:                        sp = xsym(i);
                   1120:                        if ((s=sp->n_type)==N_EXT+N_UNDF &&
                   1121:                            (t = sp->n_value)!=0) {
                   1122:                                if (t >= sizeof (double))
                   1123:                                        rnd = sizeof (double);
                   1124:                                else if (t >= sizeof (long))
                   1125:                                        rnd = sizeof (long);
                   1126:                                else
                   1127:                                        rnd = sizeof (short);
                   1128:                                csize = round(csize, rnd);
                   1129:                                sp->n_value = csize;
                   1130:                                sp->n_type = N_EXT+N_COMM;
                   1131:                                ocsize = csize; 
                   1132:                                csize += t;
                   1133:                        }
                   1134:                        if (s&N_EXT && (s&N_TYPE)==N_UNDF && s&N_STAB) {
                   1135:                                sp->n_value = ocsize;
                   1136:                                sp->n_type = (s&N_STAB) | (N_EXT+N_COMM);
                   1137:                        }
                   1138:                }
                   1139:        }
                   1140:        /*
                   1141:         * Now set symbols to their final value
                   1142:         */
                   1143:        csize = round(csize, sizeof (long));
                   1144:        torigin = textbase;
                   1145:        dorigin = database;
                   1146:        corigin = dorigin + dsize;
                   1147:        borigin = corigin + csize;
                   1148:        nund = 0;
                   1149:        nsymt = symx(nextsym);
                   1150:        for (i = symx(addsym); i<nsymt; i++) {
                   1151:                sp = xsym(i);
                   1152:                switch (sp->n_type & (N_TYPE+N_EXT)) {
                   1153: 
                   1154:                case N_EXT+N_UNDF:
                   1155:                        if (arflag == 0)
                   1156:                                errlev |= 01;
                   1157:                        if ((arflag==0 || dflag) && sp->n_value==0) {
                   1158:                                if (sp==p_end || sp==p_etext || sp==p_edata)
                   1159:                                        continue;
                   1160:                                if (nund==0)
                   1161:                                        printf("Undefined:\n");
                   1162:                                nund++;
                   1163:                                printf("%s\n", sp->n_un.n_name);
                   1164:                        }
                   1165:                        continue;
                   1166:                case N_EXT+N_ABS:
                   1167:                default:
                   1168:                        continue;
                   1169:                case N_EXT+N_TEXT:
                   1170:                        sp->n_value += torigin;
                   1171:                        continue;
                   1172:                case N_EXT+N_DATA:
                   1173:                        sp->n_value += dorigin;
                   1174:                        continue;
                   1175:                case N_EXT+N_BSS:
                   1176:                        sp->n_value += borigin;
                   1177:                        continue;
                   1178:                case N_EXT+N_COMM:
                   1179:                        sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS);
                   1180:                        sp->n_value += corigin;
                   1181:                        continue;
                   1182:                }
                   1183:        }
                   1184:        if (sflag || xflag)
                   1185:                ssize = 0;
                   1186:        bsize += csize;
                   1187:        nsym = ssize / (sizeof cursym);
                   1188:        if (Aflag) {
                   1189:                fixspec(p_etext,torigin);
                   1190:                fixspec(p_edata,dorigin);
                   1191:                fixspec(p_end,borigin);
                   1192:        }
                   1193: }
                   1194: 
                   1195: fixspec(sym,offset)
                   1196:        struct nlist *sym;
                   1197:        long offset;
                   1198: {
                   1199: 
                   1200:        if (symx(sym) < symx(addsym) && sym!=0)
                   1201:                sym->n_value += offset;
                   1202: }
                   1203: 
                   1204: ldrsym(sp, val, type)
                   1205:        register struct nlist *sp;
                   1206:        long val;
                   1207: {
                   1208: 
                   1209:        if (sp == 0)
                   1210:                return;
                   1211:        if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) {
                   1212:                printf("%s: ", sp->n_un.n_name);
                   1213:                error(0, "user attempt to redfine loader-defined symbol");
                   1214:                return;
                   1215:        }
                   1216:        sp->n_type = type;
                   1217:        sp->n_value = val;
                   1218: }
                   1219: 
                   1220: off_t  wroff;
                   1221: struct biobuf toutb;
                   1222: 
                   1223: setupout()
                   1224: {
                   1225:        int bss;
                   1226:        int newpage;
                   1227:        extern char *sys_errlist[];
                   1228:        extern int errno;
                   1229: 
                   1230:        ofilemode = 0777 & ~umask(0);
                   1231:        biofd = creat(ofilename, 0666 & ofilemode);
                   1232:        if (biofd < 0) {
                   1233:                filname = ofilename;            /* kludge */
                   1234:                archdr.ar_name[0] = 0;          /* kludge */
                   1235:                error(1, sys_errlist[errno]);   /* kludge */
                   1236:        } else {
                   1237:                struct stat mybuf;              /* kls kludge */
                   1238:                fstat(biofd, &mybuf);           /* suppose file exists, wrong*/
                   1239:                if (mybuf.st_mode & 0111) {     /* mode, ld fails? */
                   1240:                        chmod(ofilename, mybuf.st_mode & 0666);
                   1241:                        ofilemode = mybuf.st_mode;
                   1242:                }
                   1243:        }
                   1244:        tout = &toutb;
                   1245:        bopen(tout, 0);
                   1246: #ifdef sun3
                   1247:        outfilhdr.a_machtype = (use68020 ? M_68020 : M_68010);
                   1248: #endif !sun3
                   1249:        outfilhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
                   1250:        outfilhdr.a_text = round(tsize, zflag ? pagesize() : sizeof(long));
                   1251:        outfilhdr.a_data = round(dsize, zflag ? pagesize() : sizeof(long));
                   1252:        bss = bsize - (outfilhdr.a_data - dsize);
                   1253:        if (bss < 0)
                   1254:                bss = 0;
                   1255:        outfilhdr.a_bss = bss;
                   1256:        outfilhdr.a_trsize = trsize;
                   1257:        outfilhdr.a_drsize = drsize;
                   1258:        outfilhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*symx(nextsym));
                   1259:        if (entrypt) {
                   1260:                if (entrypt->n_type!=N_EXT+N_TEXT)
                   1261:                        error(0, "entry point not in text");
                   1262:                else
                   1263:                        outfilhdr.a_entry = entrypt->n_value;
                   1264:        } else
                   1265:                outfilhdr.a_entry = textbase;
                   1266:        outfilhdr.a_trsize = (rflag ? trsize:0);
                   1267:        outfilhdr.a_drsize = (rflag ? drsize:0);
                   1268:        bwrite((char *)&outfilhdr, sizeof (outfilhdr), tout);
                   1269: #ifndef        sun3
                   1270:        if (zflag) {
                   1271:                /* start text on a new page */
                   1272:                bflush1(tout);
                   1273:                biobufs = 0;
                   1274:                bopen(tout, pagesize());
                   1275:        }
                   1276: #endif !sun3
                   1277:        wroff = N_TXTOFF(outfilhdr) + outfilhdr.a_text;
                   1278:        outb(&dout, outfilhdr.a_data);
                   1279:        if (rflag) {
                   1280:                outb(&trout, outfilhdr.a_trsize);
                   1281:                outb(&drout, outfilhdr.a_drsize);
                   1282:        }
                   1283:        if (sflag==0 || xflag==0) {
                   1284:                outb(&sout, outfilhdr.a_syms);
                   1285:                wroff += sizeof (offset);
                   1286:                outb(&strout, 0);
                   1287:        }
                   1288: }
                   1289: 
                   1290: outb(bp, inc)
                   1291:        register struct biobuf **bp;
                   1292: {
                   1293: 
                   1294:        *bp = (struct biobuf *)malloc(sizeof (struct biobuf));
                   1295:        if (*bp == 0)
                   1296:                error(1, "ran out of memory (outb)");
                   1297:        bopen(*bp, wroff);
                   1298:        wroff += inc;
                   1299: }
                   1300: 
                   1301: load2arg(acp)
                   1302: char *acp;
                   1303: {
                   1304:        register char *cp;
                   1305:        off_t loc;
                   1306: 
                   1307:        cp = acp;
                   1308:        if (getfile(cp) == 0) {
                   1309:                while (*cp)
                   1310:                        cp++;
                   1311:                while (cp >= acp && *--cp != '/');
                   1312:                mkfsym(++cp);
                   1313:                load2(0L);
                   1314:        } else {        /* scan archive members referenced */
                   1315:                for (;;) {
                   1316:                        if (clibseg->li_used2 == clibseg->li_used) {
                   1317:                                if (clibseg->li_used < NROUT)
                   1318:                                        error(1, "libseg botch");
                   1319:                                clibseg++;
                   1320:                        }
                   1321:                        loc = clibseg->li_first[clibseg->li_used2++];
                   1322:                        if (loc == -1)
                   1323:                                break;
                   1324:                        dseek(&text, loc, (long)sizeof(archdr));
                   1325:                        getarhdr();
                   1326:                        mkfsym(archdr.ar_name);
                   1327:                        load2(loc + (long)sizeof(archdr));
                   1328:                }
                   1329:        }
                   1330:        close(infil);
                   1331: }
                   1332: 
                   1333: load2(loc)
                   1334: long loc;
                   1335: {
                   1336:        int size;
                   1337:        register struct nlist *sp;
                   1338:        register struct local *lp;
                   1339:        register int symno, i;
                   1340:        int type;
                   1341:        int exclude;
                   1342: 
                   1343:        exclude = 0;
                   1344:        readhdr(loc);
                   1345:        if (!funding) {
                   1346:                ctrel = torigin;
                   1347:                cdrel += dorigin;
                   1348:                cbrel += borigin;
                   1349:        }
                   1350:        /*
                   1351:         * Reread the symbol table, recording the numbering
                   1352:         * of symbols for fixing external references.
                   1353:         */
                   1354:        for (i = 0; i < LHSIZ; i++)
                   1355:                lochash[i] = 0;
                   1356:        clocseg = locseg;
                   1357:        clocseg->lo_used = 0;
                   1358:        symno = -1;
                   1359:        loc += N_TXTOFF(filhdr);
                   1360:        dseek(&text, loc+filhdr.a_text+filhdr.a_data+
                   1361:                filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t));
                   1362:        mget(&size, sizeof(size), &text);
                   1363:        dseek(&text, loc+filhdr.a_text+filhdr.a_data+
                   1364:                filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t),
                   1365:                size - sizeof(off_t));
                   1366:        curstr = (char *)malloc(size);
                   1367:        if (curstr == NULL)
                   1368:                error(1, "out of space reading string table (pass 2)");
                   1369:        mget(curstr+sizeof(off_t), size-sizeof(off_t), &text);
                   1370:        dseek(&text, loc+filhdr.a_text+filhdr.a_data+
                   1371:                filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);
                   1372:        while (text.size > 0) {
                   1373:                symno++;
                   1374:                mget((char *)&cursym, sizeof(struct nlist), &text);
                   1375:                if (cursym.n_un.n_strx) {
                   1376:                        if (cursym.n_un.n_strx<sizeof(size) ||
                   1377:                            cursym.n_un.n_strx>=size)
                   1378:                                error(1, "bad string table index (pass 2)");
                   1379:                        cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
                   1380:                }
                   1381:                if (cursym.n_type & N_STAB) {
                   1382:                        if (cursym.n_type == N_BINCL) {
                   1383:                                exclude = start_incl2(&cursym, header_num);
                   1384:                                header_num++;
                   1385:                        } else if (cursym.n_type == N_EINCL) {
                   1386:                                if (exclude) {
                   1387:                                        exclude = end_incl2();
                   1388:                                        continue;
                   1389:                                } else {
                   1390:                                        exclude = end_incl2();
                   1391:                                }
                   1392:                        } else if (exclude) {
                   1393:                                continue;
                   1394:                        }
                   1395:                }
                   1396: /* inline expansion of symreloc() */
                   1397:                switch (cursym.n_type & 017) {
                   1398:                case N_TEXT:
                   1399:                case N_EXT+N_TEXT:
                   1400:                        cursym.n_value += ctrel;
                   1401:                        break;
                   1402:                case N_DATA:
                   1403:                case N_EXT+N_DATA:
                   1404:                        cursym.n_value += cdrel;
                   1405:                        break;
                   1406:                case N_BSS:
                   1407:                case N_EXT+N_BSS:
                   1408:                        cursym.n_value += cbrel;
                   1409:                        break;
                   1410:                case N_EXT+N_UNDF:
                   1411:                        break;
                   1412:                default:
                   1413:                        if (cursym.n_type&N_EXT)
                   1414:                                cursym.n_type = N_EXT+N_ABS;
                   1415:                }
                   1416: /* end inline expansion of symreloc() */
                   1417:                type = cursym.n_type;
                   1418:                if (yflag && cursym.n_un.n_name)
                   1419:                        for (i = 0; i < yflag; i++)
                   1420:                                /* fast check for 2d character! */
                   1421:                                if (ytab[i][1] == cursym.n_un.n_name[1] &&
                   1422:                                    !strcmp(ytab[i], cursym.n_un.n_name)) {
                   1423:                                        tracesym();
                   1424:                                        break;
                   1425:                                }
                   1426:                if ((type&N_EXT) == 0) {
                   1427:                        if (!sflag&&!xflag&&
                   1428:                            (!Xflag||type&N_STAB||cursym.n_un.n_name[0]!='L'))
                   1429:                                symwrite(&cursym, sout);
                   1430:                        continue;
                   1431:                }
                   1432:                if (funding)
                   1433:                        continue;
                   1434:                if ((sp = *lookup()) == 0)
                   1435:                        error(1, "internal error: symbol not found");
                   1436:                if (cursym.n_type == N_EXT+N_UNDF) {
                   1437:                        if (clocseg->lo_used == NSYMPR) {
                   1438:                                if (++clocseg == &locseg[NSEG])
                   1439:                                        error(1, "local symbol overflow");
                   1440:                                clocseg->lo_used = 0;
                   1441:                        }
                   1442:                        if (clocseg->lo_first == 0) {
                   1443:                                clocseg->lo_first = (struct local *)
                   1444:                                    malloc(NSYMPR * sizeof (struct local));
                   1445:                                if (clocseg->lo_first == 0)
                   1446:                                        error(1, "out of memory (clocseg)");
                   1447:                        }
                   1448:                        lp = &clocseg->lo_first[clocseg->lo_used++];
                   1449:                        lp->l_index = symno;
                   1450:                        lp->l_symbol = sp;
                   1451:                        lp->l_link = lochash[symno % LHSIZ];
                   1452:                        lochash[symno % LHSIZ] = lp;
                   1453:                        continue;
                   1454:                }
                   1455:                if (cursym.n_type & N_STAB)
                   1456:                        continue;
                   1457:                if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) {
                   1458:                        printf("%s: ", cursym.n_un.n_name);
                   1459:                        error(0, "multiply defined");
                   1460:                }
                   1461:        }
                   1462:        if (funding)
                   1463:                return;
                   1464:        dseek(&text, loc, filhdr.a_text);
                   1465:        dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
                   1466:        load2td(ctrel, torigin - textbase, tout, trout);
                   1467:        dseek(&text, loc+filhdr.a_text, filhdr.a_data);
                   1468:        dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize,
                   1469:            filhdr.a_drsize);
                   1470:        load2td(cdrel, dorigin - database, dout, drout);
                   1471:        while (filhdr.a_data & (sizeof(long)-1)) {
                   1472:                bputc(0, dout);
                   1473:                filhdr.a_data++;
                   1474:        }
                   1475:        torigin += filhdr.a_text;
                   1476:        dorigin += round(filhdr.a_data, sizeof (long));
                   1477:        borigin += round(filhdr.a_bss, sizeof (long));
                   1478:        free(curstr);
                   1479: }
                   1480: 
                   1481: struct tynames {
                   1482:        int     ty_value;
                   1483:        char    *ty_name;
                   1484: } tynames[] = {
                   1485:        N_UNDF, "undefined",
                   1486:        N_ABS,  "absolute",
                   1487:        N_TEXT, "text",
                   1488:        N_DATA, "data",
                   1489:        N_BSS,  "bss",
                   1490:        N_COMM, "common",
                   1491:        0,      0,
                   1492: };
                   1493: 
                   1494: tracesym()
                   1495: {
                   1496:        register struct tynames *tp;
                   1497: 
                   1498:        if (cursym.n_type & N_STAB)
                   1499:                return;
                   1500:        printf("%s", filname);
                   1501:        if (archdr.ar_name[0])
                   1502:                printf("(%s)", archdr.ar_name);
                   1503:        printf(": ");
                   1504:        if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) {
                   1505:                printf("definition of common %s size %d\n",
                   1506:                    cursym.n_un.n_name, cursym.n_value);
                   1507:                return;
                   1508:        }
                   1509:        for (tp = tynames; tp->ty_name; tp++)
                   1510:                if (tp->ty_value == (cursym.n_type&N_TYPE))
                   1511:                        break;
                   1512:        printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to");
                   1513:        if (cursym.n_type&N_EXT)
                   1514:                printf(" external");
                   1515:        if (tp->ty_name)
                   1516:                printf(" %s", tp->ty_name);
                   1517:        printf(" %s\n", cursym.n_un.n_name);
                   1518: }
                   1519: 
                   1520: /*
                   1521:  * This routine relocates the single text or data segment argument.
                   1522:  * Offsets from external symbols are resolved by adding the value
                   1523:  * of the external symbols.  Non-external reference are updated to account
                   1524:  * for the relative motion of the segments (ctrel, cdrel, ...).  If
                   1525:  * a relocation was pc-relative, then we update it to reflect the
                   1526:  * change in the positioning of the segments by adding the displacement
                   1527:  * of the referenced segment and subtracting the displacement of the
                   1528:  * current segment (creloc).
                   1529:  *
                   1530:  * If we are saving the relocation information, then we increase
                   1531:  * each relocation datum address by our base position in the new segment.
                   1532:  */
                   1533: load2td(creloc, position, b1, b2)
                   1534:        long creloc, offset;
                   1535:        struct biobuf *b1, *b2;
                   1536: {
                   1537:        register struct nlist *sp;
                   1538:        register struct local *lp;
                   1539:        long tw;
                   1540:        register struct relocation_info *rp, *rpend;
                   1541:        struct relocation_info *relp;
                   1542:        char *codep;
                   1543:        register char *cp;
                   1544:        int relsz, codesz;
                   1545: 
                   1546:        relsz = reloc.size;
                   1547:        relp = (struct relocation_info *)malloc(relsz);
                   1548:        codesz = text.size;
                   1549:        codep = (char *)malloc(codesz);
                   1550:        if (relp == 0 || codep == 0)
                   1551:                error(1, "out of memory (load2td)");
                   1552:        mget((char *)relp, relsz, &reloc);
                   1553:        rpend = &relp[relsz / sizeof (struct relocation_info)];
                   1554:        mget(codep, codesz, &text);
                   1555:        for (rp = relp; rp < rpend; rp++) {
                   1556:                cp = codep + rp->r_address;
                   1557:                /*
                   1558:                 * Pick up previous value at location to be relocated.
                   1559:                 */
                   1560:                switch (rp->r_length) {
                   1561: 
                   1562:                case 0:         /* byte */
                   1563:                        tw = *cp;
                   1564:                        break;
                   1565: 
                   1566:                case 1:         /* word */
                   1567:                        tw = *(short *)cp;
                   1568:                        break;
                   1569: 
                   1570:                case 2:         /* long */
                   1571:                        tw = *(long *)cp;
                   1572:                        break;
                   1573: 
                   1574:                default:
                   1575:                        error(1, "load2td botch: bad length");
                   1576:                }
                   1577:                /*
                   1578:                 * If relative to an external which is defined,
                   1579:                 * resolve to a simpler kind of reference in the
                   1580:                 * result file.  If the external is undefined, just
                   1581:                 * convert the symbol number to the number of the
                   1582:                 * symbol in the result file and leave it undefined.
                   1583:                 */
                   1584:                if (rp->r_extern) {
                   1585:                        /*
                   1586:                         * Search the hash table which maps local
                   1587:                         * symbol numbers to symbol tables entries
                   1588:                         * in the new a.out file.
                   1589:                         */
                   1590:                        lp = lochash[rp->r_symbolnum % LHSIZ];
                   1591:                        while (lp->l_index != rp->r_symbolnum) {
                   1592:                                lp = lp->l_link;
                   1593:                                if (lp == 0)
                   1594:                                        error(1, "local symbol botch");
                   1595:                        }
                   1596:                        sp = lp->l_symbol;
                   1597:                        if (sp->n_type == N_EXT+N_UNDF)
                   1598:                                rp->r_symbolnum = nsym+symx(sp);
                   1599:                        else {
                   1600:                                rp->r_symbolnum = sp->n_type & N_TYPE;
                   1601:                                tw += sp->n_value;
                   1602:                                rp->r_extern = 0;
                   1603:                        }
                   1604:                } else switch (rp->r_symbolnum & N_TYPE) {
                   1605:                /*
                   1606:                 * Relocation is relative to the loaded position
                   1607:                 * of another segment.  Update by the change in position
                   1608:                 * of that segment.
                   1609:                 */
                   1610:                case N_TEXT:
                   1611:                        tw += ctrel;
                   1612:                        break;
                   1613:                case N_DATA:
                   1614:                        tw += cdrel;
                   1615:                        break;
                   1616:                case N_BSS:
                   1617:                        tw += cbrel;
                   1618:                        break;
                   1619:                case N_ABS:
                   1620:                        break;
                   1621:                default:
                   1622:                        error(1, "relocation format botch (symbol type))");
                   1623:                }
                   1624:                /*
                   1625:                 * Relocation is pc relative, so decrease the relocation
                   1626:                 * by the amount the current segment is displaced.
                   1627:                 * (E.g if we are a relative reference to a text location
                   1628:                 * from data space, we added the increase in the text address
                   1629:                 * above, and subtract the increase in our (data) address
                   1630:                 * here, leaving the net change the relative change in the
                   1631:                 * positioning of our text and data segments.)
                   1632:                 */
                   1633:                if (rp->r_pcrel)
                   1634:                        tw -= creloc;
                   1635:                /*
                   1636:                 * Put the value back in the segment,
                   1637:                 * while checking for overflow.
                   1638:                 */
                   1639:                switch (rp->r_length) {
                   1640: 
                   1641:                case 0:         /* byte */
                   1642:                        if (tw < -128 || tw > 127)
                   1643:                                error(0, "byte displacement overflow at %s+%#x",
                   1644:                                        b1==tout?"text":"data", rp->r_address);
                   1645:                        *cp = tw;
                   1646:                        break;
                   1647:                case 1:         /* word */
                   1648:                        if (tw < -32768 || tw > 32767)
                   1649:                                error(0, "word displacement overflow at %s+%#x",
                   1650:                                        b1==tout?"text":"data", rp->r_address);
                   1651:                        *(short *)cp = tw;
                   1652:                        break;
                   1653:                case 2:         /* long */
                   1654:                        *(long *)cp = tw;
                   1655:                        break;
                   1656:                }
                   1657:                /*
                   1658:                 * If we are saving relocation information,
                   1659:                 * we must convert the address in the segment from
                   1660:                 * the old .o file into an address in the segment in
                   1661:                 * the new a.out, by adding the position of our
                   1662:                 * segment in the new larger segment.
                   1663:                 */
                   1664:                if (rflag)
                   1665:                        rp->r_address += position;
                   1666:        }
                   1667:        bwrite(codep, codesz, b1);
                   1668:        if (rflag)
                   1669:                bwrite(relp, relsz, b2);
                   1670:        cfree((char *)relp);
                   1671:        cfree(codep);
                   1672: }
                   1673: 
                   1674: finishout()
                   1675: {
                   1676:        register int i;
                   1677:        int nsymt;
                   1678:        int symsize;
                   1679: 
                   1680:        if (sflag==0) {
                   1681:                nsymt = symx(nextsym);
                   1682:                for (i = 0; i < nsymt; i++)
                   1683:                        symwrite(xsym(i), sout);
                   1684:                bwrite(&offset, sizeof offset, sout);
                   1685:        }
                   1686:        filname = aoutname;
                   1687:        archdr.ar_name[0] = '\0';
                   1688:        unlink(aoutname);
                   1689:        if (link(ofilename, aoutname) < 0)
                   1690:                error(1, "cannot move temp file %s to output", ofilename );
                   1691:        delarg = errlev;
                   1692:        delexit();
                   1693: }
                   1694: 
                   1695: mkfsym(s)
                   1696:        char *s;
                   1697: {
                   1698:        static struct nlist fsym;
                   1699: 
                   1700:        if (sflag || xflag)
                   1701:                return;
                   1702:        fsym.n_un.n_name = s;
                   1703:        fsym.n_type = N_TEXT;
                   1704:        fsym.n_value = torigin;
                   1705:        symwrite(&fsym, sout);
                   1706: }
                   1707: 
                   1708: getarhdr()
                   1709: {
                   1710:        register char *cp;
                   1711: 
                   1712:        mget((char *)&archdr, sizeof archdr, &text);
                   1713:        for (cp=archdr.ar_name; cp<&archdr.ar_name[sizeof(archdr.ar_name)];)
                   1714:                if (*cp++ == ' ') {
                   1715:                        cp[-1] = 0;
                   1716:                        return;
                   1717:                }
                   1718: }
                   1719: 
                   1720: mget(loc, n, sp)
                   1721:        register STREAM *sp;
                   1722:        register char *loc;
                   1723: {
                   1724:        register char *p;
                   1725:        register int take;
                   1726: 
                   1727: top:
                   1728:        if (n == 0)
                   1729:                return;
                   1730:        if (sp->size && sp->nibuf) {
                   1731:                p = sp->ptr;
                   1732:                take = sp->size;
                   1733:                if (take > sp->nibuf)
                   1734:                        take = sp->nibuf;
                   1735:                if (take > n)
                   1736:                        take = n;
                   1737:                n -= take;
                   1738:                sp->size -= take;
                   1739:                sp->nibuf -= take;
                   1740:                sp->pos += take;
                   1741:                do
                   1742:                        *loc++ = *p++;
                   1743:                while (--take > 0);
                   1744:                sp->ptr = p;
                   1745:                goto top;
                   1746:        }
                   1747:        if (n > BUFSIZ) {
                   1748:                take = n - n % BLKSIZE;
                   1749:                lseek(infil, (sp->bno+1)*BLKSIZE, 0);
                   1750:                if (take > sp->size || read(infil, loc, take) != take)
                   1751:                        error(1, "premature EOF");
                   1752:                loc += take;
                   1753:                n -= take;
                   1754:                sp->size -= take;
                   1755:                sp->pos += take;
                   1756:                dseek(sp, (sp->bno+1+take/BLKSIZE)*BLKSIZE, -1);
                   1757:                goto top;
                   1758:        }
                   1759:        *loc++ = get(sp);
                   1760:        --n;
                   1761:        goto top;
                   1762: }
                   1763: 
                   1764: symwrite(sp, bp)
                   1765:        struct nlist *sp;
                   1766:        struct biobuf *bp;
                   1767: {
                   1768:        register int len;
                   1769:        register char *str;
                   1770: 
                   1771:        str = sp->n_un.n_name;
                   1772:        if (str) {
                   1773:                sp->n_un.n_strx = offset;
                   1774:                len = strlen(str) + 1;
                   1775:                bwrite(str, len, strout);
                   1776:                offset += len;
                   1777:        }
                   1778:        bwrite(sp, sizeof (*sp), bp);
                   1779:        sp->n_un.n_name = str;
                   1780:        nsymwrite++;
                   1781: }
                   1782: 
                   1783: dseek(sp, loc, s)
                   1784:        register STREAM *sp;
                   1785:        long loc, s;
                   1786: {
                   1787:        register PAGE *p;
                   1788:        register b, o;
                   1789:        int n;
                   1790: 
                   1791:        b = loc>>BLKSHIFT;
                   1792:        o = loc&BLKMASK;
                   1793:        if (o&01)
                   1794:                error(1, "loader error; odd offset");
                   1795:        --sp->pno->nuser;
                   1796:        if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
                   1797:                if (p->nuser==0 || (p = &page[0])->nuser==0) {
                   1798:                        if (page[0].nuser==0 && page[1].nuser==0)
                   1799:                                if (page[0].bno < page[1].bno)
                   1800:                                        p = &page[0];
                   1801:                        p->bno = b;
                   1802:                        lseek(infil, loc & ~(long)BLKMASK, 0);
                   1803:                        if ((n = read(infil, p->buff, sizeof(p->buff))) < 0)
                   1804:                                n = 0;
                   1805:                        p->nibuf = n;
                   1806:        } else
                   1807:                error(1, "botch: no pages");
                   1808:        ++p->nuser;
                   1809:        sp->bno = b;
                   1810:        sp->pno = p;
                   1811:        if (s != -1) {sp->size = s; sp->pos = 0;}
                   1812:        sp->ptr = (char *)(p->buff + o);
                   1813:        if ((sp->nibuf = p->nibuf-o) <= 0)
                   1814:                sp->size = 0;
                   1815: }
                   1816: 
                   1817: char
                   1818: get(asp)
                   1819:        STREAM *asp;
                   1820: {
                   1821:        register STREAM *sp;
                   1822: 
                   1823:        sp = asp;
                   1824:        if ((sp->nibuf -= sizeof(char)) < 0) {
                   1825:                dseek(sp, ((long)(sp->bno+1)<<BLKSHIFT), (long)-1);
                   1826:                sp->nibuf -= sizeof(char);
                   1827:        }
                   1828:        if ((sp->size -= sizeof(char)) <= 0) {
                   1829:                if (sp->size < 0)
                   1830:                        error(1, "premature EOF");
                   1831:                ++fpage.nuser;
                   1832:                --sp->pno->nuser;
                   1833:                sp->pno = (PAGE *) &fpage;
                   1834:        }
                   1835:        sp->pos += sizeof(char);
                   1836:        return(*sp->ptr++);
                   1837: }
                   1838: 
                   1839: getfile(acp)
                   1840:        char *acp;
                   1841: {
                   1842:        register char *cp;
                   1843:        register int c;
                   1844:        char arcmag[SARMAG+1];
                   1845:        struct stat stb;
                   1846: 
                   1847:        cp = acp; 
                   1848:        infil = -1;
                   1849:        archdr.ar_name[0] = '\0';
                   1850:        filname = cp;
                   1851:        if (cp[0]=='-' && cp[1]=='l') {
                   1852:                char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx";
                   1853:                if (cp[2] == '\0')
                   1854:                        cp = "-la";
                   1855:                filname = "/usr/lib/libxxxxxxxxxxxxxxx";
                   1856:                for(c=0; cp[c+2]; c++) {
                   1857:                        filname[c+12] = cp[c+2];
                   1858:                        locfilname[c+18] = cp[c+2];
                   1859:                }
                   1860:                filname[c+12] = locfilname[c+18] = '.';
                   1861:                filname[c+13] = locfilname[c+19] = 'a';
                   1862:                filname[c+14] = locfilname[c+20] = '\0';
                   1863:                if ((infil = open(filname+4, 0)) >= 0) {
                   1864:                        filname += 4;
                   1865:                } else if ((infil = open(filname, 0)) < 0) {
                   1866:                        filname = locfilname;
                   1867:                }
                   1868:        }
                   1869:        if (infil == -1 && (infil = open(filname, 0)) < 0)
                   1870:                error(1, "cannot open");
                   1871:        page[0].bno = page[1].bno = -1;
                   1872:        page[0].nuser = page[1].nuser = 0;
                   1873:        text.pno = reloc.pno = (PAGE *) &fpage;
                   1874:        fpage.nuser = 2;
                   1875:        dseek(&text, 0L, SARMAG);
                   1876:        if (text.size <= 0)
                   1877:                error(1, "premature EOF");
                   1878:        mget((char *)arcmag, SARMAG, &text);
                   1879:        arcmag[SARMAG] = 0;
                   1880:        if (strcmp(arcmag, ARMAG))
                   1881:                return (0);
                   1882:        dseek(&text, SARMAG, sizeof archdr);
                   1883:        if (text.size <= 0)
                   1884:                return (1);
                   1885:        getarhdr();
                   1886:        if (strncmp(archdr.ar_name, "__.SYMDEF", sizeof(archdr.ar_name)) != 0)
                   1887:                return (1);
                   1888:        fstat(infil, &stb);
                   1889:        return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2);
                   1890: }
                   1891: 
                   1892: struct nlist **
                   1893: lookup()
                   1894: {
                   1895:        register int sh; 
                   1896:        register struct nlist **hp;
                   1897:        register char *cp, *cp1;
                   1898:        register struct symseg *gp;
                   1899:        register int i;
                   1900: 
                   1901:        sh = 0;
                   1902:        for (cp = cursym.n_un.n_name; *cp;)
                   1903:                sh = (sh<<1) + *cp++;
                   1904:        sh = (sh & 0x7fffffff) % HSIZE;
                   1905:        for (gp = symseg; gp < &symseg[NSEG]; gp++) {
                   1906:                if (gp->sy_first == 0) {
                   1907:                        gp->sy_first = (struct nlist *)
                   1908:                            calloc(NSYM, sizeof (struct nlist));
                   1909:                        gp->sy_hfirst = (struct nlist **)
                   1910:                            calloc(HSIZE, sizeof (struct nlist *));
                   1911:                        if (gp->sy_first == 0 || gp->sy_hfirst == 0)
                   1912:                                error(1, "ran out of space for symbol table");
                   1913:                        gp->sy_last = gp->sy_first + NSYM;
                   1914:                        gp->sy_hlast = gp->sy_hfirst + HSIZE;
                   1915:                }
                   1916:                if (gp > csymseg)
                   1917:                        csymseg = gp;
                   1918:                hp = gp->sy_hfirst + sh;
                   1919:                i = 1;
                   1920:                do {
                   1921:                        if (*hp == 0) {
                   1922:                                if (gp->sy_used == NSYM)
                   1923:                                        break;
                   1924:                                return (hp);
                   1925:                        }
                   1926:                        cp1 = (*hp)->n_un.n_name; 
                   1927:                        for (cp = cursym.n_un.n_name; *cp == *cp1++;)
                   1928:                                if (*cp++ == 0)
                   1929:                                        return (hp);
                   1930:                        hp += i;
                   1931:                        i += 2;
                   1932:                        if (hp >= gp->sy_hlast)
                   1933:                                hp -= HSIZE;
                   1934:                } while (i < HSIZE);
                   1935:                if (i > HSIZE)
                   1936:                        error(1, "hash table botch");
                   1937:        }
                   1938:        error(1, "symbol table overflow");
                   1939:        /*NOTREACHED*/
                   1940: }
                   1941: 
                   1942: symfree(saved)
                   1943:        struct nlist *saved;
                   1944: {
                   1945:        register struct symseg *gp;
                   1946:        register struct nlist *sp;
                   1947: 
                   1948:        for (gp = csymseg; gp >= symseg; gp--, csymseg--) {
                   1949:                sp = gp->sy_first + gp->sy_used;
                   1950:                if (sp == saved) {
                   1951:                        nextsym = sp;
                   1952:                        return;
                   1953:                }
                   1954:                for (sp--; sp >= gp->sy_first; sp--) {
                   1955:                        gp->sy_hfirst[sp->n_hash] = 0;
                   1956:                        gp->sy_used--;
                   1957:                        if (sp == saved) {
                   1958:                                nextsym = sp;
                   1959:                                return;
                   1960:                        }
                   1961:                }
                   1962:        }
                   1963:        if (saved == 0)
                   1964:                return;
                   1965:        error(1, "symfree botch");
                   1966: }
                   1967: 
                   1968: struct nlist **
                   1969: slookup(s)
                   1970:        char *s;
                   1971: {
                   1972: 
                   1973:        cursym.n_un.n_name = s;
                   1974:        cursym.n_type = N_EXT+N_UNDF;
                   1975:        cursym.n_value = 0;
                   1976:        return (lookup());
                   1977: }
                   1978: 
                   1979: enter(hp)
                   1980: register struct nlist **hp;
                   1981: {
                   1982:        register struct nlist *sp;
                   1983: 
                   1984:        if (*hp==0) {
                   1985:                if (hp < csymseg->sy_hfirst || hp >= csymseg->sy_hlast)
                   1986:                        error(1, "enter botch");
                   1987:                *hp = lastsym = sp = csymseg->sy_first + csymseg->sy_used;
                   1988:                csymseg->sy_used++;
                   1989:                sp->n_un.n_name = cursym.n_un.n_name;
                   1990:                sp->n_type = cursym.n_type;
                   1991:                sp->n_hash = hp - csymseg->sy_hfirst;
                   1992:                sp->n_value = cursym.n_value;
                   1993:                nextsym = lastsym + 1;
                   1994:                return(1);
                   1995:        } else {
                   1996:                lastsym = *hp;
                   1997:                return(0);
                   1998:        }
                   1999: }
                   2000: 
                   2001: symx(sp)
                   2002:        struct nlist *sp;
                   2003: {
                   2004:        register struct symseg *gp;
                   2005: 
                   2006:        if (sp == 0)
                   2007:                return (0);
                   2008:        for (gp = csymseg; gp >= symseg; gp--)
                   2009:                /* <= is sloppy so nextsym will always work */
                   2010:                if (sp >= gp->sy_first && sp <= gp->sy_last)
                   2011:                        return ((gp - symseg) * NSYM + sp - gp->sy_first);
                   2012:        error(1, "symx botch");
                   2013:        /*NOTREACHED*/
                   2014: }
                   2015: 
                   2016: symreloc()
                   2017: {
                   2018:        if (funding)
                   2019:                return;
                   2020:        switch (cursym.n_type & 017) {
                   2021: 
                   2022:        case N_TEXT:
                   2023:        case N_EXT+N_TEXT:
                   2024:                cursym.n_value += ctrel;
                   2025:                return;
                   2026: 
                   2027:        case N_DATA:
                   2028:        case N_EXT+N_DATA:
                   2029:                cursym.n_value += cdrel;
                   2030:                return;
                   2031: 
                   2032:        case N_BSS:
                   2033:        case N_EXT+N_BSS:
                   2034:                cursym.n_value += cbrel;
                   2035:                return;
                   2036: 
                   2037:        case N_EXT+N_UNDF:
                   2038:                return;
                   2039: 
                   2040:        default:
                   2041:                if (cursym.n_type&N_EXT)
                   2042:                        cursym.n_type = N_EXT+N_ABS;
                   2043:                return;
                   2044:        }
                   2045: }
                   2046: 
                   2047: /*VARARGS 2*/
                   2048: error(n, s, w, x, y , z)
                   2049: char *s;
                   2050: {
                   2051: 
                   2052:        if (errlev==0)
                   2053:                printf("ld:");
                   2054:        if (filname) {
                   2055:                printf("%s", filname);
                   2056:                if (n != -1 && archdr.ar_name[0])
                   2057:                        printf("(%s)", archdr.ar_name);
                   2058:                printf(": ");
                   2059:        }
                   2060:        printf( s, w, x, y, z);
                   2061:        printf("\n");
                   2062:        if (n == -1)
                   2063:                return;
                   2064:        if (n)
                   2065:                delexit();
                   2066:        errlev = 2;
                   2067: }
                   2068: 
                   2069: readhdr(loc)
                   2070: off_t loc;
                   2071: {
                   2072: 
                   2073:        dseek(&text, loc, (long)sizeof(filhdr));
                   2074:        mget((short *)&filhdr, sizeof(filhdr), &text);
                   2075:        if (N_BADMAG(filhdr)) {
                   2076:                if (filhdr.a_magic == OARMAG)
                   2077:                        error(1, "old archive");
                   2078:                error(1, "bad magic number");
                   2079:        }
                   2080: #ifdef sun3
                   2081:        if (filhdr.a_machtype == M_68020) {
                   2082:                use68020 = 1;
                   2083:        }
                   2084: #endif sun3
                   2085:        if (filhdr.a_text&01 || filhdr.a_data&01)
                   2086:                error(1, "text/data size odd");
                   2087:        if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) {
                   2088:                cdrel = -round(filhdr.a_text, segsize());
                   2089:                cbrel = cdrel - filhdr.a_data;
                   2090:        } else if (filhdr.a_magic == OMAGIC) {
                   2091:                cdrel = -filhdr.a_text;
                   2092:                cbrel = cdrel - filhdr.a_data;
                   2093:        } else
                   2094:                error(1, "bad format");
                   2095: }
                   2096: 
                   2097: round(v, r)
                   2098:        int v;
                   2099:        u_long r;
                   2100: {
                   2101: 
                   2102:        r--;
                   2103:        v += r;
                   2104:        v &= ~(long)r;
                   2105:        return(v);
                   2106: }
                   2107: 
                   2108: #define        NSAVETAB        8192
                   2109: char   *savetab;
                   2110: int    saveleft;
                   2111: 
                   2112: char *
                   2113: savestr(cp)
                   2114:        register char *cp;
                   2115: {
                   2116:        register int len;
                   2117: 
                   2118:        len = strlen(cp) + 1;
                   2119:        if (len > saveleft) {
                   2120:                saveleft = NSAVETAB;
                   2121:                if (len > saveleft)
                   2122:                        saveleft = len;
                   2123:                savetab = (char *)malloc(saveleft);
                   2124:                if (savetab == 0)
                   2125:                        error(1, "ran out of memory (savestr)");
                   2126:        }
                   2127:        strncpy(savetab, cp, len);
                   2128:        cp = savetab;
                   2129:        savetab += len;
                   2130:        saveleft -= len;
                   2131:        return (cp);
                   2132: }
                   2133: 
                   2134: bopen(bp, off)
                   2135:        struct biobuf *bp;
                   2136: {
                   2137: 
                   2138:        bp->b_ptr = bp->b_buf;
                   2139:        bp->b_nleft = BUFSIZ - off % BUFSIZ;
                   2140:        bp->b_off = off;
                   2141:        bp->b_link = biobufs;
                   2142:        biobufs = bp;
                   2143: }
                   2144: 
                   2145: int    bwrerror;
                   2146: 
                   2147: bwrite(p, cnt, bp)
                   2148:        register char *p;
                   2149:        register int cnt;
                   2150:        register struct biobuf *bp;
                   2151: {
                   2152:        register int put;
                   2153:        register char *to;
                   2154: 
                   2155: top:
                   2156:        if (cnt == 0)
                   2157:                return;
                   2158:        if (bp->b_nleft) {
                   2159:                put = bp->b_nleft;
                   2160:                if (put > cnt)
                   2161:                        put = cnt;
                   2162:                bp->b_nleft -= put;
                   2163:                to = bp->b_ptr;
                   2164:                memcpy(to, p, put);
                   2165:                bp->b_ptr += put;
                   2166:                p += put;
                   2167:                cnt -= put;
                   2168:                goto top;
                   2169:        }
                   2170:        if (cnt >= BUFSIZ) {
                   2171:                if (bp->b_ptr != bp->b_buf)
                   2172:                        bflush1(bp);
                   2173:                put = cnt - cnt % BUFSIZ;
                   2174:                if (boffset != bp->b_off)
                   2175:                        lseek(biofd, bp->b_off, 0);
                   2176:                if (write(biofd, p, put) != put) {
                   2177:                        bwrerror = 1;
                   2178:                        error(1, "output write error");
                   2179:                }
                   2180:                bp->b_off += put;
                   2181:                boffset = bp->b_off;
                   2182:                p += put;
                   2183:                cnt -= put;
                   2184:                goto top;
                   2185:        }
                   2186:        bflush1(bp);
                   2187:        goto top;
                   2188: }
                   2189: 
                   2190: bflush()
                   2191: {
                   2192:        register struct biobuf *bp;
                   2193: 
                   2194:        if (bwrerror)
                   2195:                return;
                   2196:        for (bp = biobufs; bp; bp = bp->b_link)
                   2197:                bflush1(bp);
                   2198: }
                   2199: 
                   2200: bflush1(bp)
                   2201:        register struct biobuf *bp;
                   2202: {
                   2203:        register int cnt = bp->b_ptr - bp->b_buf;
                   2204: 
                   2205:        if (cnt == 0)
                   2206:                return;
                   2207:        if (boffset != bp->b_off)
                   2208:                lseek(biofd, bp->b_off, 0);
                   2209:        if (write(biofd, bp->b_buf, cnt) != cnt) {
                   2210:                bwrerror = 1;
                   2211:                error(1, "output write error");
                   2212:        }
                   2213:        bp->b_off += cnt;
                   2214:        boffset = bp->b_off;
                   2215:        bp->b_ptr = bp->b_buf;
                   2216:        bp->b_nleft = BUFSIZ;
                   2217: }
                   2218: 
                   2219: bflushc(bp, c)
                   2220:        register struct biobuf *bp;
                   2221: {
                   2222: 
                   2223:        bflush1(bp);
                   2224:        bputc(c, bp);
                   2225: }

unix.superglobalmegacorp.com

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