# 2.11BSD#431 - /usr/src/bin/ld/ld.c

##### Functions

    add               X
    adrof             X
    copy              X
    delexit           X
    dseek             X
    endload           X
    enter             X
    error             X
    finishout         X
    get               X
    get_arobj         X
    getfile           X
    inistr            X
    ldrand            X
    ldrsym            X
    libopen           X
    load1             X
    load1arg          X
    load2             X
    load2arg          X
    load2td           X
    lookloc           X
    lookup            X
    main              X
    mget              X
    mgets             X
    middle            X
    mkfsym            X
    readhdr           X
    rnd8k             X
    roundov           X
    setupout          X
    skip              X
    slookup           X
    step              X
    sym2va            X
    tcreat            X

##### Variables

    Mflag             X
    Oflag             X
    Sflag             X
    Vspace            X
    Xflag             X
    arflag            X
    borigin           X
    bsize             X
    cbrel             X
    cdrel             X
    ctrel             X
    curov             X
    cursym            X
    delarg            X
    dflag             X
    dirs              X
    dorigin           X
    dsize             X
    errlev            X
    filhdr            X
    filname           X
    hshtab            X
    iflag             X
    infil             X
    inov              X
    lastsym           X
    local             X
    ndir              X
    nflag             X
    nsym              X
    numov             X
    ofilename         X
    ofilfnd           X
    ovbase            X
    ovhndlr           X
    p_etext           X
    quiet             X
    rflag             X
    rstrtab           X
    sflag             X
    ssize             X
    symhash           X
    symindex          X
    tfname            X
    torgwas           X
    torigin           X
    trace             X
    tsize             X
    tsizwas           X
    verbose           X
    xflag             X

##### Macros

    AR_ATOI           X
    Cptr              X
    DECIMAL           X
    HNDLR_NUM         X
    Iptr              X
    K56               X
    K64               X
    NDEFDIRS          X
    NDIRS             X
    NNAMESIZE         X
    NROUT             X
    NSYM              X
    NSYMPR            X
    NUM_IO_PLACES     X
    NUM_VM_PAGES      X
    N_COMM            X
    OCTAL             X
    RABS              X
    RBSS              X
    RDATA             X
    RELFLG            X
    RELOC             X
    REXT              X
    RTEXT             X
    STRINGS           X
    STRINGS2          X
    SYMBOLS           X
    SYMSPERSEG        X
    SYMTAB            X
    TABSZ             X
    TEXT              X
    THUNKSIZ          X

##### struct's

    local             X
    xsymbol           X

