|
|
1.1 ! root 1: char LD[] = "@(#)ld.c 1.10 78/12/07 15:34:58"; /* sccs ident */ ! 2: /* ! 3: * link editor for VAX ! 4: */ ! 5: ! 6: /* layout of a.out file: ! 7: * ! 8: * header of 8 words magic number 0410: ! 9: data starts at 1st (PAGSIZ) ! 10: boundary above text ! 11: magic number 0407: ! 12: data starts immediately after ! 13: text ! 14: * text size ) ! 15: * data size ) in bytes ! 16: * bss size ) ! 17: * symbol table size ! 18: * entry point ! 19: * size of text relocation info ! 20: * size of data relocation info ! 21: * ! 22: * 'segment' origin comments ! 23: * header: 0 ! 24: * text: 32 0 padded to multiple of 4 bytes ! 25: * data: 32+textsize 0 padded to multiple of 4 bytes ! 26: * text relocation: 32+textsize+datasize ! 27: * data relocation: 32+textsize+datasize+textrelocationsize ! 28: * symbol table: 32+textsize+datasize+textrelocationsize+datarelocationsize ! 29: * ! 30: */ ! 31: #include <signal.h> ! 32: #include <stdio.h> ! 33: #include <ar.h> ! 34: #include <a.out.h> ! 35: #include <pagsiz.h> ! 36: ! 37: struct {short hiword; short loword;}; /* stupid fp-11 */ ! 38: fixl(p) register long *p;{ ! 39: register short t; ! 40: t=p->hiword; p->hiword=p->loword; p->loword=t; ! 41: } ! 42: ! 43: writel(p,n,f) long *p; FILE *f; { ! 44: #ifdef vax ! 45: fwrite(p,sizeof(*p),n,f); ! 46: #else ! 47: while (n--) { ! 48: fwrite(&(*p).loword,2,1,f); ! 49: fwrite(&(*p).hiword,2,1,f); ! 50: p++; ! 51: } ! 52: #endif ! 53: } ! 54: ! 55: long htoi(p) register char *p; {/* hex to integer conversion */ ! 56: register long n = 0; ! 57: while (*p) { ! 58: n <<= 4; ! 59: if (*p<='9' && *p>='0') n += *p - '0'; ! 60: else if (*p<='f' && *p>='a') n += *p -'a' +10; ! 61: else if (*p<='F' && *p>='A') n += *p -'A' +10; ! 62: p++; ! 63: } ! 64: return(n); ! 65: } ! 66: ! 67: typedef char *STRING; ! 68: typedef int BOOL; ! 69: #define TRUE 1 ! 70: #define FALSE 0 ! 71: ! 72: #define OMAGIC 0407 ! 73: #define NMAGIC 0410 ! 74: ! 75: /* ! 76: * Symbol types ! 77: */ ! 78: #define UNDEF 0x0 ! 79: #define ABS 0x2 ! 80: #define TEXT 0x4 ! 81: #define DATA 0x6 ! 82: #define BSS 0x8 ! 83: #define DATAO 0xA ! 84: #define BSSO 0xC ! 85: #define TEXTO 0xE ! 86: #define ABSO 0x10 ! 87: ! 88: #define COMM 0x12 /* for internal use only */ ! 89: ! 90: #define EXTERN 0x1 ! 91: #define TYPE 0x1E ! 92: #define STABTYPS 0xE0 ! 93: /* ! 94: * address reference types ! 95: */ ! 96: #define PCREL 1 ! 97: #define LEN1 0 ! 98: #define LEN2 2 ! 99: #define LEN4 4 ! 100: ! 101: #define HW 01 ! 102: #define FW 03 ! 103: #define DW 07 ! 104: ! 105: ! 106: #define TYPMASK 0x1E ! 107: #define TYMASK (0x1E) ! 108: #define TMASK 0x1F ! 109: ! 110: #define RABS (ABS) ! 111: #define RTEXT TEXT ! 112: #define RDATA DATA ! 113: #define RBSS BSS ! 114: #define RDATAO DATAO ! 115: #define RBSSO BSSO ! 116: #define RTEXTO TEXTO ! 117: #define RABSO ABSO ! 118: #define REXT (01<<3) ! 119: #define ROFF (02<<3) ! 120: #define REFMASK 0x7 ! 121: ! 122: #define NOVLY 1 ! 123: #define RELFLG 01 ! 124: #define NROUT 256 ! 125: #define NSYM 1103 ! 126: #define NSYMPR 500 ! 127: ! 128: char premeof[] = "Premature EOF"; ! 129: ! 130: typedef struct { ! 131: long loc; ! 132: } LIBLIST; ! 133: ! 134: /* overlay management */ ! 135: int vindex; ! 136: typedef struct { ! 137: int argsav; ! 138: int symsav; ! 139: LIBLIST *libsav; ! 140: STRING vname; ! 141: long ctsav, cdsav, cbsav; ! 142: long offt, offd, offb, offtr, offdr, offs; ! 143: } OVERLAY; ! 144: OVERLAY vnodes[NOVLY]; ! 145: ! 146: /* input management */ ! 147: typedef struct { ! 148: short *fakeptr; ! 149: int bno; ! 150: int nibuf; ! 151: int nuser; ! 152: char buff[BSIZE]; ! 153: } PAGE; ! 154: ! 155: PAGE page[2]; ! 156: ! 157: struct { ! 158: short *fakeptr; ! 159: int bno; ! 160: int nibuf; ! 161: int nuser; ! 162: } fpage; ! 163: ! 164: typedef struct { ! 165: char *ptr; ! 166: int bno; ! 167: int nibuf; ! 168: long size; ! 169: long pos; ! 170: PAGE *pno; ! 171: } STREAM; ! 172: ! 173: STREAM text; ! 174: STREAM reloc; ! 175: ! 176: struct ar_hdr archdr; ! 177: ! 178: struct exec filhdr; ! 179: ! 180: /* one entry for each archive member referenced; ! 181: * set in first pass; needs restoring for overlays ! 182: */ ! 183: ! 184: LIBLIST liblist[NROUT]; ! 185: LIBLIST *libp = liblist; ! 186: ! 187: ! 188: /* symbol management */ ! 189: typedef struct { ! 190: char sname[8]; ! 191: char stype; ! 192: char spare; ! 193: short symhash; /* index of hash table entry pointing to this symbol */ ! 194: long svalue; ! 195: } SYMBOL; ! 196: ! 197: typedef struct { ! 198: int locindex; /* index to symbol in file */ ! 199: SYMBOL *locsymbol; /* ptr to symbol table */ ! 200: } LOCAL; ! 201: ! 202: SYMBOL cursym; /* current symbol */ ! 203: SYMBOL *symtab; /* actual symbols */ ! 204: SYMBOL *lastsym; /* last symbol entered */ ! 205: SYMBOL *nextsym; /* next available symbol table entry */ ! 206: int nsym; /* number of symbols allocated in symtab */ ! 207: SYMBOL *hshtab[NSYM+2]; /* hash table for symbols */ ! 208: LOCAL *local; ! 209: ! 210: /* internal symbols */ ! 211: SYMBOL *p_data; ! 212: SYMBOL *p_etext; ! 213: SYMBOL *p_edata; ! 214: SYMBOL *p_end; ! 215: SYMBOL *entrypt; ! 216: ! 217: int trace; ! 218: /* flags */ ! 219: int xflag; /* discard local symbols */ ! 220: int Xflag; /* discard locals starting with 'L' */ ! 221: int Sflag; /* discard all except locals and globals*/ ! 222: int rflag; /* preserve relocation bits, don't define common */ ! 223: int arflag; /* original copy of rflag */ ! 224: int sflag; /* discard all symbols */ ! 225: int nflag = 1; /* pure procedure */ ! 226: int dflag; /* define common even with rflag */ ! 227: int iflag; /* I/D space separated */ ! 228: BOOL vflag; /* overlays used */ ! 229: int zflag; ! 230: ! 231: int ofilfnd; ! 232: char *ofilename = "l.out"; ! 233: int infil; ! 234: char *filname; ! 235: ! 236: long textbase; ! 237: /* cumulative sizes set in pass 1 */ ! 238: long tsize; ! 239: long dsize; ! 240: long bsize; ! 241: long trsize; ! 242: long drsize; ! 243: long ssize; ! 244: ! 245: /* symbol relocation; both passes */ ! 246: long ctrel; ! 247: long cdrel; ! 248: long cbrel; ! 249: long ctorel; ! 250: long cdorel; ! 251: long cborel; ! 252: ! 253: int errlev; ! 254: int delarg = 4; ! 255: ! 256: ! 257: FILE *tout; ! 258: FILE *dout; ! 259: char *doutn = ""; ! 260: FILE *trout; ! 261: char *troutn = ""; ! 262: FILE *drout; ! 263: char *droutn = ""; ! 264: FILE *sout; ! 265: char *soutn = ""; ! 266: ! 267: char *mktemp(); ! 268: char get(); ! 269: char getb(); ! 270: short gets(); ! 271: long get3(); ! 272: long getl(); ! 273: SYMBOL **lookup(); ! 274: FILE *tcreat(); ! 275: long round(); ! 276: SYMBOL **slookup(); ! 277: SYMBOL *lookloc(); ! 278: ! 279: symwrite(sp,n,f) SYMBOL *sp; FILE *f; { ! 280: #ifdef vax ! 281: fwrite(sp,sizeof(*symtab),n,f); ! 282: #else ! 283: while (n--) { ! 284: fwrite(sp,sizeof(*symtab)-sizeof(sp->svalue),1,f); ! 285: writel(&(sp->svalue),1,f); sp++; ! 286: } ! 287: #endif ! 288: } ! 289: ! 290: delexit() ! 291: { ! 292: unlink("l.out"); ! 293: unlink(doutn); ! 294: unlink(troutn); ! 295: unlink(droutn); ! 296: unlink(soutn); ! 297: if (delarg==0) ! 298: chmod(ofilename, 0777 &~ umask(0)); ! 299: exit(delarg); ! 300: } ! 301: ! 302: main(argc, argv) ! 303: char **argv; ! 304: { ! 305: register int c, i; ! 306: int num; ! 307: register char *ap, **p; ! 308: BOOL found; ! 309: int vscan; ! 310: char save; ! 311: ! 312: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 313: signal(SIGINT, delexit); ! 314: if (argc == 1) ! 315: exit(4); ! 316: p = argv+1; ! 317: ! 318: nextsym=symtab=sbrk(0); nsym=0; ! 319: /* scan files once to find symdefs */ ! 320: for (c=1; c<argc; c++) { ! 321: if (trace) printf("%s:\n", *p); ! 322: filname = 0; ! 323: ap = *p++; ! 324: ! 325: if (*ap == '-') { ! 326: for (i=1; ap[i]; i++) { ! 327: switch (ap[i]) { ! 328: case 'o': ! 329: if (++c >= argc) ! 330: error(1, "Bad output file"); ! 331: ofilename = *p++; ! 332: ofilfnd++; ! 333: continue; ! 334: ! 335: case 'u': ! 336: case 'e': ! 337: if (++c >= argc) ! 338: error(1, "Bad 'use' or 'entry'"); ! 339: enter(slookup(*p++)); ! 340: if (ap[i]=='e') ! 341: entrypt = lastsym; ! 342: continue; ! 343: ! 344: case 'v': ! 345: if (++c >= argc) ! 346: error(1, "-v: arg missing"); ! 347: vflag=TRUE; ! 348: vscan = vindex; ! 349: found=FALSE; ! 350: while (--vscan>=0 && found==FALSE) ! 351: found = eq(vnodes[vscan].vname, *p); ! 352: if (found) { ! 353: endload(c, argv); ! 354: restore(vscan); ! 355: } else ! 356: record(c, *p); ! 357: p++; ! 358: continue; ! 359: ! 360: case 'D': ! 361: if (++c >= argc) ! 362: error(1, "-D: arg missing"); ! 363: num = htoi(*p++); ! 364: if (dsize>num) ! 365: error(1, "-D: too small"); ! 366: dsize = num; ! 367: continue; ! 368: ! 369: case 'T': ! 370: if (++c >= argc) ! 371: error(1, "-T: arg missing"); ! 372: if (tsize!=0) ! 373: error(1, "-T: too late, some text already loaded"); ! 374: textbase = htoi(*p++); ! 375: continue; ! 376: ! 377: case 'l': ! 378: save = ap[--i]; ! 379: ap[i]='-'; ! 380: load1arg(&ap[i]); ! 381: ap[i]=save; ! 382: break; ! 383: ! 384: case 'x': ! 385: xflag++; ! 386: continue; ! 387: ! 388: case 'X': ! 389: Xflag++; ! 390: continue; ! 391: ! 392: case 'S': ! 393: Sflag++; ! 394: continue; ! 395: ! 396: case 'r': ! 397: rflag++; ! 398: arflag++; ! 399: continue; ! 400: ! 401: case 's': ! 402: sflag++; ! 403: xflag++; ! 404: continue; ! 405: ! 406: case 'n': ! 407: nflag++; ! 408: continue; ! 409: ! 410: case 'N': ! 411: nflag = 0; ! 412: continue; ! 413: ! 414: case 'd': ! 415: dflag++; ! 416: continue; ! 417: ! 418: case 'i': ! 419: iflag++; ! 420: continue; ! 421: ! 422: case 't': ! 423: trace++; ! 424: continue; ! 425: ! 426: case 'z': ! 427: zflag++; ! 428: continue; ! 429: ! 430: default: ! 431: error(1, "bad flag"); ! 432: } /*endsw*/ ! 433: break; ! 434: } /*endfor*/ ! 435: } else ! 436: load1arg(ap); ! 437: } ! 438: endload(argc, argv); ! 439: exit(0); ! 440: } ! 441: ! 442: /* used after pass 1 */ ! 443: long torigin; ! 444: long dorigin; ! 445: long borigin; ! 446: long database; ! 447: ! 448: endload(argc, argv) ! 449: int argc; ! 450: char **argv; ! 451: { ! 452: register int c, i; ! 453: long dnum; ! 454: register char *ap, **p; ! 455: ! 456: brk(nextsym); ! 457: filname = 0; ! 458: middle(); ! 459: setupout(); ! 460: if (-1==(local=sbrk(NSYMPR*sizeof(*local)))) error(1,"Memory overflow"); ! 461: p = argv+1; ! 462: libp = liblist; ! 463: for (c=1; c<argc; c++) { ! 464: ap = *p++; ! 465: if (trace) printf("%s:\n", ap); ! 466: if (*ap == '-') { ! 467: for (i=1; ap[i]; i++) { ! 468: switch (ap[i]) { ! 469: case 'D': ! 470: for (dnum = htoi(*p); dorigin<dnum; dorigin++) putc(0, dout); ! 471: case 'T': ! 472: case 'u': ! 473: case 'e': ! 474: case 'o': ! 475: case 'v': ! 476: ++c; ! 477: ++p; ! 478: ! 479: default: ! 480: continue; ! 481: ! 482: case 'l': ! 483: ap[--i]='-'; ! 484: load2arg(&ap[i]); ! 485: break; ! 486: } /*endsw*/ ! 487: break; ! 488: } /*endfor*/ ! 489: } else ! 490: load2arg(ap); ! 491: } ! 492: finishout(); ! 493: } ! 494: ! 495: record(c, nam) ! 496: int c; ! 497: STRING nam; ! 498: { ! 499: register OVERLAY *v; ! 500: ! 501: v = &vnodes[vindex++]; ! 502: v->argsav = c; ! 503: v->symsav = nextsym-symtab; ! 504: v->libsav = libp; ! 505: v->vname = nam; ! 506: v->offt = tsize; ! 507: v->offd = dsize; ! 508: v->offb = bsize; ! 509: v->offtr = trsize; ! 510: v->offdr = drsize; ! 511: v->offs = ssize; ! 512: v->ctsav = ctrel; ! 513: v->cdsav = cdrel; ! 514: v->cbsav = cbrel; ! 515: } ! 516: ! 517: restore(vscan) ! 518: int vscan; ! 519: { ! 520: register OVERLAY *v; ! 521: register SYMBOL *saved,*sp; ! 522: ! 523: v = &vnodes[vscan]; ! 524: vindex = vscan+1; ! 525: libp = v->libsav; ! 526: ctrel = v->ctsav; ! 527: cdrel = v->cdsav; ! 528: cbrel = v->cbsav; ! 529: tsize = v->offt; ! 530: dsize = v->offd; ! 531: bsize = v->offb; ! 532: trsize = v->offtr; ! 533: drsize = v->offdr; ! 534: ssize = v->offs; ! 535: saved = symtab + v->symsav; ! 536: sp = nextsym; ! 537: while (sp>saved) ! 538: hshtab[(--sp)->symhash]=0; ! 539: nextsym = saved; ! 540: } ! 541: ! 542: /* scan file to find defined symbols */ ! 543: load1arg(cp) ! 544: register char *cp; ! 545: { ! 546: long loc; ! 547: ! 548: if (getfile(cp)==0) ! 549: load1(0, 0L); ! 550: else { ! 551: loc = sizeof(int); ! 552: for (;;) { ! 553: dseek(&text, loc, (long)sizeof(archdr)); ! 554: if (text.size <= 0) { ! 555: libp->loc = -1; ! 556: if( ++libp >= liblist + NROUT) ! 557: error(1,"liblist overflow"); ! 558: /* thanks to Dennis Wasley */ ! 559: return; ! 560: } ! 561: mget((short *)&archdr, sizeof archdr, &text); ! 562: if (load1(1, loc+sizeof(archdr))) { ! 563: libp->loc = loc; ! 564: libp++; ! 565: } ! 566: #ifndef vax ! 567: if (archdr.ar_size.loword==0) fixl(&archdr.ar_size); ! 568: #endif ! 569: loc += round(archdr.ar_size, 1) + sizeof(archdr); ! 570: } ! 571: } ! 572: close(infil); ! 573: } ! 574: ! 575: /* single file or archive member */ ! 576: load1(libflg, loc) ! 577: long loc; ! 578: { ! 579: register SYMBOL *sp; ! 580: SYMBOL *savnext; ! 581: int ndef, nlocal, type; ! 582: ! 583: readhdr(loc); ! 584: ctrel = tsize; ! 585: cdrel += dsize; ! 586: cbrel += bsize; ! 587: ndef = 0; ! 588: nlocal = sizeof(cursym); ! 589: savnext = nextsym; ! 590: /* if (filhdr.a_trsize+filhdr.a_drsize==0) { ! 591: /* error(0, "No relocation bits"); ! 592: /* return(0); ! 593: /* } ! 594: */ ! 595: loc += filhdr.a_text + filhdr.a_data + ! 596: filhdr.a_trsize + filhdr.a_drsize + sizeof(filhdr); ! 597: dseek(&text, loc, filhdr.a_syms); ! 598: while (text.size > 0) { ! 599: symget(&cursym, &text); ! 600: type = cursym.stype; ! 601: if ((type&EXTERN)==0) { ! 602: if (Xflag==0 || cursym.sname[0]!='L' || type & STABTYPS) ! 603: nlocal += sizeof cursym; ! 604: continue; ! 605: } ! 606: symreloc(); ! 607: if (enter(lookup())) ! 608: continue; ! 609: if ((sp = lastsym)->stype != EXTERN+UNDEF) ! 610: continue; ! 611: if (cursym.stype == EXTERN+UNDEF) { ! 612: if (cursym.svalue > sp->svalue) ! 613: sp->svalue = cursym.svalue; ! 614: continue; ! 615: } ! 616: if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) ! 617: continue; ! 618: ndef++; ! 619: sp->stype = cursym.stype; ! 620: sp->svalue = cursym.svalue; ! 621: } ! 622: if (libflg==0 || ndef) { ! 623: tsize += filhdr.a_text; ! 624: dsize += round(filhdr.a_data, FW); ! 625: bsize += round(filhdr.a_bss, FW); ! 626: ssize += nlocal; ! 627: trsize += filhdr.a_trsize; ! 628: drsize += filhdr.a_drsize; ! 629: return(1); ! 630: } ! 631: /* ! 632: * No symbols defined by this library member. ! 633: * Rip out the hash table entries and reset the symbol table. ! 634: */ ! 635: while (nextsym>savnext) ! 636: hshtab[(--nextsym)->symhash]=0; ! 637: return(0); ! 638: } ! 639: ! 640: middle() ! 641: { ! 642: register SYMBOL *sp, *symp; ! 643: long csize, t, corigin, ocsize; ! 644: int nund, rnd; ! 645: char s; ! 646: ! 647: torigin = 0; ! 648: dorigin = 0; ! 649: borigin = 0; ! 650: ! 651: p_data = *slookup("_data"); ! 652: p_etext = *slookup("_etext"); ! 653: p_edata = *slookup("_edata"); ! 654: p_end = *slookup("_end"); ! 655: /* ! 656: * If there are any undefined symbols, save the relocation bits. ! 657: */ ! 658: symp = nextsym; ! 659: if (rflag==0) { ! 660: for (sp = symtab; sp<symp; sp++) ! 661: if (sp->stype==EXTERN+UNDEF && sp->svalue==0 ! 662: && sp!=p_end && sp!=p_edata && sp!=p_etext ! 663: && sp!=p_data) { ! 664: rflag++; ! 665: dflag = 0; ! 666: break; ! 667: } ! 668: } ! 669: if (rflag) ! 670: sflag = iflag = 0; ! 671: /* ! 672: * Assign common locations. ! 673: */ ! 674: csize = 0; ! 675: database = round(tsize+textbase, (nflag? PAGRND:FW)); ! 676: if (dflag || rflag==0) { ! 677: ldrsym(p_data, (long)0 , EXTERN+DATA); ! 678: ldrsym(p_etext, tsize, EXTERN+TEXT); ! 679: ldrsym(p_edata, dsize, EXTERN+DATA); ! 680: ldrsym(p_end, bsize, EXTERN+BSS); ! 681: for (sp = symtab; sp<symp; sp++) { ! 682: if ((s=sp->stype)==EXTERN+UNDEF && (t = sp->svalue)!=0) { ! 683: if (t>DW) ! 684: rnd = DW; ! 685: else if (t>FW) ! 686: rnd = FW; ! 687: else ! 688: rnd = HW; ! 689: csize = round(csize, rnd); ! 690: sp->svalue = csize; ! 691: sp->stype = EXTERN+COMM; ! 692: ocsize = csize; ! 693: csize += t; ! 694: } ! 695: if (((s&TMASK) == EXTERN+UNDEF) && (s & STABTYPS)) { ! 696: sp->svalue = ocsize; ! 697: sp->stype = (s & STABTYPS) | (EXTERN+COMM); ! 698: } ! 699: } ! 700: } ! 701: /* ! 702: * Now set symbols to their final value ! 703: */ ! 704: csize = round(csize, FW); ! 705: torigin = textbase; ! 706: dorigin = database; ! 707: corigin = dorigin + dsize; ! 708: borigin = corigin + csize; ! 709: /* ! 710: if (zflag) ! 711: borigin = round(borigin, PAGRND); ! 712: */ ! 713: cdorel = 0; ! 714: cborel = dsize+csize; ! 715: nund = 0; ! 716: for (sp = symtab; sp<symp; sp++) switch (sp->stype & TMASK) { ! 717: case EXTERN+UNDEF: ! 718: errlev |= 01; ! 719: if ((arflag==0 || dflag) && sp->svalue==0) { ! 720: if (nund==0) ! 721: printf("Undefined:\n"); ! 722: nund++; ! 723: printf("%.8s\n", sp->sname); ! 724: } ! 725: continue; ! 726: ! 727: case EXTERN+ABS: ! 728: default: ! 729: continue; ! 730: ! 731: case EXTERN+TEXT: ! 732: sp->svalue += torigin; ! 733: continue; ! 734: ! 735: case EXTERN+DATA: ! 736: sp->svalue += dorigin; ! 737: continue; ! 738: ! 739: case EXTERN+BSS: ! 740: sp->svalue += borigin; ! 741: continue; ! 742: ! 743: case EXTERN+COMM: ! 744: sp->stype = (sp->stype & STABTYPS) | (EXTERN+BSS); ! 745: sp->svalue += corigin; ! 746: continue; ! 747: } ! 748: if (sflag || xflag) ! 749: ssize = 0; ! 750: bsize += csize; ! 751: nsym = ssize / (sizeof cursym); ! 752: } ! 753: ! 754: ldrsym(asp, val, type) ! 755: long val; ! 756: SYMBOL *asp; ! 757: { ! 758: register SYMBOL *sp; ! 759: ! 760: if ((sp = asp) == 0) ! 761: return; ! 762: if (sp->stype != EXTERN+UNDEF || sp->svalue) { ! 763: printf("%.8s: ", sp->sname); ! 764: error(0, "Multiply defined (internal)"); ! 765: return; ! 766: } ! 767: sp->stype = type; ! 768: sp->svalue = val; ! 769: } ! 770: ! 771: extern char _sibuf[BUFSIZ]; /* the space is forced upon us; might as well use it */ ! 772: ! 773: setupout() ! 774: { ! 775: int bss; ! 776: tout = fopen(ofilename, "w"); ! 777: if (tout==NULL) ! 778: error(1, "cannot create output"); ! 779: setbuf(tout,_sibuf); ! 780: dout = tcreat(&doutn, "/tmp/ldaaXXXXX"); ! 781: if (sflag==0 || xflag==0) ! 782: sout = tcreat(&soutn, "/tmp/ldbaXXXXX"); ! 783: if (rflag) { ! 784: trout = tcreat(&troutn, "/tmp/ldcaXXXXX"); ! 785: drout = tcreat(&droutn, "/tmp/lddaXXXXX"); ! 786: } ! 787: filhdr.a_magic = nflag? NMAGIC:OMAGIC; ! 788: if (zflag) ! 789: filhdr.a_magic = nflag?0413:0412; ! 790: filhdr.a_text = nflag? tsize:round(tsize, FW); ! 791: if (zflag) ! 792: filhdr.a_text = round(tsize, PAGRND); ! 793: filhdr.a_data = dsize; ! 794: if (zflag) ! 795: filhdr.a_data = round(dsize, PAGRND); ! 796: bss = bsize - (filhdr.a_data - dsize); ! 797: if (bss < 0) ! 798: bss = 0; ! 799: filhdr.a_bss = bss; ! 800: filhdr.a_trsize = trsize; ! 801: filhdr.a_drsize = drsize; ! 802: filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*(nextsym-symtab)); ! 803: if (entrypt) { ! 804: if (entrypt->stype!=EXTERN+TEXT) ! 805: error(0, "Entry point not in text"); ! 806: else ! 807: filhdr.a_entry = entrypt->svalue; ! 808: } else ! 809: filhdr.a_entry=0; ! 810: filhdr.a_trsize = (rflag ? trsize:0); ! 811: filhdr.a_drsize = (rflag ? drsize:0); ! 812: writel(&filhdr,8,tout); ! 813: if (zflag) ! 814: fseek(tout, PAGSIZ, 0); ! 815: } ! 816: ! 817: FILE * ! 818: tcreat(namep, name) ! 819: char **namep, *name; ! 820: { ! 821: register FILE *fp; ! 822: register char *tnm; ! 823: ! 824: tnm = mktemp(name); ! 825: if ((fp = fopen(tnm, "w")) == NULL) ! 826: error(1, "Cannot create temp file"); ! 827: chmod(tnm, 0600); ! 828: *namep = tnm; ! 829: return(fp); ! 830: } ! 831: ! 832: load2arg(acp) ! 833: char *acp; ! 834: { ! 835: register char *cp; ! 836: register LIBLIST *lp; ! 837: ! 838: cp = acp; ! 839: if (getfile(cp) == 0) { ! 840: while (*cp) ! 841: cp++; ! 842: while (cp >= acp && *--cp != '/'); ! 843: mkfsym(++cp); ! 844: load2(0L); ! 845: } else { /* scan archive members referenced */ ! 846: for (lp = libp; lp->loc != -1; lp++) { ! 847: dseek(&text, lp->loc, (long)sizeof(archdr)); ! 848: mget((short *)&archdr, sizeof(archdr), &text); ! 849: mkfsym(archdr.ar_name); ! 850: load2(lp->loc + (long)sizeof(archdr)); ! 851: } ! 852: libp = ++lp; ! 853: } ! 854: close(infil); ! 855: } ! 856: ! 857: load2(loc) ! 858: long loc; ! 859: { ! 860: register SYMBOL *sp; ! 861: register LOCAL *lp; ! 862: register int symno; ! 863: int type; ! 864: ! 865: readhdr(loc); ! 866: ctrel = torigin; ! 867: cdrel += dorigin; ! 868: cbrel += borigin; ! 869: /* ! 870: * Reread the symbol table, recording the numbering ! 871: * of symbols for fixing external references. ! 872: */ ! 873: lp = local; ! 874: symno = -1; ! 875: loc += sizeof(filhdr); ! 876: dseek(&text, loc+filhdr.a_text+filhdr.a_data+ ! 877: filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms); ! 878: while (text.size > 0) { ! 879: symno++; ! 880: symget(&cursym, &text); ! 881: symreloc(); ! 882: type = cursym.stype; ! 883: if ((type&EXTERN) == 0) { ! 884: if (!sflag&&!xflag&& ! 885: (!Xflag||cursym.sname[0]!='L'||type&STABTYPS)) ! 886: symwrite(&cursym, 1, sout); ! 887: continue; ! 888: } ! 889: if ((sp = *lookup()) == 0) ! 890: error(1, "internal error: symbol not found"); ! 891: if (cursym.stype == EXTERN+UNDEF) { ! 892: if (lp >= local+NSYMPR) ! 893: error(1, "Local symbol overflow"); ! 894: lp->locindex = symno; ! 895: lp++->locsymbol = sp; ! 896: continue; ! 897: } ! 898: if(cursym.stype & STABTYPS) continue; ! 899: if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { ! 900: printf("%.8s: ", cursym.sname); ! 901: error(0, "Multiply defined"); ! 902: } ! 903: } ! 904: dseek(&text, loc, filhdr.a_text); ! 905: dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize); ! 906: load2td(lp, ctrel, tout, trout); ! 907: dseek(&text, loc+filhdr.a_text, filhdr.a_data); ! 908: dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize, filhdr.a_drsize); ! 909: load2td(lp, cdrel, dout, drout); ! 910: while (filhdr.a_data&FW) { ! 911: putc(0, dout); filhdr.a_data++; ! 912: } ! 913: torigin += filhdr.a_text; ! 914: dorigin += filhdr.a_data; ! 915: borigin += filhdr.a_bss; ! 916: cdorel += filhdr.a_data; ! 917: cborel += filhdr.a_bss; ! 918: } ! 919: ! 920: load2td(lp, creloc, b1, b2) ! 921: LOCAL *lp; ! 922: long creloc; ! 923: FILE *b1, *b2; ! 924: { ! 925: register r1; ! 926: register char r2; ! 927: register long t; ! 928: register SYMBOL *sp; ! 929: long tw,u,l; ! 930: ! 931: for (;;) { ! 932: if (reloc.size==0) {while (text.size) putc(get(&text),b1); break;} ! 933: t=getl(&reloc); /* position of relocatable stuff */ ! 934: if (rflag) putl(t+creloc,b2); /* remember for subsequent link editing */ ! 935: while (text.pos<t) putc(get(&text),b1); /* advance to proper position */ ! 936: r1=get3(&reloc); /* kind of relocation */ ! 937: r2 = getb(&reloc); ! 938: switch (r2&06) {/* read raw datum according to its length */ ! 939: case LEN1: tw=get(&text); break; ! 940: case LEN2: tw=gets(&text); break; ! 941: case LEN4: tw=getl(&text); break; ! 942: } ! 943: if (r2&REXT) { ! 944: sp=lookloc(lp,r1); /* find the symbol */ ! 945: if (sp->stype==EXTERN+UNDEF) { /* still undefined */ ! 946: r2=(r2&(REFMASK+REXT+ROFF)); ! 947: r1 = nsym+(sp-symtab); /* new reloc */ ! 948: } ! 949: else { ! 950: if (sp->stype==EXTERN+DATA && r2&ROFF) { ! 951: r1=RDATAO; ! 952: r2&=REFMASK; ! 953: } ! 954: else if (sp->stype==EXTERN+BSS && r2&ROFF) { ! 955: r1=RBSSO; ! 956: r2&=REFMASK; ! 957: } ! 958: else if (sp->stype==EXTERN+ABS && r2&ROFF) { ! 959: r1=RABSO; ! 960: r2&=REFMASK; ! 961: } ! 962: else if (sp->stype==EXTERN+TEXT && r2&ROFF) { ! 963: r1=RTEXTO; ! 964: r2&=REFMASK; ! 965: } ! 966: else {if (r2&ROFF) {if (rflag) {error(0,"!-r; see JFR"); rflag=0;}} ! 967: else tw += database; ! 968: r1=sp->stype&TYPE; ! 969: r2&=REFMASK; ! 970: } ! 971: tw += sp->svalue - database; ! 972: } ! 973: } else switch (r1&TYMASK) { ! 974: case RTEXT: tw += ctrel; break; ! 975: case RTEXTO:tw += round(filhdr.a_text,PAGRND)+ctrel-database; break; ! 976: case RDATA: tw += cdrel; break; ! 977: case RDATAO:tw += cdorel; break; ! 978: case RBSS: tw += cbrel; break; ! 979: case RBSSO: tw += cborel-filhdr.a_data; break; ! 980: case RABSO: tw += round(filhdr.a_text,PAGRND)-database; break; ! 981: } ! 982: if (rflag) { /* remember for subsequent link editing */ ! 983: put3(r1,b2); ! 984: putb(r2,b2); ! 985: } ! 986: if (r2&PCREL) tw -= creloc; /* assembler already subtracted text.pos */ ! 987: switch (r2&06) {/* output relocated datum according to its length */ ! 988: case LEN1: l= -128; u=127; putc((char)tw,b1); break; ! 989: case LEN2: l= -32768; u=32767; puts((short)tw,b1); break; ! 990: case LEN4: l=0x80000000; u=0x7FFFFFFF; putl(tw,b1); break; ! 991: } ! 992: if (tw<l || u<tw) error(0,"Displacement overflow"); ! 993: } ! 994: } ! 995: ! 996: finishout() ! 997: { ! 998: ! 999: if (!nflag) ! 1000: while (tsize&FW) { ! 1001: putc(0, tout); tsize++; ! 1002: } ! 1003: if (zflag) { ! 1004: while (tsize&PAGRND) { ! 1005: putc(0, tout); tsize++; ! 1006: } ! 1007: while (dsize&PAGRND) { ! 1008: putc(0, dout); dsize++; ! 1009: } ! 1010: } ! 1011: fclose(dout); ! 1012: copy(doutn); ! 1013: if (rflag) { ! 1014: fclose(trout); ! 1015: copy(troutn); ! 1016: fclose(drout); ! 1017: copy(droutn); ! 1018: } ! 1019: if (sflag==0) { ! 1020: if (xflag==0) { ! 1021: fclose(sout); ! 1022: copy(soutn); ! 1023: } ! 1024: symwrite(symtab, nextsym-symtab, tout); ! 1025: } ! 1026: fclose(tout); ! 1027: if (!ofilfnd) { ! 1028: unlink("a.out"); ! 1029: link("l.out", "a.out"); ! 1030: ofilename = "a.out"; ! 1031: } ! 1032: delarg = errlev; ! 1033: delexit(); ! 1034: } ! 1035: ! 1036: copy(np) ! 1037: char *np; ! 1038: { ! 1039: register c; ! 1040: register FILE *fp; ! 1041: ! 1042: if ((fp = fopen(np, "r")) == NULL) ! 1043: error(1, "cannot recopy output"); ! 1044: while ((c = getc(fp)) != EOF) ! 1045: putc(c, tout); ! 1046: fclose(fp); ! 1047: } ! 1048: ! 1049: mkfsym(s) ! 1050: char *s; ! 1051: { ! 1052: ! 1053: if (sflag || xflag) ! 1054: return; ! 1055: cp8c(s, cursym.sname); ! 1056: cursym.stype = TEXT; ! 1057: cursym.svalue = torigin; ! 1058: symwrite(&cursym, 1, sout); ! 1059: } ! 1060: ! 1061: mget(loc, n, sp) ! 1062: register STREAM *sp; ! 1063: register char *loc; ! 1064: { ! 1065: register char *p; ! 1066: ! 1067: if ((sp->nibuf -= n) >= 0) { ! 1068: if ((sp->size -= n) > 0) { ! 1069: p = sp->ptr; ! 1070: sp->pos += n; ! 1071: do ! 1072: *loc++ = *p++; ! 1073: while (--n); ! 1074: sp->ptr = p; ! 1075: return; ! 1076: } else ! 1077: sp->size += n; ! 1078: } ! 1079: sp->nibuf += n; ! 1080: do { ! 1081: *loc++ = get(sp); ! 1082: } while (--n); ! 1083: } ! 1084: ! 1085: short ! 1086: gets(sp) STREAM *sp; { ! 1087: short t; mget(&t,2,sp); return(t); ! 1088: } ! 1089: ! 1090: char ! 1091: getb(sp) STREAM *sp; { ! 1092: char t; mget(&t,1,sp); return(t); ! 1093: } ! 1094: ! 1095: long ! 1096: get3(sp) STREAM *sp; { ! 1097: long t; t=0; mget(&t,3,sp); return(t); ! 1098: } ! 1099: ! 1100: long ! 1101: getl(sp) STREAM *sp; { ! 1102: long t; mget(&t,4,sp); ! 1103: #ifndef vax ! 1104: fixl(&t); ! 1105: #endif ! 1106: return(t); ! 1107: } ! 1108: ! 1109: symget(sp,f) SYMBOL *sp; STREAM *f; { ! 1110: mget(sp,sizeof(*sp),f); ! 1111: #ifndef vax ! 1112: fixl(&sp->svalue); ! 1113: #endif ! 1114: } ! 1115: ! 1116: dseek(sp, loc, s) ! 1117: register STREAM *sp; ! 1118: long loc, s; ! 1119: { ! 1120: register PAGE *p; ! 1121: register b, o; ! 1122: int n; ! 1123: ! 1124: b = loc>>BSHIFT; ! 1125: o = loc&BMASK; ! 1126: if (o&01) ! 1127: error(1, "loader error; odd offset"); ! 1128: --sp->pno->nuser; ! 1129: if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b) ! 1130: if (p->nuser==0 || (p = &page[0])->nuser==0) { ! 1131: if (page[0].nuser==0 && page[1].nuser==0) ! 1132: if (page[0].bno < page[1].bno) ! 1133: p = &page[0]; ! 1134: p->bno = b; ! 1135: lseek(infil, loc & ~(long)BMASK, 0); ! 1136: if ((n = read(infil, p->buff, sizeof(p->buff))) < 0) ! 1137: n = 0; ! 1138: p->nibuf = n; ! 1139: } else ! 1140: error(1, "No pages"); ! 1141: ++p->nuser; ! 1142: sp->bno = b; ! 1143: sp->pno = p; ! 1144: if (s != -1) {sp->size = s; sp->pos = 0;} ! 1145: sp->ptr = (short *)(p->buff + o); ! 1146: if ((sp->nibuf = p->nibuf-o) <= 0) ! 1147: sp->size = 0; ! 1148: } ! 1149: ! 1150: char ! 1151: get(asp) ! 1152: STREAM *asp; ! 1153: { ! 1154: register STREAM *sp; ! 1155: ! 1156: sp = asp; ! 1157: if ((sp->nibuf -= sizeof(char)) < 0) { ! 1158: dseek(sp, ((long)(sp->bno+1)<<BSHIFT), (long)-1); ! 1159: sp->nibuf -= sizeof(char); ! 1160: } ! 1161: if ((sp->size -= sizeof(char)) <= 0) { ! 1162: if (sp->size < 0) ! 1163: error(1, premeof); ! 1164: ++fpage.nuser; ! 1165: --sp->pno->nuser; ! 1166: sp->pno = &fpage; ! 1167: } ! 1168: sp->pos += sizeof(char); ! 1169: return(*sp->ptr++); ! 1170: } ! 1171: ! 1172: getfile(acp) ! 1173: STRING acp; ! 1174: { ! 1175: register STRING cp; ! 1176: register int c; ! 1177: int arcmag; ! 1178: ! 1179: cp = acp; ! 1180: infil = -1; ! 1181: archdr.ar_name[0] = '\0'; ! 1182: filname = cp; ! 1183: if (cp[0]=='-' && cp[1]=='l') { ! 1184: char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx"; ! 1185: if(cp[2] == '\0') ! 1186: cp = "-la"; ! 1187: filname = "/usr/lib/libxxxxxxxxxxxxxxx"; ! 1188: for(c=0; cp[c+2]; c++) { ! 1189: filname[c+12] = cp[c+2]; ! 1190: locfilname[c+18] = cp[c+2]; ! 1191: } ! 1192: filname[c+12] = locfilname[c+18] = '.'; ! 1193: filname[c+13] = locfilname[c+19] = 'a'; ! 1194: filname[c+14] = locfilname[c+20] = '\0'; ! 1195: if ((infil = open(filname+4, 0)) >= 0) { ! 1196: filname += 4; ! 1197: } else if ((infil = open(filname, 0)) < 0) { ! 1198: filname = locfilname; ! 1199: } ! 1200: } ! 1201: if (infil == -1 && (infil = open(filname, 0)) < 0) ! 1202: error(1, "cannot open"); ! 1203: page[0].bno = page[1].bno = -1; ! 1204: page[0].nuser = page[1].nuser = 0; ! 1205: text.pno = reloc.pno = &fpage; ! 1206: fpage.nuser = 2; ! 1207: dseek(&text, 0L, (long)sizeof(int)); ! 1208: if (text.size <= 0) ! 1209: error(1, premeof); ! 1210: mget(&arcmag, sizeof(arcmag), &text); ! 1211: return(arcmag==ARMAG); ! 1212: } ! 1213: ! 1214: SYMBOL **lookup() ! 1215: { ! 1216: int i; ! 1217: BOOL clash; ! 1218: register SYMBOL **hp; ! 1219: register char *cp, *cp1; ! 1220: ! 1221: i = 0; ! 1222: for (cp = cursym.sname; cp < &cursym.sname[8];) ! 1223: i = (i<<1) + *cp++; ! 1224: for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { ! 1225: cp1 = (*hp)->sname; ! 1226: clash=FALSE; ! 1227: for (cp = cursym.sname; cp < &cursym.sname[8];) ! 1228: if (*cp++ != *cp1++) { ! 1229: clash=TRUE; ! 1230: break; ! 1231: } ! 1232: if (clash) { ! 1233: if (++hp >= &hshtab[NSYM+2]) ! 1234: hp = hshtab; ! 1235: } else ! 1236: break; ! 1237: } ! 1238: return(hp); ! 1239: } ! 1240: ! 1241: SYMBOL **slookup(s) ! 1242: char *s; ! 1243: { ! 1244: cp8c(s, cursym.sname); ! 1245: cursym.stype = EXTERN+UNDEF; ! 1246: cursym.svalue = 0; ! 1247: return(lookup()); ! 1248: } ! 1249: ! 1250: enter(hp) ! 1251: register SYMBOL **hp; ! 1252: { ! 1253: register SYMBOL *sp; ! 1254: ! 1255: if (*hp==0) { ! 1256: if ((nextsym-symtab)>=NSYM) ! 1257: error(1, "Symbol table overflow"); ! 1258: if ((nextsym-symtab)>=nsym) { ! 1259: if (-1==sbrk(NSYM/5 * sizeof(*symtab))) error(1,"Memory overflow"); ! 1260: nsym += NSYM/5; ! 1261: } ! 1262: *hp = lastsym = sp = nextsym++; ! 1263: cp8c(cursym.sname, sp->sname); ! 1264: sp->stype = cursym.stype; ! 1265: sp->symhash = hp-hshtab; ! 1266: sp->svalue = cursym.svalue; ! 1267: return(1); ! 1268: } else { ! 1269: lastsym = *hp; ! 1270: return(0); ! 1271: } ! 1272: } ! 1273: ! 1274: symreloc() ! 1275: { ! 1276: switch (cursym.stype & 017) { ! 1277: ! 1278: case TEXT: ! 1279: case EXTERN+TEXT: ! 1280: cursym.svalue += ctrel; ! 1281: return; ! 1282: ! 1283: case DATA: ! 1284: case EXTERN+DATA: ! 1285: cursym.svalue += cdrel; ! 1286: return; ! 1287: ! 1288: case BSS: ! 1289: case EXTERN+BSS: ! 1290: cursym.svalue += cbrel; ! 1291: return; ! 1292: ! 1293: case EXTERN+UNDEF: ! 1294: return; ! 1295: } ! 1296: if (cursym.stype&EXTERN) ! 1297: cursym.stype = EXTERN+ABS; ! 1298: } ! 1299: ! 1300: error(n, s) ! 1301: char *s; ! 1302: { ! 1303: if (errlev==0) ! 1304: printf("ld:"); ! 1305: if (filname) { ! 1306: printf("%s", filname); ! 1307: if (archdr.ar_name[0]) ! 1308: printf("(%.14s)", archdr.ar_name); ! 1309: printf(": "); ! 1310: } ! 1311: printf("%s\n", s); ! 1312: if (n) ! 1313: delexit(); ! 1314: errlev = 2; ! 1315: } ! 1316: ! 1317: SYMBOL * ! 1318: lookloc(lp, r) ! 1319: register LOCAL *lp; ! 1320: { ! 1321: register LOCAL *clp; ! 1322: register sn; ! 1323: ! 1324: sn = r; ! 1325: for (clp = local; clp<lp; clp++) ! 1326: if (clp->locindex == sn) ! 1327: return(clp->locsymbol); ! 1328: error(1, "Local symbol botch"); ! 1329: } ! 1330: ! 1331: readhdr(loc) ! 1332: long loc; ! 1333: { ! 1334: long *p; int i; ! 1335: dseek(&text, loc, (long)sizeof(filhdr)); ! 1336: mget((short *)&filhdr, sizeof(filhdr), &text); ! 1337: #ifndef vax ! 1338: for (p= &filhdr,i=8;--i>=0;) fixl(p++); ! 1339: #endif ! 1340: if (filhdr.a_magic!=A_MAGIC1 && filhdr.a_magic!=A_MAGIC2 && ! 1341: filhdr.a_magic!=A_MAGIC3 && filhdr.a_magic!=A_MAGIC4) ! 1342: error(1,"Bad magic number"); ! 1343: if (filhdr.a_text&01 || filhdr.a_data&01) { ! 1344: printf("tsize=%X dsize=%X\n",filhdr.a_text,filhdr.a_data); ! 1345: error(1, "Text/data size odd"); ! 1346: } ! 1347: filhdr.a_bss = round(filhdr.a_bss, FW); ! 1348: if (filhdr.a_magic == NMAGIC) { ! 1349: cdrel = -round(filhdr.a_text, PAGRND); ! 1350: cbrel = cdrel - filhdr.a_data; ! 1351: } else if (filhdr.a_magic == OMAGIC) { ! 1352: cdrel = -filhdr.a_text; ! 1353: cbrel = cdrel - filhdr.a_data; ! 1354: } else ! 1355: error(1, "Bad format"); ! 1356: } ! 1357: ! 1358: cp8c(from, to) ! 1359: char *from, *to; ! 1360: { ! 1361: register char *f, *t, *te; ! 1362: ! 1363: f = from; ! 1364: t = to; ! 1365: te = t+8; ! 1366: while ((*t++ = *f++) && t<te); ! 1367: while (t<te) ! 1368: *t++ = 0; ! 1369: } ! 1370: ! 1371: eq(s1, s2) ! 1372: STRING s1; ! 1373: STRING s2; ! 1374: { ! 1375: while (*s1==*s2++) ! 1376: if ((*s1++)==0) ! 1377: return(TRUE); ! 1378: return(FALSE); ! 1379: } ! 1380: ! 1381: long ! 1382: round(v, r) ! 1383: long v; ! 1384: unsigned r; ! 1385: { ! 1386: v += r; ! 1387: v &= ~(long)r; ! 1388: return(v); ! 1389: } ! 1390: ! 1391: puts(w, f) ! 1392: FILE *f; short w; { ! 1393: fwrite(&w,sizeof(short),1,f); ! 1394: } ! 1395: ! 1396: putb(w, f) ! 1397: FILE *f; char w; { ! 1398: fwrite(&w,sizeof(char),1,f); ! 1399: } ! 1400: ! 1401: put3(w, f) ! 1402: FILE *f; long w; { ! 1403: fwrite(&w,3,1,f); ! 1404: } ! 1405: ! 1406: putl(w, f) ! 1407: FILE *f; long w; { ! 1408: #ifndef vax ! 1409: fixl(&w); ! 1410: #endif ! 1411: fwrite(&w,sizeof(long),1,f); ! 1412: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.