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