##### typedef's

    HDR               X

       1: #if defined(DOSCCS) && !defined(lint)
       2: static char *sccsid = "@(#)ld.c	4.6 1998/01/19";
       3: #endif
       4:
       5: /*
       6:  * 4.6 1998/01/19 - Tim Shoppa (shoppa@triumf.ca)
       7:  *      Minor bug fix: when tsize was being incremented by THUNKSZ,
       8:  *      no check was being made for 16-bit overflow.  Fix was to
       9:  *      call add().  Same was done for the round up to the nearest
      10:  *      0100 on tsize.  Modify add()'s error reporting to reduce memory
      11:  *	usage - sms.
      12:  *
      13:  * 4.5 1997/10/31 - sms
      14:  *	Minor cleanup.  Use unistd.h and stdlib.h instead of local definitions.
      15:  *	Correct comment about number of VM pages.
      16:  *
      17:  * 4.4 1995/05/08 - sms
      18:  *	Add -q to turn off undefined symbol reporting.  Used when building
      19:  *	networking kernels and many undefineds are expected but look worrisome.
      20:  *	Add -v to enable the VM statistics printout (now optional).
      21:  *
      22:  * 4.3 1/14/94 - sms
      23:  *	Make the number of VM segments a compile time option in the Makefile.
      24:  * 4.2 1/2/94 - sms
      25:  *	Fixed a couple serious bugs, one dealing with overlaid programs - the
      26:  *	overlay header wasn't being written out, the second was a typographical
      27:  *	error causing the relocation information to be wrong.
      28:  *
      29:  * 4.1 11/27/93 -sms
      30:  *	Success at reading new style object files and libraries but the
      31:  *	speed was abysmal.  Logic added to attempt to hold string tables
      32:  *	in memory when possible (less than 8kb) and to use a larger buffer
      33:  *	when reading strings.  Also, added a fifth i/o stream area for use
      34:  *	by the library scanning routine 'ldrand' - this prevents the 'thrashing'
      35:  *	between 'load1' and 'ldrand' (each of these was undoing the other's
      36:  *	seek for a string).
      37:  *
      38:  * 4.0 11/1/93 - sms
      39:  *	Previous versions not released.  With 'ar' and 'ranlib' ported it
      40:  *	is now 'ld's turn to be modified to support the new object file
      41:  *	format.  Major changes (and unfortunately another slip in speed).
      42:  *
      43:  * 3.0 9/15/93 - sms
      44:  *	Implement a VM tmp file for the symbol table.
      45:  *
      46:  * 2.x 9/3/93 - sms@wlv.iipo.gtegsc.com
      47:  *	Couple of major changes made in preparation for supporting long
      48:  *	symbol names.  'ld' was approximately 1kb away from not running
      49:  *	at all (due to data+bss exceeding 56kb).  The first change
      50:  *	made 'syshash' a bitmap saving 3.75kb.  The next change involved
      51:  *	modifying 'ldrand' so that the entire table of contents from a
      52:  *	library did not have to fit in memory at once - this saved about
      53:  *	8kb.  The last major change was a rewrite of the input subsystem
      54:  *	making it faster and simpler.
      55: */
      56:
      57: #include <sys/param.h>
      58: #include <sys/dir.h>
      59: #include <stdio.h>
      60: #include <signal.h>
      61: #include <sys/stat.h>
      62: #include <sys/file.h>
      63: #include <a.out.h>
      64: #include <ar.h>
      65: #include <ranlib.h>
      66: #include <vmf.h>
      67: #include <unistd.h>
      68: #include <stdlib.h>
      69: #include "archive.h"
      70:
      71: /*
      72:  *	Layout of standard part of a.out file header:
      73:  *		u_int	a_magic;	magic number
      74:  *		u_int	a_text;		text size	)
      75:  *		u_int	a_data;		data size	) in bytes but even
      76:  *		u_int	a_bss;		bss size	)
      77:  *		u_int	a_syms;		symbol table size
      78:  *		u_int	a_entry;	entry point
      79:  *		u_int	a_unused;	(unused)
      80:  *		u_int	a_flag		bit 0 set if no relocation
      81:  *
      82:  *	Layout of overlaid part of a.out file header:
      83:  *		int	max_ovl;	maximum overlay size
      84:  *		u_int	ov_siz[NOVL];	overlay sizes
      85:  *
      86:  *	Non-overlaid offsets:
      87:  *		header:		0
      88:  *		text:		16
      89:  *		data:		16 + a_text
      90:  *		relocation:	16 + a_text + a_data
      91:  *
      92:  *		If relocation info stripped:
      93:  *			symbol table: 16 + a_text + a_data
      94:  *			string table: 16 + a_text + a_data + a_syms
      95:  *		else
      96:  *			symbol table: 16 + 2 * (a_text + a_data)
      97:  *			string table: 16 + 2 * (a_text + a_data) + a_syms
      98:  *
      99:  *	Overlaid offsets:
     100:  *		header:		0
     101:  *		overlay header:	16
     102:  *		text:		16 + 2 + 2*NOVL = 16 + 2 + 2*15 = 48
     103:  *		data:		48 + a_text + SUM(ov_siz)
     104:  *		relocation:	48 + a_text + SUM(ov_siz) + a_data
     105:  *
     106:  *		If relocation info stripped:
     107:  *			symbol table: 48 + a_text + SUM(ov_siz) + a_data
     108:  *			string table: symbol_table + a_syms
     109:  *		else
     110:  *		       symbol table: 48 + 2 * (a_text + SUM(ov_siz) + a_data)
     111:  *		       string table: symbol_table + a_syms
     112:  *
     113:  *		where SUM(ov_siz) is the sum of the overlays.
     114:  */
     115:
     116: /*
     117:  * Do not set the following too high (normally set in the Makefile) or
     118:  * 'ld' will not be able to allocate room (currently 8kb) for string
     119:  * tables and performance will suffer badly.  It is possible that this
     120:  * could be raised a bit higher but 20 gives 'adequate' performance on
     121:  * all but the largest ('tcsh' for example) programs, and even there it's
     122:  * not _too_ bad.
     123: */
     124: #ifndef NUM_VM_PAGES
     125: #define NUM_VM_PAGES 20
     126: #endif
     127: #define NNAMESIZE 32        /* Maximum symbol string length */
     128: #define SYMSPERSEG (BYTESPERSEG / sizeof (SYMBOL))
     129:
     130: #define NSYM    2000        /* 1103 originally */
     131: #define NROUT   350     /* 256 originally */
     132: #define NSYMPR  800     /* 1000 originally */
     133:
     134: #define N_COMM  05  /* internal use only; other values in a.out.h */
     135:
     136: #define RABS    00
     137: #define RTEXT   02
     138: #define RDATA   04
     139: #define RBSS    06
     140: #define REXT    010
     141:
     142: #define RELFLG  01
     143:
     144: #define THUNKSIZ    8
     145:
     146: /*
     147:  * one entry for each archive member referenced;
     148:  * set in first pass; needs restoring for overlays
     149:  */
     150: typedef struct {
     151:     long    loc;
     152:     } LIBLIST;
     153:
     154:     LIBLIST liblist[NROUT];
     155:     LIBLIST *libp = liblist;
     156:
     157:     typedef struct
     158:         {
     159:         union   {
     160:             int *iptr;
     161:             char    *cptr;
     162:             } ptr;
     163:         int bno;
     164:         int nibuf;
     165:         int nsize;
     166:         int nread;
     167:         int bsize;      /* MUST be a power of 2 */
     168:         int *buff;
     169:         } STREAM;
     170: #define Iptr    ptr.iptr
     171: #define Cptr    ptr.cptr
     172:
     173: #define TEXT        0
     174: #define RELOC       1
     175: #define SYMBOLS     2
     176: #define STRINGS     3
     177: #define STRINGS2    4
     178: #define NUM_IO_PLACES   5
     179:
     180:     STREAM  Input[NUM_IO_PLACES];
     181:
     182: /*
     183:  * Header from the a.out and the archive it is from (if any).
     184:  */
     185:     struct  xexec   filhdr;
     186:     CHDR    chdr;
     187:
     188: /* symbol management */
     189: typedef struct {
     190:     char    n_name[NNAMESIZE];
     191:     char    n_type;
     192:     char    n_ovly;
     193:     u_int   n_value;
     194:     u_int   sovalue;
     195:     } SYMBOL;
     196:
     197: #define SYMTAB  ((VADDR)0)  /* virtual base address of symbol table */
     198:     u_short symhash[(NSYM+15)/16];  /* bitmap of hash table entries */
     199:     short   lastsym;        /* index # of last symbol entered */
     200:     short   hshtab[NSYM+2];     /* hash table for symbols */
     201:     short   p_etext = -1, p_edata = -1, p_end = -1, entrypt = -1;
     202:
     203: struct  xsymbol {
     204:     char    n_name[NNAMESIZE];
     205:     char    n_type;
     206:     char    n_ovly;
     207:     u_int   n_value;
     208:     };
     209:
     210:     struct xsymbol  cursym;     /* current symbol */
     211:     int nsym;           /* pass2: number of local symbols */
     212:
     213: struct local {
     214:     short locindex;     /* index to symbol in file */
     215:     short locsymbol;    /* ptr to symbol table */
     216:     };
     217:
     218:     struct local    local[NSYMPR];
     219:     short   symindex;       /* next available symbol table entry */
     220:
     221: /*
     222:  * Options.
     223:  */
     224: int quiet;      /* -q, suppress undefined error message */
     225: int trace;
     226: int verbose;    /* -v, emit VM statistics */
     227: int xflag;      /* discard local symbols */
     228: int Xflag;      /* discard locals starting with 'L' */
     229: int Sflag;      /* discard all except locals and globals*/
     230: int rflag;      /* preserve relocation bits, don't define common */
     231: int arflag;     /* original copy of rflag */
     232: int sflag;      /* discard all symbols */
     233: int Mflag;      /* print rudimentary load map */
     234: int nflag;      /* pure procedure */
     235: int Oflag;      /* set magic # to 0405 (overlay) */
     236: int dflag;      /* define common even with rflag */
     237: int iflag;      /* I/D space separated */
     238:
     239: /*
     240:  * These are the cumulative sizes, set in pass1, which
     241:  * appear in the a.out header when the loader is finished.
     242:  */
     243:     u_int   tsize, dsize, bsize;
     244:     long    ssize, rnd8k();
     245:
     246: /*
     247:  * Symbol relocation:
     248:  */
     249:     u_int   ctrel, cdrel, cbrel;
     250:
     251: /*
     252:  * The base addresses for the loaded text, data and bass from the
     253:  * current module during pass2 are given by torigin, dorigin and borigin.
     254:  */
     255:     u_int   torigin, dorigin, borigin;
     256:
     257: /*
     258:  * Errlev is nonzero when errors have occured.
     259:  * Delarg is an implicit argument to the routine delexit
     260:  * which is called on error.  We do ``delarg = errlev'' before normal
     261:  * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the
     262:  * result file executable.
     263:  */
     264:     int errlev, delarg  = 4;
     265:
     266:     int ofilfnd;    /* -o given; otherwise move l.out to a.out */
     267:     char    *ofilename = "l.out";
     268:     int infil;          /* current input file descriptor */
     269:     char    *filname;       /* and its name */
     270:     char    tfname[] = "/tmp/ldaXXXXX";
     271:
     272:     FILE    *toutb, *doutb, *troutb, *droutb, *soutb, *voutb;
     273:
     274:     u_int   torgwas;        /* Saves torigin while doing overlays */
     275:     u_int   tsizwas;        /* Saves tsize while doing overlays */
     276:     int numov;          /* Total number of overlays */
     277:     int curov;          /* Overlay being worked on just now */
     278:     int inov;           /* 1 if working on an overlay */
     279:
     280: /* Kernel overlays have a special subroutine to do the switch */
     281:
     282: struct  xsymbol ovhndlr =
     283:     { "ovhndlr1", N_EXT+N_UNDF, 0, 0 };
     284: #define HNDLR_NUM 7     /* position of ov number in ovhndlr.n_name[] */
     285: u_int   ovbase;         /* The base address of the overlays */
     286:
     287: #define NDIRS   25
     288: #define NDEFDIRS 3      /* number of default directories in dirs[] */
     289:     char    *dirs[NDIRS];       /* directories for library search */
     290:     int ndir;           /* number of directories */
     291:
     292:     struct  vspace  Vspace; /* The virtual address space for symbols */
     293:
     294:     short   *lookup(), *slookup(), *lookloc();
     295:     char    *rstrtab;   /* ranlib string table pointer */
     296:     u_int   add();
     297:     int delexit();
     298:     VADDR   sym2va();
     299:     off_t   skip();
     300:
     301: main(argc, argv)
     302: char **argv;
     303: {
     304:     register int c, i;
     305:     int num;
     306:     register char *ap, **p;
     307:     char save;
     308:
     309: /*
     310:  * Initialize the hash table, indicating that all entries are unused.
     311:  * -1 is used as a "no symbol" flag.
     312: */
     313:     memset(hshtab, -1, sizeof(hshtab));
     314:
     315: /*
     316:  * Initialize the first three input buffers.  The remaining two are
     317:  * left for later because it may be possible to hold the string table
     318:  * in memory and the input buffer won't be needed.
     319: */
     320:     Input[TEXT].buff = (int *)malloc(512);
     321:     Input[TEXT].bsize = 512;
     322:     Input[RELOC].buff = (int *)malloc(512);
     323:     Input[RELOC].bsize = 512;
     324:     Input[SYMBOLS].buff = (int *)malloc(512);
     325:     Input[SYMBOLS].bsize = 512;
     326:
     327:     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
     328:         signal(SIGINT, delexit);
     329:         signal(SIGTERM, delexit);
     330:     }
     331:     if (argc == 1)
     332:         exit(4);
     333: /*
     334:  * Initialize the "VM" system with NUM_VM_PAGES memory segments (memory
     335:  * resident pages).  Then "open the address space" - this creates the paging
     336:  * (tmp) file.
     337: */
     338:     if  (vminit(NUM_VM_PAGES) < 0)
     339:         error(1, "vminit failed");
     340:     if  (vmopen(&Vspace, (char *)NULL) < 0)
     341:         error(1, "vmopen failed");
     342:
     343:     /*
     344: 	 * Pull out search directories.
     345: 	 */
     346:     for (c = 1; c < argc; c++) {
     347:         ap = argv[c];
     348:         if (ap[0] == '-' && ap[1] == 'L') {
     349:             if (ap[2] == 0)
     350:                 error(1, "-L: pathname missing");
     351:             if (ndir >= NDIRS - NDEFDIRS)
     352:                 error(1, "-L: too many directories");
     353:             dirs[ndir++] = &ap[2];
     354:         }
     355:     }
     356:     /* add default search directories */
     357:     dirs[ndir++] = "/lib";
     358:     dirs[ndir++] = "/usr/lib";
     359:     dirs[ndir++] = "/usr/local/lib";
     360:
     361:     p = argv+1;
     362:     /*
     363: 	 * Scan files once to find where symbols are defined.
     364: 	 */
     365:     for (c=1; c<argc; c++) {
     366:         if (trace)
     367:             printf("%s:\n", *p);
     368:         filname = 0;
     369:         ap = *p++;
     370:         if (*ap != '-') {
     371:             load1arg(ap, 1);
     372:             continue;
     373:         }
     374:         for (i=1; ap[i]; i++) switch (ap[i]) {
     375:
     376:         case 'o':
     377:             if (++c >= argc)
     378:                 error(1, "-o where?");
     379:             ofilename = *p++;
     380:             ofilfnd++;
     381:             continue;
     382:         case 'u':
     383:         case 'e':
     384:             if (++c >= argc)
     385:                 error(1, "-u or -c: arg missing");
     386:             enter(slookup(*p++));
     387:             if (ap[i]=='e')
     388:                 entrypt = lastsym;
     389:             continue;
     390:         case 'D':
     391:             if (++c >= argc)
     392:                 error(1, "-D: arg missing");
     393:             num = atoi(*p++);
     394:             if (dsize>num)
     395:                 error(1, "-D: too small");
     396:             dsize = num;
     397:             continue;
     398:         case 'l':
     399:             save = ap[--i];
     400:             ap[i]='-';
     401:             load1arg(&ap[i], -1);
     402:             ap[i]=save;
     403:             goto next;
     404:         case 'M':
     405:             Mflag++;
     406:             continue;
     407:         case 'x':
     408:             xflag++;
     409:             continue;
     410:         case 'X':
     411:             Xflag++;
     412:             continue;
     413:         case 'S':
     414:             Sflag++;
     415:             continue;
     416:         case 'r':
     417:             rflag++;
     418:             arflag++;
     419:             continue;
     420:         case 's':
     421:             sflag++;
     422:             xflag++;
     423:             continue;
     424:         case 'n':
     425:             nflag++;
     426:             continue;
     427:         case 'd':
     428:             dflag++;
     429:             continue;
     430:         case 'i':
     431:         case 'z':
     432:             iflag++;
     433:             continue;
     434:         case 't':
     435:             trace++;
     436:             continue;
     437:         case 'q':
     438:             quiet++;
     439:             continue;
     440:         case 'v':
     441:             verbose++;
     442:             continue;
     443:         case 'L':
     444:             goto next;
     445:         case 'O':
     446:             Oflag++;
     447:             continue;
     448:         case 'Y':
     449:             if (inov == 0)
     450:                 error(1, "-Y: Not in overlay");
     451:             filhdr.o.ov_siz[curov - 1] = tsize;
     452:             if (trace)
     453:                 printf("overlay %d size %d\n", curov,
     454:                     filhdr.o.ov_siz[curov - 1]);
     455:             curov = inov = 0;
     456:             tsize = tsizwas;
     457:             continue;
     458:         case 'Z':
     459:             if (!inov) {
     460:                 tsizwas = tsize;
     461:                 if (numov == 0) {
     462:                     cursym = ovhndlr;
     463:                     enter(lookup());
     464:                 }
     465:             }
     466:             else {
     467:                 filhdr.o.ov_siz[curov - 1] = tsize;
     468:                 if (trace)
     469:                     printf("overlay %d size %d\n", curov,
     470:                         filhdr.o.ov_siz[curov - 1]);
     471:             }
     472:             tsize = 0;
     473:             inov = 1;
     474:             numov++;
     475:             if (numov > NOVL) {
     476:                 printf("ld:too many overlays, max is %d\n",NOVL);
     477:                 error(1, (char *)NULL);
     478:             }
     479:             curov++;
     480:             continue;
     481:         case 'y':
     482:         case 'A':
     483:         case 'H':
     484:         case 'N':
     485:         case 'T':
     486:         default:
     487:             printf("ld:bad flag %c\n",ap[i]);
     488:             error(1, (char *)NULL);
     489:         }
     490: next:
     491:         ;
     492:     }
     493:     endload(argc, argv);
     494:     exit(0);
     495: }
     496:
     497: delexit()
     498:     {
     499:
     500:     unlink("l.out");
     501:     if (delarg==0)
     502:         chmod(ofilename, 0777 & ~umask(0));
     503:     if (verbose)
     504:         printf("ld: nswaps: %ld, nmapsegs: %ld sbrk(0): %u\n", nswaps,
     505:             nmapsegs, sbrk(0));
     506:     exit(delarg);
     507:     }
     508:
     509: endload(argc, argv)
     510:     int argc;
     511:     char **argv;
     512: {
     513:     register int c, i;
     514:     int dnum;
     515:     register char *ap, **p;
     516:
     517:     if (numov)
     518:         rflag = 0;
     519:     filname = 0;
     520:     middle();
     521:     setupout();
     522:     p = argv+1;
     523:     libp = liblist;
     524:     for (c=1; c<argc; c++) {
     525:         ap = *p++;
     526:         if (trace)
     527:             printf("%s:\n", ap);
     528:         if (*ap != '-') {
     529:             load2arg(ap, 1);
     530:             continue;
     531:         }
     532:         for (i=1; ap[i]; i++) switch (ap[i]) {
     533:
     534:         case 'D':
     535:             for (dnum = atoi(*p);dorigin < dnum; dorigin += 2) {
     536:                 putw(0, doutb);
     537:                 if (rflag)
     538:                     putw(0, droutb);
     539:             }
     540:             /* fall into ... */
     541:         case 'u':
     542:         case 'e':
     543:         case 'o':
     544:             ++c;
     545:             ++p;
     546:             /* fall into ... */
     547:         default:
     548:             continue;
     549:         case 'L':
     550:             goto next;
     551:         case 'l':
     552:             ap[--i]='-';
     553:             load2arg(&ap[i], -1);
     554:             goto next;
     555:         case 'Y':
     556:             roundov();
     557:             inov = 0;
     558:             if (trace)
     559:                 printf("end overlay generation\n");
     560:             torigin = torgwas;
     561:             continue;
     562:         case 'Z':
     563:             if (inov == 0)
     564:                 torgwas = torigin;
     565:             else
     566:                 roundov();
     567:             torigin = ovbase;
     568:             inov = 1;
     569:             curov++;
     570:             continue;
     571:         }
     572: next:
     573:         ;
     574:     }
     575:     finishout();
     576: }
     577:
     578: /*
     579:  * Compute a symbol's virtual address from its index number.  The code is
     580:  * a bit ugly (and made a routine rather than a macro) because the page
     581:  * size does not divide evenly by the size of a symbol.
     582: */
     583:
     584: VADDR
     585: sym2va(x)
     586:     u_short x;
     587:     {
     588:     register u_short i, j;
     589:
     590:     i = (x % SYMSPERSEG) * sizeof (SYMBOL);
     591:     j = x / SYMSPERSEG;
     592:     return(SYMTAB+ i + ((long)j << LOG2BPS));
     593:     }
     594:
     595: /*
     596:  * Scan file to find defined symbols.
     597:  */
     598: load1arg(cp, flag)
     599:     register char *cp;
     600:     int flag;
     601:     {
     602:     off_t nloc;
     603:     int kind, tnum;
     604:     long    ltnum, strsize;
     605:
     606:     kind = getfile(cp, flag, 1);
     607:     if (Mflag)
     608:         printf("%s\n", filname);
     609:     switch (kind) {
     610:
     611:     /*
     612: 	 * Plain file.
     613: 	 */
     614:     case 0:
     615:         load1(0, 0L);
     616:         break;
     617:
     618:     /*
     619: 	 * Archive without table of contents.
     620: 	 * (Slowly) process each member.
     621: 	 */
     622:     case 1:
     623:         error(-1,
     624: "warning: archive has no table of contents; add one using ranlib(1)");
     625:         nloc = SARMAG;
     626:         while (step(nloc))
     627:             nloc += skip();
     628:         break;
     629:
     630:     /*
     631: 	 * Archive with table of contents.
     632: 	 * Read the table of contents and its associated string table.
     633: 	 * Pass through the library resolving symbols until nothing changes
     634: 	 * for an entire pass (i.e. you can get away with backward references
     635: 	 * when there is a table of contents!)
     636: 	 */
     637:     case 2:
     638:         nloc = SARMAG + sizeof (struct ar_hdr) + chdr.lname;
     639:         lseek(infil, nloc, L_SET);
     640: /*
     641:  * Read the size of the ranlib structures (a long).
     642: */
     643:         read(infil, &ltnum, sizeof (ltnum));
     644: /*
     645:  * calculate string table position.  Add in the ranlib size (4 bytes),
     646:  * the size of the ranlib structures (ltnum) from above.
     647: */
     648:         nloc += (sizeof (ltnum) + ltnum);
     649:         tnum = ltnum / sizeof (struct ranlib);
     650:
     651:         rstrtab = NULL;
     652:         lseek(infil, nloc, L_SET);
     653:         read(infil, &strsize, sizeof (long));
     654:         if  (strsize <= 8192L)
     655:             {
     656:             rstrtab = (char *)malloc((int)strsize);
     657:             if  (rstrtab)
     658:                 read(infil, rstrtab, (int)strsize);
     659:             }
     660:         if  (!rstrtab)
     661:             inistr(STRINGS2);
     662:
     663:         while (ldrand(tnum, nloc))
     664:             ;
     665:         libp->loc = -1;
     666:         libp++;
     667:
     668:         if  (rstrtab)
     669:             free(rstrtab);
     670:         if  (Input[STRINGS2].buff)
     671:             {
     672:             free(Input[STRINGS2].buff);
     673:             Input[STRINGS2].buff = NULL;
     674:             }
     675:         break;
     676:
     677:     /*
     678: 	 * Table of contents is out of date, so search
     679: 	 * as a normal library (but skip the __.SYMDEF file).
     680: 	 */
     681:     case 3:
     682:         error(-1,
     683: "warning: table of contents for archive is out of date; rerun ranlib(1)");
     684:         nloc = SARMAG;
     685:         do
     686:             nloc += skip();
     687:         while (step(nloc));
     688:         break;
     689:     case -1:
     690:         return;
     691:     }
     692:     close(infil);
     693: }
     694:
     695: /*
     696:  * Advance to the next archive member, which
     697:  * is at offset nloc in the archive.  If the member
     698:  * is useful, record its location in the liblist structure
     699:  * for use in pass2.  Mark the end of the archive in libilst with a -1.
     700:  */
     701: step(nloc)
     702:     off_t nloc;
     703:     {
     704:
     705:     lseek(infil, nloc, L_SET);
     706:     if  (get_arobj(infil) <= 0)
     707:         {
     708:         libp->loc = -1;
     709:         libp++;
     710:         return (0);
     711:         }
     712:     if  (load1(1, nloc + sizeof (struct ar_hdr) + chdr.lname))
     713:         {
     714:         libp->loc = nloc;
     715:         libp++;
     716:         if  (Mflag)
     717:             printf("\t%s\n", chdr.name);
     718:         }
     719:     return (1);
     720:     }
     721:
     722: ldrand(totnum, sloc)
     723:     int totnum;
     724:     off_t   sloc;
     725:     {
     726:     register int ntab;
     727:     SYMBOL  *sp;
     728:     short   *hp;
     729:     VADDR   vsym;
     730:     LIBLIST *oldp = libp;
     731:     int amt, tnum = totnum;
     732:     off_t   loc;
     733: /*
     734:  * 'ar' header + member header + SYMDEF table.of.contents + long filename
     735: */
     736:     off_t   opos = (off_t)SARMAG + sizeof (struct ar_hdr) + sizeof (long) +
     737:             chdr.lname;
     738: #define TABSZ 64
     739:     char    localname[NNAMESIZE];
     740:     register struct ranlib *tp;
     741:     struct ranlib tab[TABSZ], *tplast;
     742:
     743:     while   (tnum)
     744:         {
     745:         if  (tnum > TABSZ)
     746:             ntab = TABSZ;
     747:         else
     748:             ntab = tnum;
     749:         tplast = &tab[ntab - 1];
     750:         (void)lseek(infil, opos, L_SET);
     751:         amt = ntab * sizeof (struct ranlib);
     752:         if  (read(infil, tab, amt) != amt)
     753:             error(1, "EOF in ldrand");
     754:         tnum -= ntab;
     755:         opos += amt;
     756:
     757:         for (tp = tab; tp <= tplast; tp++)
     758:             {
     759: /*
     760:  * This is slower and uglier than we would like, but it is not always
     761:  * possible to hold the entire string table in memory.  Need to add
     762:  * an extra increment to skip over the string table size longword.
     763: */
     764:             if  (rstrtab)
     765:                 strncpy(localname, (int)tp->ran_un.ran_strx +
     766:                         rstrtab, NNAMESIZE);
     767:             else
     768:                 {
     769:                 dseek(STRINGS2, tp->ran_un.ran_strx + sloc +
     770:                     sizeof (long), 07777);
     771:                 mgets(localname, NNAMESIZE, STRINGS2);
     772:                 }
     773:             hp = slookup(localname);
     774:             if  (*hp == -1)
     775:                 continue;
     776:             vsym = sym2va(*hp);
     777:             sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo +
     778:                     VOFF(vsym));
     779:             if  (sp->n_type != N_EXT+N_UNDF)
     780:                 continue;
     781:             step(tp->ran_off);
     782:             loc = tp->ran_off;
     783:             while   (tp < tplast && (tp+1)->ran_off == loc)
     784:                 tp++;
     785:             }
     786:         }
     787:     return(oldp != libp);
     788:     }
     789:
     790: mgets(buf, maxlen, which)
     791:     register char *buf;
     792:     int maxlen, which;
     793:     {
     794:     register STREAM *sp;
     795:     register int n;
     796:
     797:     sp = &Input[which];
     798:     for (n = 0; n < maxlen; n++)
     799:         {
     800:         if  (--sp->nibuf < 0)
     801:             {
     802:             dseek(which, (off_t)(sp->bno + 1) * sp->bsize, 077777);
     803:             sp->nibuf--;
     804:             }
     805:         if  ((*buf++ = *sp->Cptr++) == 0)
     806:             break;
     807:         }
     808:     }
     809:
     810: /*
     811:  * Examine a single file or archive member on pass 1.
     812:  */
     813: load1(libflg, loc)
     814:     off_t loc;
     815: {
     816:     register SYMBOL *sp;
     817:     int savindex;
     818:     int ndef, type, mtype;
     819:     long nlocal;
     820:     VADDR   vsym;
     821:     struct  nlist objsym;
     822:     off_t   strloc;
     823:     long    strsize;
     824:     char    *strtab;
     825: register struct vseg *seg;
     826:
     827:     readhdr(loc);
     828:     if (filhdr.e.a_syms == 0) {
     829:         if (filhdr.e.a_text+filhdr.e.a_data == 0)
     830:             return (0);
     831:         error(1, "no namelist");
     832:     }
     833:     ctrel = tsize; cdrel += dsize; cbrel += bsize;
     834:     ndef = 0;
     835:     nlocal = sizeof (cursym);
     836:     savindex = symindex;
     837:     bzero(symhash, sizeof (symhash));
     838:     if ((filhdr.e.a_flag&RELFLG)==1) {
     839:         error(1, "No relocation bits");
     840:         return(0);
     841:     }
     842:     dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms);
     843:
     844:     strloc = loc + N_STROFF(filhdr);
     845:     lseek(infil, strloc, L_SET);
     846:     read(infil, &strsize, sizeof (long));
     847:     strtab = NULL;
     848:     if  (strsize <= 8192L)
     849:         {
     850:         strtab = (char *)malloc((int)strsize);
     851:         if  (strtab)
     852:             read(infil, strtab, (int)strsize);
     853:         }
     854:     if  (!strtab)
     855:         inistr(STRINGS);
     856:
     857:     while (Input[SYMBOLS].nsize > 0) {
     858:         mget((int *)&objsym, sizeof objsym, SYMBOLS);
     859:         type = objsym.n_type;
     860:         if (Sflag) {
     861:             mtype = type&037;
     862:             if (mtype==1 || mtype>4) {
     863:                 continue;
     864:             }
     865:         }
     866: /*
     867:  * Now convert 'nlist' format symbol to 'fixed' (semi old style) format.
     868:  * This may look strange but it greatly simplifies things and avoids having
     869:  * to read the entire string table into virtual memory.
     870:  *
     871:  * Also, we access the symbols in order.  The assembler was nice enough
     872:  * to place the strings in the same order as the symbols - so effectively
     873:  * we are doing a sequential read of the string table.
     874: */
     875:         if  (strtab)
     876:             strncpy(cursym.n_name, (int)objsym.n_un.n_strx +
     877:                 strtab - sizeof (long), NNAMESIZE);
     878:         else
     879:             {
     880:             dseek(STRINGS, objsym.n_un.n_strx + strloc, 077777);
     881:             mgets(cursym.n_name, NNAMESIZE, STRINGS);
     882:             }
     883:         cursym.n_type = objsym.n_type;
     884:         cursym.n_value = objsym.n_value;
     885:         cursym.n_ovly = objsym.n_ovly;
     886:         if ((type&N_EXT)==0) {
     887:             if (Xflag==0 || cursym.n_name[0]!='L')
     888:                 nlocal += sizeof (cursym);
     889:             continue;
     890:         }
     891:
     892:         switch (cursym.n_type) {
     893:         case N_TEXT:
     894:         case N_EXT+N_TEXT:
     895:             cursym.n_value += ctrel;
     896:             break;
     897:         case N_DATA:
     898:         case N_EXT+N_DATA:
     899:             cursym.n_value += cdrel;
     900:             break;
     901:         case N_BSS:
     902:         case N_EXT+N_BSS:
     903:             cursym.n_value += cbrel;
     904:             break;
     905:         case N_EXT+N_UNDF:
     906:             break;
     907:         default:
     908:             if (cursym.n_type&N_EXT)
     909:                 cursym.n_type = N_EXT+N_ABS;
     910:             break;
     911:         }
     912:
     913:         if (enter(lookup()))
     914:             continue;
     915:         vsym = sym2va(lastsym);
     916:         seg = vmmapseg(&Vspace, VSEG(vsym));
     917:         sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
     918:         if (sp->n_type != N_EXT+N_UNDF)
     919:             continue;
     920:         if (cursym.n_type == N_EXT+N_UNDF) {
     921:             if (cursym.n_value > sp->n_value) {
     922:                 sp->n_value = cursym.n_value;
     923:                 vmmodify(seg);
     924:             }
     925:             continue;
     926:         }
     927:         if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT)
     928:             continue;
     929:         ndef++;
     930:         sp->n_type = cursym.n_type;
     931:         sp->n_value = cursym.n_value;
     932:         sp->n_ovly = ((sp->n_type &~ N_EXT) == N_TEXT) ? curov : 0;
     933:         VMMODIFY(seg);
     934:         if (trace)
     935:             printf("%.*s type 0%o in overlay %u at %u\n", NNAMESIZE,
     936:                 sp->n_name, sp->n_type, sp->n_ovly, sp->n_value);
     937:     }
     938:
     939:     if  (strtab)
     940:         free(strtab);
     941:     if  (Input[STRINGS].buff)
     942:         {
     943:         free(Input[STRINGS].buff);
     944:         Input[STRINGS].buff = NULL;
     945:         }
     946:
     947:     if (libflg==0 || ndef) {
     948:         tsize = add(tsize,filhdr.e.a_text,"text");
     949:         dsize = add(dsize,filhdr.e.a_data,"data");
     950:         bsize = add(bsize,filhdr.e.a_bss,"bss");
     951:         ssize += nlocal;
     952:         return (1);
     953:     }
     954:     /*
     955: 	 * No symbols defined by this library member.
     956: 	 * Rip out the hash table entries and reset the symbol table.
     957: 	 */
     958:     hreset();
     959:     symindex = savindex;
     960:     return(0);
     961: }
     962:
     963: static
     964: hreset()
     965:     {
     966:     register u_short *sp, i;
     967:     u_short j;
     968:     register u_short mask;
     969:
     970:     sp = symhash;
     971:     for (i = 0; i < NSYM; sp++, i += 16)
     972:         {
     973:         if  (*sp == 0)
     974:             continue;
     975:         for (mask = 1, j = i; *sp; j++)
     976:             {
     977:             if  (*sp & mask)
     978:                 {
     979:                 hshtab[j] = -1;
     980:                 *sp &= ~mask;
     981:                 }
     982:             mask <<= 1;
     983:             }
     984:         }
     985:     }
     986:
     987: middle()
     988: {
     989:     VADDR   vsym;
     990:     register SYMBOL *sp;
     991:     register int    i;
     992:     register struct vseg *seg;
     993:     u_int csize;
     994:     u_int nund, corigin;
     995:     u_int ttsize;
     996:
     997:     torigin = 0;
     998:     dorigin = 0;
     999:     borigin = 0;
    1000:
    1001:     p_etext = *slookup("_etext");
    1002:     p_edata = *slookup("_edata");
    1003:     p_end = *slookup("_end");
    1004:     /*
    1005: 	 * If there are any undefined symbols, save the relocation bits.
    1006: 	 * (Unless we are overlaying.)
    1007: 	 */
    1008:     if (rflag==0 && !numov) {
    1009:         for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) {
    1010:             sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo +
    1011:                     VOFF(vsym));
    1012:             if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0
    1013:                 && i != p_end && i != p_edata && i != p_etext) {
    1014:                 rflag++;
    1015:                 dflag = 0;
    1016:                 break;
    1017:             }
    1018:         }
    1019:     }
    1020:     if (rflag)
    1021:         nflag = sflag = iflag = Oflag = 0;
    1022:     /*
    1023: 	 * Assign common locations.
    1024: 	 */
    1025:     csize = 0;
    1026:     if (dflag || rflag==0) {
    1027:         ldrsym(p_etext, tsize, N_EXT+N_TEXT);
    1028:         ldrsym(p_edata, dsize, N_EXT+N_DATA);
    1029:         ldrsym(p_end, bsize, N_EXT+N_BSS);
    1030:         for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) {
    1031:             register int t;
    1032:
    1033:             seg = vmmapseg(&Vspace, VSEG(vsym));
    1034:             sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1035:             if (sp->n_type==N_EXT+N_UNDF && (t = sp->n_value)!=0) {
    1036:                 t = (t+1) & ~01;
    1037:                 sp->n_value = csize;
    1038:                 sp->n_type = N_EXT+N_COMM;
    1039:                 VMMODIFY(seg);
    1040:                 csize = add(csize, t, "bss");
    1041:             }
    1042:         }
    1043:     }
    1044:     if (numov) {
    1045:         for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) {
    1046:             seg = vmmapseg(&Vspace, VSEG(vsym));
    1047:             sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1048:             if (trace)
    1049:                 printf("%.*s n_type %o n_value %o sovalue %o ovly %d\n",
    1050:                     NNAMESIZE, sp->n_name, sp->n_type,
    1051:                     sp->n_value, sp->sovalue, sp->n_ovly);
    1052:             if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) {
    1053:                 sp->sovalue = sp->n_value;
    1054:                 sp->n_value = tsize;
    1055:                 VMMODIFY(seg);
    1056:                 tsize = add(tsize, THUNKSIZ, "text");
    1057:                 if (trace)
    1058:                     printf("relocating %.*s in overlay %d from %o to %o\n",
    1059:                         NNAMESIZE,sp->n_name,sp->n_ovly,
    1060:                         sp->sovalue, sp->n_value);
    1061:             }
    1062:         }
    1063:     }
    1064:     /*
    1065: 	 * Now set symbols to their final value
    1066: 	 */
    1067:     if (nflag || iflag)
    1068:         tsize = add(tsize, 077, "text") & ~077;
    1069:     ttsize = tsize;
    1070:     if (numov) {
    1071:         register int i;
    1072:
    1073:         ovbase = (u_int)rnd8k(tsize);
    1074:         if (trace)
    1075:             printf("overlay base is %u.\n", ovbase);
    1076:         for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) {
    1077:             seg = vmmapseg(&Vspace, VSEG(vsym));
    1078:             sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1079:             if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) {
    1080:                 sp->sovalue += ovbase;
    1081:                 VMMODIFY(seg);
    1082:                 if (trace)
    1083:                     printf("%.*s at %u overlay %d\n",
    1084:                         NNAMESIZE, sp->n_name,
    1085:                         sp->sovalue, sp->n_ovly);
    1086:             }
    1087:         }
    1088:         for (i = 0; i < NOVL; i++) {
    1089:             filhdr.o.ov_siz[i] = (filhdr.o.ov_siz[i] + 077) &~ 077;
    1090:             if (filhdr.o.ov_siz[i] > filhdr.o.max_ovl)
    1091:                 filhdr.o.max_ovl = filhdr.o.ov_siz[i];
    1092:         }
    1093:         if (trace)
    1094:             printf("max overlay size is %u\n", filhdr.o.max_ovl);
    1095:         ttsize = (u_int)rnd8k(ovbase + filhdr.o.max_ovl);
    1096:         if (trace)
    1097:             printf("overlays end before %u.\n", ttsize);
    1098:     }
    1099:     dorigin = ttsize;
    1100:     if (nflag)
    1101:         dorigin = (u_int)rnd8k(ttsize);
    1102:     if (iflag)
    1103:         dorigin = 0;
    1104:     corigin = dorigin + dsize;
    1105:     borigin = corigin + csize;
    1106:     nund = 0;
    1107:     for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) {
    1108:         seg = vmmapseg(&Vspace, VSEG(vsym));
    1109:         sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1110:
    1111:         switch (sp->n_type) {
    1112:
    1113:         case N_EXT+N_UNDF:
    1114:             if (arflag == 0)
    1115:                 errlev |= 01;
    1116:             if ((arflag==0 || dflag) && sp->n_value==0) {
    1117:                 if (i == p_end || i == p_etext || i == p_edata)
    1118:                     continue;
    1119:                 if (quiet)
    1120:                     continue;
    1121:                 if (nund==0)
    1122:                     printf("Undefined:\n");
    1123:                 nund++;
    1124:                 printf("%.*s\n", NNAMESIZE, sp->n_name);
    1125:             }
    1126:             continue;
    1127:         case N_EXT+N_ABS:
    1128:         default:
    1129:             continue;
    1130:         case N_EXT+N_TEXT:
    1131:             sp->n_value += torigin;
    1132:             VMMODIFY(seg);
    1133:             continue;
    1134:         case N_EXT+N_DATA:
    1135:             sp->n_value += dorigin;
    1136:             VMMODIFY(seg);
    1137:             continue;
    1138:         case N_EXT+N_BSS:
    1139:             sp->n_value += borigin;
    1140:             VMMODIFY(seg);
    1141:             continue;
    1142:         case N_EXT+N_COMM:
    1143:             sp->n_type = N_EXT+N_BSS;
    1144:             sp->n_value += corigin;
    1145:             VMMODIFY(seg);
    1146:             continue;
    1147:         }
    1148:     }
    1149:     if (sflag || xflag)
    1150:         ssize = 0;
    1151:     bsize = add(bsize, csize, "bss");
    1152:     nsym = ssize / (sizeof cursym);
    1153: }
    1154:
    1155: ldrsym(ix, val, type)
    1156:     short   ix;
    1157:     u_int   val;
    1158:     int type;
    1159: {
    1160:     VADDR   vsym;
    1161:     register struct vseg *seg;
    1162:     register SYMBOL *sp;
    1163:
    1164:     if (ix == -1)
    1165:         return;
    1166:     vsym = sym2va(ix);
    1167:     seg = vmmapseg(&Vspace, VSEG(vsym));
    1168:     sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1169:     if (sp->n_type != N_EXT+N_UNDF || sp->n_value) {
    1170:         printf("%.*s: n_value %o", NNAMESIZE, sp->n_name, sp->n_value);
    1171:         error(0, "attempt to redefine loader-defined symbol");
    1172:         return;
    1173:     }
    1174:     sp->n_type = type;
    1175:     sp->n_value = val;
    1176:     VMMODIFY(seg);
    1177: }
    1178:
    1179: setupout()
    1180: {
    1181:     VADDR   vsym;
    1182:     register SYMBOL *sp;
    1183:
    1184:     tcreat(&toutb, 0);
    1185:     mktemp(tfname);
    1186:     tcreat(&doutb, 1);
    1187:     if (sflag==0 || xflag==0)
    1188:         tcreat(&soutb, 1);
    1189:     if (rflag) {
    1190:         tcreat(&troutb, 1);
    1191:         tcreat(&droutb, 1);
    1192:     }
    1193:     if (numov)
    1194:         tcreat(&voutb, 1);
    1195:     filhdr.e.a_magic = (Oflag ? A_MAGIC4 : (iflag ? A_MAGIC3 : (nflag ? A_MAGIC2 : A_MAGIC1)));
    1196:     if (numov) {
    1197:         if (filhdr.e.a_magic == A_MAGIC1)
    1198:             error(1, "-n or -i must be used with overlays");
    1199:         filhdr.e.a_magic |= 020;
    1200:     }
    1201:     filhdr.e.a_text = tsize;
    1202:     filhdr.e.a_data = dsize;
    1203:     filhdr.e.a_bss = bsize;
    1204:     ssize = sflag? 0 : (ssize + (sizeof (struct nlist)) * symindex);
    1205: /*
    1206:  * This is an estimate, the real size is computed later and the
    1207:  * a.out header rewritten with the correct value.
    1208: */
    1209:     filhdr.e.a_syms = ssize&0177777;
    1210:     if (entrypt != -1) {
    1211:         vsym = sym2va(entrypt);
    1212:         sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo +
    1213:                 VOFF(vsym));
    1214:         if (sp->n_type!=N_EXT+N_TEXT)
    1215:             error(0, "entry point not in text");
    1216:         else if (sp->n_ovly)
    1217:             error(0, "entry point in overlay");
    1218:         else
    1219:             filhdr.e.a_entry = sp->n_value | 01;
    1220:     } else
    1221:         filhdr.e.a_entry = 0;
    1222:     filhdr.e.a_flag = (rflag==0);
    1223:     fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb);
    1224:     if (numov)
    1225:         fwrite(&filhdr.o, sizeof (filhdr.o), 1, toutb);
    1226: }
    1227:
    1228: load2arg(acp, flag)
    1229:     char *acp;
    1230:     int flag;
    1231: {
    1232:     register char *cp;
    1233:     register LIBLIST *lp;
    1234:
    1235:     cp = acp;
    1236:     switch  (getfile(cp, flag, 2))
    1237:         {
    1238:         case 0:
    1239:             while (*cp)
    1240:                 cp++;
    1241:             while (cp >= acp && *--cp != '/')
    1242:                 ;
    1243:             mkfsym(++cp);
    1244:             load2(0L);
    1245:             break;
    1246:         case -1:
    1247:             return;
    1248:         default:    /* scan archive members referenced */
    1249:             for (lp = libp; lp->loc != -1; lp++) {
    1250:                 lseek(infil, lp->loc, L_SET);
    1251:                 get_arobj(infil);
    1252:                 mkfsym(chdr.name);
    1253:                 load2(lp->loc + sizeof (struct ar_hdr) +
    1254:                     chdr.lname);
    1255:             }
    1256:             libp = ++lp;
    1257:             break;
    1258:         }
    1259:     close(infil);
    1260: }
    1261:
    1262: load2(loc)
    1263: long loc;
    1264: {
    1265:     register SYMBOL *sp;
    1266:     register struct local *lp;
    1267:     register int symno;
    1268:     int type, mtype;
    1269:     VADDR   vsym;
    1270:     short   i;
    1271:     struct  nlist objsym;
    1272:     off_t   stroff;
    1273:     char    *strtab;
    1274:     long    strsize;
    1275:
    1276:     readhdr(loc);
    1277:     ctrel = torigin;
    1278:     cdrel += dorigin;
    1279:     cbrel += borigin;
    1280:     /*
    1281: 	 * Reread the symbol table, recording the numbering
    1282: 	 * of symbols for fixing external references.
    1283: 	 */
    1284:     lp = local;
    1285:     symno = -1;
    1286:     dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms);
    1287:     stroff = loc + N_STROFF(filhdr);
    1288:
    1289:     lseek(infil, stroff, L_SET);
    1290:     read(infil, &strsize, sizeof (long));
    1291:     strtab = NULL;
    1292:     if  (strsize <= 8192L)
    1293:         {
    1294:         strtab = (char *)malloc((int)strsize);
    1295:         if  (strtab)
    1296:             read(infil, strtab, (int)strsize);
    1297:         }
    1298:     if  (!strtab)
    1299:         inistr(STRINGS);
    1300:
    1301:     while (Input[SYMBOLS].nsize > 0) {
    1302:         symno++;
    1303:         mget((int *)&objsym, sizeof objsym, SYMBOLS);
    1304:         if  (strtab)
    1305:             strncpy(cursym.n_name, (int)objsym.n_un.n_strx +
    1306:                 strtab - sizeof (long), NNAMESIZE);
    1307:         else
    1308:             {
    1309:             dseek(STRINGS, objsym.n_un.n_strx + stroff, 07777);
    1310:             mgets(cursym.n_name, NNAMESIZE, STRINGS);
    1311:             }
    1312:         cursym.n_type = objsym.n_type;
    1313:         cursym.n_value = objsym.n_value;
    1314:         cursym.n_ovly = objsym.n_ovly;
    1315:
    1316:         switch (cursym.n_type) {
    1317:         case N_TEXT:
    1318:         case N_EXT+N_TEXT:
    1319:             cursym.n_value += ctrel;
    1320:             break;
    1321:         case N_DATA:
    1322:         case N_EXT+N_DATA:
    1323:             cursym.n_value += cdrel;
    1324:             break;
    1325:         case N_BSS:
    1326:         case N_EXT+N_BSS:
    1327:             cursym.n_value += cbrel;
    1328:             break;
    1329:         case N_EXT+N_UNDF:
    1330:             break;
    1331:         default:
    1332:             if (cursym.n_type&N_EXT)
    1333:                 cursym.n_type = N_EXT+N_ABS;
    1334:             break;
    1335:         }
    1336:
    1337:         type = cursym.n_type;
    1338:         if (Sflag) {
    1339:             mtype = type&037;
    1340:             if (mtype==1 || mtype>4) continue;
    1341:         }
    1342:         if ((type&N_EXT) == 0) {
    1343:             if (!sflag && !xflag &&
    1344:                 (!Xflag || cursym.n_name[0] != 'L')) {
    1345:                 /*
    1346: 				 * preserve overlay number for locals
    1347: 				 * mostly for adb.   mjk 7/81
    1348: 				 */
    1349:                 if ((type == N_TEXT) && inov)
    1350:                     cursym.n_ovly = curov;
    1351:                 fwrite(&cursym, sizeof cursym, 1, soutb);
    1352:             }
    1353:             continue;
    1354:         }
    1355:         i = *lookup();
    1356:         if (i == -1)
    1357:             error(1, "internal error: symbol not found");
    1358:         if (cursym.n_type == N_EXT+N_UNDF ||
    1359:             cursym.n_type == N_EXT+N_TEXT) {
    1360:             if (lp >= &local[NSYMPR])
    1361:                 error(2, "Local symbol overflow");
    1362:             lp->locindex = symno;
    1363:             lp++->locsymbol = i;
    1364:             continue;
    1365:         }
    1366:         vsym = sym2va(i);
    1367:         sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo +
    1368:                 VOFF(vsym));
    1369:         if (cursym.n_type != sp->n_type
    1370:             || cursym.n_value != sp->n_value && !sp->n_ovly
    1371:             || sp->n_ovly && cursym.n_value != sp->sovalue) {
    1372:             printf("%.*s: ", NNAMESIZE, cursym.n_name);
    1373:             if (trace)
    1374:                 printf(" ovly %d sovalue %o new %o hav %o ",
    1375:                     sp->n_ovly, sp->sovalue,
    1376:                     cursym.n_value, sp->n_value);
    1377:             error(0, "multiply defined");
    1378:         }
    1379:     }
    1380:     if  (strtab)
    1381:         free(strtab);
    1382:     if  (Input[STRINGS].buff)
    1383:         {
    1384:         free(Input[STRINGS].buff);
    1385:         Input[STRINGS].buff = NULL;
    1386:         }
    1387:     dseek(TEXT, loc + N_TXTOFF(filhdr.e), filhdr.e.a_text);
    1388:     dseek(RELOC, loc + N_TRELOC(filhdr.e), filhdr.e.a_text);
    1389:     load2td(lp, ctrel, inov ? voutb : toutb, troutb);
    1390:     dseek(TEXT, loc + N_DATOFF(filhdr), filhdr.e.a_data);
    1391:     dseek(RELOC, loc + N_DRELOC(filhdr), filhdr.e.a_data);
    1392:     load2td(lp, cdrel, doutb, droutb);
    1393:     torigin += filhdr.e.a_text;
    1394:     dorigin += filhdr.e.a_data;
    1395:     borigin += filhdr.e.a_bss;
    1396: }
    1397:
    1398: load2td(lp, creloc, b1, b2)
    1399:     struct local *lp;
    1400:     u_int creloc;
    1401:     FILE *b1, *b2;
    1402: {
    1403:     register u_int r, t;
    1404:     register SYMBOL *sp;
    1405:     short   i;
    1406:     VADDR   vsym;
    1407:
    1408:     for (;;) {
    1409: /*
    1410:  * Can't do this because of the word/byte count fakery that's used to
    1411:  * prevrent erroneous EOF indications.  Yuck.
    1412:
    1413: 		t = get(TEXT);
    1414: 		t = get(RELOC);
    1415: */
    1416:         /*
    1417: 		 * The pickup code is copied from "get" for speed.
    1418: 		 */
    1419:
    1420:         /* next text or data word */
    1421:         if (--Input[TEXT].nsize <= 0) {
    1422:             if (Input[TEXT].nsize < 0)
    1423:                 break;
    1424:             Input[TEXT].nsize++;
    1425:             t = get(TEXT);
    1426:         } else if (--Input[TEXT].nibuf < 0) {
    1427:             Input[TEXT].nibuf++;
    1428:             Input[TEXT].nsize++;
    1429:             t = get(TEXT);
    1430:         } else
    1431:             t = *Input[TEXT].Iptr++;
    1432:
    1433:         /* next relocation word */
    1434:         if (--Input[RELOC].nsize <= 0) {
    1435:             if (Input[RELOC].nsize < 0)
    1436:                 error(1, "relocation error");
    1437:             Input[RELOC].nsize++;
    1438:             r = get(RELOC);
    1439:         } else if (--Input[RELOC].nibuf < 0) {
    1440:             Input[RELOC].nibuf++;
    1441:             Input[RELOC].nsize++;
    1442:             r = get(RELOC);
    1443:         } else
    1444:             r = *Input[RELOC].Iptr++;
    1445:
    1446:         switch (r&016) {
    1447:
    1448:         case RTEXT:
    1449:             t += ctrel;
    1450:             break;
    1451:         case RDATA:
    1452:             t += cdrel;
    1453:             break;
    1454:         case RBSS:
    1455:             t += cbrel;
    1456:             break;
    1457:         case REXT:
    1458:             i = *lookloc(lp, r);
    1459:             vsym = sym2va(i);
    1460:             sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo +
    1461:                     VOFF(vsym));
    1462:             if (sp->n_type==N_EXT+N_UNDF) {
    1463:                 r = (r&01) + ((nsym + i)<<4) + REXT;
    1464:                 break;
    1465:             }
    1466:             t += sp->n_value;
    1467:             r = (r&01) + ((sp->n_type-(N_EXT+N_ABS))<<1);
    1468:             break;
    1469: #ifndef pdp11
    1470:         default:
    1471:             error(1, "relocation format botch (symbol type))");
    1472: #endif
    1473:         }
    1474:         if (r&01)
    1475:             t -= creloc;
    1476:         putw(t, b1);
    1477:         if (rflag)
    1478:             putw(r, b2);
    1479:     }
    1480: }
    1481:
    1482: finishout()
    1483: {
    1484:     register u_int n;
    1485:     register SYMBOL *sp;
    1486:     struct  nlist objsym;
    1487:     VADDR   vsym;
    1488:     int type, len;
    1489:     off_t   stroff;
    1490:     long dtotal, ovrnd;
    1491:     int thunk[THUNKSIZ / sizeof (int)];
    1492:
    1493:     if (numov) {
    1494:         int aovhndlr[NOVL+1];
    1495:
    1496:         for (n=1; n<=numov; n++) {
    1497:             /* Note that NOVL can be up to 15 with this */
    1498:             ovhndlr.n_name[HNDLR_NUM] = "0123456789abcdef"[n];
    1499:             aovhndlr[n] = adrof(ovhndlr.n_name);
    1500:         }
    1501:         for (n=0,vsym=sym2va(0); n < symindex; n++,vsym=sym2va(n)) {
    1502:             sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo +
    1503:                     VOFF(vsym));
    1504:             if (sp->n_ovly && (sp->n_type & (N_EXT+N_TEXT))) {
    1505:                 thunk[0] = 012701;  /* mov $~foo+4, r1 */
    1506:                 thunk[1] = sp->sovalue + 4;
    1507:                 thunk[2] = 04537;   /* jsr r5, ovhndlrx */
    1508:                 thunk[3] = aovhndlr[sp->n_ovly];
    1509:                 fwrite(thunk, THUNKSIZ, 1, toutb);
    1510:                 torigin += THUNKSIZ;
    1511:             }
    1512:         }
    1513:     }
    1514:     if (nflag||iflag) {
    1515:         n = torigin;
    1516:         while (n&077) {
    1517:             n += 2;
    1518:             putw(0, toutb);
    1519:             if (rflag)
    1520:                 putw(0, troutb);
    1521:         }
    1522:     }
    1523:     if (numov)
    1524:         copy(voutb);
    1525:     copy(doutb);
    1526:     if (rflag) {
    1527:         copy(troutb);
    1528:         copy(droutb);
    1529:     }
    1530:
    1531:     if  (sflag==0)
    1532:         {
    1533: /*
    1534:  * Now write the symbol table out, converting from the 'fixed' style
    1535:  * symbol table used internally to the string table version used in
    1536:  * object/executable files.  First the "local" (non-global) symbols
    1537:  * are written out, these are the symbols placed in the temporary file
    1538:  * accessed via 'soutb'.
    1539:  *
    1540:  * 'voutb' (overlay temp file), 'troutb' (text relocation temp file),
    1541:  * 'droutb' (data relocation temp file), and 'doutb' (data temp file)
    1542:  * have all been finished with and closed by this point.  We reuse one
    1543:  * of these ('doutb') to build the string table.
    1544: */
    1545:
    1546:         tcreat(&doutb, 1);
    1547:         nsym = 0;
    1548:         stroff = sizeof (long);     /* string table size */
    1549:         if  (xflag == 0)
    1550:             {
    1551:             fflush(soutb);      /* flush local symbol file */
    1552:             rewind(soutb);
    1553:             while   (fread(&cursym, sizeof (cursym), 1, soutb) == 1)
    1554:                 {
    1555:                 if  (feof(soutb))
    1556:                     break;
    1557:                 objsym.n_value = cursym.n_value;
    1558:                 objsym.n_type = cursym.n_type;
    1559:                 objsym.n_ovly = cursym.n_ovly;
    1560:                 objsym.n_un.n_strx = stroff;
    1561:                 len = strlen(cursym.n_name);
    1562:                 if  (len >= NNAMESIZE)
    1563:                     len = NNAMESIZE;
    1564:                 fwrite(cursym.n_name, 1, len, doutb);
    1565:                 fputc('\0', doutb);
    1566:                 stroff += (len + 1);
    1567:                 fwrite(&objsym, sizeof (objsym), 1, toutb);
    1568:                 nsym++;
    1569:                 }
    1570:             fclose(soutb);
    1571:             }
    1572: /*
    1573:  * Now we dump the global/external symbol table by marching thru the
    1574:  * 'vm' addresss space.
    1575: */
    1576:         for (n = 0, vsym = sym2va(0); n < symindex; n++,
    1577:                             vsym = sym2va(n))
    1578:             {
    1579:             sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo +
    1580:                     VOFF(vsym));
    1581:             objsym.n_value = sp->n_value;
    1582:             objsym.n_type = sp->n_type;
    1583:             objsym.n_ovly = sp->n_ovly;
    1584:             objsym.n_un.n_strx = stroff;
    1585:             len = strlen(sp->n_name);
    1586:             if  (len > NNAMESIZE)
    1587:                 len = NNAMESIZE;
    1588:             fwrite(sp->n_name, 1, len, doutb);
    1589:             fputc('\0', doutb);
    1590:             stroff += (len + 1);
    1591:             fwrite(&objsym, sizeof (objsym), 1, toutb);
    1592:             nsym++;
    1593:             }
    1594: #ifdef  whybother
    1595:         if  (stroff & 1)
    1596:             {
    1597:             fputc('\0', doutb);
    1598:             stroff++;
    1599:             }
    1600: #endif
    1601: /*
    1602:  * Now write the length of the string table out.  Then copy the temp
    1603:  * file containing the strings to the image being built.
    1604: */
    1605:         fwrite(&stroff, sizeof (stroff), 1, toutb);
    1606:         copy(doutb);
    1607:         }
    1608: /*
    1609:  * Fix up the header with the correct symbol table size - we now know
    1610:  * _exactly_ how many symbols were placed in the symbol table (the size
    1611:  * used earlier was only an estimate
    1612: */
    1613:     fflush(toutb);
    1614:     rewind(toutb);
    1615:     fread(&filhdr.e, sizeof (filhdr.e), 1, toutb);
    1616:     filhdr.e.a_syms = nsym * sizeof (objsym);
    1617:     rewind(toutb);
    1618:     fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb);
    1619:     fclose(toutb);
    1620:
    1621:     if (!ofilfnd) {
    1622:         if (rename("l.out", "a.out") < 0)
    1623:             error(1, "cannot move l.out to a.out");
    1624:         ofilename = "a.out";
    1625:     }
    1626: /*
    1627:  * we now do a sanity check on the total sizes of things.  Previously the
    1628:  * linker could produce a program marked as executable but which had bogus
    1629:  * overlay+root sizes, etc.
    1630: */
    1631: #define K56 (56L * 1024L)
    1632: #define K64 (64L * 1024L)
    1633:
    1634:     dtotal = (long)dsize + (long)bsize;
    1635:     ovrnd = rnd8k(filhdr.o.max_ovl);    /* 0 if not overlaid */
    1636:     type = 0;
    1637:     if (nflag) {
    1638:         if (rnd8k(tsize) + ovrnd + dtotal > K56)
    1639:             type = filhdr.e.a_magic;
    1640:     }
    1641:     else if (iflag) {
    1642:         if ((rnd8k(tsize) + ovrnd > K64) || (dtotal > K56))
    1643:             type = filhdr.e.a_magic;
    1644:     }
    1645:     else {
    1646:         if ((long)tsize + dtotal > K56)
    1647:             type = filhdr.e.a_magic;
    1648:     }
    1649:     if (type && !rflag) {
    1650:         fprintf(stderr, "ld: too big for type %o\n", type);
    1651:         errlev = 2;
    1652:     }
    1653:     delarg = errlev;
    1654:     delexit();
    1655: }
    1656:
    1657: long
    1658: rnd8k(siz)
    1659:     u_int siz;
    1660:     {
    1661:     long l = siz;
    1662:
    1663:     return((l + 017777) & ~017777L);
    1664:     }
    1665:
    1666: mkfsym(s)
    1667:     char *s;
    1668:     {
    1669:
    1670:     if (sflag || xflag)
    1671:         return;
    1672:     strncpy(cursym.n_name, s, NNAMESIZE);
    1673:     cursym.n_type = N_FN;
    1674:     cursym.n_value = torigin;
    1675:     fwrite(&cursym, sizeof (cursym), 1, soutb);
    1676:     }
    1677:
    1678: mget(loc, an, which)
    1679:     register int *loc;
    1680:     int an, which;
    1681: {
    1682:     register int n;
    1683:     register STREAM *tp = &Input[which];
    1684:
    1685:     n = an >> 1;
    1686:     if ((tp->nibuf -= n) >= 0) {
    1687:         if ((tp->nsize -= n) > 0) {
    1688:             bcopy(tp->ptr, loc, an);
    1689:             tp->Iptr += n;
    1690:             return;
    1691:         }
    1692:         tp->nsize += n;
    1693:     }
    1694:     tp->nibuf += n;
    1695:     do {
    1696:         *loc++ = get(which);
    1697:     } while (--n);
    1698: }
    1699:
    1700: dseek(which, aloc, s)
    1701:     int which;
    1702:     off_t aloc;
    1703:     int s;
    1704:     {
    1705:     register STREAM *sp = &Input[which];
    1706:     register u_int b, o;
    1707:     int n;
    1708:
    1709:     b = aloc / sp->bsize;
    1710:     o = aloc & (sp->bsize - 1);
    1711:     if  (sp->bno != b)
    1712:         {
    1713:         (void)lseek(infil, (off_t)sp->bsize * b, L_SET);
    1714:         if  ((n = read(infil, (char *)sp->buff, sp->bsize)) < 0)
    1715:             n = 0;
    1716:         sp->bno = b;
    1717:         sp->nread = n;
    1718:         }
    1719:     sp->nibuf = sp->nread - o;
    1720:     sp->Cptr = (char *)sp->buff + o;
    1721:     if  (which != STRINGS)
    1722:         sp->nibuf >>= 1;
    1723:     if  (s != -1)
    1724:         sp->nsize = (s >> 1) & 077777;
    1725:     if  (sp->nibuf <= 0)
    1726:         sp->nsize = 0;
    1727:     }
    1728:
    1729: get(which)
    1730:     int which;
    1731: {
    1732:     register STREAM *sp = &Input[which];
    1733:
    1734:     if (--sp->nibuf < 0) {
    1735:         dseek(which, (off_t)(sp->bno + 1) * sp->bsize, -1);
    1736:         --sp->nibuf;
    1737:     }
    1738:     if (--sp->nsize <= 0) {
    1739:         if (sp->nsize < 0)
    1740:             error(1, "premature EOF#1");
    1741:     }
    1742:     return(*sp->Iptr++);
    1743: }
    1744:
    1745: getfile(acp, flag, phase)
    1746: char *acp;
    1747:     int flag;   /* 1 = fatal if file not found, -1 = not fatal */
    1748: {
    1749:     char arcmag[SARMAG+1];
    1750:     struct stat stb;
    1751:
    1752:     filname = acp;
    1753:     chdr.name[0] = '\0';        /* not in archive for now */
    1754:     if (filname[0] == '-' && filname[1] == 'l')
    1755:         infil = libopen(filname + 2, O_RDONLY);
    1756:     else
    1757:         infil = open(filname, O_RDONLY);
    1758:     if (infil < 0) {
    1759:         if (phase == 1)     /* only complain once on phase 1 */
    1760:             error(flag, "cannot open");
    1761:         return(-1);
    1762:     }
    1763:     fstat(infil, &stb);
    1764:     Input[TEXT].bno = -1;
    1765:     Input[RELOC].bno = -1;
    1766:     Input[SYMBOLS].bno = -1;
    1767:     Input[STRINGS].bno = -1;
    1768:     dseek(TEXT, 0L, SARMAG);
    1769:     if (Input[TEXT].nsize <= 0)
    1770:         error(1, "premature EOF#2");
    1771:     mget((char *)arcmag, SARMAG, TEXT);
    1772:     arcmag[SARMAG] = 0;
    1773:     if (strcmp(arcmag, ARMAG))
    1774:         return(0);
    1775:     lseek(infil, (off_t)SARMAG, L_SET);
    1776:     if (get_arobj(infil) <= 0)
    1777:         return(1);
    1778:     if  (strcmp(chdr.name, RANLIBMAG))
    1779:         return(1);  /* regular archive */
    1780:     return (stb.st_mtime > chdr.date ? 3 : 2);
    1781: }
    1782:
    1783: /*
    1784:  * Search for a library with given name
    1785:  * using the directory search array.
    1786:  */
    1787: libopen(name, oflags)
    1788:     char *name;
    1789:     int oflags;
    1790: {
    1791:     register char *p, *cp;
    1792:     register int i;
    1793:     static char buf[100];
    1794:     int fd;
    1795:
    1796:     for (i = 0; i < ndir ; i++) {
    1797:         p = buf;
    1798:         for (cp = dirs[i]; *cp; *p++ = *cp++)
    1799:             ;
    1800:         *p++ = '/';
    1801:         *p++ = 'l';
    1802:         *p++ = 'i';
    1803:         *p++ = 'b';
    1804:         for (cp = name; *cp; *p++ = *cp++)
    1805:             ;
    1806:         *p++ = '.';
    1807:         *p++ = 'a';
    1808:         *p++ = '\0';
    1809:         fd = open(buf, oflags);
    1810:         if (fd != -1) {
    1811:             filname = buf;
    1812:             return(fd);
    1813:         }
    1814:     }
    1815:     return(-1);
    1816: }
    1817:
    1818: short *
    1819: lookup()
    1820:     {
    1821:     register short *hp;
    1822:     register char *cp;
    1823:     SYMBOL  *sp;
    1824:     union
    1825:         {
    1826:         long    x;
    1827:         short   y[2];
    1828:         } sh;
    1829:     VADDR   vsym;
    1830:
    1831:     sh.x = 0;
    1832:     for (cp = cursym.n_name; cp < &cursym.n_name[NNAMESIZE] && *cp;)
    1833:         sh.x = (sh.x<<1) + *cp++;
    1834:     sh.y[1] += sh.y[0];
    1835:     hp = &hshtab[(sh.y[1]&077777)%NSYM+2];
    1836:     while   (*hp != -1)
    1837:         {
    1838:         vsym = sym2va(*hp);
    1839:         sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo +
    1840:                 VOFF(vsym));
    1841:         if  (!strncmp(sp->n_name, cursym.n_name, NNAMESIZE))
    1842:             break;
    1843:         if  (++hp >= &hshtab[NSYM+2])
    1844:             hp = hshtab;
    1845:         }
    1846:     return(hp);
    1847:     }
    1848:
    1849: short *
    1850: slookup(s)
    1851:     char *s;
    1852:     {
    1853:
    1854:     strncpy(cursym.n_name, s, NNAMESIZE);
    1855:     cursym.n_type = N_EXT+N_UNDF;
    1856:     cursym.n_value = 0;
    1857:     return(lookup());
    1858:     }
    1859:
    1860: enter(hp)
    1861:     short   *hp;
    1862:     {
    1863:     register SYMBOL *sp;
    1864:     u_int word, bit, hnum;
    1865:     VADDR   vsym;
    1866:     register struct vseg    *seg;
    1867:
    1868:     if  (*hp == -1)
    1869:         {
    1870:         if  (symindex>=NSYM)
    1871:             error(1, "symbol table overflow");
    1872:         hnum = hp - hshtab;
    1873:         word = hnum / 16;
    1874:         bit = hnum % 16;
    1875:         symhash[word] |= (1 << bit);
    1876:         vsym = sym2va(symindex);
    1877:         *hp = lastsym = symindex;
    1878:         symindex++;
    1879:         seg = vmmapseg(&Vspace, VSEG(vsym));
    1880:         sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym));
    1881:         strncpy(sp->n_name, cursym.n_name, NNAMESIZE);
    1882:         sp->n_type = cursym.n_type;
    1883:         sp->n_value = cursym.n_value;
    1884:         if  (sp->n_type == N_EXT+N_TEXT)
    1885:             {
    1886:             sp->n_ovly = curov;
    1887:             if  (trace)
    1888:                 printf("found %.*s in overlay %d at %u\n",
    1889:                     NNAMESIZE, sp->n_name, sp->n_ovly,
    1890:                     sp->n_value);
    1891:             }
    1892:         VMMODIFY(seg);
    1893:         return(1);
    1894:         }
    1895:     lastsym = *hp;
    1896:     return(0);
    1897:     }
    1898:
    1899: error(n, s)
    1900: char *s;
    1901: {
    1902:     if (!s)
    1903:         delexit();
    1904:     if (errlev==0)
    1905:         printf("ld:");
    1906:     if (filname) {
    1907:         printf("%s", filname);
    1908:         if (n != -1 && chdr.name[0])
    1909:             printf("(%s)", chdr.name);
    1910:         printf(": ");
    1911:     }
    1912:     printf("%s\n", s);
    1913:     if (n == -1)
    1914:         return;
    1915:     if (n)
    1916:         delexit();
    1917:     errlev = 2;
    1918: }
    1919:
    1920: readhdr(loc)
    1921: off_t loc;
    1922: {
    1923:     dseek(TEXT, loc, sizeof filhdr);
    1924:     mget((int *)&filhdr.e, sizeof filhdr.e, TEXT);
    1925:     if (filhdr.e.a_magic != A_MAGIC1)
    1926:         error(1, "bad magic number");
    1927:     if (filhdr.e.a_text&01)
    1928:         ++filhdr.e.a_text;
    1929:     if (filhdr.e.a_data&01)
    1930:         ++filhdr.e.a_data;
    1931:     if (filhdr.e.a_bss&01)
    1932:         ++filhdr.e.a_bss;
    1933:     cdrel = -filhdr.e.a_text;
    1934:     cbrel = cdrel - filhdr.e.a_data;
    1935: }
    1936:
    1937: tcreat(fpp, tempflg)
    1938:     FILE    **fpp;
    1939:     int tempflg;
    1940:     {
    1941:     register int ufd;
    1942:     char    *nam;
    1943:
    1944:     nam = (tempflg ? tfname : ofilename);
    1945:     if  ((ufd = open(nam, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
    1946:         error(2, tempflg?"cannot create temp":"cannot create output");
    1947:     if  (tempflg)
    1948:         unlink(tfname);
    1949:     *fpp = fdopen(ufd, "r+");
    1950:     }
    1951:
    1952: adrof(s)
    1953:     char *s;
    1954:     {
    1955:     register short *p;
    1956:     register SYMBOL *sp;
    1957:     VADDR   vsym;
    1958:
    1959:     p = slookup(s);
    1960:     if  (*p == -1)
    1961:         {
    1962:         printf("%.*s: ", NNAMESIZE, s);
    1963:         error(1, "undefined");
    1964:         }
    1965:     vsym = sym2va(*p);
    1966:     sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym));
    1967:     return(sp->n_value);
    1968:     }
    1969:
    1970: copy(fp)
    1971:     register FILE   *fp;
    1972:     {
    1973:     register int c;
    1974:
    1975:     fflush(fp);
    1976:     rewind(fp);
    1977:     while   ((c = getc(fp)) != EOF)
    1978:         putc(c, toutb);
    1979:     fclose(fp);
    1980:     }
    1981:
    1982: short *
    1983: lookloc(alp, r)
    1984: struct local *alp;
    1985: {
    1986:     register struct local *clp, *lp;
    1987:     register int sn;
    1988:
    1989:     lp = alp;
    1990:     sn = (r>>4) & 07777;
    1991:     for (clp = local; clp<lp; clp++)
    1992:         if (clp->locindex == sn)
    1993:             return(&clp->locsymbol);
    1994:     error(1, "local symbol botch");
    1995:     /*NOTREACHED*/
    1996: }
    1997:
    1998: roundov()
    1999:     {
    2000:
    2001:     while   (torigin & 077)
    2002:         {
    2003:         putw(0, voutb);
    2004:         torigin += sizeof (int);
    2005:         }
    2006:     }
    2007:
    2008: u_int
    2009: add(a,b,s)
    2010: int a, b;
    2011: char *s;
    2012: {
    2013:     long r;
    2014:     register char *ap;
    2015:
    2016:     r = (long)(u_int)a + (u_int)b;
    2017:     if (r >= 0200000)
    2018:         {
    2019:         ap = (char *)alloca(strlen(s) + 1 + sizeof (" overflow"));
    2020:         strcpy(ap, s);
    2021:         strcat(ap, " overflow");
    2022:         error(1, ap);
    2023:         }
    2024:     return(r);
    2025: }
    2026:
    2027: /*
    2028:  * "borrowed" from 'ar' because we didn't want to drag in everything else
    2029:  * from 'ar'.  The error checking was also ripped out, basically if any
    2030:  * of the criteria for being an archive are not met then a -1 is returned
    2031:  * and the rest of 'ld' figures out what to do.
    2032: */
    2033:
    2034: typedef struct ar_hdr HDR;
    2035: static char hb[sizeof(HDR) + 1];    /* real header */
    2036:
    2037: /* Convert ar header field to an integer. */
    2038: #define AR_ATOI(from, to, len, base) { \
    2039:     bcopy(from, buf, len); \
    2040:     buf[len] = '\0'; \
    2041:     to = strtol(buf, (char **)NULL, base); \
    2042: }
    2043:
    2044: /*
    2045:  * get_arobj --
    2046:  *	read the archive header for this member
    2047:  */
    2048: get_arobj(fd)
    2049:     int fd;
    2050: {
    2051:     HDR *hdr;
    2052:     register int len, nr;
    2053:     register char *p;
    2054:     char buf[20];
    2055:
    2056:     nr = read(fd, hb, sizeof(HDR));
    2057:     if (nr != sizeof(HDR))
    2058:         return(-1);
    2059:
    2060:     hdr = (HDR *)hb;
    2061:     if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))
    2062:         return(-1);
    2063:
    2064:     /* Convert the header into the internal format. */
    2065: #define DECIMAL 10
    2066: #define OCTAL    8
    2067:
    2068:     AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL);
    2069:     AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL);
    2070:     AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL);
    2071:     AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL);
    2072:     AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL);
    2073:
    2074:     /* Leading spaces should never happen. */
    2075:     if (hdr->ar_name[0] == ' ')
    2076:         return(-1);
    2077:
    2078:     /*
    2079: 	 * Long name support.  Set the "real" size of the file, and the
    2080: 	 * long name flag/size.
    2081: 	 */
    2082:     if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) {
    2083:         chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1);
    2084:         if (len <= 0 || len > MAXNAMLEN)
    2085:             return(-1);
    2086:         nr = read(fd, chdr.name, (size_t)len);
    2087:         if (nr != len)
    2088:             return(-1);
    2089:         chdr.name[len] = 0;
    2090:         chdr.size -= len;
    2091:     } else {
    2092:         chdr.lname = 0;
    2093:         bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name));
    2094:
    2095:         /* Strip trailing spaces, null terminate. */
    2096:         for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p);
    2097:         *++p = '\0';
    2098:     }
    2099:     return(1);
    2100: }
    2101:
    2102: /*
    2103:  * skip - where to seek for next archive member.
    2104:  */
    2105: off_t
    2106: skip()
    2107:     {
    2108:     off_t len;
    2109:
    2110:     len = chdr.size + (chdr.size + chdr.lname & 1);
    2111:     len += sizeof (HDR);
    2112:     return(len);
    2113:     }
    2114:
    2115: inistr(which)
    2116:     int which;
    2117:     {
    2118:     register STREAM *sp = &Input[which];
    2119:     register int    size = 4096;
    2120:
    2121:     if  (sp->buff == (int *)NULL)
    2122:         {
    2123:         while   (size > 256)
    2124:             {
    2125:             sp->buff = (int *)malloc(size);
    2126:             if  (sp->buff)
    2127:                 {
    2128:                 sp->bsize = size;
    2129:                 return;
    2130:                 }
    2131:             size >>= 1;
    2132:             }
    2133:         error(1, "No memory for strings");
    2134:         }
    2135:     }

