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