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