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