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