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