#### Defined functions

add defined in line 2008; used 8 times

- in line 296, 948-950(3), 1040, 1056, 1068, 1151

adrof defined in line 1952; used 1 times

- in line 1499

copy defined in line 1970; used 5 times

- in line 1524-1528(4), 1606

delexit defined in line 497; used 6 times

- in line 297, 328-329(2), 1654, 1903, 1916

dseek defined in line 1700; used 13 times

- in line 769, 802, 842, 880, 1286, 1309, 1387-1391(4), 1735, 1768, 1923

endload defined in line 509; used 1 times

- in line 493

enter defined in line 1860; used 3 times

- in line 386, 463, 913

error defined in line 1899; used 36 times

- in line 339-341(2), 350-352(2), 378, 385, 392-395(2), 450, 477, 488, 623, 682, 753, 831, 839, 1171, 1198, 1215-1217(2), 1357-1361(2), 1377, 1436, 1471, 1623, 1740, 1760, 1770, 1871, 1926, 1946, 1963, 1994, 2022, 2133

finishout defined in line 1482; used 1 times

- in line 575

get defined in line 1729; used 5 times

- in line 1425-1429(2), 1438-1442(2), 1696

get_arobj defined in line 2048; used 3 times

- in line 706, 1251, 1776

getfile defined in line 1745; used 2 times

