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