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