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