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