Annotation of researchv9/cmd/sun/ld/ld.c, revision 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.