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