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