- in line 606, 1236

hreset defined in line 963; used 1 times

- in line 958

inistr defined in line 2115; used 3 times

- in line 661, 855, 1299

ldrand defined in line 722; used 1 times

- in line 663

ldrsym defined in line 1155; used 3 times

- in line 1027-1029(3)

libopen defined in line 1787; used 1 times

- in line 1755

load1 defined in line 813; used 2 times

- in line 615, 712

load1arg defined in line 598; used 2 times

- in line 371, 401

load2 defined in line 1262; used 2 times

- in line 1244, 1253

load2arg defined in line 1228; used 2 times

- in line 529, 553

load2td defined in line 1398; used 2 times

- in line 1389-1392(2)

lookloc defined in line 1982; used 2 times

- in line 294, 1458

lookup defined in line 1818; used 5 times

- in line 294, 463, 913, 1355, 1857

main defined in line 301; never used
mget defined in line 1678; used 4 times

- in line 858, 1303, 1771, 1924

mgets defined in line 790; used 3 times

- in line 771, 881, 1310

middle defined in line 987; used 1 times

- in line 520

mkfsym defined in line 1666; used 2 times

- in line 1243, 1252

readhdr defined in line 1920; used 2 times

- in line 827, 1276

rnd8k defined in line 1657; used 7 times

