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