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