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