|
|
1.1 root 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:
39: typedef struct {short hiword; short loword;} *bless; /* stupid fp-11 */
40: fixl(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:
45: writel(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:
57: long htoi(p) register char *p; {/* hex to integer conversion */
58: register long n = 0;
59: while (*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: }
66: return(n);
67: }
68:
69: typedef char *STRING;
70: typedef 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:
131: char premeof[] = "Premature EOF";
132:
133: typedef struct {
134: long loc;
135: } LIBLIST;
136:
137: /* overlay management */
138: int vindex;
139: typedef 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;
147: OVERLAY vnodes[NOVLY];
148:
149: /* input management */
150: typedef struct {
151: short *fakeptr;
152: int bno;
153: int nibuf;
154: int nuser;
155: char buff[512];
156: } PAGE;
157:
158: PAGE page[2];
159:
160: struct {
161: short *fakeptr;
162: int bno;
163: int nibuf;
164: int nuser;
165: } fpage;
166:
167: typedef struct {
168: char *ptr;
169: int bno;
170: int nibuf;
171: long size;
172: long pos;
173: PAGE *pno;
174: } STREAM;
175:
176: STREAM text;
177: STREAM reloc;
178:
179: struct ar_hdr archdr;
180:
181: struct exec filhdr;
182:
183: /* one entry for each archive member referenced;
184: * set in first pass; needs restoring for overlays
185: */
186:
187: LIBLIST liblist[NROUT];
188: LIBLIST *libp = liblist;
189:
190:
191: /* symbol management */
192: typedef 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:
200: typedef struct {
201: int locindex; /* index to symbol in file */
202: SYMBOL *locsymbol; /* ptr to symbol table */
203: } LOCAL;
204:
205: SYMBOL cursym; /* current symbol */
206: SYMBOL *symtab; /* actual symbols */
207: SYMBOL *lastsym; /* last symbol entered */
208: SYMBOL *nextsym; /* next available symbol table entry */
209: SYMBOL *addsym; /* first symbol defined during incremental
210: load */
211: int nsym; /* number of symbols allocated in symtab */
212: SYMBOL *hshtab[NSYM+2]; /* hash table for symbols */
213: LOCAL *local;
214:
215: /* internal symbols */
216: SYMBOL *p_data;
217: SYMBOL *p_etext;
218: SYMBOL *p_edata;
219: SYMBOL *p_end;
220: SYMBOL *entrypt;
221:
222: int trace;
223: /* flags */
224: int xflag; /* discard local symbols */
225: int Xflag; /* discard locals starting with 'L' */
226: int Sflag; /* discard all except locals and globals*/
227: int rflag; /* preserve relocation bits, don't define common */
228: int arflag; /* original copy of rflag */
229: int sflag; /* discard all symbols */
230: int nflag = 1; /* pure procedure */
231: int dflag; /* define common even with rflag */
232: int iflag; /* I/D space separated */
233: BOOL vflag; /* overlays used */
234: int Aflag; /* doing incremental load */
235: int RFflag; /* used to escape while reading fundament file*/
236:
237: int ofilfnd;
238: char *ofilename = "l.out";
239: int infil;
240: char *filname;
241:
242: long textbase;
243: /* cumulative sizes set in pass 1 */
244: long tsize;
245: long dsize;
246: long bsize;
247: long trsize;
248: long drsize;
249: long ssize;
250:
251: /* symbol relocation; both passes */
252: long ctrel;
253: long cdrel;
254: long cbrel;
255: long ctorel;
256: long cdorel;
257: long cborel;
258:
259: int errlev;
260: int delarg = 4;
261:
262:
263: FILE *tout;
264: FILE *dout;
265: char *doutn = "";
266: FILE *trout;
267: char *troutn = "";
268: FILE *drout;
269: char *droutn = "";
270: FILE *sout;
271: char *soutn = "";
272:
273: char *mktemp();
274: char get();
275: char getb();
276: short gets();
277: long get3();
278: long getl();
279: SYMBOL **lookup();
280: FILE *tcreat();
281: long round();
282: SYMBOL **slookup();
283: SYMBOL *lookloc();
284:
285: symwrite(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:
296: delexit()
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:
308: main(argc, argv)
309: char **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 */
455: long torigin;
456: long dorigin;
457: long borigin;
458: long database;
459:
460: endload(argc, argv)
461: int argc;
462: char **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:
512: record(c, nam)
513: int c;
514: STRING 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:
534: restore(vscan)
535: int 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 */
560: load1arg(cp)
561: register 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 */
593: load1(libflg, loc)
594: long 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:
658: middle()
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: }
774: fixspec(sym,offset)
775: SYMBOL *sym; long offset;
776: {
777: if(sym < addsym && sym!=0)
778: sym->svalue += offset;
779: }
780:
781:
782: ldrsym(asp, val, type)
783: long val;
784: SYMBOL *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:
799: extern char _sibuf[BUFSIZ]; /* the space is forced upon us; might as well use it */
800:
801: setupout()
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:
833: FILE *
834: tcreat(namep, name)
835: char **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:
848: load2arg(acp)
849: char *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:
873: load2(loc)
874: long 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:
940: load2td(lp, creloc, b1, b2)
941: LOCAL *lp;
942: long creloc;
943: FILE *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:
1016: finishout()
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:
1048: copy(np)
1049: char *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:
1061: mkfsym(s)
1062: char *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:
1073: mget(loc, n, sp)
1074: register STREAM *sp;
1075: register 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:
1097: short
1098: gets(sp) STREAM *sp; {
1099: short t; mget(&t,2,sp); return(t);
1100: }
1101:
1102: char
1103: getb(sp) STREAM *sp; {
1104: char t; mget(&t,1,sp); return(t);
1105: }
1106:
1107: long
1108: get3(sp) STREAM *sp; {
1109: long t; t=0; mget(&t,3,sp); return(t);
1110: }
1111:
1112: long
1113: getl(sp) STREAM *sp; {
1114: long t; mget(&t,4,sp);
1115: #ifndef vax
1116: fixl(&t);
1117: #endif
1118: return(t);
1119: }
1120:
1121: symget(sp,f) SYMBOL *sp; STREAM *f; {
1122: mget(sp,sizeof(*sp),f);
1123: #ifndef vax
1124: fixl(&sp->svalue);
1125: #endif
1126: }
1127:
1128: dseek(sp, loc, s)
1129: register STREAM *sp;
1130: long 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:
1162: char
1163: get(asp)
1164: STREAM *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:
1184: getfile(acp)
1185: STRING 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:
1221: SYMBOL **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:
1248: SYMBOL **slookup(s)
1249: char *s;
1250: {
1251: cp8c(s, cursym.sname);
1252: cursym.stype = EXTERN+UNDEF;
1253: cursym.svalue = 0;
1254: return(lookup());
1255: }
1256:
1257: enter(hp)
1258: register 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:
1281: symreloc()
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:
1308: error(n, s)
1309: char *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:
1325: SYMBOL *
1326: lookloc(lp, r)
1327: register 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:
1339: readhdr(loc)
1340: long 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:
1366: cp8c(from, to)
1367: char *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:
1379: eq(s1, s2)
1380: STRING s1;
1381: STRING s2;
1382: {
1383: while (*s1==*s2++)
1384: if ((*s1++)==0)
1385: return(TRUE);
1386: return(FALSE);
1387: }
1388:
1389: long
1390: round(v, r)
1391: long v;
1392: unsigned r;
1393: {
1394: v += r;
1395: v &= ~(long)r;
1396: return(v);
1397: }
1398:
1399: puts(w, f)
1400: FILE *f; short w; {
1401: fwrite(&w,sizeof(short),1,f);
1402: }
1403:
1404: putb(w, f)
1405: FILE *f; char w; {
1406: fwrite(&w,sizeof(char),1,f);
1407: }
1408:
1409: put3(w, f)
1410: FILE *f; long w; {
1411: fwrite(&w,3,1,f);
1412: }
1413:
1414: putl(w, f)
1415: FILE *f; long w; {
1416: #ifndef vax
1417: fixl(&w);
1418: #endif
1419: fwrite(&w,sizeof(long),1,f);
1420: }
1421: static fundament(name)
1422: STRING 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: }
1430: fund2(name)
1431: STRING name;
1432: {
1433: RFflag = TRUE;
1434: load2arg(name);
1435: RFflag = FALSE;
1436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.