- in line 244, 1073, 1095, 1101, 1635-1642(3)

roundov defined in line 1998; used 2 times

- in line 556, 566

setupout defined in line 1179; used 1 times

- in line 521

skip defined in line 2105; used 3 times

- in line 299, 627, 686

slookup defined in line 1849; used 7 times

- in line 294, 386, 773, 1001-1003(3), 1959

step defined in line 701; used 3 times

- in line 626, 687, 781

sym2va defined in line 584; used 24 times

- in line 298, 776, 915, 1009(2), 1030(2), 1045(2), 1076(2), 1107(2), 1166, 1211, 1366, 1459, 1501(2), 1576-1577(2), 1838, 1876, 1965

tcreat defined in line 1937; used 7 times

- in line 1184-1194(6), 1546

#### Defined variables

Mflag defined in line 233; used 3 times

- in line 405, 607, 716

Oflag defined in line 235; used 3 times

- in line 446, 1021, 1195

Sflag defined in line 229; used 3 times

- in line 414, 860, 1338

Vspace defined in line 292; used 17 times

- in line 340, 777, 916, 1010, 1033, 1046, 1077, 1108, 1167, 1212, 1367, 1460, 1502, 1579, 1839, 1879, 1966

Xflag defined in line 228; used 3 times

- in line 411, 887, 1344

