1: /* 2: * link editor 3: */ 4: 5: #include <signal.h> 6: #include "sys/types.h" 7: #include "sys/stat.h" 8: 9: /* Layout of a.out file : 10: * 11: * header of 8 words magic number 405, 407, 410, 411 12: * text size ) 13: * data size ) in bytes but even 14: * bss size ) 15: * symbol table size 16: * entry point 17: * {unused} 18: * flag set if no relocation 19: * 20: * 21: * header: 0 22: * text: 16 23: * data: 16+textsize 24: * relocation: 16+textsize+datasize 25: * symbol table: 16+2*(textsize+datasize) or 16+textsize+datasize 26: * 27: */ 28: #define TRUE 1 29: #define FALSE 0 30: 31: 32: #define ARCMAGIC 0177545 33: #define OMAGIC 0405 34: #define FMAGIC 0407 35: #define NMAGIC 0410 36: #define IMAGIC 0411 37: 38: #define EXTERN 040 39: #define UNDEF 00 40: #define ABS 01 41: #define TEXT 02 42: #define DATA 03 43: #define BSS 04 44: #define COMM 05 /* internal use only */ 45: 46: #define RABS 00 47: #define RTEXT 02 48: #define RDATA 04 49: #define RBSS 06 50: #define REXT 010 51: 52: #define NOVLY 16 53: #define RELFLG 01 54: #define NROUT 256 55: #define NSYM 1103 56: #define NSYMPR 1000 57: 58: char premeof[] = "Premature EOF"; 59: char goodnm[] = "__.SYMDEF"; 60: 61: /* table of contents stuff */ 62: #define TABSZ 700 63: struct tab 64: { char cname[8]; 65: long cloc; 66: } tab[TABSZ]; 67: int tnum; 68: 69: 70: /* overlay management */ 71: int vindex; 72: struct overlay { 73: int argsav; 74: int symsav; 75: struct liblist *libsav; 76: char *vname; 77: int ctsav, cdsav, cbsav; 78: int offt, offd, offb, offs; 79: } vnodes[NOVLY]; 80: 81: /* input management */ 82: struct page { 83: int nuser; 84: int bno; 85: int nibuf; 86: int buff[256]; 87: } page[2]; 88: 89: struct { 90: int nuser; 91: int bno; 92: } fpage; 93: 94: struct stream { 95: int *ptr; 96: int bno; 97: int nibuf; 98: int size; 99: struct page *pno; 100: }; 101: 102: struct stream text; 103: struct stream reloc; 104: 105: struct { 106: char aname[14]; 107: long atime; 108: char auid, agid; 109: int amode; 110: long asize; 111: } archdr; 112: 113: struct { 114: int fmagic; 115: int tsize; 116: int dsize; 117: int bsize; 118: int ssize; 119: int entry; 120: int pad; 121: int relflg; 122: } filhdr; 123: 124: 125: /* one entry for each archive member referenced; 126: * set in first pass; needs restoring for overlays 127: */ 128: struct liblist { 129: long loc; 130: }; 131: 132: struct liblist liblist[NROUT]; 133: struct liblist *libp = liblist; 134: 135: 136: /* symbol management */ 137: struct symbol { 138: char sname[8]; 139: char stype; 140: char spare; 141: int svalue; 142: }; 143: 144: struct local { 145: int locindex; /* index to symbol in file */ 146: struct symbol *locsymbol; /* ptr to symbol table */ 147: }; 148: 149: struct symbol cursym; /* current symbol */ 150: struct symbol symtab[NSYM]; /* actual symbols */ 151: struct symbol **symhash[NSYM]; /* ptr to hash table entry */ 152: struct symbol *lastsym; /* last symbol entered */ 153: int symindex; /* next available symbol table entry */ 154: struct symbol *hshtab[NSYM+2]; /* hash table for symbols */ 155: struct local local[NSYMPR]; 156: 157: /* internal symbols */ 158: struct symbol *p_etext; 159: struct symbol *p_edata; 160: struct symbol *p_end; 161: struct symbol *entrypt; 162: 163: int trace; 164: /* flags */ 165: int xflag; /* discard local symbols */ 166: int Xflag; /* discard locals starting with 'L' */ 167: int Sflag; /* discard all except locals and globals*/ 168: int rflag; /* preserve relocation bits, don't define common */ 169: int arflag; /* original copy of rflag */ 170: int sflag; /* discard all symbols */ 171: int nflag; /* pure procedure */ 172: int Oflag; /* set magic # to 0405 (overlay) */ 173: int dflag; /* define common even with rflag */ 174: int iflag; /* I/D space separated */ 175: int vflag; /* overlays used */ 176: 177: int ofilfnd; 178: char *ofilename = "l.out"; 179: int infil; 180: char *filname; 181: 182: /* cumulative sizes set in pass 1 */ 183: int tsize; 184: int dsize; 185: int bsize; 186: int ssize; 187: 188: /* symbol relocation; both passes */ 189: int ctrel; 190: int cdrel; 191: int cbrel; 192: 193: int errlev; 194: int delarg = 4; 195: char tfname[] = "/tmp/ldaXXXXX"; 196: 197: 198: /* output management */ 199: struct buf { 200: int fildes; 201: int nleft; 202: int *xnext; 203: int iobuf[256]; 204: }; 205: struct buf toutb; 206: struct buf doutb; 207: struct buf troutb; 208: struct buf droutb; 209: struct buf soutb; 210: 211: struct symbol **lookup(); 212: struct symbol **slookup(); 213: struct symbol *lookloc(); 214: 215: delexit() 216: { 217: unlink("l.out"); 218: if (delarg==0) 219: chmod(ofilename, 0777 & ~umask(0)); 220: exit(delarg); 221: } 222: 223: main(argc, argv) 224: char **argv; 225: { 226: register int c, i; 227: int num; 228: register char *ap, **p; 229: int found; 230: int vscan; 231: char save; 232: 233: if (signal(SIGINT, SIG_IGN) != SIG_IGN) 234: signal(SIGINT, delexit); 235: if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 236: signal(SIGTERM, delexit); 237: if (argc == 1) 238: exit(4); 239: p = argv+1; 240: 241: /* scan files once to find symdefs */ 242: for (c=1; c<argc; c++) { 243: if (trace) printf("%s:\n", *p); 244: filname = 0; 245: ap = *p++; 246: 247: if (*ap == '-') { 248: for (i=1; ap[i]; i++) { 249: switch (ap[i]) { 250: case 'o': 251: if (++c >= argc) 252: error(2, "Bad output file"); 253: ofilename = *p++; 254: ofilfnd++; 255: continue; 256: 257: case 'u': 258: case 'e': 259: if (++c >= argc) 260: error(2, "Bad 'use' or 'entry'"); 261: enter(slookup(*p++)); 262: if (ap[i]=='e') 263: entrypt = lastsym; 264: continue; 265: 266: case 'v': 267: if (++c >= argc) 268: error(2, "-v: arg missing"); 269: vflag=TRUE; 270: vscan = vindex; 271: found=FALSE; 272: while (--vscan>=0 && found==FALSE) 273: found = eq(vnodes[vscan].vname, *p); 274: if (found) { 275: endload(c, argv); 276: restore(vscan); 277: } else 278: record(c, *p); 279: p++; 280: continue; 281: 282: case 'D': 283: if (++c >= argc) 284: error(2, "-D: arg missing"); 285: num = atoi(*p++); 286: if (dsize>num) 287: error(2, "-D: too small"); 288: dsize = num; 289: continue; 290: 291: case 'l': 292: save = ap[--i]; 293: ap[i]='-'; 294: load1arg(&ap[i]); 295: ap[i]=save; 296: break; 297: 298: case 'x': 299: xflag++; 300: continue; 301: 302: case 'X': 303: Xflag++; 304: continue; 305: 306: case 'S': 307: Sflag++; 308: continue; 309: 310: case 'r': 311: rflag++; 312: arflag++; 313: continue; 314: 315: case 's': 316: sflag++; 317: xflag++; 318: continue; 319: 320: case 'n': 321: nflag++; 322: continue; 323: 324: case 'd': 325: dflag++; 326: continue; 327: 328: case 'i': 329: iflag++; 330: continue; 331: 332: case 'O': 333: Oflag++; 334: continue; 335: 336: case 't': 337: trace++; 338: continue; 339: 340: default: 341: error(2, "bad flag"); 342: } /*endsw*/ 343: break; 344: } /*endfor*/ 345: } else 346: load1arg(ap); 347: } 348: endload(argc, argv); 349: } 350: 351: /* used after pass 1 */ 352: int nsym; 353: int torigin; 354: int dorigin; 355: int borigin; 356: 357: endload(argc, argv) 358: int argc; 359: char **argv; 360: { 361: register int c, i; 362: int dnum; 363: register char *ap, **p; 364: filname = 0; 365: middle(); 366: setupout(); 367: p = argv+1; 368: libp = liblist; 369: for (c=1; c<argc; c++) { 370: ap = *p++; 371: if (trace) printf("%s:\n", ap); 372: if (*ap == '-') { 373: for (i=1; ap[i]; i++) { 374: switch (ap[i]) { 375: case 'D': 376: for (dnum = atoi(*p); dorigin<dnum; dorigin += 2) { 377: putw(0, &doutb); 378: if (rflag) 379: putw(0, &droutb); 380: } 381: case 'u': 382: case 'e': 383: case 'o': 384: case 'v': 385: ++c; 386: ++p; 387: 388: default: 389: continue; 390: 391: case 'l': 392: ap[--i]='-'; 393: load2arg(&ap[i]); 394: break; 395: } /*endsw*/ 396: break; 397: } /*endfor*/ 398: } else 399: load2arg(ap); 400: } 401: finishout(); 402: } 403: 404: record(c, nam) 405: int c; 406: char *nam; 407: { 408: register struct overlay *v; 409: 410: v = &vnodes[vindex++]; 411: v->argsav = c; 412: v->symsav = symindex; 413: v->libsav = libp; 414: v->vname = nam; 415: v->offt = tsize; 416: v->offd = dsize; 417: v->offb = bsize; 418: v->offs = ssize; 419: v->ctsav = ctrel; 420: v->cdsav = cdrel; 421: v->cbsav = cbrel; 422: } 423: 424: restore(vscan) 425: int vscan; 426: { 427: register struct overlay *v; 428: register int saved; 429: 430: v = &vnodes[vscan]; 431: vindex = vscan+1; 432: libp = v->libsav; 433: ctrel = v->ctsav; 434: cdrel = v->cdsav; 435: cbrel = v->cbsav; 436: tsize = v->offt; 437: dsize = v->offd; 438: bsize = v->offb; 439: ssize = v->offs; 440: saved = v->symsav; 441: while (symindex>saved) 442: *symhash[--symindex]=0; 443: } 444: 445: /* scan file to find defined symbols */ 446: load1arg(acp) 447: char *acp; 448: { 449: register char *cp; 450: long nloc; 451: 452: cp = acp; 453: switch ( getfile(cp)) { 454: case 0: 455: load1(0, 0L); 456: break; 457: 458: /* regular archive */ 459: case 1: 460: nloc = 1; 461: while ( step(nloc)) 462: nloc += (archdr.asize + sizeof(archdr) + 1) >> 1; 463: break; 464: 465: /* table of contents */ 466: case 2: 467: tnum = archdr.asize / sizeof(struct tab); 468: if (tnum >= TABSZ) { 469: error(2, "fast load buffer too small"); 470: } 471: lseek(infil, (long)(sizeof(filhdr.fmagic)+sizeof(archdr)), 0); 472: read(infil, (char *)tab, tnum * sizeof(struct tab)); 473: while (ldrand()); 474: libp->loc = -1; 475: libp++; 476: break; 477: /* out of date table of contents */ 478: case 3: 479: error(0, "out of date (warning)"); 480: for(nloc = 1+((archdr.asize+sizeof(archdr)+1) >> 1); step(nloc); 481: nloc += (archdr.asize + sizeof(archdr) + 1) >> 1); 482: break; 483: } 484: close(infil); 485: } 486: 487: step(nloc) 488: long nloc; 489: { 490: dseek(&text, nloc, sizeof archdr); 491: if (text.size <= 0) { 492: libp->loc = -1; 493: libp++; 494: return(0); 495: } 496: mget((int *)&archdr, sizeof archdr); 497: if (load1(1, nloc + (sizeof archdr) / 2)) { 498: libp->loc = nloc; 499: libp++; 500: } 501: return(1); 502: } 503: 504: ldrand() 505: { 506: int i; 507: struct symbol *sp, **pp; 508: struct liblist *oldp = libp; 509: for(i = 0; i<tnum; i++) { 510: if ((pp = slookup(tab[i].cname)) == 0) 511: continue; 512: sp = *pp; 513: if (sp->stype != EXTERN+UNDEF) 514: continue; 515: step(tab[i].cloc >> 1); 516: } 517: return(oldp != libp); 518: } 519: 520: add(a,b,s) 521: int a, b; 522: char *s; 523: { 524: long r; 525: 526: r = (long)(unsigned)a + (unsigned)b; 527: if (r >= 0200000) 528: error(1,s); 529: return(r); 530: } 531: 532: 533: /* single file or archive member */ 534: load1(libflg, loc) 535: long loc; 536: { 537: register struct symbol *sp; 538: int savindex; 539: int ndef, nloc, type, mtype; 540: 541: readhdr(loc); 542: ctrel = tsize; 543: cdrel += dsize; 544: cbrel += bsize; 545: ndef = 0; 546: nloc = sizeof cursym; 547: savindex = symindex; 548: if ((filhdr.relflg&RELFLG)==1) { 549: error(1, "No relocation bits"); 550: return(0); 551: } 552: loc += (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize; 553: dseek(&text, loc, filhdr.ssize); 554: while (text.size > 0) { 555: mget((int *)&cursym, sizeof cursym); 556: type = cursym.stype; 557: if (Sflag) { 558: mtype = type&037; 559: if (mtype==1 || mtype>4) { 560: continue; 561: } 562: } 563: if ((type&EXTERN)==0) { 564: if (Xflag==0 || cursym.sname[0]!='L') 565: nloc += sizeof cursym; 566: continue; 567: } 568: symreloc(); 569: if (enter(lookup())) 570: continue; 571: if ((sp = lastsym)->stype != EXTERN+UNDEF) 572: continue; 573: if (cursym.stype == EXTERN+UNDEF) { 574: if (cursym.svalue > sp->svalue) 575: sp->svalue = cursym.svalue; 576: continue; 577: } 578: if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) 579: continue; 580: ndef++; 581: sp->stype = cursym.stype; 582: sp->svalue = cursym.svalue; 583: } 584: if (libflg==0 || ndef) { 585: tsize = add(tsize,filhdr.tsize,"text overflow"); 586: dsize = add(dsize,filhdr.dsize,"data overflow"); 587: bsize = add(bsize,filhdr.bsize,"bss overflow"); 588: ssize = add(ssize,nloc,"symbol table overflow"); 589: return(1); 590: } 591: /* 592: * No symbols defined by this library member. 593: * Rip out the hash table entries and reset the symbol table. 594: */ 595: while (symindex>savindex) 596: *symhash[--symindex]=0; 597: return(0); 598: } 599: 600: middle() 601: { 602: register struct symbol *sp, *symp; 603: register t, csize; 604: int nund, corigin; 605: 606: torigin=0; 607: dorigin=0; 608: borigin=0; 609: 610: p_etext = *slookup("_etext"); 611: p_edata = *slookup("_edata"); 612: p_end = *slookup("_end"); 613: /* 614: * If there are any undefined symbols, save the relocation bits. 615: */ 616: symp = &symtab[symindex]; 617: if (rflag==0) { 618: for (sp = symtab; sp<symp; sp++) 619: if (sp->stype==EXTERN+UNDEF && sp->svalue==0 620: && sp!=p_end && sp!=p_edata && sp!=p_etext) { 621: rflag++; 622: dflag = 0; 623: break; 624: } 625: } 626: if (rflag) 627: nflag = sflag = iflag = Oflag = 0; 628: /* 629: * Assign common locations. 630: */ 631: csize = 0; 632: if (dflag || rflag==0) { 633: ldrsym(p_etext, tsize, EXTERN+TEXT); 634: ldrsym(p_edata, dsize, EXTERN+DATA); 635: ldrsym(p_end, bsize, EXTERN+BSS); 636: for (sp = symtab; sp<symp; sp++) 637: if (sp->stype==EXTERN+UNDEF && (t = sp->svalue)!=0) { 638: t = (t+1) & ~01; 639: sp->svalue = csize; 640: sp->stype = EXTERN+COMM; 641: csize = add(csize, t, "bss overflow"); 642: } 643: } 644: /* 645: * Now set symbols to their final value 646: */ 647: if (nflag || iflag) 648: tsize = (tsize + 077) & ~077; 649: dorigin = tsize; 650: if (nflag) 651: dorigin = (tsize+017777) & ~017777; 652: if (iflag) 653: dorigin = 0; 654: corigin = dorigin + dsize; 655: borigin = corigin + csize; 656: nund = 0; 657: for (sp = symtab; sp<symp; sp++) switch (sp->stype) { 658: case EXTERN+UNDEF: 659: errlev |= 01; 660: if (arflag==0 && sp->svalue==0) { 661: if (nund==0) 662: printf("Undefined:\n"); 663: nund++; 664: printf("%.8s\n", sp->sname); 665: } 666: continue; 667: 668: case EXTERN+ABS: 669: default: 670: continue; 671: 672: case EXTERN+TEXT: 673: sp->svalue += torigin; 674: continue; 675: 676: case EXTERN+DATA: 677: sp->svalue += dorigin; 678: continue; 679: 680: case EXTERN+BSS: 681: sp->svalue += borigin; 682: continue; 683: 684: case EXTERN+COMM: 685: sp->stype = EXTERN+BSS; 686: sp->svalue += corigin; 687: continue; 688: } 689: if (sflag || xflag) 690: ssize = 0; 691: bsize = add(bsize, csize, "bss overflow"); 692: nsym = ssize / (sizeof cursym); 693: } 694: 695: ldrsym(asp, val, type) 696: struct symbol *asp; 697: { 698: register struct symbol *sp; 699: 700: if ((sp = asp) == 0) 701: return; 702: if (sp->stype != EXTERN+UNDEF || sp->svalue) { 703: printf("%.8s: ", sp->sname); 704: error(1, "Multiply defined"); 705: return; 706: } 707: sp->stype = type; 708: sp->svalue = val; 709: } 710: 711: setupout() 712: { 713: tcreat(&toutb, 0); 714: mktemp(tfname); 715: tcreat(&doutb, 1); 716: if (sflag==0 || xflag==0) 717: tcreat(&soutb, 1); 718: if (rflag) { 719: tcreat(&troutb, 1); 720: tcreat(&droutb, 1); 721: } 722: filhdr.fmagic = (Oflag ? OMAGIC :( iflag ? IMAGIC : ( nflag ? NMAGIC : FMAGIC ))); 723: filhdr.tsize = tsize; 724: filhdr.dsize = dsize; 725: filhdr.bsize = bsize; 726: filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*symindex); 727: if (entrypt) { 728: if (entrypt->stype!=EXTERN+TEXT) 729: error(1, "Entry point not in text"); 730: else 731: filhdr.entry = entrypt->svalue | 01; 732: } else 733: filhdr.entry=0; 734: filhdr.pad = 0; 735: filhdr.relflg = (rflag==0); 736: mput(&toutb, (int *)&filhdr, sizeof filhdr); 737: } 738: 739: tcreat(buf, tempflg) 740: struct buf *buf; 741: { 742: register int ufd; 743: char *nam; 744: nam = (tempflg ? tfname : ofilename); 745: if ((ufd = creat(nam, 0666)) < 0) 746: error(2, tempflg?"cannot create temp":"cannot create output"); 747: close(ufd); 748: buf->fildes = open(nam, 2); 749: if (tempflg) 750: unlink(tfname); 751: buf->nleft = sizeof(buf->iobuf)/sizeof(int); 752: buf->xnext = buf->iobuf; 753: } 754: 755: load2arg(acp) 756: char *acp; 757: { 758: register char *cp; 759: register struct liblist *lp; 760: 761: cp = acp; 762: if (getfile(cp) == 0) { 763: while (*cp) 764: cp++; 765: while (cp >= acp && *--cp != '/'); 766: mkfsym(++cp); 767: load2(0L); 768: } else { /* scan archive members referenced */ 769: for (lp = libp; lp->loc != -1; lp++) { 770: dseek(&text, lp->loc, sizeof archdr); 771: mget((int *)&archdr, sizeof archdr); 772: mkfsym(archdr.aname); 773: load2(lp->loc + (sizeof archdr) / 2); 774: } 775: libp = ++lp; 776: } 777: close(infil); 778: } 779: 780: load2(loc) 781: long loc; 782: { 783: register struct symbol *sp; 784: register struct local *lp; 785: register int symno; 786: int type, mtype; 787: 788: readhdr(loc); 789: ctrel = torigin; 790: cdrel += dorigin; 791: cbrel += borigin; 792: /* 793: * Reread the symbol table, recording the numbering 794: * of symbols for fixing external references. 795: */ 796: lp = local; 797: symno = -1; 798: loc += (sizeof filhdr)/2; 799: dseek(&text, loc + filhdr.tsize + filhdr.dsize, filhdr.ssize); 800: while (text.size > 0) { 801: symno++; 802: mget((int *)&cursym, sizeof cursym); 803: symreloc(); 804: type = cursym.stype; 805: if (Sflag) { 806: mtype = type&037; 807: if (mtype==1 || mtype>4) continue; 808: } 809: if ((type&EXTERN) == 0) { 810: if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L')) 811: mput(&soutb, (int *)&cursym, sizeof cursym); 812: continue; 813: } 814: if ((sp = *lookup()) == 0) 815: error(2, "internal error: symbol not found"); 816: if (cursym.stype == EXTERN+UNDEF) { 817: if (lp >= &local[NSYMPR]) 818: error(2, "Local symbol overflow"); 819: lp->locindex = symno; 820: lp++->locsymbol = sp; 821: continue; 822: } 823: if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { 824: printf("%.8s: ", cursym.sname); 825: error(1, "Multiply defined"); 826: } 827: } 828: dseek(&text, loc, filhdr.tsize); 829: dseek(&reloc, loc + half(filhdr.tsize + filhdr.dsize), filhdr.tsize); 830: load2td(lp, ctrel, &toutb, &troutb); 831: dseek(&text, loc+half(filhdr.tsize), filhdr.dsize); 832: dseek(&reloc, loc+filhdr.tsize+half(filhdr.dsize), filhdr.dsize); 833: load2td(lp, cdrel, &doutb, &droutb); 834: torigin += filhdr.tsize; 835: dorigin += filhdr.dsize; 836: borigin += filhdr.bsize; 837: } 838: 839: load2td(lp, creloc, b1, b2) 840: struct local *lp; 841: struct buf *b1, *b2; 842: { 843: register r, t; 844: register struct symbol *sp; 845: 846: for (;;) { 847: /* 848: * The pickup code is copied from "get" for speed. 849: */ 850: 851: /* next text or data word */ 852: if (--text.size <= 0) { 853: if (text.size < 0) 854: break; 855: text.size++; 856: t = get(&text); 857: } else if (--text.nibuf < 0) { 858: text.nibuf++; 859: text.size++; 860: t = get(&text); 861: } else 862: t = *text.ptr++; 863: 864: /* next relocation word */ 865: if (--reloc.size <= 0) { 866: if (reloc.size < 0) 867: error(2, "Relocation error"); 868: reloc.size++; 869: r = get(&reloc); 870: } else if (--reloc.nibuf < 0) { 871: reloc.nibuf++; 872: reloc.size++; 873: r = get(&reloc); 874: } else 875: r = *reloc.ptr++; 876: 877: switch (r&016) { 878: 879: case RTEXT: 880: t += ctrel; 881: break; 882: 883: case RDATA: 884: t += cdrel; 885: break; 886: 887: case RBSS: 888: t += cbrel; 889: break; 890: 891: case REXT: 892: sp = lookloc(lp, r); 893: if (sp->stype==EXTERN+UNDEF) { 894: r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT; 895: break; 896: } 897: t += sp->svalue; 898: r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1); 899: break; 900: } 901: if (r&01) 902: t -= creloc; 903: putw(t, b1); 904: if (rflag) 905: putw(r, b2); 906: } 907: } 908: 909: finishout() 910: { 911: register n, *p; 912: 913: if (nflag||iflag) { 914: n = torigin; 915: while (n&077) { 916: n += 2; 917: putw(0, &toutb); 918: if (rflag) 919: putw(0, &troutb); 920: } 921: } 922: copy(&doutb); 923: if (rflag) { 924: copy(&troutb); 925: copy(&droutb); 926: } 927: if (sflag==0) { 928: if (xflag==0) 929: copy(&soutb); 930: for (p = (int *)symtab; p < (int *)&symtab[symindex];) 931: putw(*p++, &toutb); 932: } 933: flush(&toutb); 934: close(toutb.fildes); 935: if (!ofilfnd) { 936: unlink("a.out"); 937: link("l.out", "a.out"); 938: ofilename = "a.out"; 939: } 940: delarg = errlev; 941: delexit(); 942: } 943: 944: copy(buf) 945: struct buf *buf; 946: { 947: register f, *p, n; 948: 949: flush(buf); 950: lseek(f = buf->fildes, (long)0, 0); 951: while ((n = read(f, (char *)doutb.iobuf, sizeof(doutb.iobuf))) > 1) { 952: n >>= 1; 953: p = (int *)doutb.iobuf; 954: do 955: putw(*p++, &toutb); 956: while (--n); 957: } 958: close(f); 959: } 960: 961: mkfsym(s) 962: char *s; 963: { 964: 965: if (sflag || xflag) 966: return; 967: cp8c(s, cursym.sname); 968: cursym.stype = 037; 969: cursym.svalue = torigin; 970: mput(&soutb, (int *)&cursym, sizeof cursym); 971: } 972: 973: mget(aloc, an) 974: int *aloc; 975: { 976: register *loc, n; 977: register *p; 978: 979: n = an; 980: n >>= 1; 981: loc = aloc; 982: if ((text.nibuf -= n) >= 0) { 983: if ((text.size -= n) > 0) { 984: p = text.ptr; 985: do 986: *loc++ = *p++; 987: while (--n); 988: text.ptr = p; 989: return; 990: } else 991: text.size += n; 992: } 993: text.nibuf += n; 994: do { 995: *loc++ = get(&text); 996: } 997: while (--n); 998: } 999: 1000: mput(buf, aloc, an) 1001: struct buf *buf; 1002: int *aloc; 1003: { 1004: register *loc; 1005: register n; 1006: 1007: loc = aloc; 1008: n = an>>1; 1009: do { 1010: putw(*loc++, buf); 1011: } 1012: while (--n); 1013: } 1014: 1015: dseek(asp, aloc, s) 1016: long aloc; 1017: struct stream *asp; 1018: { 1019: register struct stream *sp; 1020: register struct page *p; 1021: /* register */ long b, o; 1022: int n; 1023: 1024: b = aloc >> 8; 1025: o = aloc & 0377; 1026: sp = asp; 1027: --sp->pno->nuser; 1028: if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) 1029: if (p->nuser==0 || (p = &page[0])->nuser==0) { 1030: if (page[0].nuser==0 && page[1].nuser==0) 1031: if (page[0].bno < page[1].bno) 1032: p = &page[0]; 1033: p->bno = b; 1034: lseek(infil, (aloc & ~0377L) << 1, 0); 1035: if ((n = read(infil, (char *)p->buff, 512)>>1) < 0) 1036: n = 0; 1037: p->nibuf = n; 1038: } else 1039: error(2, "No pages"); 1040: ++p->nuser; 1041: sp->bno = b; 1042: sp->pno = p; 1043: sp->ptr = p->buff + o; 1044: if (s != -1) 1045: sp->size = half(s); 1046: if ((sp->nibuf = p->nibuf-o) <= 0) 1047: sp->size = 0; 1048: } 1049: 1050: half(i) 1051: { 1052: return((i>>1)&077777); 1053: } 1054: 1055: get(asp) 1056: struct stream *asp; 1057: { 1058: register struct stream *sp; 1059: 1060: sp = asp; 1061: if (--sp->nibuf < 0) { 1062: dseek(sp, (long)(sp->bno + 1) << 8, -1); 1063: --sp->nibuf; 1064: } 1065: if (--sp->size <= 0) { 1066: if (sp->size < 0) 1067: error(2, premeof); 1068: ++fpage.nuser; 1069: --sp->pno->nuser; 1070: sp->pno = (struct page *)&fpage; 1071: } 1072: return(*sp->ptr++); 1073: } 1074: 1075: getfile(acp) 1076: char *acp; 1077: { 1078: register char *cp; 1079: register int c; 1080: struct stat x; 1081: 1082: cp = acp; 1083: infil = -1; 1084: archdr.aname[0] = '\0'; 1085: filname = cp; 1086: if (cp[0]=='-' && cp[1]=='l') { 1087: if(cp[2] == '\0') 1088: cp = "-la"; 1089: filname = "/usr/lib/libxxxxxxxxxxxxxxx"; 1090: for(c=0; cp[c+2]; c++) 1091: filname[c+12] = cp[c+2]; 1092: filname[c+12] = '.'; 1093: filname[c+13] = 'a'; 1094: filname[c+14] = '\0'; 1095: if ((infil = open(filname+4, 0)) >= 0) { 1096: filname += 4; 1097: } 1098: } 1099: if (infil == -1 && (infil = open(filname, 0)) < 0) 1100: error(2, "cannot open"); 1101: page[0].bno = page[1].bno = -1; 1102: page[0].nuser = page[1].nuser = 0; 1103: text.pno = reloc.pno = (struct page *)&fpage; 1104: fpage.nuser = 2; 1105: dseek(&text, 0L, 2); 1106: if (text.size <= 0) 1107: error(2, premeof); 1108: if(get(&text) != ARCMAGIC) 1109: return(0); /* regualr file */ 1110: dseek(&text, 1L, sizeof archdr); /* word addressing */ 1111: if(text.size <= 0) 1112: return(1); /* regular archive */ 1113: mget((int *)&archdr, sizeof archdr); 1114: if(strncmp(archdr.aname, goodnm, 14) != 0) 1115: return(1); /* regular archive */ 1116: else { 1117: fstat(infil, &x); 1118: if(x.st_mtime > archdr.atime) 1119: { 1120: return(3); 1121: } 1122: else return(2); 1123: } 1124: } 1125: 1126: struct symbol **lookup() 1127: { 1128: int i; 1129: int clash; 1130: register struct symbol **hp; 1131: register char *cp, *cp1; 1132: 1133: i = 0; 1134: for (cp = cursym.sname; cp < &cursym.sname[8];) 1135: i = (i<<1) + *cp++; 1136: for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { 1137: cp1 = (*hp)->sname; 1138: clash=FALSE; 1139: for (cp = cursym.sname; cp < &cursym.sname[8];) 1140: if (*cp++ != *cp1++) { 1141: clash=TRUE; 1142: break; 1143: } 1144: if (clash) { 1145: if (++hp >= &hshtab[NSYM+2]) 1146: hp = hshtab; 1147: } else 1148: break; 1149: } 1150: return(hp); 1151: } 1152: 1153: struct symbol **slookup(s) 1154: char *s; 1155: { 1156: cp8c(s, cursym.sname); 1157: cursym.stype = EXTERN+UNDEF; 1158: cursym.svalue = 0; 1159: return(lookup()); 1160: } 1161: 1162: enter(hp) 1163: struct symbol **hp; 1164: { 1165: register struct symbol *sp; 1166: 1167: if (*hp==0) { 1168: if (symindex>=NSYM) 1169: error(2, "Symbol table overflow"); 1170: symhash[symindex] = hp; 1171: *hp = lastsym = sp = &symtab[symindex++]; 1172: cp8c(cursym.sname, sp->sname); 1173: sp->stype = cursym.stype; 1174: sp->svalue = cursym.svalue; 1175: return(1); 1176: } else { 1177: lastsym = *hp; 1178: return(0); 1179: } 1180: } 1181: 1182: symreloc() 1183: { 1184: switch (cursym.stype) { 1185: 1186: case TEXT: 1187: case EXTERN+TEXT: 1188: cursym.svalue += ctrel; 1189: return; 1190: 1191: case DATA: 1192: case EXTERN+DATA: 1193: cursym.svalue += cdrel; 1194: return; 1195: 1196: case BSS: 1197: case EXTERN+BSS: 1198: cursym.svalue += cbrel; 1199: return; 1200: 1201: case EXTERN+UNDEF: 1202: return; 1203: } 1204: if (cursym.stype&EXTERN) 1205: cursym.stype = EXTERN+ABS; 1206: } 1207: 1208: error(n, s) 1209: char *s; 1210: { 1211: if (errlev==0) 1212: printf("ld:"); 1213: if (filname) { 1214: printf("%s", filname); 1215: if (archdr.aname[0]) 1216: printf("(%.14s)", archdr.aname); 1217: printf(": "); 1218: } 1219: printf("%s\n", s); 1220: if (n > 1) 1221: delexit(); 1222: errlev = n; 1223: } 1224: 1225: struct symbol * 1226: lookloc(alp, r) 1227: struct local *alp; 1228: { 1229: register struct local *clp, *lp; 1230: register sn; 1231: 1232: lp = alp; 1233: sn = (r>>4) & 07777; 1234: for (clp = local; clp<lp; clp++) 1235: if (clp->locindex == sn) 1236: return(clp->locsymbol); 1237: error(2, "Local symbol botch"); 1238: } 1239: 1240: readhdr(loc) 1241: long loc; 1242: { 1243: register st, sd; 1244: 1245: dseek(&text, loc, sizeof filhdr); 1246: mget((int *)&filhdr, sizeof filhdr); 1247: if (filhdr.fmagic != FMAGIC) 1248: error(2, "Bad format"); 1249: st = (filhdr.tsize+01) & ~01; 1250: filhdr.tsize = st; 1251: cdrel = -st; 1252: sd = (filhdr.dsize+01) & ~01; 1253: cbrel = - (st+sd); 1254: filhdr.bsize = (filhdr.bsize+01) & ~01; 1255: } 1256: 1257: cp8c(from, to) 1258: char *from, *to; 1259: { 1260: register char *f, *t, *te; 1261: 1262: f = from; 1263: t = to; 1264: te = t+8; 1265: while ((*t++ = *f++) && t<te); 1266: while (t<te) 1267: *t++ = 0; 1268: } 1269: 1270: eq(s1, s2) 1271: char *s1; 1272: char *s2; 1273: { 1274: while (*s1==*s2++) 1275: if ((*s1++)==0) 1276: return(TRUE); 1277: return(FALSE); 1278: } 1279: 1280: putw(w, b) 1281: register struct buf *b; 1282: { 1283: *(b->xnext)++ = w; 1284: if (--b->nleft <= 0) 1285: flush(b); 1286: } 1287: 1288: flush(b) 1289: register struct buf *b; 1290: { 1291: register n; 1292: 1293: if ((n = (char *)b->xnext - (char *)b->iobuf) > 0) 1294: if (write(b->fildes, (char *)b->iobuf, n) != n) 1295: error(2, "output error"); 1296: b->xnext = b->iobuf; 1297: b->nleft = sizeof(b->iobuf)/sizeof(int); 1298: }