1: #if defined(DOSCCS) && !defined(lint) 2: static char *sccsid = "@(#)ld.c 4.6 1998/01/19"; 3: #endif 4: 5: /* 6: * 4.6 1998/01/19 - Tim Shoppa (shoppa@triumf.ca) 7: * Minor bug fix: when tsize was being incremented by THUNKSZ, 8: * no check was being made for 16-bit overflow. Fix was to 9: * call add(). Same was done for the round up to the nearest 10: * 0100 on tsize. Modify add()'s error reporting to reduce memory 11: * usage - sms. 12: * 13: * 4.5 1997/10/31 - sms 14: * Minor cleanup. Use unistd.h and stdlib.h instead of local definitions. 15: * Correct comment about number of VM pages. 16: * 17: * 4.4 1995/05/08 - sms 18: * Add -q to turn off undefined symbol reporting. Used when building 19: * networking kernels and many undefineds are expected but look worrisome. 20: * Add -v to enable the VM statistics printout (now optional). 21: * 22: * 4.3 1/14/94 - sms 23: * Make the number of VM segments a compile time option in the Makefile. 24: * 4.2 1/2/94 - sms 25: * Fixed a couple serious bugs, one dealing with overlaid programs - the 26: * overlay header wasn't being written out, the second was a typographical 27: * error causing the relocation information to be wrong. 28: * 29: * 4.1 11/27/93 -sms 30: * Success at reading new style object files and libraries but the 31: * speed was abysmal. Logic added to attempt to hold string tables 32: * in memory when possible (less than 8kb) and to use a larger buffer 33: * when reading strings. Also, added a fifth i/o stream area for use 34: * by the library scanning routine 'ldrand' - this prevents the 'thrashing' 35: * between 'load1' and 'ldrand' (each of these was undoing the other's 36: * seek for a string). 37: * 38: * 4.0 11/1/93 - sms 39: * Previous versions not released. With 'ar' and 'ranlib' ported it 40: * is now 'ld's turn to be modified to support the new object file 41: * format. Major changes (and unfortunately another slip in speed). 42: * 43: * 3.0 9/15/93 - sms 44: * Implement a VM tmp file for the symbol table. 45: * 46: * 2.x 9/3/93 - sms@wlv.iipo.gtegsc.com 47: * Couple of major changes made in preparation for supporting long 48: * symbol names. 'ld' was approximately 1kb away from not running 49: * at all (due to data+bss exceeding 56kb). The first change 50: * made 'syshash' a bitmap saving 3.75kb. The next change involved 51: * modifying 'ldrand' so that the entire table of contents from a 52: * library did not have to fit in memory at once - this saved about 53: * 8kb. The last major change was a rewrite of the input subsystem 54: * making it faster and simpler. 55: */ 56: 57: #include <sys/param.h> 58: #include <sys/dir.h> 59: #include <stdio.h> 60: #include <signal.h> 61: #include <sys/stat.h> 62: #include <sys/file.h> 63: #include <a.out.h> 64: #include <ar.h> 65: #include <ranlib.h> 66: #include <vmf.h> 67: #include <unistd.h> 68: #include <stdlib.h> 69: #include "archive.h" 70: 71: /* 72: * Layout of standard part of a.out file header: 73: * u_int a_magic; magic number 74: * u_int a_text; text size ) 75: * u_int a_data; data size ) in bytes but even 76: * u_int a_bss; bss size ) 77: * u_int a_syms; symbol table size 78: * u_int a_entry; entry point 79: * u_int a_unused; (unused) 80: * u_int a_flag bit 0 set if no relocation 81: * 82: * Layout of overlaid part of a.out file header: 83: * int max_ovl; maximum overlay size 84: * u_int ov_siz[NOVL]; overlay sizes 85: * 86: * Non-overlaid offsets: 87: * header: 0 88: * text: 16 89: * data: 16 + a_text 90: * relocation: 16 + a_text + a_data 91: * 92: * If relocation info stripped: 93: * symbol table: 16 + a_text + a_data 94: * string table: 16 + a_text + a_data + a_syms 95: * else 96: * symbol table: 16 + 2 * (a_text + a_data) 97: * string table: 16 + 2 * (a_text + a_data) + a_syms 98: * 99: * Overlaid offsets: 100: * header: 0 101: * overlay header: 16 102: * text: 16 + 2 + 2*NOVL = 16 + 2 + 2*15 = 48 103: * data: 48 + a_text + SUM(ov_siz) 104: * relocation: 48 + a_text + SUM(ov_siz) + a_data 105: * 106: * If relocation info stripped: 107: * symbol table: 48 + a_text + SUM(ov_siz) + a_data 108: * string table: symbol_table + a_syms 109: * else 110: * symbol table: 48 + 2 * (a_text + SUM(ov_siz) + a_data) 111: * string table: symbol_table + a_syms 112: * 113: * where SUM(ov_siz) is the sum of the overlays. 114: */ 115: 116: /* 117: * Do not set the following too high (normally set in the Makefile) or 118: * 'ld' will not be able to allocate room (currently 8kb) for string 119: * tables and performance will suffer badly. It is possible that this 120: * could be raised a bit higher but 20 gives 'adequate' performance on 121: * all but the largest ('tcsh' for example) programs, and even there it's 122: * not _too_ bad. 123: */ 124: #ifndef NUM_VM_PAGES 125: #define NUM_VM_PAGES 20 126: #endif 127: #define NNAMESIZE 32 /* Maximum symbol string length */ 128: #define SYMSPERSEG (BYTESPERSEG / sizeof (SYMBOL)) 129: 130: #define NSYM 2000 /* 1103 originally */ 131: #define NROUT 350 /* 256 originally */ 132: #define NSYMPR 800 /* 1000 originally */ 133: 134: #define N_COMM 05 /* internal use only; other values in a.out.h */ 135: 136: #define RABS 00 137: #define RTEXT 02 138: #define RDATA 04 139: #define RBSS 06 140: #define REXT 010 141: 142: #define RELFLG 01 143: 144: #define THUNKSIZ 8 145: 146: /* 147: * one entry for each archive member referenced; 148: * set in first pass; needs restoring for overlays 149: */ 150: typedef struct { 151: long loc; 152: } LIBLIST; 153: 154: LIBLIST liblist[NROUT]; 155: LIBLIST *libp = liblist; 156: 157: typedef struct 158: { 159: union { 160: int *iptr; 161: char *cptr; 162: } ptr; 163: int bno; 164: int nibuf; 165: int nsize; 166: int nread; 167: int bsize; /* MUST be a power of 2 */ 168: int *buff; 169: } STREAM; 170: #define Iptr ptr.iptr 171: #define Cptr ptr.cptr 172: 173: #define TEXT 0 174: #define RELOC 1 175: #define SYMBOLS 2 176: #define STRINGS 3 177: #define STRINGS2 4 178: #define NUM_IO_PLACES 5 179: 180: STREAM Input[NUM_IO_PLACES]; 181: 182: /* 183: * Header from the a.out and the archive it is from (if any). 184: */ 185: struct xexec filhdr; 186: CHDR chdr; 187: 188: /* symbol management */ 189: typedef struct { 190: char n_name[NNAMESIZE]; 191: char n_type; 192: char n_ovly; 193: u_int n_value; 194: u_int sovalue; 195: } SYMBOL; 196: 197: #define SYMTAB ((VADDR)0) /* virtual base address of symbol table */ 198: u_short symhash[(NSYM+15)/16]; /* bitmap of hash table entries */ 199: short lastsym; /* index # of last symbol entered */ 200: short hshtab[NSYM+2]; /* hash table for symbols */ 201: short p_etext = -1, p_edata = -1, p_end = -1, entrypt = -1; 202: 203: struct xsymbol { 204: char n_name[NNAMESIZE]; 205: char n_type; 206: char n_ovly; 207: u_int n_value; 208: }; 209: 210: struct xsymbol cursym; /* current symbol */ 211: int nsym; /* pass2: number of local symbols */ 212: 213: struct local { 214: short locindex; /* index to symbol in file */ 215: short locsymbol; /* ptr to symbol table */ 216: }; 217: 218: struct local local[NSYMPR]; 219: short symindex; /* next available symbol table entry */ 220: 221: /* 222: * Options. 223: */ 224: int quiet; /* -q, suppress undefined error message */ 225: int trace; 226: int verbose; /* -v, emit VM statistics */ 227: int xflag; /* discard local symbols */ 228: int Xflag; /* discard locals starting with 'L' */ 229: int Sflag; /* discard all except locals and globals*/ 230: int rflag; /* preserve relocation bits, don't define common */ 231: int arflag; /* original copy of rflag */ 232: int sflag; /* discard all symbols */ 233: int Mflag; /* print rudimentary load map */ 234: int nflag; /* pure procedure */ 235: int Oflag; /* set magic # to 0405 (overlay) */ 236: int dflag; /* define common even with rflag */ 237: int iflag; /* I/D space separated */ 238: 239: /* 240: * These are the cumulative sizes, set in pass1, which 241: * appear in the a.out header when the loader is finished. 242: */ 243: u_int tsize, dsize, bsize; 244: long ssize, rnd8k(); 245: 246: /* 247: * Symbol relocation: 248: */ 249: u_int ctrel, cdrel, cbrel; 250: 251: /* 252: * The base addresses for the loaded text, data and bass from the 253: * current module during pass2 are given by torigin, dorigin and borigin. 254: */ 255: u_int torigin, dorigin, borigin; 256: 257: /* 258: * Errlev is nonzero when errors have occured. 259: * Delarg is an implicit argument to the routine delexit 260: * which is called on error. We do ``delarg = errlev'' before normal 261: * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the 262: * result file executable. 263: */ 264: int errlev, delarg = 4; 265: 266: int ofilfnd; /* -o given; otherwise move l.out to a.out */ 267: char *ofilename = "l.out"; 268: int infil; /* current input file descriptor */ 269: char *filname; /* and its name */ 270: char tfname[] = "/tmp/ldaXXXXX"; 271: 272: FILE *toutb, *doutb, *troutb, *droutb, *soutb, *voutb; 273: 274: u_int torgwas; /* Saves torigin while doing overlays */ 275: u_int tsizwas; /* Saves tsize while doing overlays */ 276: int numov; /* Total number of overlays */ 277: int curov; /* Overlay being worked on just now */ 278: int inov; /* 1 if working on an overlay */ 279: 280: /* Kernel overlays have a special subroutine to do the switch */ 281: 282: struct xsymbol ovhndlr = 283: { "ovhndlr1", N_EXT+N_UNDF, 0, 0 }; 284: #define HNDLR_NUM 7 /* position of ov number in ovhndlr.n_name[] */ 285: u_int ovbase; /* The base address of the overlays */ 286: 287: #define NDIRS 25 288: #define NDEFDIRS 3 /* number of default directories in dirs[] */ 289: char *dirs[NDIRS]; /* directories for library search */ 290: int ndir; /* number of directories */ 291: 292: struct vspace Vspace; /* The virtual address space for symbols */ 293: 294: short *lookup(), *slookup(), *lookloc(); 295: char *rstrtab; /* ranlib string table pointer */ 296: u_int add(); 297: int delexit(); 298: VADDR sym2va(); 299: off_t skip(); 300: 301: main(argc, argv) 302: char **argv; 303: { 304: register int c, i; 305: int num; 306: register char *ap, **p; 307: char save; 308: 309: /* 310: * Initialize the hash table, indicating that all entries are unused. 311: * -1 is used as a "no symbol" flag. 312: */ 313: memset(hshtab, -1, sizeof(hshtab)); 314: 315: /* 316: * Initialize the first three input buffers. The remaining two are 317: * left for later because it may be possible to hold the string table 318: * in memory and the input buffer won't be needed. 319: */ 320: Input[TEXT].buff = (int *)malloc(512); 321: Input[TEXT].bsize = 512; 322: Input[RELOC].buff = (int *)malloc(512); 323: Input[RELOC].bsize = 512; 324: Input[SYMBOLS].buff = (int *)malloc(512); 325: Input[SYMBOLS].bsize = 512; 326: 327: if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 328: signal(SIGINT, delexit); 329: signal(SIGTERM, delexit); 330: } 331: if (argc == 1) 332: exit(4); 333: /* 334: * Initialize the "VM" system with NUM_VM_PAGES memory segments (memory 335: * resident pages). Then "open the address space" - this creates the paging 336: * (tmp) file. 337: */ 338: if (vminit(NUM_VM_PAGES) < 0) 339: error(1, "vminit failed"); 340: if (vmopen(&Vspace, (char *)NULL) < 0) 341: error(1, "vmopen failed"); 342: 343: /* 344: * Pull out search directories. 345: */ 346: for (c = 1; c < argc; c++) { 347: ap = argv[c]; 348: if (ap[0] == '-' && ap[1] == 'L') { 349: if (ap[2] == 0) 350: error(1, "-L: pathname missing"); 351: if (ndir >= NDIRS - NDEFDIRS) 352: error(1, "-L: too many directories"); 353: dirs[ndir++] = &ap[2]; 354: } 355: } 356: /* add default search directories */ 357: dirs[ndir++] = "/lib"; 358: dirs[ndir++] = "/usr/lib"; 359: dirs[ndir++] = "/usr/local/lib"; 360: 361: p = argv+1; 362: /* 363: * Scan files once to find where symbols are defined. 364: */ 365: for (c=1; c<argc; c++) { 366: if (trace) 367: printf("%s:\n", *p); 368: filname = 0; 369: ap = *p++; 370: if (*ap != '-') { 371: load1arg(ap, 1); 372: continue; 373: } 374: for (i=1; ap[i]; i++) switch (ap[i]) { 375: 376: case 'o': 377: if (++c >= argc) 378: error(1, "-o where?"); 379: ofilename = *p++; 380: ofilfnd++; 381: continue; 382: case 'u': 383: case 'e': 384: if (++c >= argc) 385: error(1, "-u or -c: arg missing"); 386: enter(slookup(*p++)); 387: if (ap[i]=='e') 388: entrypt = lastsym; 389: continue; 390: case 'D': 391: if (++c >= argc) 392: error(1, "-D: arg missing"); 393: num = atoi(*p++); 394: if (dsize>num) 395: error(1, "-D: too small"); 396: dsize = num; 397: continue; 398: case 'l': 399: save = ap[--i]; 400: ap[i]='-'; 401: load1arg(&ap[i], -1); 402: ap[i]=save; 403: goto next; 404: case 'M': 405: Mflag++; 406: continue; 407: case 'x': 408: xflag++; 409: continue; 410: case 'X': 411: Xflag++; 412: continue; 413: case 'S': 414: Sflag++; 415: continue; 416: case 'r': 417: rflag++; 418: arflag++; 419: continue; 420: case 's': 421: sflag++; 422: xflag++; 423: continue; 424: case 'n': 425: nflag++; 426: continue; 427: case 'd': 428: dflag++; 429: continue; 430: case 'i': 431: case 'z': 432: iflag++; 433: continue; 434: case 't': 435: trace++; 436: continue; 437: case 'q': 438: quiet++; 439: continue; 440: case 'v': 441: verbose++; 442: continue; 443: case 'L': 444: goto next; 445: case 'O': 446: Oflag++; 447: continue; 448: case 'Y': 449: if (inov == 0) 450: error(1, "-Y: Not in overlay"); 451: filhdr.o.ov_siz[curov - 1] = tsize; 452: if (trace) 453: printf("overlay %d size %d\n", curov, 454: filhdr.o.ov_siz[curov - 1]); 455: curov = inov = 0; 456: tsize = tsizwas; 457: continue; 458: case 'Z': 459: if (!inov) { 460: tsizwas = tsize; 461: if (numov == 0) { 462: cursym = ovhndlr; 463: enter(lookup()); 464: } 465: } 466: else { 467: filhdr.o.ov_siz[curov - 1] = tsize; 468: if (trace) 469: printf("overlay %d size %d\n", curov, 470: filhdr.o.ov_siz[curov - 1]); 471: } 472: tsize = 0; 473: inov = 1; 474: numov++; 475: if (numov > NOVL) { 476: printf("ld:too many overlays, max is %d\n",NOVL); 477: error(1, (char *)NULL); 478: } 479: curov++; 480: continue; 481: case 'y': 482: case 'A': 483: case 'H': 484: case 'N': 485: case 'T': 486: default: 487: printf("ld:bad flag %c\n",ap[i]); 488: error(1, (char *)NULL); 489: } 490: next: 491: ; 492: } 493: endload(argc, argv); 494: exit(0); 495: } 496: 497: delexit() 498: { 499: 500: unlink("l.out"); 501: if (delarg==0) 502: chmod(ofilename, 0777 & ~umask(0)); 503: if (verbose) 504: printf("ld: nswaps: %ld, nmapsegs: %ld sbrk(0): %u\n", nswaps, 505: nmapsegs, sbrk(0)); 506: exit(delarg); 507: } 508: 509: endload(argc, argv) 510: int argc; 511: char **argv; 512: { 513: register int c, i; 514: int dnum; 515: register char *ap, **p; 516: 517: if (numov) 518: rflag = 0; 519: filname = 0; 520: middle(); 521: setupout(); 522: p = argv+1; 523: libp = liblist; 524: for (c=1; c<argc; c++) { 525: ap = *p++; 526: if (trace) 527: printf("%s:\n", ap); 528: if (*ap != '-') { 529: load2arg(ap, 1); 530: continue; 531: } 532: for (i=1; ap[i]; i++) switch (ap[i]) { 533: 534: case 'D': 535: for (dnum = atoi(*p);dorigin < dnum; dorigin += 2) { 536: putw(0, doutb); 537: if (rflag) 538: putw(0, droutb); 539: } 540: /* fall into ... */ 541: case 'u': 542: case 'e': 543: case 'o': 544: ++c; 545: ++p; 546: /* fall into ... */ 547: default: 548: continue; 549: case 'L': 550: goto next; 551: case 'l': 552: ap[--i]='-'; 553: load2arg(&ap[i], -1); 554: goto next; 555: case 'Y': 556: roundov(); 557: inov = 0; 558: if (trace) 559: printf("end overlay generation\n"); 560: torigin = torgwas; 561: continue; 562: case 'Z': 563: if (inov == 0) 564: torgwas = torigin; 565: else 566: roundov(); 567: torigin = ovbase; 568: inov = 1; 569: curov++; 570: continue; 571: } 572: next: 573: ; 574: } 575: finishout(); 576: } 577: 578: /* 579: * Compute a symbol's virtual address from its index number. The code is 580: * a bit ugly (and made a routine rather than a macro) because the page 581: * size does not divide evenly by the size of a symbol. 582: */ 583: 584: VADDR 585: sym2va(x) 586: u_short x; 587: { 588: register u_short i, j; 589: 590: i = (x % SYMSPERSEG) * sizeof (SYMBOL); 591: j = x / SYMSPERSEG; 592: return(SYMTAB+ i + ((long)j << LOG2BPS)); 593: } 594: 595: /* 596: * Scan file to find defined symbols. 597: */ 598: load1arg(cp, flag) 599: register char *cp; 600: int flag; 601: { 602: off_t nloc; 603: int kind, tnum; 604: long ltnum, strsize; 605: 606: kind = getfile(cp, flag, 1); 607: if (Mflag) 608: printf("%s\n", filname); 609: switch (kind) { 610: 611: /* 612: * Plain file. 613: */ 614: case 0: 615: load1(0, 0L); 616: break; 617: 618: /* 619: * Archive without table of contents. 620: * (Slowly) process each member. 621: */ 622: case 1: 623: error(-1, 624: "warning: archive has no table of contents; add one using ranlib(1)"); 625: nloc = SARMAG; 626: while (step(nloc)) 627: nloc += skip(); 628: break; 629: 630: /* 631: * Archive with table of contents. 632: * Read the table of contents and its associated string table. 633: * Pass through the library resolving symbols until nothing changes 634: * for an entire pass (i.e. you can get away with backward references 635: * when there is a table of contents!) 636: */ 637: case 2: 638: nloc = SARMAG + sizeof (struct ar_hdr) + chdr.lname; 639: lseek(infil, nloc, L_SET); 640: /* 641: * Read the size of the ranlib structures (a long). 642: */ 643: read(infil, <num, sizeof (ltnum)); 644: /* 645: * calculate string table position. Add in the ranlib size (4 bytes), 646: * the size of the ranlib structures (ltnum) from above. 647: */ 648: nloc += (sizeof (ltnum) + ltnum); 649: tnum = ltnum / sizeof (struct ranlib); 650: 651: rstrtab = NULL; 652: lseek(infil, nloc, L_SET); 653: read(infil, &strsize, sizeof (long)); 654: if (strsize <= 8192L) 655: { 656: rstrtab = (char *)malloc((int)strsize); 657: if (rstrtab) 658: read(infil, rstrtab, (int)strsize); 659: } 660: if (!rstrtab) 661: inistr(STRINGS2); 662: 663: while (ldrand(tnum, nloc)) 664: ; 665: libp->loc = -1; 666: libp++; 667: 668: if (rstrtab) 669: free(rstrtab); 670: if (Input[STRINGS2].buff) 671: { 672: free(Input[STRINGS2].buff); 673: Input[STRINGS2].buff = NULL; 674: } 675: break; 676: 677: /* 678: * Table of contents is out of date, so search 679: * as a normal library (but skip the __.SYMDEF file). 680: */ 681: case 3: 682: error(-1, 683: "warning: table of contents for archive is out of date; rerun ranlib(1)"); 684: nloc = SARMAG; 685: do 686: nloc += skip(); 687: while (step(nloc)); 688: break; 689: case -1: 690: return; 691: } 692: close(infil); 693: } 694: 695: /* 696: * Advance to the next archive member, which 697: * is at offset nloc in the archive. If the member 698: * is useful, record its location in the liblist structure 699: * for use in pass2. Mark the end of the archive in libilst with a -1. 700: */ 701: step(nloc) 702: off_t nloc; 703: { 704: 705: lseek(infil, nloc, L_SET); 706: if (get_arobj(infil) <= 0) 707: { 708: libp->loc = -1; 709: libp++; 710: return (0); 711: } 712: if (load1(1, nloc + sizeof (struct ar_hdr) + chdr.lname)) 713: { 714: libp->loc = nloc; 715: libp++; 716: if (Mflag) 717: printf("\t%s\n", chdr.name); 718: } 719: return (1); 720: } 721: 722: ldrand(totnum, sloc) 723: int totnum; 724: off_t sloc; 725: { 726: register int ntab; 727: SYMBOL *sp; 728: short *hp; 729: VADDR vsym; 730: LIBLIST *oldp = libp; 731: int amt, tnum = totnum; 732: off_t loc; 733: /* 734: * 'ar' header + member header + SYMDEF table.of.contents + long filename 735: */ 736: off_t opos = (off_t)SARMAG + sizeof (struct ar_hdr) + sizeof (long) + 737: chdr.lname; 738: #define TABSZ 64 739: char localname[NNAMESIZE]; 740: register struct ranlib *tp; 741: struct ranlib tab[TABSZ], *tplast; 742: 743: while (tnum) 744: { 745: if (tnum > TABSZ) 746: ntab = TABSZ; 747: else 748: ntab = tnum; 749: tplast = &tab[ntab - 1]; 750: (void)lseek(infil, opos, L_SET); 751: amt = ntab * sizeof (struct ranlib); 752: if (read(infil, tab, amt) != amt) 753: error(1, "EOF in ldrand"); 754: tnum -= ntab; 755: opos += amt; 756: 757: for (tp = tab; tp <= tplast; tp++) 758: { 759: /* 760: * This is slower and uglier than we would like, but it is not always 761: * possible to hold the entire string table in memory. Need to add 762: * an extra increment to skip over the string table size longword. 763: */ 764: if (rstrtab) 765: strncpy(localname, (int)tp->ran_un.ran_strx + 766: rstrtab, NNAMESIZE); 767: else 768: { 769: dseek(STRINGS2, tp->ran_un.ran_strx + sloc + 770: sizeof (long), 07777); 771: mgets(localname, NNAMESIZE, STRINGS2); 772: } 773: hp = slookup(localname); 774: if (*hp == -1) 775: continue; 776: vsym = sym2va(*hp); 777: sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + 778: VOFF(vsym)); 779: if (sp->n_type != N_EXT+N_UNDF) 780: continue; 781: step(tp->ran_off); 782: loc = tp->ran_off; 783: while (tp < tplast && (tp+1)->ran_off == loc) 784: tp++; 785: } 786: } 787: return(oldp != libp); 788: } 789: 790: mgets(buf, maxlen, which) 791: register char *buf; 792: int maxlen, which; 793: { 794: register STREAM *sp; 795: register int n; 796: 797: sp = &Input[which]; 798: for (n = 0; n < maxlen; n++) 799: { 800: if (--sp->nibuf < 0) 801: { 802: dseek(which, (off_t)(sp->bno + 1) * sp->bsize, 077777); 803: sp->nibuf--; 804: } 805: if ((*buf++ = *sp->Cptr++) == 0) 806: break; 807: } 808: } 809: 810: /* 811: * Examine a single file or archive member on pass 1. 812: */ 813: load1(libflg, loc) 814: off_t loc; 815: { 816: register SYMBOL *sp; 817: int savindex; 818: int ndef, type, mtype; 819: long nlocal; 820: VADDR vsym; 821: struct nlist objsym; 822: off_t strloc; 823: long strsize; 824: char *strtab; 825: register struct vseg *seg; 826: 827: readhdr(loc); 828: if (filhdr.e.a_syms == 0) { 829: if (filhdr.e.a_text+filhdr.e.a_data == 0) 830: return (0); 831: error(1, "no namelist"); 832: } 833: ctrel = tsize; cdrel += dsize; cbrel += bsize; 834: ndef = 0; 835: nlocal = sizeof (cursym); 836: savindex = symindex; 837: bzero(symhash, sizeof (symhash)); 838: if ((filhdr.e.a_flag&RELFLG)==1) { 839: error(1, "No relocation bits"); 840: return(0); 841: } 842: dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms); 843: 844: strloc = loc + N_STROFF(filhdr); 845: lseek(infil, strloc, L_SET); 846: read(infil, &strsize, sizeof (long)); 847: strtab = NULL; 848: if (strsize <= 8192L) 849: { 850: strtab = (char *)malloc((int)strsize); 851: if (strtab) 852: read(infil, strtab, (int)strsize); 853: } 854: if (!strtab) 855: inistr(STRINGS); 856: 857: while (Input[SYMBOLS].nsize > 0) { 858: mget((int *)&objsym, sizeof objsym, SYMBOLS); 859: type = objsym.n_type; 860: if (Sflag) { 861: mtype = type&037; 862: if (mtype==1 || mtype>4) { 863: continue; 864: } 865: } 866: /* 867: * Now convert 'nlist' format symbol to 'fixed' (semi old style) format. 868: * This may look strange but it greatly simplifies things and avoids having 869: * to read the entire string table into virtual memory. 870: * 871: * Also, we access the symbols in order. The assembler was nice enough 872: * to place the strings in the same order as the symbols - so effectively 873: * we are doing a sequential read of the string table. 874: */ 875: if (strtab) 876: strncpy(cursym.n_name, (int)objsym.n_un.n_strx + 877: strtab - sizeof (long), NNAMESIZE); 878: else 879: { 880: dseek(STRINGS, objsym.n_un.n_strx + strloc, 077777); 881: mgets(cursym.n_name, NNAMESIZE, STRINGS); 882: } 883: cursym.n_type = objsym.n_type; 884: cursym.n_value = objsym.n_value; 885: cursym.n_ovly = objsym.n_ovly; 886: if ((type&N_EXT)==0) { 887: if (Xflag==0 || cursym.n_name[0]!='L') 888: nlocal += sizeof (cursym); 889: continue; 890: } 891: 892: switch (cursym.n_type) { 893: case N_TEXT: 894: case N_EXT+N_TEXT: 895: cursym.n_value += ctrel; 896: break; 897: case N_DATA: 898: case N_EXT+N_DATA: 899: cursym.n_value += cdrel; 900: break; 901: case N_BSS: 902: case N_EXT+N_BSS: 903: cursym.n_value += cbrel; 904: break; 905: case N_EXT+N_UNDF: 906: break; 907: default: 908: if (cursym.n_type&N_EXT) 909: cursym.n_type = N_EXT+N_ABS; 910: break; 911: } 912: 913: if (enter(lookup())) 914: continue; 915: vsym = sym2va(lastsym); 916: seg = vmmapseg(&Vspace, VSEG(vsym)); 917: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 918: if (sp->n_type != N_EXT+N_UNDF) 919: continue; 920: if (cursym.n_type == N_EXT+N_UNDF) { 921: if (cursym.n_value > sp->n_value) { 922: sp->n_value = cursym.n_value; 923: vmmodify(seg); 924: } 925: continue; 926: } 927: if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) 928: continue; 929: ndef++; 930: sp->n_type = cursym.n_type; 931: sp->n_value = cursym.n_value; 932: sp->n_ovly = ((sp->n_type &~ N_EXT) == N_TEXT) ? curov : 0; 933: VMMODIFY(seg); 934: if (trace) 935: printf("%.*s type 0%o in overlay %u at %u\n", NNAMESIZE, 936: sp->n_name, sp->n_type, sp->n_ovly, sp->n_value); 937: } 938: 939: if (strtab) 940: free(strtab); 941: if (Input[STRINGS].buff) 942: { 943: free(Input[STRINGS].buff); 944: Input[STRINGS].buff = NULL; 945: } 946: 947: if (libflg==0 || ndef) { 948: tsize = add(tsize,filhdr.e.a_text,"text"); 949: dsize = add(dsize,filhdr.e.a_data,"data"); 950: bsize = add(bsize,filhdr.e.a_bss,"bss"); 951: ssize += nlocal; 952: return (1); 953: } 954: /* 955: * No symbols defined by this library member. 956: * Rip out the hash table entries and reset the symbol table. 957: */ 958: hreset(); 959: symindex = savindex; 960: return(0); 961: } 962: 963: static 964: hreset() 965: { 966: register u_short *sp, i; 967: u_short j; 968: register u_short mask; 969: 970: sp = symhash; 971: for (i = 0; i < NSYM; sp++, i += 16) 972: { 973: if (*sp == 0) 974: continue; 975: for (mask = 1, j = i; *sp; j++) 976: { 977: if (*sp & mask) 978: { 979: hshtab[j] = -1; 980: *sp &= ~mask; 981: } 982: mask <<= 1; 983: } 984: } 985: } 986: 987: middle() 988: { 989: VADDR vsym; 990: register SYMBOL *sp; 991: register int i; 992: register struct vseg *seg; 993: u_int csize; 994: u_int nund, corigin; 995: u_int ttsize; 996: 997: torigin = 0; 998: dorigin = 0; 999: borigin = 0; 1000: 1001: p_etext = *slookup("_etext"); 1002: p_edata = *slookup("_edata"); 1003: p_end = *slookup("_end"); 1004: /* 1005: * If there are any undefined symbols, save the relocation bits. 1006: * (Unless we are overlaying.) 1007: */ 1008: if (rflag==0 && !numov) { 1009: for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { 1010: sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + 1011: VOFF(vsym)); 1012: if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 1013: && i != p_end && i != p_edata && i != p_etext) { 1014: rflag++; 1015: dflag = 0; 1016: break; 1017: } 1018: } 1019: } 1020: if (rflag) 1021: nflag = sflag = iflag = Oflag = 0; 1022: /* 1023: * Assign common locations. 1024: */ 1025: csize = 0; 1026: if (dflag || rflag==0) { 1027: ldrsym(p_etext, tsize, N_EXT+N_TEXT); 1028: ldrsym(p_edata, dsize, N_EXT+N_DATA); 1029: ldrsym(p_end, bsize, N_EXT+N_BSS); 1030: for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { 1031: register int t; 1032: 1033: seg = vmmapseg(&Vspace, VSEG(vsym)); 1034: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1035: if (sp->n_type==N_EXT+N_UNDF && (t = sp->n_value)!=0) { 1036: t = (t+1) & ~01; 1037: sp->n_value = csize; 1038: sp->n_type = N_EXT+N_COMM; 1039: VMMODIFY(seg); 1040: csize = add(csize, t, "bss"); 1041: } 1042: } 1043: } 1044: if (numov) { 1045: for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { 1046: seg = vmmapseg(&Vspace, VSEG(vsym)); 1047: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1048: if (trace) 1049: printf("%.*s n_type %o n_value %o sovalue %o ovly %d\n", 1050: NNAMESIZE, sp->n_name, sp->n_type, 1051: sp->n_value, sp->sovalue, sp->n_ovly); 1052: if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) { 1053: sp->sovalue = sp->n_value; 1054: sp->n_value = tsize; 1055: VMMODIFY(seg); 1056: tsize = add(tsize, THUNKSIZ, "text"); 1057: if (trace) 1058: printf("relocating %.*s in overlay %d from %o to %o\n", 1059: NNAMESIZE,sp->n_name,sp->n_ovly, 1060: sp->sovalue, sp->n_value); 1061: } 1062: } 1063: } 1064: /* 1065: * Now set symbols to their final value 1066: */ 1067: if (nflag || iflag) 1068: tsize = add(tsize, 077, "text") & ~077; 1069: ttsize = tsize; 1070: if (numov) { 1071: register int i; 1072: 1073: ovbase = (u_int)rnd8k(tsize); 1074: if (trace) 1075: printf("overlay base is %u.\n", ovbase); 1076: for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { 1077: seg = vmmapseg(&Vspace, VSEG(vsym)); 1078: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1079: if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) { 1080: sp->sovalue += ovbase; 1081: VMMODIFY(seg); 1082: if (trace) 1083: printf("%.*s at %u overlay %d\n", 1084: NNAMESIZE, sp->n_name, 1085: sp->sovalue, sp->n_ovly); 1086: } 1087: } 1088: for (i = 0; i < NOVL; i++) { 1089: filhdr.o.ov_siz[i] = (filhdr.o.ov_siz[i] + 077) &~ 077; 1090: if (filhdr.o.ov_siz[i] > filhdr.o.max_ovl) 1091: filhdr.o.max_ovl = filhdr.o.ov_siz[i]; 1092: } 1093: if (trace) 1094: printf("max overlay size is %u\n", filhdr.o.max_ovl); 1095: ttsize = (u_int)rnd8k(ovbase + filhdr.o.max_ovl); 1096: if (trace) 1097: printf("overlays end before %u.\n", ttsize); 1098: } 1099: dorigin = ttsize; 1100: if (nflag) 1101: dorigin = (u_int)rnd8k(ttsize); 1102: if (iflag) 1103: dorigin = 0; 1104: corigin = dorigin + dsize; 1105: borigin = corigin + csize; 1106: nund = 0; 1107: for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { 1108: seg = vmmapseg(&Vspace, VSEG(vsym)); 1109: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1110: 1111: switch (sp->n_type) { 1112: 1113: case N_EXT+N_UNDF: 1114: if (arflag == 0) 1115: errlev |= 01; 1116: if ((arflag==0 || dflag) && sp->n_value==0) { 1117: if (i == p_end || i == p_etext || i == p_edata) 1118: continue; 1119: if (quiet) 1120: continue; 1121: if (nund==0) 1122: printf("Undefined:\n"); 1123: nund++; 1124: printf("%.*s\n", NNAMESIZE, sp->n_name); 1125: } 1126: continue; 1127: case N_EXT+N_ABS: 1128: default: 1129: continue; 1130: case N_EXT+N_TEXT: 1131: sp->n_value += torigin; 1132: VMMODIFY(seg); 1133: continue; 1134: case N_EXT+N_DATA: 1135: sp->n_value += dorigin; 1136: VMMODIFY(seg); 1137: continue; 1138: case N_EXT+N_BSS: 1139: sp->n_value += borigin; 1140: VMMODIFY(seg); 1141: continue; 1142: case N_EXT+N_COMM: 1143: sp->n_type = N_EXT+N_BSS; 1144: sp->n_value += corigin; 1145: VMMODIFY(seg); 1146: continue; 1147: } 1148: } 1149: if (sflag || xflag) 1150: ssize = 0; 1151: bsize = add(bsize, csize, "bss"); 1152: nsym = ssize / (sizeof cursym); 1153: } 1154: 1155: ldrsym(ix, val, type) 1156: short ix; 1157: u_int val; 1158: int type; 1159: { 1160: VADDR vsym; 1161: register struct vseg *seg; 1162: register SYMBOL *sp; 1163: 1164: if (ix == -1) 1165: return; 1166: vsym = sym2va(ix); 1167: seg = vmmapseg(&Vspace, VSEG(vsym)); 1168: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1169: if (sp->n_type != N_EXT+N_UNDF || sp->n_value) { 1170: printf("%.*s: n_value %o", NNAMESIZE, sp->n_name, sp->n_value); 1171: error(0, "attempt to redefine loader-defined symbol"); 1172: return; 1173: } 1174: sp->n_type = type; 1175: sp->n_value = val; 1176: VMMODIFY(seg); 1177: } 1178: 1179: setupout() 1180: { 1181: VADDR vsym; 1182: register SYMBOL *sp; 1183: 1184: tcreat(&toutb, 0); 1185: mktemp(tfname); 1186: tcreat(&doutb, 1); 1187: if (sflag==0 || xflag==0) 1188: tcreat(&soutb, 1); 1189: if (rflag) { 1190: tcreat(&troutb, 1); 1191: tcreat(&droutb, 1); 1192: } 1193: if (numov) 1194: tcreat(&voutb, 1); 1195: filhdr.e.a_magic = (Oflag ? A_MAGIC4 : (iflag ? A_MAGIC3 : (nflag ? A_MAGIC2 : A_MAGIC1))); 1196: if (numov) { 1197: if (filhdr.e.a_magic == A_MAGIC1) 1198: error(1, "-n or -i must be used with overlays"); 1199: filhdr.e.a_magic |= 020; 1200: } 1201: filhdr.e.a_text = tsize; 1202: filhdr.e.a_data = dsize; 1203: filhdr.e.a_bss = bsize; 1204: ssize = sflag? 0 : (ssize + (sizeof (struct nlist)) * symindex); 1205: /* 1206: * This is an estimate, the real size is computed later and the 1207: * a.out header rewritten with the correct value. 1208: */ 1209: filhdr.e.a_syms = ssize&0177777; 1210: if (entrypt != -1) { 1211: vsym = sym2va(entrypt); 1212: sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + 1213: VOFF(vsym)); 1214: if (sp->n_type!=N_EXT+N_TEXT) 1215: error(0, "entry point not in text"); 1216: else if (sp->n_ovly) 1217: error(0, "entry point in overlay"); 1218: else 1219: filhdr.e.a_entry = sp->n_value | 01; 1220: } else 1221: filhdr.e.a_entry = 0; 1222: filhdr.e.a_flag = (rflag==0); 1223: fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb); 1224: if (numov) 1225: fwrite(&filhdr.o, sizeof (filhdr.o), 1, toutb); 1226: } 1227: 1228: load2arg(acp, flag) 1229: char *acp; 1230: int flag; 1231: { 1232: register char *cp; 1233: register LIBLIST *lp; 1234: 1235: cp = acp; 1236: switch (getfile(cp, flag, 2)) 1237: { 1238: case 0: 1239: while (*cp) 1240: cp++; 1241: while (cp >= acp && *--cp != '/') 1242: ; 1243: mkfsym(++cp); 1244: load2(0L); 1245: break; 1246: case -1: 1247: return; 1248: default: /* scan archive members referenced */ 1249: for (lp = libp; lp->loc != -1; lp++) { 1250: lseek(infil, lp->loc, L_SET); 1251: get_arobj(infil); 1252: mkfsym(chdr.name); 1253: load2(lp->loc + sizeof (struct ar_hdr) + 1254: chdr.lname); 1255: } 1256: libp = ++lp; 1257: break; 1258: } 1259: close(infil); 1260: } 1261: 1262: load2(loc) 1263: long loc; 1264: { 1265: register SYMBOL *sp; 1266: register struct local *lp; 1267: register int symno; 1268: int type, mtype; 1269: VADDR vsym; 1270: short i; 1271: struct nlist objsym; 1272: off_t stroff; 1273: char *strtab; 1274: long strsize; 1275: 1276: readhdr(loc); 1277: ctrel = torigin; 1278: cdrel += dorigin; 1279: cbrel += borigin; 1280: /* 1281: * Reread the symbol table, recording the numbering 1282: * of symbols for fixing external references. 1283: */ 1284: lp = local; 1285: symno = -1; 1286: dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms); 1287: stroff = loc + N_STROFF(filhdr); 1288: 1289: lseek(infil, stroff, L_SET); 1290: read(infil, &strsize, sizeof (long)); 1291: strtab = NULL; 1292: if (strsize <= 8192L) 1293: { 1294: strtab = (char *)malloc((int)strsize); 1295: if (strtab) 1296: read(infil, strtab, (int)strsize); 1297: } 1298: if (!strtab) 1299: inistr(STRINGS); 1300: 1301: while (Input[SYMBOLS].nsize > 0) { 1302: symno++; 1303: mget((int *)&objsym, sizeof objsym, SYMBOLS); 1304: if (strtab) 1305: strncpy(cursym.n_name, (int)objsym.n_un.n_strx + 1306: strtab - sizeof (long), NNAMESIZE); 1307: else 1308: { 1309: dseek(STRINGS, objsym.n_un.n_strx + stroff, 07777); 1310: mgets(cursym.n_name, NNAMESIZE, STRINGS); 1311: } 1312: cursym.n_type = objsym.n_type; 1313: cursym.n_value = objsym.n_value; 1314: cursym.n_ovly = objsym.n_ovly; 1315: 1316: switch (cursym.n_type) { 1317: case N_TEXT: 1318: case N_EXT+N_TEXT: 1319: cursym.n_value += ctrel; 1320: break; 1321: case N_DATA: 1322: case N_EXT+N_DATA: 1323: cursym.n_value += cdrel; 1324: break; 1325: case N_BSS: 1326: case N_EXT+N_BSS: 1327: cursym.n_value += cbrel; 1328: break; 1329: case N_EXT+N_UNDF: 1330: break; 1331: default: 1332: if (cursym.n_type&N_EXT) 1333: cursym.n_type = N_EXT+N_ABS; 1334: break; 1335: } 1336: 1337: type = cursym.n_type; 1338: if (Sflag) { 1339: mtype = type&037; 1340: if (mtype==1 || mtype>4) continue; 1341: } 1342: if ((type&N_EXT) == 0) { 1343: if (!sflag && !xflag && 1344: (!Xflag || cursym.n_name[0] != 'L')) { 1345: /* 1346: * preserve overlay number for locals 1347: * mostly for adb. mjk 7/81 1348: */ 1349: if ((type == N_TEXT) && inov) 1350: cursym.n_ovly = curov; 1351: fwrite(&cursym, sizeof cursym, 1, soutb); 1352: } 1353: continue; 1354: } 1355: i = *lookup(); 1356: if (i == -1) 1357: error(1, "internal error: symbol not found"); 1358: if (cursym.n_type == N_EXT+N_UNDF || 1359: cursym.n_type == N_EXT+N_TEXT) { 1360: if (lp >= &local[NSYMPR]) 1361: error(2, "Local symbol overflow"); 1362: lp->locindex = symno; 1363: lp++->locsymbol = i; 1364: continue; 1365: } 1366: vsym = sym2va(i); 1367: sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + 1368: VOFF(vsym)); 1369: if (cursym.n_type != sp->n_type 1370: || cursym.n_value != sp->n_value && !sp->n_ovly 1371: || sp->n_ovly && cursym.n_value != sp->sovalue) { 1372: printf("%.*s: ", NNAMESIZE, cursym.n_name); 1373: if (trace) 1374: printf(" ovly %d sovalue %o new %o hav %o ", 1375: sp->n_ovly, sp->sovalue, 1376: cursym.n_value, sp->n_value); 1377: error(0, "multiply defined"); 1378: } 1379: } 1380: if (strtab) 1381: free(strtab); 1382: if (Input[STRINGS].buff) 1383: { 1384: free(Input[STRINGS].buff); 1385: Input[STRINGS].buff = NULL; 1386: } 1387: dseek(TEXT, loc + N_TXTOFF(filhdr.e), filhdr.e.a_text); 1388: dseek(RELOC, loc + N_TRELOC(filhdr.e), filhdr.e.a_text); 1389: load2td(lp, ctrel, inov ? voutb : toutb, troutb); 1390: dseek(TEXT, loc + N_DATOFF(filhdr), filhdr.e.a_data); 1391: dseek(RELOC, loc + N_DRELOC(filhdr), filhdr.e.a_data); 1392: load2td(lp, cdrel, doutb, droutb); 1393: torigin += filhdr.e.a_text; 1394: dorigin += filhdr.e.a_data; 1395: borigin += filhdr.e.a_bss; 1396: } 1397: 1398: load2td(lp, creloc, b1, b2) 1399: struct local *lp; 1400: u_int creloc; 1401: FILE *b1, *b2; 1402: { 1403: register u_int r, t; 1404: register SYMBOL *sp; 1405: short i; 1406: VADDR vsym; 1407: 1408: for (;;) { 1409: /* 1410: * Can't do this because of the word/byte count fakery that's used to 1411: * prevrent erroneous EOF indications. Yuck. 1412: 1413: t = get(TEXT); 1414: t = get(RELOC); 1415: */ 1416: /* 1417: * The pickup code is copied from "get" for speed. 1418: */ 1419: 1420: /* next text or data word */ 1421: if (--Input[TEXT].nsize <= 0) { 1422: if (Input[TEXT].nsize < 0) 1423: break; 1424: Input[TEXT].nsize++; 1425: t = get(TEXT); 1426: } else if (--Input[TEXT].nibuf < 0) { 1427: Input[TEXT].nibuf++; 1428: Input[TEXT].nsize++; 1429: t = get(TEXT); 1430: } else 1431: t = *Input[TEXT].Iptr++; 1432: 1433: /* next relocation word */ 1434: if (--Input[RELOC].nsize <= 0) { 1435: if (Input[RELOC].nsize < 0) 1436: error(1, "relocation error"); 1437: Input[RELOC].nsize++; 1438: r = get(RELOC); 1439: } else if (--Input[RELOC].nibuf < 0) { 1440: Input[RELOC].nibuf++; 1441: Input[RELOC].nsize++; 1442: r = get(RELOC); 1443: } else 1444: r = *Input[RELOC].Iptr++; 1445: 1446: switch (r&016) { 1447: 1448: case RTEXT: 1449: t += ctrel; 1450: break; 1451: case RDATA: 1452: t += cdrel; 1453: break; 1454: case RBSS: 1455: t += cbrel; 1456: break; 1457: case REXT: 1458: i = *lookloc(lp, r); 1459: vsym = sym2va(i); 1460: sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + 1461: VOFF(vsym)); 1462: if (sp->n_type==N_EXT+N_UNDF) { 1463: r = (r&01) + ((nsym + i)<<4) + REXT; 1464: break; 1465: } 1466: t += sp->n_value; 1467: r = (r&01) + ((sp->n_type-(N_EXT+N_ABS))<<1); 1468: break; 1469: #ifndef pdp11 1470: default: 1471: error(1, "relocation format botch (symbol type))"); 1472: #endif 1473: } 1474: if (r&01) 1475: t -= creloc; 1476: putw(t, b1); 1477: if (rflag) 1478: putw(r, b2); 1479: } 1480: } 1481: 1482: finishout() 1483: { 1484: register u_int n; 1485: register SYMBOL *sp; 1486: struct nlist objsym; 1487: VADDR vsym; 1488: int type, len; 1489: off_t stroff; 1490: long dtotal, ovrnd; 1491: int thunk[THUNKSIZ / sizeof (int)]; 1492: 1493: if (numov) { 1494: int aovhndlr[NOVL+1]; 1495: 1496: for (n=1; n<=numov; n++) { 1497: /* Note that NOVL can be up to 15 with this */ 1498: ovhndlr.n_name[HNDLR_NUM] = "0123456789abcdef"[n]; 1499: aovhndlr[n] = adrof(ovhndlr.n_name); 1500: } 1501: for (n=0,vsym=sym2va(0); n < symindex; n++,vsym=sym2va(n)) { 1502: sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + 1503: VOFF(vsym)); 1504: if (sp->n_ovly && (sp->n_type & (N_EXT+N_TEXT))) { 1505: thunk[0] = 012701; /* mov $~foo+4, r1 */ 1506: thunk[1] = sp->sovalue + 4; 1507: thunk[2] = 04537; /* jsr r5, ovhndlrx */ 1508: thunk[3] = aovhndlr[sp->n_ovly]; 1509: fwrite(thunk, THUNKSIZ, 1, toutb); 1510: torigin += THUNKSIZ; 1511: } 1512: } 1513: } 1514: if (nflag||iflag) { 1515: n = torigin; 1516: while (n&077) { 1517: n += 2; 1518: putw(0, toutb); 1519: if (rflag) 1520: putw(0, troutb); 1521: } 1522: } 1523: if (numov) 1524: copy(voutb); 1525: copy(doutb); 1526: if (rflag) { 1527: copy(troutb); 1528: copy(droutb); 1529: } 1530: 1531: if (sflag==0) 1532: { 1533: /* 1534: * Now write the symbol table out, converting from the 'fixed' style 1535: * symbol table used internally to the string table version used in 1536: * object/executable files. First the "local" (non-global) symbols 1537: * are written out, these are the symbols placed in the temporary file 1538: * accessed via 'soutb'. 1539: * 1540: * 'voutb' (overlay temp file), 'troutb' (text relocation temp file), 1541: * 'droutb' (data relocation temp file), and 'doutb' (data temp file) 1542: * have all been finished with and closed by this point. We reuse one 1543: * of these ('doutb') to build the string table. 1544: */ 1545: 1546: tcreat(&doutb, 1); 1547: nsym = 0; 1548: stroff = sizeof (long); /* string table size */ 1549: if (xflag == 0) 1550: { 1551: fflush(soutb); /* flush local symbol file */ 1552: rewind(soutb); 1553: while (fread(&cursym, sizeof (cursym), 1, soutb) == 1) 1554: { 1555: if (feof(soutb)) 1556: break; 1557: objsym.n_value = cursym.n_value; 1558: objsym.n_type = cursym.n_type; 1559: objsym.n_ovly = cursym.n_ovly; 1560: objsym.n_un.n_strx = stroff; 1561: len = strlen(cursym.n_name); 1562: if (len >= NNAMESIZE) 1563: len = NNAMESIZE; 1564: fwrite(cursym.n_name, 1, len, doutb); 1565: fputc('\0', doutb); 1566: stroff += (len + 1); 1567: fwrite(&objsym, sizeof (objsym), 1, toutb); 1568: nsym++; 1569: } 1570: fclose(soutb); 1571: } 1572: /* 1573: * Now we dump the global/external symbol table by marching thru the 1574: * 'vm' addresss space. 1575: */ 1576: for (n = 0, vsym = sym2va(0); n < symindex; n++, 1577: vsym = sym2va(n)) 1578: { 1579: sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + 1580: VOFF(vsym)); 1581: objsym.n_value = sp->n_value; 1582: objsym.n_type = sp->n_type; 1583: objsym.n_ovly = sp->n_ovly; 1584: objsym.n_un.n_strx = stroff; 1585: len = strlen(sp->n_name); 1586: if (len > NNAMESIZE) 1587: len = NNAMESIZE; 1588: fwrite(sp->n_name, 1, len, doutb); 1589: fputc('\0', doutb); 1590: stroff += (len + 1); 1591: fwrite(&objsym, sizeof (objsym), 1, toutb); 1592: nsym++; 1593: } 1594: #ifdef whybother 1595: if (stroff & 1) 1596: { 1597: fputc('\0', doutb); 1598: stroff++; 1599: } 1600: #endif 1601: /* 1602: * Now write the length of the string table out. Then copy the temp 1603: * file containing the strings to the image being built. 1604: */ 1605: fwrite(&stroff, sizeof (stroff), 1, toutb); 1606: copy(doutb); 1607: } 1608: /* 1609: * Fix up the header with the correct symbol table size - we now know 1610: * _exactly_ how many symbols were placed in the symbol table (the size 1611: * used earlier was only an estimate 1612: */ 1613: fflush(toutb); 1614: rewind(toutb); 1615: fread(&filhdr.e, sizeof (filhdr.e), 1, toutb); 1616: filhdr.e.a_syms = nsym * sizeof (objsym); 1617: rewind(toutb); 1618: fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb); 1619: fclose(toutb); 1620: 1621: if (!ofilfnd) { 1622: if (rename("l.out", "a.out") < 0) 1623: error(1, "cannot move l.out to a.out"); 1624: ofilename = "a.out"; 1625: } 1626: /* 1627: * we now do a sanity check on the total sizes of things. Previously the 1628: * linker could produce a program marked as executable but which had bogus 1629: * overlay+root sizes, etc. 1630: */ 1631: #define K56 (56L * 1024L) 1632: #define K64 (64L * 1024L) 1633: 1634: dtotal = (long)dsize + (long)bsize; 1635: ovrnd = rnd8k(filhdr.o.max_ovl); /* 0 if not overlaid */ 1636: type = 0; 1637: if (nflag) { 1638: if (rnd8k(tsize) + ovrnd + dtotal > K56) 1639: type = filhdr.e.a_magic; 1640: } 1641: else if (iflag) { 1642: if ((rnd8k(tsize) + ovrnd > K64) || (dtotal > K56)) 1643: type = filhdr.e.a_magic; 1644: } 1645: else { 1646: if ((long)tsize + dtotal > K56) 1647: type = filhdr.e.a_magic; 1648: } 1649: if (type && !rflag) { 1650: fprintf(stderr, "ld: too big for type %o\n", type); 1651: errlev = 2; 1652: } 1653: delarg = errlev; 1654: delexit(); 1655: } 1656: 1657: long 1658: rnd8k(siz) 1659: u_int siz; 1660: { 1661: long l = siz; 1662: 1663: return((l + 017777) & ~017777L); 1664: } 1665: 1666: mkfsym(s) 1667: char *s; 1668: { 1669: 1670: if (sflag || xflag) 1671: return; 1672: strncpy(cursym.n_name, s, NNAMESIZE); 1673: cursym.n_type = N_FN; 1674: cursym.n_value = torigin; 1675: fwrite(&cursym, sizeof (cursym), 1, soutb); 1676: } 1677: 1678: mget(loc, an, which) 1679: register int *loc; 1680: int an, which; 1681: { 1682: register int n; 1683: register STREAM *tp = &Input[which]; 1684: 1685: n = an >> 1; 1686: if ((tp->nibuf -= n) >= 0) { 1687: if ((tp->nsize -= n) > 0) { 1688: bcopy(tp->ptr, loc, an); 1689: tp->Iptr += n; 1690: return; 1691: } 1692: tp->nsize += n; 1693: } 1694: tp->nibuf += n; 1695: do { 1696: *loc++ = get(which); 1697: } while (--n); 1698: } 1699: 1700: dseek(which, aloc, s) 1701: int which; 1702: off_t aloc; 1703: int s; 1704: { 1705: register STREAM *sp = &Input[which]; 1706: register u_int b, o; 1707: int n; 1708: 1709: b = aloc / sp->bsize; 1710: o = aloc & (sp->bsize - 1); 1711: if (sp->bno != b) 1712: { 1713: (void)lseek(infil, (off_t)sp->bsize * b, L_SET); 1714: if ((n = read(infil, (char *)sp->buff, sp->bsize)) < 0) 1715: n = 0; 1716: sp->bno = b; 1717: sp->nread = n; 1718: } 1719: sp->nibuf = sp->nread - o; 1720: sp->Cptr = (char *)sp->buff + o; 1721: if (which != STRINGS) 1722: sp->nibuf >>= 1; 1723: if (s != -1) 1724: sp->nsize = (s >> 1) & 077777; 1725: if (sp->nibuf <= 0) 1726: sp->nsize = 0; 1727: } 1728: 1729: get(which) 1730: int which; 1731: { 1732: register STREAM *sp = &Input[which]; 1733: 1734: if (--sp->nibuf < 0) { 1735: dseek(which, (off_t)(sp->bno + 1) * sp->bsize, -1); 1736: --sp->nibuf; 1737: } 1738: if (--sp->nsize <= 0) { 1739: if (sp->nsize < 0) 1740: error(1, "premature EOF#1"); 1741: } 1742: return(*sp->Iptr++); 1743: } 1744: 1745: getfile(acp, flag, phase) 1746: char *acp; 1747: int flag; /* 1 = fatal if file not found, -1 = not fatal */ 1748: { 1749: char arcmag[SARMAG+1]; 1750: struct stat stb; 1751: 1752: filname = acp; 1753: chdr.name[0] = '\0'; /* not in archive for now */ 1754: if (filname[0] == '-' && filname[1] == 'l') 1755: infil = libopen(filname + 2, O_RDONLY); 1756: else 1757: infil = open(filname, O_RDONLY); 1758: if (infil < 0) { 1759: if (phase == 1) /* only complain once on phase 1 */ 1760: error(flag, "cannot open"); 1761: return(-1); 1762: } 1763: fstat(infil, &stb); 1764: Input[TEXT].bno = -1; 1765: Input[RELOC].bno = -1; 1766: Input[SYMBOLS].bno = -1; 1767: Input[STRINGS].bno = -1; 1768: dseek(TEXT, 0L, SARMAG); 1769: if (Input[TEXT].nsize <= 0) 1770: error(1, "premature EOF#2"); 1771: mget((char *)arcmag, SARMAG, TEXT); 1772: arcmag[SARMAG] = 0; 1773: if (strcmp(arcmag, ARMAG)) 1774: return(0); 1775: lseek(infil, (off_t)SARMAG, L_SET); 1776: if (get_arobj(infil) <= 0) 1777: return(1); 1778: if (strcmp(chdr.name, RANLIBMAG)) 1779: return(1); /* regular archive */ 1780: return (stb.st_mtime > chdr.date ? 3 : 2); 1781: } 1782: 1783: /* 1784: * Search for a library with given name 1785: * using the directory search array. 1786: */ 1787: libopen(name, oflags) 1788: char *name; 1789: int oflags; 1790: { 1791: register char *p, *cp; 1792: register int i; 1793: static char buf[100]; 1794: int fd; 1795: 1796: for (i = 0; i < ndir ; i++) { 1797: p = buf; 1798: for (cp = dirs[i]; *cp; *p++ = *cp++) 1799: ; 1800: *p++ = '/'; 1801: *p++ = 'l'; 1802: *p++ = 'i'; 1803: *p++ = 'b'; 1804: for (cp = name; *cp; *p++ = *cp++) 1805: ; 1806: *p++ = '.'; 1807: *p++ = 'a'; 1808: *p++ = '\0'; 1809: fd = open(buf, oflags); 1810: if (fd != -1) { 1811: filname = buf; 1812: return(fd); 1813: } 1814: } 1815: return(-1); 1816: } 1817: 1818: short * 1819: lookup() 1820: { 1821: register short *hp; 1822: register char *cp; 1823: SYMBOL *sp; 1824: union 1825: { 1826: long x; 1827: short y[2]; 1828: } sh; 1829: VADDR vsym; 1830: 1831: sh.x = 0; 1832: for (cp = cursym.n_name; cp < &cursym.n_name[NNAMESIZE] && *cp;) 1833: sh.x = (sh.x<<1) + *cp++; 1834: sh.y[1] += sh.y[0]; 1835: hp = &hshtab[(sh.y[1]&077777)%NSYM+2]; 1836: while (*hp != -1) 1837: { 1838: vsym = sym2va(*hp); 1839: sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + 1840: VOFF(vsym)); 1841: if (!strncmp(sp->n_name, cursym.n_name, NNAMESIZE)) 1842: break; 1843: if (++hp >= &hshtab[NSYM+2]) 1844: hp = hshtab; 1845: } 1846: return(hp); 1847: } 1848: 1849: short * 1850: slookup(s) 1851: char *s; 1852: { 1853: 1854: strncpy(cursym.n_name, s, NNAMESIZE); 1855: cursym.n_type = N_EXT+N_UNDF; 1856: cursym.n_value = 0; 1857: return(lookup()); 1858: } 1859: 1860: enter(hp) 1861: short *hp; 1862: { 1863: register SYMBOL *sp; 1864: u_int word, bit, hnum; 1865: VADDR vsym; 1866: register struct vseg *seg; 1867: 1868: if (*hp == -1) 1869: { 1870: if (symindex>=NSYM) 1871: error(1, "symbol table overflow"); 1872: hnum = hp - hshtab; 1873: word = hnum / 16; 1874: bit = hnum % 16; 1875: symhash[word] |= (1 << bit); 1876: vsym = sym2va(symindex); 1877: *hp = lastsym = symindex; 1878: symindex++; 1879: seg = vmmapseg(&Vspace, VSEG(vsym)); 1880: sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); 1881: strncpy(sp->n_name, cursym.n_name, NNAMESIZE); 1882: sp->n_type = cursym.n_type; 1883: sp->n_value = cursym.n_value; 1884: if (sp->n_type == N_EXT+N_TEXT) 1885: { 1886: sp->n_ovly = curov; 1887: if (trace) 1888: printf("found %.*s in overlay %d at %u\n", 1889: NNAMESIZE, sp->n_name, sp->n_ovly, 1890: sp->n_value); 1891: } 1892: VMMODIFY(seg); 1893: return(1); 1894: } 1895: lastsym = *hp; 1896: return(0); 1897: } 1898: 1899: error(n, s) 1900: char *s; 1901: { 1902: if (!s) 1903: delexit(); 1904: if (errlev==0) 1905: printf("ld:"); 1906: if (filname) { 1907: printf("%s", filname); 1908: if (n != -1 && chdr.name[0]) 1909: printf("(%s)", chdr.name); 1910: printf(": "); 1911: } 1912: printf("%s\n", s); 1913: if (n == -1) 1914: return; 1915: if (n) 1916: delexit(); 1917: errlev = 2; 1918: } 1919: 1920: readhdr(loc) 1921: off_t loc; 1922: { 1923: dseek(TEXT, loc, sizeof filhdr); 1924: mget((int *)&filhdr.e, sizeof filhdr.e, TEXT); 1925: if (filhdr.e.a_magic != A_MAGIC1) 1926: error(1, "bad magic number"); 1927: if (filhdr.e.a_text&01) 1928: ++filhdr.e.a_text; 1929: if (filhdr.e.a_data&01) 1930: ++filhdr.e.a_data; 1931: if (filhdr.e.a_bss&01) 1932: ++filhdr.e.a_bss; 1933: cdrel = -filhdr.e.a_text; 1934: cbrel = cdrel - filhdr.e.a_data; 1935: } 1936: 1937: tcreat(fpp, tempflg) 1938: FILE **fpp; 1939: int tempflg; 1940: { 1941: register int ufd; 1942: char *nam; 1943: 1944: nam = (tempflg ? tfname : ofilename); 1945: if ((ufd = open(nam, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) 1946: error(2, tempflg?"cannot create temp":"cannot create output"); 1947: if (tempflg) 1948: unlink(tfname); 1949: *fpp = fdopen(ufd, "r+"); 1950: } 1951: 1952: adrof(s) 1953: char *s; 1954: { 1955: register short *p; 1956: register SYMBOL *sp; 1957: VADDR vsym; 1958: 1959: p = slookup(s); 1960: if (*p == -1) 1961: { 1962: printf("%.*s: ", NNAMESIZE, s); 1963: error(1, "undefined"); 1964: } 1965: vsym = sym2va(*p); 1966: sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); 1967: return(sp->n_value); 1968: } 1969: 1970: copy(fp) 1971: register FILE *fp; 1972: { 1973: register int c; 1974: 1975: fflush(fp); 1976: rewind(fp); 1977: while ((c = getc(fp)) != EOF) 1978: putc(c, toutb); 1979: fclose(fp); 1980: } 1981: 1982: short * 1983: lookloc(alp, r) 1984: struct local *alp; 1985: { 1986: register struct local *clp, *lp; 1987: register int sn; 1988: 1989: lp = alp; 1990: sn = (r>>4) & 07777; 1991: for (clp = local; clp<lp; clp++) 1992: if (clp->locindex == sn) 1993: return(&clp->locsymbol); 1994: error(1, "local symbol botch"); 1995: /*NOTREACHED*/ 1996: } 1997: 1998: roundov() 1999: { 2000: 2001: while (torigin & 077) 2002: { 2003: putw(0, voutb); 2004: torigin += sizeof (int); 2005: } 2006: } 2007: 2008: u_int 2009: add(a,b,s) 2010: int a, b; 2011: char *s; 2012: { 2013: long r; 2014: register char *ap; 2015: 2016: r = (long)(u_int)a + (u_int)b; 2017: if (r >= 0200000) 2018: { 2019: ap = (char *)alloca(strlen(s) + 1 + sizeof (" overflow")); 2020: strcpy(ap, s); 2021: strcat(ap, " overflow"); 2022: error(1, ap); 2023: } 2024: return(r); 2025: } 2026: 2027: /* 2028: * "borrowed" from 'ar' because we didn't want to drag in everything else 2029: * from 'ar'. The error checking was also ripped out, basically if any 2030: * of the criteria for being an archive are not met then a -1 is returned 2031: * and the rest of 'ld' figures out what to do. 2032: */ 2033: 2034: typedef struct ar_hdr HDR; 2035: static char hb[sizeof(HDR) + 1]; /* real header */ 2036: 2037: /* Convert ar header field to an integer. */ 2038: #define AR_ATOI(from, to, len, base) { \ 2039: bcopy(from, buf, len); \ 2040: buf[len] = '\0'; \ 2041: to = strtol(buf, (char **)NULL, base); \ 2042: } 2043: 2044: /* 2045: * get_arobj -- 2046: * read the archive header for this member 2047: */ 2048: get_arobj(fd) 2049: int fd; 2050: { 2051: HDR *hdr; 2052: register int len, nr; 2053: register char *p; 2054: char buf[20]; 2055: 2056: nr = read(fd, hb, sizeof(HDR)); 2057: if (nr != sizeof(HDR)) 2058: return(-1); 2059: 2060: hdr = (HDR *)hb; 2061: if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) 2062: return(-1); 2063: 2064: /* Convert the header into the internal format. */ 2065: #define DECIMAL 10 2066: #define OCTAL 8 2067: 2068: AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); 2069: AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); 2070: AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); 2071: AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); 2072: AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); 2073: 2074: /* Leading spaces should never happen. */ 2075: if (hdr->ar_name[0] == ' ') 2076: return(-1); 2077: 2078: /* 2079: * Long name support. Set the "real" size of the file, and the 2080: * long name flag/size. 2081: */ 2082: if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { 2083: chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); 2084: if (len <= 0 || len > MAXNAMLEN) 2085: return(-1); 2086: nr = read(fd, chdr.name, (size_t)len); 2087: if (nr != len) 2088: return(-1); 2089: chdr.name[len] = 0; 2090: chdr.size -= len; 2091: } else { 2092: chdr.lname = 0; 2093: bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); 2094: 2095: /* Strip trailing spaces, null terminate. */ 2096: for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); 2097: *++p = '\0'; 2098: } 2099: return(1); 2100: } 2101: 2102: /* 2103: * skip - where to seek for next archive member. 2104: */ 2105: off_t 2106: skip() 2107: { 2108: off_t len; 2109: 2110: len = chdr.size + (chdr.size + chdr.lname & 1); 2111: len += sizeof (HDR); 2112: return(len); 2113: } 2114: 2115: inistr(which) 2116: int which; 2117: { 2118: register STREAM *sp = &Input[which]; 2119: register int size = 4096; 2120: 2121: if (sp->buff == (int *)NULL) 2122: { 2123: while (size > 256) 2124: { 2125: sp->buff = (int *)malloc(size); 2126: if (sp->buff) 2127: { 2128: sp->bsize = size; 2129: return; 2130: } 2131: size >>= 1; 2132: } 2133: error(1, "No memory for strings"); 2134: } 2135: }