arflag defined in line 231; used 3 times

- in line 418, 1114-1116(2)

borigin defined in line 255; used 5 times

- in line 999, 1105, 1139, 1279, 1395

bsize defined in line 243; used 19 times

- in line 167, 321-325(3), 802, 833, 950(2), 1029, 1151(2), 1203, 1634, 1709-1714(4), 1735, 2128

cbrel defined in line 249; used 6 times

- in line 833, 903, 1279, 1327, 1455, 1934

cdrel defined in line 249; used 8 times

- in line 833, 899, 1278, 1323, 1392, 1452, 1933-1934(2)

ctrel defined in line 249; used 6 times

- in line 833, 895, 1277, 1319, 1389, 1449

curov defined in line 277; used 12 times

- in line 451-455(4), 467-470(3), 479, 569, 932, 1350, 1886

cursym defined in line 210; used 66 times

- in line 462, 835, 876-909(13), 920-931(6), 1152, 1305-1337(12), 1344, 1350-1351(3), 1358-1359(2), 1369-1376(5), 1553-1564(7), 1672-1675(5), 1832(2), 1841, 1854-1856(3), 1881-1883(3)

delarg defined in line 264; used 3 times

- in line 501-506(2), 1653

dflag defined in line 236; used 4 times

- in line 428, 1015, 1026, 1116

