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