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