dirs defined in line 289; used 5 times

- in line 353-359(4), 1798

dorigin defined in line 255; used 10 times

- in line 535(2), 998, 1099-1104(4), 1135, 1278, 1394

dsize defined in line 243; used 9 times

- in line 394-396(2), 833, 949(2), 1028, 1104, 1202, 1634

errlev defined in line 264; used 5 times

- in line 1115, 1651-1653(2), 1904, 1917

filhdr defined in line 185; used 71 times

- in line 451-454(2), 467-470(2), 828-829(3), 838-844(4), 948-950(3), 1089-1095(8), 1195-1203(6), 1209, 1219-1225(7), 1286-1287(3), 1387-1395(11), 1615-1618(5), 1635-1647(4), 1923-1934(12)

filname defined in line 269; used 11 times

- in line 368, 519, 608, 1752-1757(5), 1811, 1906-1907(2)

hb defined in line 2035; used 2 times

- in line 2056-2060(2)

hshtab defined in line 200; used 7 times

- in line 313(2), 979, 1835, 1843-1844(2), 1872

iflag defined in line 237; used 7 times

- in line 432, 1021, 1067, 1102, 1195, 1514, 1641

infil defined in line 268; used 27 times

- in line 639-643(2), 652-658(3), 692, 705-706(2), 750-752(2), 845-846(2), 852, 1250-1251(2), 1259, 1289-1290(2), 1296, 1713-1714(2), 1755-1763(4), 1775-1776(2)

