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