|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)ld.c 5.16 (Berkeley) 6/30/90";
15: #endif not lint
16:
17: /*
18: * ld - string table version for VAX
19: */
20:
21: #include <sys/param.h>
22: #include <sys/stat.h>
23: #include <sys/file.h>
24: #include <sys/signal.h>
25: #include <ar.h>
26: #include <a.out.h>
27: #include <ranlib.h>
28: #include <stdio.h>
29: #include <ctype.h>
30: #include <string.h>
31: #include "pathnames.h"
32:
33: /*
34: * Basic strategy:
35: *
36: * The loader takes a number of files and libraries as arguments.
37: * A first pass examines each file in turn. Normal files are
38: * unconditionally loaded, and the (external) symbols they define and require
39: * are noted in the symbol table. Libraries are searched, and the
40: * library members which define needed symbols are remembered
41: * in a special data structure so they can be selected on the second
42: * pass. Symbols defined and required by library members are also
43: * recorded.
44: *
45: * After the first pass, the loader knows the size of the basic text
46: * data, and bss segments from the sum of the sizes of the modules which
47: * were required. It has computed, for each ``common'' symbol, the
48: * maximum size of any reference to it, and these symbols are then assigned
49: * storage locations after their sizes are appropriately rounded.
50: * The loader now knows all sizes for the eventual output file, and
51: * can determine the final locations of external symbols before it
52: * begins a second pass.
53: *
54: * On the second pass each normal file and required library member
55: * is processed again. The symbol table for each such file is
56: * reread and relevant parts of it are placed in the output. The offsets
57: * in the local symbol table for externally defined symbols are recorded
58: * since relocation information refers to symbols in this way.
59: * Armed with all necessary information, the text and data segments
60: * are relocated and the result is placed in the output file, which
61: * is pasted together, ``in place'', by writing to it in several
62: * different places concurrently.
63: */
64:
65: /*
66: * Internal data structures
67: *
68: * All internal data structures are segmented and dynamically extended.
69: * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT)
70: * referenced library members, and 100 (NSYMPR) private (local) symbols
71: * per object module. For large programs and/or modules, these structures
72: * expand to be up to 40 (NSEG) times as large as this as necessary.
73: */
74: #define NSEG 40 /* Number of segments, each data structure */
75: #define NSYM 1103 /* Number of symbols per segment */
76: #define NROUT 250 /* Number of library references per segment */
77: #define NSYMPR 100 /* Number of private symbols per segment */
78:
79: /*
80: * Structure describing each symbol table segment.
81: * Each segment has its own hash table. We record the first
82: * address in and first address beyond both the symbol and hash
83: * tables, for use in the routine symx and the lookup routine respectively.
84: * The symfree routine also understands this structure well as it used
85: * to back out symbols from modules we decide that we don't need in pass 1.
86: *
87: * Csymseg points to the current symbol table segment;
88: * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated,
89: * (unless csymseg->sy_used == NSYM in which case we will allocate another
90: * symbol table segment first.)
91: */
92: struct symseg {
93: struct nlist *sy_first; /* base of this alloc'ed segment */
94: struct nlist *sy_last; /* end of this segment, for n_strx */
95: int sy_used; /* symbols used in this seg */
96: struct nlist **sy_hfirst; /* base of hash table, this seg */
97: struct nlist **sy_hlast; /* end of hash table, this seg */
98: } symseg[NSEG], *csymseg;
99:
100: /*
101: * The lookup routine uses quadratic rehash. Since a quadratic rehash
102: * only probes 1/2 of the buckets in the table, and since the hash
103: * table is segmented the same way the symbol table is, we make the
104: * hash table have twice as many buckets as there are symbol table slots
105: * in the segment. This guarantees that the quadratic rehash will never
106: * fail to find an empty bucket if the segment is not full and the
107: * symbol is not there.
108: */
109: #define HSIZE (NSYM*2)
110:
111: /*
112: * Xsym converts symbol table indices (ala x) into symbol table pointers.
113: * Symx (harder, but never used in loops) inverts pointers into the symbol
114: * table into indices using the symseg[] structure.
115: */
116: #define xsym(x) (symseg[(x)/NSYM].sy_first+((x)%NSYM))
117: /* symx() is a function, defined below */
118:
119: struct nlist cursym; /* current symbol */
120: struct nlist *lastsym; /* last symbol entered */
121: struct nlist *nextsym; /* next available symbol table entry */
122: struct nlist *addsym; /* first sym defined during incr load */
123: int nsym; /* pass2: number of local symbols in a.out */
124: /* nsym + symx(nextsym) is the symbol table size during pass2 */
125:
126: struct nlist **lookup(), **slookup();
127: struct nlist *p_etext, *p_edata, *p_end, *entrypt;
128:
129: /*
130: * Definitions of segmentation for library member table.
131: * For each library we encounter on pass 1 we record pointers to all
132: * members which we will load on pass 2. These are recorded as offsets
133: * into the archive in the library member table. Libraries are
134: * separated in the table by the special offset value -1.
135: */
136: off_t li_init[NROUT];
137: struct libseg {
138: off_t *li_first;
139: int li_used;
140: int li_used2;
141: } libseg[NSEG] = {
142: li_init, 0, 0,
143: }, *clibseg = libseg;
144:
145: /*
146: * In processing each module on pass 2 we must relocate references
147: * relative to external symbols. These references are recorded
148: * in the relocation information as relative to local symbol numbers
149: * assigned to the external symbols when the module was created.
150: * Thus before relocating the module in pass 2 we create a table
151: * which maps these internal numbers to symbol table entries.
152: * A hash table is constructed, based on the local symbol table indices,
153: * for quick lookup of these symbols.
154: */
155: #define LHSIZ 31
156: struct local {
157: int l_index; /* index to symbol in file */
158: struct nlist *l_symbol; /* ptr to symbol table */
159: struct local *l_link; /* hash link */
160: } *lochash[LHSIZ], lhinit[NSYMPR];
161: struct locseg {
162: struct local *lo_first;
163: int lo_used;
164: } locseg[NSEG] = {
165: lhinit, 0
166: }, *clocseg;
167:
168: /*
169: * Libraries are typically built with a table of contents,
170: * which is the first member of a library with special file
171: * name __.SYMDEF and contains a list of symbol names
172: * and with each symbol the offset of the library member which defines
173: * it. The loader uses this table to quickly tell which library members
174: * are (potentially) useful. The alternative, examining the symbol
175: * table of each library member, is painfully slow for large archives.
176: *
177: * See <ranlib.h> for the definition of the ranlib structure and an
178: * explanation of the __.SYMDEF file format.
179: */
180: int tnum; /* number of symbols in table of contents */
181: int ssiz; /* size of string table for table of contents */
182: struct ranlib *tab; /* the table of contents (dynamically allocated) */
183: char *tabstr; /* string table for table of contents */
184:
185: /*
186: * We open each input file or library only once, but in pass2 we
187: * (historically) read from such a file at 2 different places at the
188: * same time. These structures are remnants from those days,
189: * and now serve only to catch ``Premature EOF''.
190: * In order to make I/O more efficient, we provide routines which
191: * use the optimal block size returned by stat().
192: */
193: #define BLKSIZE 1024
194: typedef struct {
195: short *fakeptr;
196: int bno;
197: int nibuf;
198: int nuser;
199: char *buff;
200: int bufsize;
201: } PAGE;
202:
203: PAGE page[2];
204: int p_blksize;
205: int p_blkshift;
206: int p_blkmask;
207:
208: struct {
209: short *fakeptr;
210: int bno;
211: int nibuf;
212: int nuser;
213: } fpage;
214:
215: typedef struct {
216: char *ptr;
217: int bno;
218: int nibuf;
219: long size;
220: long pos;
221: PAGE *pno;
222: } STREAM;
223:
224: STREAM text;
225: STREAM reloc;
226:
227: /*
228: * Header from the a.out and the archive it is from (if any).
229: */
230: struct exec filhdr;
231: struct ar_hdr archdr;
232: #define OARMAG 0177545
233:
234: /*
235: * Options.
236: */
237: int trace;
238: int xflag; /* discard local symbols */
239: int Xflag; /* discard locals starting with 'L' */
240: int Sflag; /* discard all except locals and globals*/
241: int rflag; /* preserve relocation bits, don't define common */
242: int arflag; /* original copy of rflag */
243: int sflag; /* discard all symbols */
244: int Mflag; /* print rudimentary load map */
245: int nflag; /* pure procedure */
246: int dflag; /* define common even with rflag */
247: int zflag; /* demand paged */
248: long hsize; /* size of hole at beginning of data to be squashed */
249: int Aflag; /* doing incremental load */
250: int Nflag; /* want impure a.out */
251: int funding; /* reading fundamental file for incremental load */
252: int yflag; /* number of symbols to be traced */
253: char **ytab; /* the symbols */
254:
255: /*
256: * These are the cumulative sizes, set in pass 1, which
257: * appear in the a.out header when the loader is finished.
258: */
259: off_t tsize, dsize, bsize, trsize, drsize, ssize;
260:
261: /*
262: * Symbol relocation: c?rel is a scale factor which is
263: * added to an old relocation to convert it to new units;
264: * i.e. it is the difference between segment origins.
265: * (Thus if we are loading from a data segment which began at location
266: * 4 in a .o file into an a.out where it will be loaded starting at
267: * 1024, cdrel will be 1020.)
268: */
269: long ctrel, cdrel, cbrel;
270:
271: /*
272: * Textbase is the start address of all text, 0 unless given by -T.
273: * Database is the base of all data, computed before and used during pass2.
274: */
275: long textbase, database;
276:
277: /*
278: * The base addresses for the loaded text, data and bss from the
279: * current module during pass2 are given by torigin, dorigin and borigin.
280: */
281: long torigin, dorigin, borigin;
282:
283: /*
284: * Errlev is nonzero when errors have occured.
285: * Delarg is an implicit argument to the routine delexit
286: * which is called on error. We do ``delarg = errlev'' before normal
287: * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the
288: * result file executable.
289: */
290: int errlev;
291: int delarg = 4;
292:
293: /*
294: * The biobuf structure and associated routines are used to write
295: * into one file at several places concurrently. Calling bopen
296: * with a biobuf structure sets it up to write ``biofd'' starting
297: * at the specified offset. You can then use ``bwrite'' and/or ``bputc''
298: * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
299: * Calling bflush drains all the buffers and MUST be done before exit.
300: */
301: struct biobuf {
302: short b_nleft; /* Number free spaces left in b_buf */
303: /* Initialize to be less than b_bufsize initially, to boundary align in file */
304: char *b_ptr; /* Next place to stuff characters */
305: char *b_buf; /* Pointer to the buffer */
306: int b_bufsize; /* Size of the buffer */
307: off_t b_off; /* Current file offset */
308: struct biobuf *b_link; /* Link in chain for bflush() */
309: } *biobufs;
310: #define bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
311: : bflushc(b, c))
312: int biofd;
313: off_t boffset;
314: struct biobuf *tout, *dout, *trout, *drout, *sout, *strout;
315:
316: /*
317: * Offset is the current offset in the string file.
318: * Its initial value reflects the fact that we will
319: * eventually stuff the size of the string table at the
320: * beginning of the string table (i.e. offset itself!).
321: */
322: off_t offset = sizeof (off_t);
323:
324: int ofilfnd; /* -o given; otherwise move l.out to a.out */
325: char *ofilename = "l.out";
326: int ofilemode; /* respect umask even for unsucessful ld's */
327: int infil; /* current input file descriptor */
328: char *filname; /* and its name */
329:
330: #define NDIRS 25
331: #define NDEFDIRS 3 /* number of default directories in dirs[] */
332: char *dirs[NDIRS]; /* directories for library search */
333: int ndir; /* number of directories */
334:
335: /*
336: * Base of the string table of the current module (pass1 and pass2).
337: */
338: char *curstr;
339:
340: /*
341: * System software page size, as returned by getpagesize.
342: */
343: int pagesize;
344:
345: char get();
346: int delexit();
347: char *savestr();
348: char *malloc();
349:
350: main(argc, argv)
351: char **argv;
352: {
353: register int c, i;
354: int num;
355: register char *ap, **p;
356: char save;
357:
358: if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
359: signal(SIGINT, delexit);
360: signal(SIGTERM, delexit);
361: }
362: if (argc == 1)
363: exit(4);
364: pagesize = getpagesize();
365:
366: /*
367: * Pull out search directories.
368: */
369: for (c = 1; c < argc; c++) {
370: ap = argv[c];
371: if (ap[0] == '-' && ap[1] == 'L') {
372: if (ap[2] == 0)
373: error(1, "-L: pathname missing");
374: if (ndir >= NDIRS - NDEFDIRS)
375: error(1, "-L: too many directories");
376: dirs[ndir++] = &ap[2];
377: }
378: }
379: /* add default search directories */
380: dirs[ndir++] = _PATH_USRLIB;
381: dirs[ndir++] = _PATH_LOCALLIB;
382:
383: p = argv+1;
384: /*
385: * Scan files once to find where symbols are defined.
386: */
387: for (c=1; c<argc; c++) {
388: if (trace)
389: printf("%s:\n", *p);
390: filname = 0;
391: ap = *p++;
392: if (*ap != '-') {
393: load1arg(ap);
394: continue;
395: }
396: for (i=1; ap[i]; i++) switch (ap[i]) {
397:
398: case 'o':
399: if (++c >= argc)
400: error(1, "-o where?");
401: ofilename = *p++;
402: ofilfnd++;
403: continue;
404: case 'u':
405: case 'e':
406: if (++c >= argc)
407: error(1, " -u or -e: arg missing");
408: enter(slookup(*p++));
409: if (ap[i]=='e')
410: entrypt = lastsym;
411: continue;
412: case 'H':
413: if (++c >= argc)
414: error(1, "-H: arg missing");
415: if (tsize!=0)
416: error(1, "-H: too late, some text already loaded");
417: hsize = atoi(*p++);
418: continue;
419: case 'A':
420: if (++c >= argc)
421: error(1, "-A: arg missing");
422: if (Aflag)
423: error(1, "-A: only one base file allowed");
424: Aflag = 1;
425: nflag = 0;
426: funding = 1;
427: load1arg(*p++);
428: trsize = drsize = tsize = dsize = bsize = 0;
429: ctrel = cdrel = cbrel = 0;
430: funding = 0;
431: addsym = nextsym;
432: continue;
433: case 'D':
434: if (++c >= argc)
435: error(1, "-D: arg missing");
436: num = htoi(*p++);
437: if (dsize > num)
438: error(1, "-D: too small");
439: dsize = num;
440: continue;
441: case 'T':
442: if (++c >= argc)
443: error(1, "-T: arg missing");
444: if (tsize!=0)
445: error(1, "-T: too late, some text already loaded");
446: textbase = htoi(*p++);
447: continue;
448: case 'l':
449: save = ap[--i];
450: ap[i]='-';
451: load1arg(&ap[i]);
452: ap[i]=save;
453: goto next;
454: case 'M':
455: Mflag++;
456: continue;
457: case 'x':
458: xflag++;
459: continue;
460: case 'X':
461: Xflag++;
462: continue;
463: case 'S':
464: Sflag++;
465: continue;
466: case 'r':
467: rflag++;
468: arflag++;
469: continue;
470: case 's':
471: sflag++;
472: xflag++;
473: continue;
474: case 'n':
475: nflag++;
476: Nflag = zflag = 0;
477: continue;
478: case 'N':
479: Nflag++;
480: nflag = zflag = 0;
481: continue;
482: case 'd':
483: dflag++;
484: continue;
485: case 'i':
486: printf("ld: -i ignored\n");
487: continue;
488: case 't':
489: trace++;
490: continue;
491: case 'y':
492: if (ap[i+1] == 0)
493: error(1, "-y: symbol name missing");
494: if (yflag == 0) {
495: ytab = (char **)calloc(argc, sizeof (char **));
496: if (ytab == 0)
497: error(1, "ran out of memory (-y)");
498: }
499: ytab[yflag++] = &ap[i+1];
500: goto next;
501: case 'z':
502: zflag++;
503: Nflag = nflag = 0;
504: continue;
505: case 'L':
506: goto next;
507: default:
508: filname = savestr("-x"); /* kludge */
509: filname[1] = ap[i]; /* kludge */
510: archdr.ar_name[0] = 0; /* kludge */
511: error(1, "bad flag");
512: }
513: next:
514: ;
515: }
516: if (rflag == 0 && Nflag == 0 && nflag == 0)
517: zflag++;
518: endload(argc, argv);
519: exit(0);
520: }
521:
522: /*
523: * Convert a ascii string which is a hex number.
524: * Used by -T and -D options.
525: */
526: htoi(p)
527: register char *p;
528: {
529: register int c, n;
530:
531: n = 0;
532: while (c = *p++) {
533: n <<= 4;
534: if (isdigit(c))
535: n += c - '0';
536: else if (c >= 'a' && c <= 'f')
537: n += 10 + (c - 'a');
538: else if (c >= 'A' && c <= 'F')
539: n += 10 + (c - 'A');
540: else
541: error(1, "badly formed hex number");
542: }
543: return (n);
544: }
545:
546: delexit()
547: {
548: struct stat stbuf;
549: long size;
550: char c = 0;
551:
552: bflush();
553: unlink("l.out");
554: /*
555: * We have to insure that the last block of the data segment
556: * is allocated a full pagesize block. If the underlying
557: * file system allocates frags that are smaller than pagesize,
558: * a full zero filled pagesize block needs to be allocated so
559: * that when it is demand paged, the paged in block will be
560: * appropriately filled with zeros.
561: */
562: fstat(biofd, &stbuf);
563: size = round(stbuf.st_size, pagesize);
564: if (!rflag && size > stbuf.st_size) {
565: lseek(biofd, size - 1, 0);
566: if (write(biofd, &c, 1) != 1)
567: delarg |= 4;
568: }
569: if (delarg==0 && Aflag==0)
570: (void) chmod(ofilename, ofilemode);
571: exit (delarg);
572: }
573:
574: endload(argc, argv)
575: int argc;
576: char **argv;
577: {
578: register int c, i;
579: long dnum;
580: register char *ap, **p;
581:
582: clibseg = libseg;
583: filname = 0;
584: middle();
585: setupout();
586: p = argv+1;
587: for (c=1; c<argc; c++) {
588: ap = *p++;
589: if (trace)
590: printf("%s:\n", ap);
591: if (*ap != '-') {
592: load2arg(ap);
593: continue;
594: }
595: for (i=1; ap[i]; i++) switch (ap[i]) {
596:
597: case 'D':
598: dnum = htoi(*p);
599: if (dorigin < dnum)
600: while (dorigin < dnum)
601: bputc(0, dout), dorigin++;
602: /* fall into ... */
603: case 'T':
604: case 'u':
605: case 'e':
606: case 'o':
607: case 'H':
608: ++c;
609: ++p;
610: /* fall into ... */
611: default:
612: continue;
613: case 'A':
614: funding = 1;
615: load2arg(*p++);
616: funding = 0;
617: c++;
618: continue;
619: case 'y':
620: case 'L':
621: goto next;
622: case 'l':
623: ap[--i]='-';
624: load2arg(&ap[i]);
625: goto next;
626: }
627: next:
628: ;
629: }
630: finishout();
631: }
632:
633: /*
634: * Scan file to find defined symbols.
635: */
636: load1arg(cp)
637: register char *cp;
638: {
639: register struct ranlib *tp;
640: off_t nloc;
641: int kind;
642:
643: kind = getfile(cp);
644: if (Mflag)
645: printf("%s\n", filname);
646: switch (kind) {
647:
648: /*
649: * Plain file.
650: */
651: case 0:
652: load1(0, 0L);
653: break;
654:
655: /*
656: * Archive without table of contents.
657: * (Slowly) process each member.
658: */
659: case 1:
660: error(-1,
661: "warning: archive has no table of contents; add one using ranlib(1)");
662: nloc = SARMAG;
663: while (step(nloc))
664: nloc += sizeof(archdr) +
665: round(atol(archdr.ar_size), sizeof (short));
666: break;
667:
668: /*
669: * Archive with table of contents.
670: * Read the table of contents and its associated string table.
671: * Pass through the library resolving symbols until nothing changes
672: * for an entire pass (i.e. you can get away with backward references
673: * when there is a table of contents!)
674: */
675: case 2:
676: nloc = SARMAG + sizeof (archdr);
677: dseek(&text, nloc, sizeof (tnum));
678: mget((char *)&tnum, sizeof (tnum), &text);
679: nloc += sizeof (tnum);
680: tab = (struct ranlib *)malloc(tnum);
681: if (tab == 0)
682: error(1, "ran out of memory (toc)");
683: dseek(&text, nloc, tnum);
684: mget((char *)tab, tnum, &text);
685: nloc += tnum;
686: tnum /= sizeof (struct ranlib);
687: dseek(&text, nloc, sizeof (ssiz));
688: mget((char *)&ssiz, sizeof (ssiz), &text);
689: nloc += sizeof (ssiz);
690: tabstr = (char *)malloc(ssiz);
691: if (tabstr == 0)
692: error(1, "ran out of memory (tocstr)");
693: dseek(&text, nloc, ssiz);
694: mget((char *)tabstr, ssiz, &text);
695: for (tp = &tab[tnum]; --tp >= tab;) {
696: if (tp->ran_un.ran_strx < 0 ||
697: tp->ran_un.ran_strx >= ssiz)
698: error(1, "mangled archive table of contents");
699: tp->ran_un.ran_name = tabstr + tp->ran_un.ran_strx;
700: }
701: while (ldrand())
702: continue;
703: free((char *)tab);
704: free(tabstr);
705: nextlibp(-1);
706: break;
707:
708: /*
709: * Table of contents is out of date, so search
710: * as a normal library (but skip the __.SYMDEF file).
711: */
712: case 3:
713: error(-1,
714: "warning: table of contents for archive is out of date; rerun ranlib(1)");
715: nloc = SARMAG;
716: do
717: nloc += sizeof(archdr) +
718: round(atol(archdr.ar_size), sizeof(short));
719: while (step(nloc));
720: break;
721: }
722: close(infil);
723: }
724:
725: /*
726: * Advance to the next archive member, which
727: * is at offset nloc in the archive. If the member
728: * is useful, record its location in the liblist structure
729: * for use in pass2. Mark the end of the archive in libilst with a -1.
730: */
731: step(nloc)
732: off_t nloc;
733: {
734:
735: dseek(&text, nloc, (long) sizeof archdr);
736: if (text.size <= 0) {
737: nextlibp(-1);
738: return (0);
739: }
740: getarhdr();
741: if (load1(1, nloc + (sizeof archdr)))
742: nextlibp(nloc);
743: return (1);
744: }
745:
746: /*
747: * Record the location of a useful archive member.
748: * Recording -1 marks the end of files from an archive.
749: * The liblist data structure is dynamically extended here.
750: */
751: nextlibp(val)
752: off_t val;
753: {
754:
755: if (clibseg->li_used == NROUT) {
756: if (++clibseg == &libseg[NSEG])
757: error(1, "too many files loaded from libraries");
758: clibseg->li_first = (off_t *)malloc(NROUT * sizeof (off_t));
759: if (clibseg->li_first == 0)
760: error(1, "ran out of memory (nextlibp)");
761: }
762: clibseg->li_first[clibseg->li_used++] = val;
763: if (val != -1 && Mflag)
764: printf("\t%s\n", archdr.ar_name);
765: }
766:
767: /*
768: * One pass over an archive with a table of contents.
769: * Remember the number of symbols currently defined,
770: * then call step on members which look promising (i.e.
771: * that define a symbol which is currently externally undefined).
772: * Indicate to our caller whether this process netted any more symbols.
773: */
774: ldrand()
775: {
776: register struct nlist *sp, **hp;
777: register struct ranlib *tp, *tplast;
778: off_t loc;
779: int nsymt = symx(nextsym);
780:
781: tplast = &tab[tnum-1];
782: for (tp = tab; tp <= tplast; tp++) {
783: if ((hp = slookup(tp->ran_un.ran_name)) == 0 || *hp == 0)
784: continue;
785: sp = *hp;
786: if (sp->n_type != N_EXT+N_UNDF)
787: continue;
788: step(tp->ran_off);
789: loc = tp->ran_off;
790: while (tp < tplast && (tp+1)->ran_off == loc)
791: tp++;
792: }
793: return (symx(nextsym) != nsymt);
794: }
795:
796: /*
797: * Examine a single file or archive member on pass 1.
798: */
799: load1(libflg, loc)
800: off_t loc;
801: {
802: register struct nlist *sp;
803: struct nlist *savnext;
804: int ndef, nlocal, type, size, nsymt;
805: register int i;
806: off_t maxoff;
807: struct stat stb;
808:
809: readhdr(loc);
810: if (filhdr.a_syms == 0) {
811: if (filhdr.a_text+filhdr.a_data == 0) {
812: /* load2() adds a symbol for the file name */
813: if (!libflg)
814: ssize += sizeof (cursym);
815: return (0);
816: }
817: error(1, "no namelist");
818: }
819: if (libflg)
820: maxoff = atol(archdr.ar_size);
821: else {
822: fstat(infil, &stb);
823: maxoff = stb.st_size;
824: }
825: if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff)
826: error(1, "too small (old format .o?)");
827: ctrel = tsize; cdrel += dsize; cbrel += bsize;
828: ndef = 0;
829: nlocal = sizeof(cursym);
830: savnext = nextsym;
831: loc += N_SYMOFF(filhdr);
832: dseek(&text, loc, filhdr.a_syms);
833: dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t));
834: mget(&size, sizeof (size), &reloc);
835: dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t));
836: curstr = (char *)malloc(size);
837: if (curstr == NULL)
838: error(1, "no space for string table");
839: mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc);
840: while (text.size > 0) {
841: mget((char *)&cursym, sizeof(struct nlist), &text);
842: if (cursym.n_un.n_strx) {
843: if (cursym.n_un.n_strx<sizeof(size) ||
844: cursym.n_un.n_strx>=size)
845: error(1, "bad string table index (pass 1)");
846: cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
847: }
848: type = cursym.n_type;
849: if ((type&N_EXT)==0) {
850: if (Xflag==0 || cursym.n_un.n_name[0]!='L' ||
851: type & N_STAB)
852: nlocal += sizeof cursym;
853: continue;
854: }
855: symreloc();
856: if (enter(lookup()))
857: continue;
858: if ((sp = lastsym)->n_type != N_EXT+N_UNDF)
859: continue;
860: if (cursym.n_type == N_EXT+N_UNDF) {
861: if (cursym.n_value > sp->n_value)
862: sp->n_value = cursym.n_value;
863: continue;
864: }
865: if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT)
866: continue;
867: ndef++;
868: sp->n_type = cursym.n_type;
869: sp->n_value = cursym.n_value;
870: }
871: if (libflg==0 || ndef) {
872: tsize += filhdr.a_text;
873: dsize += round(filhdr.a_data, sizeof (long));
874: bsize += round(filhdr.a_bss, sizeof (long));
875: ssize += nlocal;
876: trsize += filhdr.a_trsize;
877: drsize += filhdr.a_drsize;
878: if (funding)
879: textbase = (*slookup("_end"))->n_value;
880: nsymt = symx(nextsym);
881: for (i = symx(savnext); i < nsymt; i++) {
882: sp = xsym(i);
883: sp->n_un.n_name = savestr(sp->n_un.n_name);
884: }
885: free(curstr);
886: return (1);
887: }
888: /*
889: * No symbols defined by this library member.
890: * Rip out the hash table entries and reset the symbol table.
891: */
892: symfree(savnext);
893: free(curstr);
894: return(0);
895: }
896:
897: middle()
898: {
899: register struct nlist *sp;
900: long csize, t, corigin, ocsize;
901: int nund, rnd;
902: char s;
903: register int i;
904: int nsymt;
905:
906: torigin = 0;
907: dorigin = 0;
908: borigin = 0;
909:
910: p_etext = *slookup("_etext");
911: p_edata = *slookup("_edata");
912: p_end = *slookup("_end");
913: /*
914: * If there are any undefined symbols, save the relocation bits.
915: */
916: nsymt = symx(nextsym);
917: if (rflag==0) {
918: for (i = 0; i < nsymt; i++) {
919: sp = xsym(i);
920: if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 &&
921: sp!=p_end && sp!=p_edata && sp!=p_etext) {
922: rflag++;
923: dflag = 0;
924: break;
925: }
926: }
927: }
928: if (rflag)
929: sflag = zflag = 0;
930: /*
931: * Assign common locations.
932: */
933: csize = 0;
934: if (!Aflag)
935: addsym = symseg[0].sy_first;
936: database = round(tsize+textbase,
937: (nflag||zflag? pagesize : sizeof (long)));
938: database += hsize;
939: if (dflag || rflag==0) {
940: ldrsym(p_etext, tsize, N_EXT+N_TEXT);
941: ldrsym(p_edata, dsize, N_EXT+N_DATA);
942: ldrsym(p_end, bsize, N_EXT+N_BSS);
943: for (i = symx(addsym); i < nsymt; i++) {
944: sp = xsym(i);
945: if ((s=sp->n_type)==N_EXT+N_UNDF &&
946: (t = sp->n_value)!=0) {
947: if (t >= sizeof (double))
948: rnd = sizeof (double);
949: else if (t >= sizeof (long))
950: rnd = sizeof (long);
951: else
952: rnd = sizeof (short);
953: csize = round(csize, rnd);
954: sp->n_value = csize;
955: sp->n_type = N_EXT+N_COMM;
956: ocsize = csize;
957: csize += t;
958: }
959: if (s&N_EXT && (s&N_TYPE)==N_UNDF && s&N_STAB) {
960: sp->n_value = ocsize;
961: sp->n_type = (s&N_STAB) | (N_EXT+N_COMM);
962: }
963: }
964: }
965: /*
966: * Now set symbols to their final value
967: */
968: csize = round(csize, sizeof (long));
969: torigin = textbase;
970: dorigin = database;
971: corigin = dorigin + dsize;
972: borigin = corigin + csize;
973: nund = 0;
974: nsymt = symx(nextsym);
975: for (i = symx(addsym); i<nsymt; i++) {
976: sp = xsym(i);
977: switch (sp->n_type & (N_TYPE+N_EXT)) {
978:
979: case N_EXT+N_UNDF:
980: if (arflag == 0)
981: errlev |= 01;
982: if ((arflag==0 || dflag) && sp->n_value==0) {
983: if (sp==p_end || sp==p_etext || sp==p_edata)
984: continue;
985: if (nund==0)
986: printf("Undefined:\n");
987: nund++;
988: printf("%s\n", sp->n_un.n_name);
989: }
990: continue;
991: case N_EXT+N_ABS:
992: default:
993: continue;
994: case N_EXT+N_TEXT:
995: sp->n_value += torigin;
996: continue;
997: case N_EXT+N_DATA:
998: sp->n_value += dorigin;
999: continue;
1000: case N_EXT+N_BSS:
1001: sp->n_value += borigin;
1002: continue;
1003: case N_EXT+N_COMM:
1004: sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS);
1005: sp->n_value += corigin;
1006: continue;
1007: }
1008: }
1009: if (sflag || xflag)
1010: ssize = 0;
1011: bsize += csize;
1012: nsym = ssize / (sizeof cursym);
1013: if (Aflag) {
1014: fixspec(p_etext,torigin);
1015: fixspec(p_edata,dorigin);
1016: fixspec(p_end,borigin);
1017: }
1018: }
1019:
1020: fixspec(sym,offset)
1021: struct nlist *sym;
1022: long offset;
1023: {
1024:
1025: if(symx(sym) < symx(addsym) && sym!=0)
1026: sym->n_value += offset;
1027: }
1028:
1029: ldrsym(sp, val, type)
1030: register struct nlist *sp;
1031: long val;
1032: {
1033:
1034: if (sp == 0)
1035: return;
1036: if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) {
1037: printf("%s: ", sp->n_un.n_name);
1038: error(0, "user attempt to redfine loader-defined symbol");
1039: return;
1040: }
1041: sp->n_type = type;
1042: sp->n_value = val;
1043: }
1044:
1045: off_t wroff;
1046: struct biobuf toutb;
1047:
1048: setupout()
1049: {
1050: extern int errno;
1051: int bss;
1052: struct stat stbuf;
1053:
1054: ofilemode = 0777 & ~umask(0);
1055: biofd = creat(ofilename, 0666 & ofilemode);
1056: if (biofd < 0) {
1057: filname = ofilename; /* kludge */
1058: archdr.ar_name[0] = 0; /* kludge */
1059: error(1, strerror(errno)); /* kludge */
1060: }
1061: fstat(biofd, &stbuf); /* suppose file exists, wrong*/
1062: if (stbuf.st_mode & 0111) { /* mode, ld fails? */
1063: chmod(ofilename, stbuf.st_mode & 0666);
1064: ofilemode = stbuf.st_mode;
1065: }
1066: #ifdef hp300
1067: filhdr.a_mid = (rflag ? MID_ZERO : MID_HP300);
1068: #endif
1069: filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);
1070: filhdr.a_text = nflag ? tsize :
1071: round(tsize, zflag ? pagesize : sizeof (long));
1072: filhdr.a_data = zflag ? round(dsize, pagesize) : dsize;
1073: bss = bsize - (filhdr.a_data - dsize);
1074: if (bss < 0)
1075: bss = 0;
1076: filhdr.a_bss = bss;
1077: filhdr.a_trsize = trsize;
1078: filhdr.a_drsize = drsize;
1079: filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*symx(nextsym));
1080: if (entrypt) {
1081: if (entrypt->n_type!=N_EXT+N_TEXT)
1082: error(0, "entry point not in text");
1083: else
1084: filhdr.a_entry = entrypt->n_value;
1085: } else
1086: filhdr.a_entry = 0;
1087: filhdr.a_trsize = (rflag ? trsize:0);
1088: filhdr.a_drsize = (rflag ? drsize:0);
1089: tout = &toutb;
1090: bopen(tout, 0, stbuf.st_blksize);
1091: bwrite((char *)&filhdr, sizeof (filhdr), tout);
1092: if (zflag)
1093: bseek(tout, pagesize);
1094: wroff = N_TXTOFF(filhdr) + filhdr.a_text;
1095: outb(&dout, filhdr.a_data, stbuf.st_blksize);
1096: if (rflag) {
1097: outb(&trout, filhdr.a_trsize, stbuf.st_blksize);
1098: outb(&drout, filhdr.a_drsize, stbuf.st_blksize);
1099: }
1100: if (sflag==0 || xflag==0) {
1101: outb(&sout, filhdr.a_syms, stbuf.st_blksize);
1102: wroff += sizeof (offset);
1103: outb(&strout, 0, stbuf.st_blksize);
1104: }
1105: }
1106:
1107: outb(bp, inc, bufsize)
1108: register struct biobuf **bp;
1109: {
1110:
1111: *bp = (struct biobuf *)malloc(sizeof (struct biobuf));
1112: if (*bp == 0)
1113: error(1, "ran out of memory (outb)");
1114: bopen(*bp, wroff, bufsize);
1115: wroff += inc;
1116: }
1117:
1118: load2arg(acp)
1119: char *acp;
1120: {
1121: register char *cp;
1122: off_t loc;
1123:
1124: cp = acp;
1125: if (getfile(cp) == 0) {
1126: while (*cp)
1127: cp++;
1128: while (cp >= acp && *--cp != '/');
1129: mkfsym(++cp);
1130: load2(0L);
1131: } else { /* scan archive members referenced */
1132: for (;;) {
1133: if (clibseg->li_used2 == clibseg->li_used) {
1134: if (clibseg->li_used < NROUT)
1135: error(1, "libseg botch");
1136: clibseg++;
1137: }
1138: loc = clibseg->li_first[clibseg->li_used2++];
1139: if (loc == -1)
1140: break;
1141: dseek(&text, loc, (long)sizeof(archdr));
1142: getarhdr();
1143: mkfsym(archdr.ar_name);
1144: load2(loc + (long)sizeof(archdr));
1145: }
1146: }
1147: close(infil);
1148: }
1149:
1150: load2(loc)
1151: long loc;
1152: {
1153: int size;
1154: register struct nlist *sp;
1155: register struct local *lp;
1156: register int symno, i;
1157: int type;
1158:
1159: readhdr(loc);
1160: if (!funding) {
1161: ctrel = torigin;
1162: cdrel += dorigin;
1163: cbrel += borigin;
1164: }
1165: /*
1166: * Reread the symbol table, recording the numbering
1167: * of symbols for fixing external references.
1168: */
1169: for (i = 0; i < LHSIZ; i++)
1170: lochash[i] = 0;
1171: clocseg = locseg;
1172: clocseg->lo_used = 0;
1173: symno = -1;
1174: loc += N_TXTOFF(filhdr);
1175: dseek(&text, loc+filhdr.a_text+filhdr.a_data+
1176: filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t));
1177: mget(&size, sizeof(size), &text);
1178: dseek(&text, loc+filhdr.a_text+filhdr.a_data+
1179: filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t),
1180: size - sizeof(off_t));
1181: curstr = (char *)malloc(size);
1182: if (curstr == NULL)
1183: error(1, "out of space reading string table (pass 2)");
1184: mget(curstr+sizeof(off_t), size-sizeof(off_t), &text);
1185: dseek(&text, loc+filhdr.a_text+filhdr.a_data+
1186: filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);
1187: while (text.size > 0) {
1188: symno++;
1189: mget((char *)&cursym, sizeof(struct nlist), &text);
1190: if (cursym.n_un.n_strx) {
1191: if (cursym.n_un.n_strx<sizeof(size) ||
1192: cursym.n_un.n_strx>=size)
1193: error(1, "bad string table index (pass 2)");
1194: cursym.n_un.n_name = curstr + cursym.n_un.n_strx;
1195: }
1196: /* inline expansion of symreloc() */
1197: switch (cursym.n_type & 017) {
1198:
1199: case N_TEXT:
1200: case N_EXT+N_TEXT:
1201: cursym.n_value += ctrel;
1202: break;
1203: case N_DATA:
1204: case N_EXT+N_DATA:
1205: cursym.n_value += cdrel;
1206: break;
1207: case N_BSS:
1208: case N_EXT+N_BSS:
1209: cursym.n_value += cbrel;
1210: break;
1211: case N_EXT+N_UNDF:
1212: break;
1213: default:
1214: if (cursym.n_type&N_EXT)
1215: cursym.n_type = N_EXT+N_ABS;
1216: }
1217: /* end inline expansion of symreloc() */
1218: type = cursym.n_type;
1219: if (yflag && cursym.n_un.n_name)
1220: for (i = 0; i < yflag; i++)
1221: /* fast check for 2d character! */
1222: if (ytab[i][1] == cursym.n_un.n_name[1] &&
1223: !strcmp(ytab[i], cursym.n_un.n_name)) {
1224: tracesym();
1225: break;
1226: }
1227: if ((type&N_EXT) == 0) {
1228: if (!sflag&&!xflag&&
1229: (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB))
1230: symwrite(&cursym, sout);
1231: continue;
1232: }
1233: if (funding)
1234: continue;
1235: if ((sp = *lookup()) == 0)
1236: error(1, "internal error: symbol not found");
1237: if (cursym.n_type == N_EXT+N_UNDF) {
1238: if (clocseg->lo_used == NSYMPR) {
1239: if (++clocseg == &locseg[NSEG])
1240: error(1, "local symbol overflow");
1241: clocseg->lo_used = 0;
1242: }
1243: if (clocseg->lo_first == 0) {
1244: clocseg->lo_first = (struct local *)
1245: malloc(NSYMPR * sizeof (struct local));
1246: if (clocseg->lo_first == 0)
1247: error(1, "out of memory (clocseg)");
1248: }
1249: lp = &clocseg->lo_first[clocseg->lo_used++];
1250: lp->l_index = symno;
1251: lp->l_symbol = sp;
1252: lp->l_link = lochash[symno % LHSIZ];
1253: lochash[symno % LHSIZ] = lp;
1254: continue;
1255: }
1256: if (cursym.n_type & N_STAB)
1257: continue;
1258: if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) {
1259: printf("%s: ", cursym.n_un.n_name);
1260: error(0, "multiply defined");
1261: }
1262: }
1263: if (funding)
1264: return;
1265: dseek(&text, loc, filhdr.a_text);
1266: dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
1267: load2td(ctrel, torigin - textbase, tout, trout);
1268: dseek(&text, loc+filhdr.a_text, filhdr.a_data);
1269: dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize,
1270: filhdr.a_drsize);
1271: load2td(cdrel, dorigin - database, dout, drout);
1272: while (filhdr.a_data & (sizeof(long)-1)) {
1273: bputc(0, dout);
1274: filhdr.a_data++;
1275: }
1276: torigin += filhdr.a_text;
1277: dorigin += round(filhdr.a_data, sizeof (long));
1278: borigin += round(filhdr.a_bss, sizeof (long));
1279: free(curstr);
1280: }
1281:
1282: struct tynames {
1283: int ty_value;
1284: char *ty_name;
1285: } tynames[] = {
1286: N_UNDF, "undefined",
1287: N_ABS, "absolute",
1288: N_TEXT, "text",
1289: N_DATA, "data",
1290: N_BSS, "bss",
1291: N_COMM, "common",
1292: 0, 0,
1293: };
1294:
1295: tracesym()
1296: {
1297: register struct tynames *tp;
1298:
1299: if (cursym.n_type & N_STAB)
1300: return;
1301: printf("%s", filname);
1302: if (archdr.ar_name[0])
1303: printf("(%s)", archdr.ar_name);
1304: printf(": ");
1305: if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) {
1306: printf("definition of common %s size %d\n",
1307: cursym.n_un.n_name, cursym.n_value);
1308: return;
1309: }
1310: for (tp = tynames; tp->ty_name; tp++)
1311: if (tp->ty_value == (cursym.n_type&N_TYPE))
1312: break;
1313: printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to");
1314: if (cursym.n_type&N_EXT)
1315: printf(" external");
1316: if (tp->ty_name)
1317: printf(" %s", tp->ty_name);
1318: printf(" %s\n", cursym.n_un.n_name);
1319: }
1320:
1321: #if !defined(tahoe)
1322: /* for machines which allow arbitrarily aligned word and longword accesses */
1323: #define getw(cp) (*(short *)(cp))
1324: #define getl(cp) (*(long *)(cp))
1325: #define putw(cp, w) (*(short *)(cp) = (w))
1326: #define putl(cp, l) (*(long *)(cp) = (l))
1327: #else
1328: short
1329: getw(cp)
1330: char *cp;
1331: {
1332: union {
1333: short w;
1334: char c[2];
1335: } w;
1336:
1337: w.c[0] = *cp++;
1338: w.c[1] = *cp++;
1339: return (w.w);
1340: }
1341:
1342: getl(cp)
1343: char *cp;
1344: {
1345: union {
1346: long l;
1347: char c[4];
1348: } l;
1349:
1350: l.c[0] = *cp++;
1351: l.c[1] = *cp++;
1352: l.c[2] = *cp++;
1353: l.c[3] = *cp++;
1354: return (l.l);
1355: }
1356:
1357: putw(cp, v)
1358: char *cp;
1359: short v;
1360: {
1361: union {
1362: short w;
1363: char c[2];
1364: } w;
1365:
1366: w.w = v;
1367: *cp++ = w.c[0];
1368: *cp++ = w.c[1];
1369: }
1370:
1371: putl(cp, v)
1372: char *cp;
1373: long v;
1374: {
1375: union {
1376: long l;
1377: char c[4];
1378: } l;
1379:
1380: l.l = v;
1381: *cp++ = l.c[0];
1382: *cp++ = l.c[1];
1383: *cp++ = l.c[2];
1384: *cp++ = l.c[3];
1385: }
1386: #endif
1387:
1388: /*
1389: * This routine relocates the single text or data segment argument.
1390: * Offsets from external symbols are resolved by adding the value
1391: * of the external symbols. Non-external reference are updated to account
1392: * for the relative motion of the segments (ctrel, cdrel, ...). If
1393: * a relocation was pc-relative, then we update it to reflect the
1394: * change in the positioning of the segments by adding the displacement
1395: * of the referenced segment and subtracting the displacement of the
1396: * current segment (creloc).
1397: *
1398: * If we are saving the relocation information, then we increase
1399: * each relocation datum address by our base position in the new segment.
1400: */
1401: load2td(creloc, position, b1, b2)
1402: long creloc, position;
1403: struct biobuf *b1, *b2;
1404: {
1405: register struct nlist *sp;
1406: register struct local *lp;
1407: long tw;
1408: register struct relocation_info *rp, *rpend;
1409: struct relocation_info *relp;
1410: char *codep;
1411: register char *cp;
1412: int relsz, codesz;
1413:
1414: relsz = reloc.size;
1415: relp = (struct relocation_info *)malloc(relsz);
1416: codesz = text.size;
1417: codep = (char *)malloc(codesz);
1418: if (relp == 0 || codep == 0)
1419: error(1, "out of memory (load2td)");
1420: mget((char *)relp, relsz, &reloc);
1421: rpend = &relp[relsz / sizeof (struct relocation_info)];
1422: mget(codep, codesz, &text);
1423: for (rp = relp; rp < rpend; rp++) {
1424: cp = codep + rp->r_address;
1425: /*
1426: * Pick up previous value at location to be relocated.
1427: */
1428: switch (rp->r_length) {
1429:
1430: case 0: /* byte */
1431: tw = *cp;
1432: break;
1433:
1434: case 1: /* word */
1435: tw = getw(cp);
1436: break;
1437:
1438: case 2: /* long */
1439: tw = getl(cp);
1440: break;
1441:
1442: default:
1443: error(1, "load2td botch: bad length");
1444: }
1445: /*
1446: * If relative to an external which is defined,
1447: * resolve to a simpler kind of reference in the
1448: * result file. If the external is undefined, just
1449: * convert the symbol number to the number of the
1450: * symbol in the result file and leave it undefined.
1451: */
1452: if (rp->r_extern) {
1453: /*
1454: * Search the hash table which maps local
1455: * symbol numbers to symbol tables entries
1456: * in the new a.out file.
1457: */
1458: lp = lochash[rp->r_symbolnum % LHSIZ];
1459: while (lp->l_index != rp->r_symbolnum) {
1460: lp = lp->l_link;
1461: if (lp == 0)
1462: error(1, "local symbol botch");
1463: }
1464: sp = lp->l_symbol;
1465: if (sp->n_type == N_EXT+N_UNDF)
1466: rp->r_symbolnum = nsym+symx(sp);
1467: else {
1468: rp->r_symbolnum = sp->n_type & N_TYPE;
1469: tw += sp->n_value;
1470: rp->r_extern = 0;
1471: }
1472: } else switch (rp->r_symbolnum & N_TYPE) {
1473: /*
1474: * Relocation is relative to the loaded position
1475: * of another segment. Update by the change in position
1476: * of that segment.
1477: */
1478: case N_TEXT:
1479: tw += ctrel;
1480: break;
1481: case N_DATA:
1482: tw += cdrel;
1483: break;
1484: case N_BSS:
1485: tw += cbrel;
1486: break;
1487: case N_ABS:
1488: break;
1489: default:
1490: error(1, "relocation format botch (symbol type))");
1491: }
1492: /*
1493: * Relocation is pc relative, so decrease the relocation
1494: * by the amount the current segment is displaced.
1495: * (E.g if we are a relative reference to a text location
1496: * from data space, we added the increase in the text address
1497: * above, and subtract the increase in our (data) address
1498: * here, leaving the net change the relative change in the
1499: * positioning of our text and data segments.)
1500: */
1501: if (rp->r_pcrel)
1502: tw -= creloc;
1503: /*
1504: * Put the value back in the segment,
1505: * while checking for overflow.
1506: */
1507: switch (rp->r_length) {
1508:
1509: case 0: /* byte */
1510: if (tw < -128 || tw > 127)
1511: error(0, "byte displacement overflow");
1512: *cp = tw;
1513: break;
1514: case 1: /* word */
1515: if (tw < -32768 || tw > 32767)
1516: error(0, "word displacement overflow");
1517: putw(cp, tw);
1518: break;
1519: case 2: /* long */
1520: putl(cp, tw);
1521: break;
1522: }
1523: /*
1524: * If we are saving relocation information,
1525: * we must convert the address in the segment from
1526: * the old .o file into an address in the segment in
1527: * the new a.out, by adding the position of our
1528: * segment in the new larger segment.
1529: */
1530: if (rflag)
1531: rp->r_address += position;
1532: }
1533: bwrite(codep, codesz, b1);
1534: if (rflag)
1535: bwrite(relp, relsz, b2);
1536: free((char *)relp);
1537: free(codep);
1538: }
1539:
1540: finishout()
1541: {
1542: register int i;
1543: int nsymt;
1544:
1545: if (sflag==0) {
1546: nsymt = symx(nextsym);
1547: for (i = 0; i < nsymt; i++)
1548: symwrite(xsym(i), sout);
1549: bwrite(&offset, sizeof offset, sout);
1550: }
1551: if (!ofilfnd) {
1552: unlink("a.out");
1553: if (link("l.out", "a.out") < 0)
1554: error(1, "cannot move l.out to a.out");
1555: ofilename = "a.out";
1556: }
1557: delarg = errlev;
1558: delexit();
1559: }
1560:
1561: mkfsym(s)
1562: char *s;
1563: {
1564:
1565: if (sflag || xflag)
1566: return;
1567: cursym.n_un.n_name = s;
1568: cursym.n_type = N_EXT | N_FN;
1569: cursym.n_value = torigin;
1570: symwrite(&cursym, sout);
1571: }
1572:
1573: getarhdr()
1574: {
1575: register char *cp;
1576:
1577: mget((char *)&archdr, sizeof archdr, &text);
1578: for (cp=archdr.ar_name; cp<&archdr.ar_name[sizeof(archdr.ar_name)];)
1579: if (*cp++ == ' ') {
1580: cp[-1] = 0;
1581: return;
1582: }
1583: }
1584:
1585: mget(loc, n, sp)
1586: register STREAM *sp;
1587: register char *loc;
1588: {
1589: register char *p;
1590: register int take;
1591:
1592: top:
1593: if (n == 0)
1594: return;
1595: if (sp->size && sp->nibuf) {
1596: p = sp->ptr;
1597: take = sp->size;
1598: if (take > sp->nibuf)
1599: take = sp->nibuf;
1600: if (take > n)
1601: take = n;
1602: n -= take;
1603: sp->size -= take;
1604: sp->nibuf -= take;
1605: sp->pos += take;
1606: do
1607: *loc++ = *p++;
1608: while (--take > 0);
1609: sp->ptr = p;
1610: goto top;
1611: }
1612: if (n > p_blksize) {
1613: take = n - n % p_blksize;
1614: lseek(infil, (sp->bno+1)<<p_blkshift, 0);
1615: if (take > sp->size || read(infil, loc, take) != take)
1616: error(1, "premature EOF");
1617: loc += take;
1618: n -= take;
1619: sp->size -= take;
1620: sp->pos += take;
1621: dseek(sp, (sp->bno+1+(take>>p_blkshift))<<p_blkshift, -1);
1622: goto top;
1623: }
1624: *loc++ = get(sp);
1625: --n;
1626: goto top;
1627: }
1628:
1629: symwrite(sp, bp)
1630: struct nlist *sp;
1631: struct biobuf *bp;
1632: {
1633: register int len;
1634: register char *str;
1635:
1636: str = sp->n_un.n_name;
1637: if (str) {
1638: sp->n_un.n_strx = offset;
1639: len = strlen(str) + 1;
1640: bwrite(str, len, strout);
1641: offset += len;
1642: }
1643: bwrite(sp, sizeof (*sp), bp);
1644: sp->n_un.n_name = str;
1645: }
1646:
1647: dseek(sp, loc, s)
1648: register STREAM *sp;
1649: long loc, s;
1650: {
1651: register PAGE *p;
1652: register b, o;
1653: int n;
1654:
1655: b = loc>>p_blkshift;
1656: o = loc&p_blkmask;
1657: if (o&01)
1658: error(1, "loader error; odd offset");
1659: --sp->pno->nuser;
1660: if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
1661: if (p->nuser==0 || (p = &page[0])->nuser==0) {
1662: if (page[0].nuser==0 && page[1].nuser==0)
1663: if (page[0].bno < page[1].bno)
1664: p = &page[0];
1665: p->bno = b;
1666: lseek(infil, loc & ~(long)p_blkmask, 0);
1667: if ((n = read(infil, p->buff, p_blksize)) < 0)
1668: n = 0;
1669: p->nibuf = n;
1670: } else
1671: error(1, "botch: no pages");
1672: ++p->nuser;
1673: sp->bno = b;
1674: sp->pno = p;
1675: if (s != -1) {sp->size = s; sp->pos = 0;}
1676: sp->ptr = (char *)(p->buff + o);
1677: if ((sp->nibuf = p->nibuf-o) <= 0)
1678: sp->size = 0;
1679: }
1680:
1681: char
1682: get(asp)
1683: STREAM *asp;
1684: {
1685: register STREAM *sp;
1686:
1687: sp = asp;
1688: if ((sp->nibuf -= sizeof(char)) < 0) {
1689: dseek(sp, ((long)(sp->bno+1)<<p_blkshift), (long)-1);
1690: sp->nibuf -= sizeof(char);
1691: }
1692: if ((sp->size -= sizeof(char)) <= 0) {
1693: if (sp->size < 0)
1694: error(1, "premature EOF");
1695: ++fpage.nuser;
1696: --sp->pno->nuser;
1697: sp->pno = (PAGE *) &fpage;
1698: }
1699: sp->pos += sizeof(char);
1700: return(*sp->ptr++);
1701: }
1702:
1703: getfile(acp)
1704: char *acp;
1705: {
1706: register int c;
1707: char arcmag[SARMAG+1];
1708: struct stat stb;
1709:
1710: archdr.ar_name[0] = '\0';
1711: filname = acp;
1712: if (filname[0] == '-' && filname[1] == 'l')
1713: infil = libopen(filname + 2, O_RDONLY);
1714: else
1715: infil = open(filname, O_RDONLY);
1716: if (infil < 0)
1717: error(1, "cannot open");
1718: fstat(infil, &stb);
1719: page[0].bno = page[1].bno = -1;
1720: page[0].nuser = page[1].nuser = 0;
1721: c = stb.st_blksize;
1722: if (c == 0 || (c & (c - 1)) != 0) {
1723: /* use default size if not a power of two */
1724: c = BLKSIZE;
1725: }
1726: if (p_blksize != c) {
1727: p_blksize = c;
1728: p_blkmask = c - 1;
1729: for (p_blkshift = 0; c > 1 ; p_blkshift++)
1730: c >>= 1;
1731: if (page[0].buff != NULL)
1732: free(page[0].buff);
1733: page[0].buff = (char *)malloc(p_blksize);
1734: if (page[0].buff == NULL)
1735: error(1, "ran out of memory (getfile)");
1736: if (page[1].buff != NULL)
1737: free(page[1].buff);
1738: page[1].buff = (char *)malloc(p_blksize);
1739: if (page[1].buff == NULL)
1740: error(1, "ran out of memory (getfile)");
1741: }
1742: text.pno = reloc.pno = (PAGE *) &fpage;
1743: fpage.nuser = 2;
1744: dseek(&text, 0L, SARMAG);
1745: if (text.size <= 0)
1746: error(1, "premature EOF");
1747: mget((char *)arcmag, SARMAG, &text);
1748: arcmag[SARMAG] = 0;
1749: if (strcmp(arcmag, ARMAG))
1750: return (0);
1751: dseek(&text, SARMAG, sizeof archdr);
1752: if (text.size <= 0)
1753: return (1);
1754: getarhdr();
1755: if (strncmp(archdr.ar_name, RANLIBMAG, sizeof(archdr.ar_name)) != 0)
1756: return (1);
1757: return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2);
1758: }
1759:
1760: /*
1761: * Search for a library with given name
1762: * using the directory search array.
1763: */
1764: libopen(name, oflags)
1765: char *name;
1766: int oflags;
1767: {
1768: register char *p, *cp;
1769: register int i;
1770: static char buf[MAXPATHLEN+1];
1771: int fd = -1;
1772:
1773: if (*name == '\0') /* backwards compat */
1774: name = "a";
1775: for (i = 0; i < ndir && fd == -1; i++) {
1776: p = buf;
1777: for (cp = dirs[i]; *cp; *p++ = *cp++)
1778: ;
1779: *p++ = '/';
1780: for (cp = "lib"; *cp; *p++ = *cp++)
1781: ;
1782: for (cp = name; *cp; *p++ = *cp++)
1783: ;
1784: cp = ".a";
1785: while (*p++ = *cp++)
1786: ;
1787: fd = open(buf, oflags);
1788: }
1789: if (fd != -1)
1790: filname = buf;
1791: return (fd);
1792: }
1793:
1794: struct nlist **
1795: lookup()
1796: {
1797: register int sh;
1798: register struct nlist **hp;
1799: register char *cp, *cp1;
1800: register struct symseg *gp;
1801: register int i;
1802:
1803: sh = 0;
1804: for (cp = cursym.n_un.n_name; *cp;)
1805: sh = (sh<<1) + *cp++;
1806: sh = (sh & 0x7fffffff) % HSIZE;
1807: for (gp = symseg; gp < &symseg[NSEG]; gp++) {
1808: if (gp->sy_first == 0) {
1809: gp->sy_first = (struct nlist *)
1810: calloc(NSYM, sizeof (struct nlist));
1811: gp->sy_hfirst = (struct nlist **)
1812: calloc(HSIZE, sizeof (struct nlist *));
1813: if (gp->sy_first == 0 || gp->sy_hfirst == 0)
1814: error(1, "ran out of space for symbol table");
1815: gp->sy_last = gp->sy_first + NSYM;
1816: gp->sy_hlast = gp->sy_hfirst + HSIZE;
1817: }
1818: if (gp > csymseg)
1819: csymseg = gp;
1820: hp = gp->sy_hfirst + sh;
1821: i = 1;
1822: do {
1823: if (*hp == 0) {
1824: if (gp->sy_used == NSYM)
1825: break;
1826: return (hp);
1827: }
1828: cp1 = (*hp)->n_un.n_name;
1829: for (cp = cursym.n_un.n_name; *cp == *cp1++;)
1830: if (*cp++ == 0)
1831: return (hp);
1832: hp += i;
1833: i += 2;
1834: if (hp >= gp->sy_hlast)
1835: hp -= HSIZE;
1836: } while (i < HSIZE);
1837: if (i > HSIZE)
1838: error(1, "hash table botch");
1839: }
1840: error(1, "symbol table overflow");
1841: /*NOTREACHED*/
1842: }
1843:
1844: symfree(saved)
1845: struct nlist *saved;
1846: {
1847: register struct symseg *gp;
1848: register struct nlist *sp;
1849:
1850: for (gp = csymseg; gp >= symseg; gp--, csymseg--) {
1851: sp = gp->sy_first + gp->sy_used;
1852: if (sp == saved) {
1853: nextsym = sp;
1854: return;
1855: }
1856: for (sp--; sp >= gp->sy_first; sp--) {
1857: gp->sy_hfirst[sp->n_hash] = 0;
1858: gp->sy_used--;
1859: if (sp == saved) {
1860: nextsym = sp;
1861: return;
1862: }
1863: }
1864: }
1865: if (saved == 0)
1866: return;
1867: error(1, "symfree botch");
1868: }
1869:
1870: struct nlist **
1871: slookup(s)
1872: char *s;
1873: {
1874:
1875: cursym.n_un.n_name = s;
1876: cursym.n_type = N_EXT+N_UNDF;
1877: cursym.n_value = 0;
1878: return (lookup());
1879: }
1880:
1881: enter(hp)
1882: register struct nlist **hp;
1883: {
1884: register struct nlist *sp;
1885:
1886: if (*hp==0) {
1887: if (hp < csymseg->sy_hfirst || hp >= csymseg->sy_hlast)
1888: error(1, "enter botch");
1889: *hp = lastsym = sp = csymseg->sy_first + csymseg->sy_used;
1890: csymseg->sy_used++;
1891: sp->n_un.n_name = cursym.n_un.n_name;
1892: sp->n_type = cursym.n_type;
1893: sp->n_hash = hp - csymseg->sy_hfirst;
1894: sp->n_value = cursym.n_value;
1895: nextsym = lastsym + 1;
1896: return(1);
1897: } else {
1898: lastsym = *hp;
1899: return(0);
1900: }
1901: }
1902:
1903: symx(sp)
1904: struct nlist *sp;
1905: {
1906: register struct symseg *gp;
1907:
1908: if (sp == 0)
1909: return (0);
1910: for (gp = csymseg; gp >= symseg; gp--)
1911: /* <= is sloppy so nextsym will always work */
1912: if (sp >= gp->sy_first && sp <= gp->sy_last)
1913: return ((gp - symseg) * NSYM + sp - gp->sy_first);
1914: error(1, "symx botch");
1915: /*NOTREACHED*/
1916: }
1917:
1918: symreloc()
1919: {
1920: if(funding) return;
1921: switch (cursym.n_type & 017) {
1922:
1923: case N_TEXT:
1924: case N_EXT+N_TEXT:
1925: cursym.n_value += ctrel;
1926: return;
1927:
1928: case N_DATA:
1929: case N_EXT+N_DATA:
1930: cursym.n_value += cdrel;
1931: return;
1932:
1933: case N_BSS:
1934: case N_EXT+N_BSS:
1935: cursym.n_value += cbrel;
1936: return;
1937:
1938: case N_EXT+N_UNDF:
1939: return;
1940:
1941: default:
1942: if (cursym.n_type&N_EXT)
1943: cursym.n_type = N_EXT+N_ABS;
1944: return;
1945: }
1946: }
1947:
1948: error(n, s)
1949: char *s;
1950: {
1951:
1952: if (errlev==0)
1953: printf("ld:");
1954: if (filname) {
1955: printf("%s", filname);
1956: if (n != -1 && archdr.ar_name[0])
1957: printf("(%s)", archdr.ar_name);
1958: printf(": ");
1959: }
1960: printf("%s\n", s);
1961: if (n == -1)
1962: return;
1963: if (n)
1964: delexit();
1965: errlev = 2;
1966: }
1967:
1968: readhdr(loc)
1969: off_t loc;
1970: {
1971:
1972: dseek(&text, loc, (long)sizeof(filhdr));
1973: mget((short *)&filhdr, sizeof(filhdr), &text);
1974: if (N_BADMAG(filhdr)) {
1975: if (filhdr.a_magic == OARMAG)
1976: error(1, "old archive");
1977: error(1, "bad magic number");
1978: }
1979: if (filhdr.a_text&01 || filhdr.a_data&01)
1980: error(1, "text/data size odd");
1981: if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) {
1982: cdrel = -round(filhdr.a_text, pagesize);
1983: cbrel = cdrel - filhdr.a_data;
1984: } else if (filhdr.a_magic == OMAGIC) {
1985: cdrel = -filhdr.a_text;
1986: cbrel = cdrel - filhdr.a_data;
1987: } else
1988: error(1, "bad format");
1989: }
1990:
1991: round(v, r)
1992: int v;
1993: u_long r;
1994: {
1995:
1996: r--;
1997: v += r;
1998: v &= ~(long)r;
1999: return(v);
2000: }
2001:
2002: #define NSAVETAB 8192
2003: char *savetab;
2004: int saveleft;
2005:
2006: char *
2007: savestr(cp)
2008: register char *cp;
2009: {
2010: register int len;
2011:
2012: len = strlen(cp) + 1;
2013: if (len > saveleft) {
2014: saveleft = NSAVETAB;
2015: if (len > saveleft)
2016: saveleft = len;
2017: savetab = malloc(saveleft);
2018: if (savetab == 0)
2019: error(1, "ran out of memory (savestr)");
2020: }
2021: strncpy(savetab, cp, len);
2022: cp = savetab;
2023: savetab += len;
2024: saveleft -= len;
2025: return (cp);
2026: }
2027:
2028: bopen(bp, off, bufsize)
2029: register struct biobuf *bp;
2030: {
2031:
2032: bp->b_ptr = bp->b_buf = malloc(bufsize);
2033: if (bp->b_ptr == (char *)0)
2034: error(1, "ran out of memory (bopen)");
2035: bp->b_bufsize = bufsize;
2036: bp->b_nleft = bufsize - (off % bufsize);
2037: bp->b_off = off;
2038: bp->b_link = biobufs;
2039: biobufs = bp;
2040: }
2041:
2042: int bwrerror;
2043:
2044: bwrite(p, cnt, bp)
2045: register char *p;
2046: register int cnt;
2047: register struct biobuf *bp;
2048: {
2049: register int put;
2050: register char *to;
2051:
2052: top:
2053: if (cnt == 0)
2054: return;
2055: if (bp->b_nleft) {
2056: put = bp->b_nleft;
2057: if (put > cnt)
2058: put = cnt;
2059: bp->b_nleft -= put;
2060: to = bp->b_ptr;
2061: bcopy(p, to, put);
2062: bp->b_ptr += put;
2063: p += put;
2064: cnt -= put;
2065: goto top;
2066: }
2067: if (cnt >= bp->b_bufsize) {
2068: if (bp->b_ptr != bp->b_buf)
2069: bflush1(bp);
2070: put = cnt - cnt % bp->b_bufsize;
2071: if (boffset != bp->b_off)
2072: lseek(biofd, bp->b_off, 0);
2073: if (write(biofd, p, put) != put) {
2074: bwrerror = 1;
2075: error(1, "output write error");
2076: }
2077: bp->b_off += put;
2078: boffset = bp->b_off;
2079: p += put;
2080: cnt -= put;
2081: goto top;
2082: }
2083: bflush1(bp);
2084: goto top;
2085: }
2086:
2087: bflush()
2088: {
2089: register struct biobuf *bp;
2090:
2091: if (bwrerror)
2092: return;
2093: for (bp = biobufs; bp; bp = bp->b_link)
2094: bflush1(bp);
2095: }
2096:
2097: bflush1(bp)
2098: register struct biobuf *bp;
2099: {
2100: register int cnt = bp->b_ptr - bp->b_buf;
2101:
2102: if (cnt == 0)
2103: return;
2104: if (boffset != bp->b_off)
2105: lseek(biofd, bp->b_off, 0);
2106: if (write(biofd, bp->b_buf, cnt) != cnt) {
2107: bwrerror = 1;
2108: error(1, "output write error");
2109: }
2110: bp->b_off += cnt;
2111: boffset = bp->b_off;
2112: bp->b_ptr = bp->b_buf;
2113: bp->b_nleft = bp->b_bufsize;
2114: }
2115:
2116: bflushc(bp, c)
2117: register struct biobuf *bp;
2118: {
2119:
2120: bflush1(bp);
2121: bputc(c, bp);
2122: }
2123:
2124: bseek(bp, off)
2125: register struct biobuf *bp;
2126: register off_t off;
2127: {
2128: bflush1(bp);
2129:
2130: bp->b_nleft = bp->b_bufsize - (off % bp->b_bufsize);
2131: bp->b_off = off;
2132: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.