inov defined in line 278; used 9 times

- in line 449, 455-459(2), 473, 557, 563-568(2), 1349, 1389

lastsym defined in line 199; used 4 times

- in line 388, 915, 1877, 1895

local defined in line 218; used 3 times

- in line 1284, 1360, 1991

ndir defined in line 290; used 6 times

- in line 351-359(5), 1796

nflag defined in line 234; used 7 times

- in line 425, 1021, 1067, 1100, 1195, 1514, 1637

nsym defined in line 211; used 6 times

- in line 1152, 1463, 1547, 1568, 1592, 1616

numov defined in line 276; used 13 times

- in line 461, 474-475(2), 517, 1008, 1044, 1070, 1193-1196(2), 1224, 1493-1496(2), 1523

ofilename defined in line 267; used 4 times

- in line 379, 502, 1624, 1944

ofilfnd defined in line 266; used 2 times

- in line 380, 1621

ovbase defined in line 285; used 5 times

- in line 567, 1073-1080(3), 1095

ovhndlr defined in line 282; used 3 times

- in line 462, 1498-1499(2)

p_etext defined in line 201; used 4 times

- in line 1001, 1013, 1027, 1117

quiet defined in line 224; used 2 times

- in line 438, 1119

rflag defined in line 230; used 13 times

- in line 417, 518, 537, 1008, 1014, 1020, 1026, 1189, 1222, 1477, 1519, 1526, 1649

rstrtab defined in line 295; used 9 times

- in line 651-660(5), 668-669(2), 764-766(2)

sccsid defined in line 2; never used
sflag defined in line 232; used 8 times

- in line 421, 1021, 1149, 1187, 1204, 1343, 1531, 1670

ssize defined in line 244; used 6 times

- in line 951, 1150-1152(2), 1204-1209(3)

symhash defined in line 198; used 4 times

- in line 837(2), 970, 1875

symindex defined in line 219; used 14 times

- in line 836, 959, 1009, 1030, 1045, 1076, 1107, 1204, 1501, 1576, 1870, 1876-1878(3)

tfname defined in line 270; used 3 times

- in line 1185, 1944-1948(2)

torgwas defined in line 274; used 2 times

- in line 560-564(2)

torigin defined in line 255; used 12 times

- in line 560-567(3), 997, 1131, 1277, 1393, 1510-1515(2), 1674, 2001-2004(2)

trace defined in line 225; used 15 times

- in line 366, 435, 452, 468, 526, 558, 934, 1048, 1057, 1074, 1082, 1093-1096(2), 1373, 1887

tsize defined in line 243; used 20 times

- in line 451-460(3), 467-472(2), 833, 948(2), 1027, 1054-1056(3), 1068-1073(4), 1201, 1638-1646(3)

tsizwas defined in line 275; used 2 times

- in line 456-460(2)

verbose defined in line 226; used 2 times

- in line 441, 503

xflag defined in line 227; used 7 times

- in line 408, 422, 1149, 1187, 1343, 1549, 1670

#### Defined struct's

local defined in line 213; used 10 times

- in line 218(2), 1266(2), 1399(2), 1984-1986(4)

xsymbol defined in line 203; used 4 times

- in line 210(2), 282(2)

#### Defined typedef's

HDR defined in line 2034; used 6 times

- in line 2035, 2051-2060(4), 2111

#### Defined macros

AR_ATOI defined in line 2038; used 5 times

- in line 2068-2072(5)

Cptr defined in line 171; used 2 times

- in line 805, 1720

DECIMAL defined in line 2065; used 4 times

- in line 2068-2072(4)

HNDLR_NUM defined in line 284; used 1 times

- in line 1498

Iptr defined in line 170; used 4 times

- in line 1431, 1444, 1689, 1742

K56 defined in line 1631; used 3 times

- in line 1638-1646(3)

K64 defined in line 1632; used 1 times

- in line 1642

NDEFDIRS defined in line 288; used 1 times

- in line 351

NDIRS defined in line 287; used 2 times

- in line 289, 351

NNAMESIZE defined in line 127; used 27 times

- in line 190, 204, 739, 766-771(2), 877-881(2), 935, 1050, 1059, 1084, 1124, 1170, 1306-1310(2), 1372, 1562-1563(2), 1586-1587(2), 1672, 1832, 1841, 1854, 1881, 1889, 1962

NROUT defined in line 131; used 1 times

- in line 154

NSYM defined in line 130; used 6 times

- in line 198-200(2), 971, 1835, 1843, 1870

NSYMPR defined in line 132; used 2 times

- in line 218, 1360

NUM_IO_PLACES defined in line 178; used 1 times

- in line 180

NUM_VM_PAGES defined in line 125; used 2 times

- in line 124, 338

N_COMM defined in line 134; used 1 times

- in line 1038

OCTAL defined in line 2066; used 1 times

- in line 2071

RABS defined in line 136; never used
RBSS defined in line 139; never used
RDATA defined in line 138; never used
RELFLG defined in line 142; used 1 times

- in line 838

RELOC defined in line 174; used 14 times

- in line 322-323(2), 1388-1391(2), 1434-1444(9), 1765

REXT defined in line 140; used 1 times

- in line 1463

RTEXT defined in line 137; never used
STRINGS defined in line 176; used 14 times

- in line 855, 880-881(2), 941-944(3), 1299, 1309-1310(2), 1382-1385(3), 1721, 1767

STRINGS2 defined in line 177; used 6 times

- in line 661, 670-673(3), 769-771(2)

SYMBOLS defined in line 175; used 9 times

- in line 324-325(2), 842, 857-858(2), 1286, 1301-1303(2), 1766

SYMSPERSEG defined in line 128; used 2 times

- in line 590-591(2)

SYMTAB defined in line 197; used 1 times

- in line 592

TABSZ defined in line 738; used 3 times

- in line 741-746(3)

TEXT defined in line 173; used 19 times

- in line 320-321(2), 1387-1390(2), 1421-1431(9), 1764-1771(4), 1923-1924(2)

THUNKSIZ defined in line 144; used 4 times

- in line 1056, 1491, 1509-1510(2)

Last modified: 1998-01-25 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 5167 |