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