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
adrof defined in line 1952; used 1 times
copy defined in line 1970; used 5 times
delexit defined in line 497; used 6 times
dseek defined in line 1700; used 13 times
endload defined in line 509; used 1 times
enter defined in line 1860; used 3 times
error defined in line 1899; used 36 times
finishout defined in line 1482; used 1 times
get defined in line 1729; used 5 times
get_arobj defined in line 2048; used 3 times
getfile defined in line 1745; used 2 times
hreset defined in line 963; used 1 times
inistr defined in line 2115; used 3 times
ldrand defined in line 722; used 1 times
ldrsym defined in line 1155; used 3 times
libopen defined in line 1787; used 1 times
load1 defined in line 813; used 2 times
load1arg defined in line 598; used 2 times
load2 defined in line 1262; used 2 times
load2arg defined in line 1228; used 2 times
load2td defined in line 1398; used 2 times
lookloc defined in line 1982; used 2 times
lookup defined in line 1818; used 5 times
main defined in line 301; never used
mget defined in line 1678; used 4 times
mgets defined in line 790; used 3 times
middle defined in line 987; used 1 times
mkfsym defined in line 1666; used 2 times
readhdr defined in line 1920; used 2 times
rnd8k defined in line 1657; used 7 times
roundov defined in line 1998; used 2 times
setupout defined in line 1179; used 1 times
skip defined in line 2105; used 3 times
slookup defined in line 1849; used 7 times
step defined in line 701; used 3 times
sym2va defined in line 584; used 24 times
tcreat defined in line 1937; used 7 times

Defined variables

Mflag defined in line 233; used 3 times
Oflag defined in line 235; used 3 times
Sflag defined in line 229; used 3 times
Vspace defined in line 292; used 17 times
Xflag defined in line 228; used 3 times
arflag defined in line 231; used 3 times
borigin defined in line 255; used 5 times
bsize defined in line 243; used 19 times
cbrel defined in line 249; used 6 times
cdrel defined in line 249; used 8 times
ctrel defined in line 249; used 6 times
curov defined in line 277; used 12 times
cursym defined in line 210; used 66 times
delarg defined in line 264; used 3 times
dflag defined in line 236; used 4 times
dirs defined in line 289; used 5 times
dorigin defined in line 255; used 10 times
dsize defined in line 243; used 9 times
errlev defined in line 264; used 5 times
filhdr defined in line 185; used 71 times
filname defined in line 269; used 11 times
hb defined in line 2035; used 2 times
hshtab defined in line 200; used 7 times
iflag defined in line 237; used 7 times
infil defined in line 268; used 27 times
inov defined in line 278; used 9 times
lastsym defined in line 199; used 4 times
local defined in line 218; used 3 times
ndir defined in line 290; used 6 times
nflag defined in line 234; used 7 times
nsym defined in line 211; used 6 times
numov defined in line 276; used 13 times
ofilename defined in line 267; used 4 times
ofilfnd defined in line 266; used 2 times
ovbase defined in line 285; used 5 times
ovhndlr defined in line 282; used 3 times
p_etext defined in line 201; used 4 times
quiet defined in line 224; used 2 times
rflag defined in line 230; used 13 times
rstrtab defined in line 295; used 9 times
sccsid defined in line 2; never used
sflag defined in line 232; used 8 times
ssize defined in line 244; used 6 times
symhash defined in line 198; used 4 times
symindex defined in line 219; used 14 times
tfname defined in line 270; used 3 times
torgwas defined in line 274; used 2 times
torigin defined in line 255; used 12 times
trace defined in line 225; used 15 times
tsize defined in line 243; used 20 times
tsizwas defined in line 275; used 2 times
verbose defined in line 226; used 2 times
xflag defined in line 227; used 7 times

Defined struct's

local defined in line 213; used 10 times
xsymbol defined in line 203; used 4 times

Defined typedef's

HDR defined in line 2034; used 6 times

Defined macros

AR_ATOI defined in line 2038; used 5 times
Cptr defined in line 171; used 2 times
DECIMAL defined in line 2065; used 4 times
HNDLR_NUM defined in line 284; used 1 times
Iptr defined in line 170; used 4 times
K56 defined in line 1631; used 3 times
K64 defined in line 1632; used 1 times
NDEFDIRS defined in line 288; used 1 times
NDIRS defined in line 287; used 2 times
NNAMESIZE defined in line 127; used 27 times
NROUT defined in line 131; used 1 times
NSYM defined in line 130; used 6 times
NSYMPR defined in line 132; used 2 times
NUM_IO_PLACES defined in line 178; used 1 times
NUM_VM_PAGES defined in line 125; used 2 times
N_COMM defined in line 134; used 1 times
OCTAL defined in line 2066; used 1 times
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
RELOC defined in line 174; used 14 times
REXT defined in line 140; used 1 times
RTEXT defined in line 137; never used
STRINGS defined in line 176; used 14 times
STRINGS2 defined in line 177; used 6 times
SYMBOLS defined in line 175; used 9 times
SYMSPERSEG defined in line 128; used 2 times
SYMTAB defined in line 197; used 1 times
TABSZ defined in line 738; used 3 times
TEXT defined in line 173; used 19 times
THUNKSIZ defined in line 144; used 4 times
Last modified: 1998-01-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8948
Valid CSS Valid XHTML 1.0 Strict