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: }

Defined functions

add defined in line 520; used 6 times
copy defined in line 944; used 4 times
cp8c defined in line 1257; used 3 times
delexit defined in line 215; used 4 times
dseek defined in line 1015; used 12 times
endload defined in line 357; used 2 times
enter defined in line 1162; used 2 times
eq defined in line 1270; used 1 times
error defined in line 1208; used 25 times
finishout defined in line 909; used 1 times
flush defined in line 1288; used 3 times
get defined in line 1055; used 6 times
getfile defined in line 1075; used 2 times
half defined in line 1050; used 4 times
ldrand defined in line 504; used 1 times
ldrsym defined in line 695; used 3 times
load1 defined in line 534; used 2 times
load1arg defined in line 446; used 2 times
load2 defined in line 780; used 2 times
load2arg defined in line 755; used 2 times
load2td defined in line 839; used 2 times
lookloc defined in line 1225; used 2 times
lookup defined in line 1126; used 4 times
main defined in line 223; never used
mget defined in line 973; used 6 times
middle defined in line 600; used 1 times
mkfsym defined in line 961; used 2 times
mput defined in line 1000; used 3 times
putw defined in line 1280; used 9 times
readhdr defined in line 1240; used 2 times
record defined in line 404; used 1 times
restore defined in line 424; used 1 times
setupout defined in line 711; used 1 times
slookup defined in line 1153; used 6 times
step defined in line 487; used 3 times
symreloc defined in line 1182; used 2 times
tcreat defined in line 739; used 5 times

Defined variables

Oflag defined in line 172; used 3 times
Sflag defined in line 167; used 3 times
Xflag defined in line 166; used 3 times
arflag defined in line 169; used 2 times
borigin defined in line 355; used 5 times
bsize defined in line 185; used 15 times
cbrel defined in line 191; used 7 times
cdrel defined in line 190; used 8 times
ctrel defined in line 189; used 7 times
cursym defined in line 149; used 45 times
delarg defined in line 194; used 3 times
dflag defined in line 173; used 3 times
dorigin defined in line 354; used 10 times
doutb defined in line 206; used 7 times
droutb defined in line 208; used 4 times
dsize defined in line 184; used 21 times
entrypt defined in line 161; used 4 times
errlev defined in line 193; used 4 times
filname defined in line 180; used 13 times
goodnm defined in line 59; used 1 times
hshtab defined in line 154; used 3 times
iflag defined in line 174; used 6 times
infil defined in line 179; used 11 times
lastsym defined in line 152; used 4 times
liblist defined in line 132; used 2 times
libp defined in line 133; used 13 times
local defined in line 155; used 3 times
nflag defined in line 171; used 6 times
nsym defined in line 352; used 2 times
ofilename defined in line 178; used 4 times
ofilfnd defined in line 177; used 2 times
p_edata defined in line 159; used 3 times
p_end defined in line 160; used 3 times
p_etext defined in line 158; used 3 times
page defined in line 87; used 12 times
premeof defined in line 58; used 2 times
reloc defined in line 103; used 12 times
rflag defined in line 168; used 11 times
sflag defined in line 170; used 8 times
soutb defined in line 209; used 4 times
ssize defined in line 186; used 11 times
symhash defined in line 151; used 3 times
symindex defined in line 153; used 12 times
symtab defined in line 150; used 8 times
tab defined in line 66; used 3 times
text defined in line 102; used 32 times
tfname defined in line 195; used 3 times
tnum defined in line 67; used 4 times
torigin defined in line 353; used 6 times
toutb defined in line 205; used 8 times
trace defined in line 163; used 3 times
troutb defined in line 207; used 4 times
tsize defined in line 183; used 24 times
vflag defined in line 175; used 1 times
vindex defined in line 71; used 3 times
vnodes defined in line 79; used 3 times
xflag defined in line 165; used 7 times

Defined struct's

buf defined in line 199; used 22 times
liblist defined in line 128; used 9 times
local defined in line 144; used 10 times
overlay defined in line 72; used 4 times
page defined in line 82; used 8 times
stream defined in line 94; used 12 times
symbol defined in line 137; used 52 times
tab defined in line 63; used 4 times

Defined macros

ABS defined in line 40; used 2 times
ARCMAGIC defined in line 32; used 1 times
BSS defined in line 43; used 2 times
COMM defined in line 44; used 1 times
DATA defined in line 42; used 1 times
EXTERN defined in line 38; used 31 times
FALSE defined in line 29; used 4 times
FMAGIC defined in line 34; used 2 times
IMAGIC defined in line 36; used 1 times
NMAGIC defined in line 35; used 1 times
NOVLY defined in line 52; used 1 times
  • in line 79
NROUT defined in line 54; used 1 times
NSYM defined in line 55; used 6 times
NSYMPR defined in line 56; used 2 times
OMAGIC defined in line 33; used 1 times
RABS defined in line 46; never used
RBSS defined in line 49; never used
RDATA defined in line 48; never used
RELFLG defined in line 53; used 1 times
REXT defined in line 50; used 1 times
RTEXT defined in line 47; never used
TABSZ defined in line 62; used 2 times
TEXT defined in line 41; used 3 times
TRUE defined in line 28; used 3 times
UNDEF defined in line 39; used 9 times
Last modified: 1979-05-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3177
Valid CSS Valid XHTML 1.0 Strict