Initial import from FreeBSD RELENG_4:
[dragonfly.git] / gnu / usr.bin / ld / rrs.c
1 /*
2  * Copyright (c) 1993 Paul Kranenburg
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Paul Kranenburg.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $FreeBSD: src/gnu/usr.bin/ld/rrs.c,v 1.24 1999/08/27 23:36:01 peter Exp $
31  */
32
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/file.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <err.h>
44 #include <fcntl.h>
45 #include <ar.h>
46 #include <ranlib.h>
47 #include <a.out.h>
48 #include <stab.h>
49 #include <string.h>
50
51 #include "ld.h"
52 #include "dynamic.h"
53
54 static struct _dynamic          rrs_dyn;                /* defined in link.h */
55 static struct so_debug          rrs_so_debug;           /* defined in link.h */
56 static struct section_dispatch_table    rrs_sdt;        /* defined in link.h */
57 static got_t                    *rrs_got;
58 static jmpslot_t                *rrs_plt;               /* defined in md.h */
59 static struct relocation_info   *rrs_reloc;
60 static struct nzlist            *rrs_symbols;           /* RRS symbol table */
61 static char                     *rrs_strtab;            /* RRS strings */
62 static struct rrs_hash          *rrs_hashtab;           /* RT hash table */
63 static struct shobj             *rrs_shobjs;
64 char                            *rrs_search_paths;      /* `-L' RT search */
65 static int                      rrs_search_paths_size;
66
67 static int      reserved_rrs_relocs;
68 static int      claimed_rrs_relocs;
69 static int      discarded_rrs_relocs;
70
71 static int      number_of_gotslots = 1;
72 static int      number_of_jmpslots = 1;
73 static int      number_of_rrs_hash_entries;
74 static int      number_of_rrs_symbols;
75 static int      rrs_strtab_size;
76 static int      rrs_symbol_size;
77
78 static int      current_jmpslot_offset;
79 static int      current_got_offset;
80 static int      max_got_offset;
81 static int      min_got_offset;
82 static int      got_origin;
83 static int      current_reloc_offset;
84 static int      current_hash_index;
85 int             number_of_shobjs;
86
87 /* Convert a GOT offset into a table entry */
88 #define GOTP(off)               ((got_t *)((long)rrs_got + got_origin + (off)))
89
90 struct shobj {
91         struct shobj            *next;
92         struct file_entry       *entry;
93 };
94
95 /*
96 RRS text segment:
97                 +-------------------+  <-- sdt_rel (rrs_text_start)
98                 |                   |
99                 |    relocation     |
100                 |                   |
101                 +-------------------+  <-- <sdt>.sdt_hash
102                 |                   |
103                 |    hash buckets   |
104                 |                   |
105                 +-------------------+  <-- <sdt>.sdt_nzlist
106                 |                   |
107                 |     symbols       |
108                 |                   |
109                 +-------------------+  <-- <sdt>.sdt_strings
110                 |                   |
111                 |     strings       |
112                 |                   |
113                 +-------------------+  <-- <sdt>.sdt_sods
114                 |                   |
115                 |     shobjs        |
116                 |                   |
117                 +-------------------+
118                 |                   |
119                 |  shobjs strings   |  <-- <shobj>.sod_name
120                 |                   |
121                 +-------------------+
122
123
124 RRS data segment:
125
126                 +-------------------+  <-- __DYNAMIC (rrs_data_start)
127                 |                   |
128                 |     _dymamic      |
129                 |                   |
130                 +-------------------+  <-- __DYNAMIC.d_debug
131                 |                   |
132                 |    so_debug       |
133                 |                   |
134                 +-------------------+  <-- __DYNAMIC.d_un.d_sdt
135                 |                   |
136                 |       sdt         |
137                 |                   |
138                 +-------------------+  <-- sdt_got
139                 |                   |
140                 |      _GOT_        |  <-- _GLOBAL_OFFSET_TABLE_
141                 |                   |           ( == sdt_got + got_origin)
142                 |                   |
143                 +-------------------+  <-- sdt_plt
144                 |                   |
145                 |       PLT         |
146                 |                   |
147                 +-------------------+
148 */
149
150 /*
151  * Add NAME to the list of needed run-time objects.
152  * Return 1 if ENTRY was added to the list.
153  */
154 int
155 rrs_add_shobj(entry)
156         struct file_entry       *entry;
157 {
158         struct shobj    **p;
159
160         for (p = &rrs_shobjs; *p != NULL; p = &(*p)->next)
161                 if (strcmp((*p)->entry->filename, entry->filename) == 0)
162                         return 0;
163         *p = (struct shobj *)xmalloc(sizeof(struct shobj));
164         (*p)->next = NULL;
165         (*p)->entry = entry;
166
167         number_of_shobjs++;
168         return 1;
169 }
170
171 void
172 alloc_rrs_reloc(entry, sp)
173         struct file_entry       *entry;
174         symbol                  *sp;
175 {
176 #ifdef DEBUG
177 printf("alloc_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
178 #endif
179         reserved_rrs_relocs++;
180 }
181
182 void
183 alloc_rrs_segment_reloc(entry, r)
184         struct file_entry       *entry;
185         struct relocation_info  *r;
186 {
187 #ifdef DEBUG
188 printf("alloc_rrs_segment_reloc at %#x in %s\n",
189         r->r_address, get_file_name(entry));
190 #endif
191         reserved_rrs_relocs++;
192 }
193
194 void
195 alloc_rrs_jmpslot(entry, sp)
196         struct file_entry       *entry;
197         symbol                  *sp;
198 {
199         if (sp->flags & GS_HASJMPSLOT)
200                 return;
201
202         sp->flags |= GS_HASJMPSLOT;
203         number_of_jmpslots++;
204         reserved_rrs_relocs++;
205 }
206
207 void
208 alloc_rrs_gotslot(entry, r, lsp)
209         struct file_entry       *entry;
210         struct relocation_info  *r;
211         struct localsymbol      *lsp;
212 {
213         symbol  *sp = lsp->symbol;
214
215         if (!RELOC_EXTERN_P(r)) {
216
217                 if (sp != NULL) {
218                         warnx("%s: relocation for internal symbol "
219                               "expected at %#x",
220                               get_file_name(entry), RELOC_ADDRESS(r));
221                         return;
222                 }
223
224                 if (!RELOC_STATICS_THROUGH_GOT_P(r))
225                         /* No need for a GOT slot */
226                         return;
227
228                 if (lsp->flags & LS_HASGOTSLOT)
229                         return;
230
231                 lsp->flags |= LS_HASGOTSLOT;
232
233         } else {
234
235                 if (sp == NULL) {
236                         warnx("%s: relocation must refer "
237                               "to global symbol at %#x",
238                               get_file_name(entry), RELOC_ADDRESS(r));
239                         return;
240                 }
241
242                 if (sp->alias)
243                         sp = sp->alias;
244
245                 if (sp->flags & GS_HASGOTSLOT)
246                         return;
247
248                 sp->flags |= GS_HASGOTSLOT;
249         }
250
251         number_of_gotslots++;
252         reserved_rrs_relocs++;
253 }
254
255 void
256 alloc_rrs_cpy_reloc(entry, sp)
257         struct file_entry       *entry;
258         symbol                  *sp;
259 {
260         if (sp->flags & GS_CPYRELOCRESERVED)
261                 return;
262 #ifdef DEBUG
263 printf("alloc_rrs_copy: %s in %s\n", demangle(sp->name), get_file_name(entry));
264 #endif
265         sp->flags |= GS_CPYRELOCRESERVED;
266         reserved_rrs_relocs++;
267 }
268
269 static struct relocation_info *
270 rrs_next_reloc()
271 {
272         struct relocation_info  *r;
273
274         r = rrs_reloc + claimed_rrs_relocs++;
275         if (claimed_rrs_relocs > reserved_rrs_relocs)
276                 errx(1, "internal error: RRS relocs exceed allocation %d",
277                         reserved_rrs_relocs);
278         return r;
279 }
280
281 /*
282  * Claim a RRS relocation as a result of a regular (ie. non-PIC)
283  * relocation record in a rel file.
284  *
285  * Return 1 if the output file needs no further updating.
286  * Return 0 if the relocation value pointed to by RELOCATION must
287  * written to a.out.
288  */
289 int
290 claim_rrs_reloc(entry, rp, sp, relocation)
291         struct file_entry       *entry;
292         struct relocation_info  *rp;
293         symbol                  *sp;
294         long                    *relocation;
295 {
296         struct relocation_info  *r = rrs_next_reloc();
297
298         if (rp->r_address < text_start + text_size
299             && (link_mode & WARNRRSTEXT))
300                 warnx("%s: RRS text relocation at %#x for \"%s\"",
301                         get_file_name(entry), rp->r_address, demangle(sp->name));
302
303 #ifdef DEBUG
304 printf("claim_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
305 #endif
306         r->r_address = rp->r_address;
307         r->r_symbolnum = sp->rrs_symbolnum;
308
309         if (link_mode & SYMBOLIC) {
310                 if (!sp->defined)
311                         warnx("Cannot reduce symbol \"%s\" in %s",
312                                 demangle(sp->name), get_file_name(entry));
313                 RELOC_EXTERN_P(r) = 0;
314                 *relocation += sp->value;
315                 (void) md_make_reloc(rp, r, RELTYPE_RELATIVE);
316                 return 0;
317         } else {
318                 RELOC_EXTERN_P(r) = 1;
319                 return md_make_reloc(rp, r, RELTYPE_EXTERN);
320         }
321 }
322
323 /*
324  * Claim a jmpslot. Setup RRS relocation if claimed for the first time.
325  */
326 long
327 claim_rrs_jmpslot(entry, rp, sp, addend)
328         struct file_entry       *entry;
329         struct relocation_info  *rp;
330         symbol                  *sp;
331         long                    addend;
332 {
333         struct relocation_info *r;
334
335         if (!(sp->flags & GS_HASJMPSLOT))
336                 errx(1, "internal error: "
337                         "%s: claim_rrs_jmpslot: %s: no reservation",
338                         get_file_name(entry),
339                         demangle(sp->name));
340
341         if (sp->jmpslot_offset != -1)
342                 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
343
344         sp->jmpslot_offset = current_jmpslot_offset;
345         current_jmpslot_offset += sizeof(jmpslot_t);
346
347 #ifdef DEBUG
348 printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n",
349         get_file_name(entry),
350         demangle(sp->name), sp->rrs_symbolnum, sp->jmpslot_offset);
351 #endif
352
353         if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
354                 if (!sp->defined)
355                         warnx("Cannot reduce symbol \"%s\" in %s",
356                                 demangle(sp->name), get_file_name(entry));
357
358                 md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
359                                 rrs_sdt.sdt_plt + sp->jmpslot_offset,
360                                 sp->value);
361                 if (rrs_section_type == RRS_PARTIAL || !JMPSLOT_NEEDS_RELOC) {
362                         /* PLT is self-contained */
363                         discarded_rrs_relocs++;
364                         return rrs_sdt.sdt_plt + sp->jmpslot_offset;
365                 }
366         } else {
367                 md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
368                                 sp->jmpslot_offset,
369                                 claimed_rrs_relocs);
370         }
371
372         /*
373          * Install a run-time relocation for this PLT entry.
374          */
375         r = rrs_next_reloc();
376
377         RELOC_SYMBOL(r) = sp->rrs_symbolnum;
378
379         r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset;
380
381         if (link_mode & SYMBOLIC) {
382                 RELOC_EXTERN_P(r) = 0;
383                 md_make_jmpreloc(rp, r, RELTYPE_RELATIVE);
384         } else {
385                 RELOC_EXTERN_P(r) = 1;
386                 md_make_jmpreloc(rp, r, 0);
387         }
388
389         return rrs_sdt.sdt_plt + sp->jmpslot_offset;
390 }
391
392 /*
393  * Claim GOT entry for a global symbol. If this is the first relocation
394  * claiming the entry, setup a RRS relocation for it.
395  * Return offset into the GOT allocated to this symbol.
396  */
397 long
398 claim_rrs_gotslot(entry, rp, lsp, addend)
399         struct file_entry       *entry;
400         struct relocation_info  *rp;
401         struct localsymbol      *lsp;
402         long                    addend;
403 {
404         struct relocation_info  *r;
405         symbol  *sp = lsp->symbol;
406         int     reloc_type = 0;
407
408         if (sp == NULL) {
409                 return 0;
410         }
411
412         if (sp->alias)
413                 sp = sp->alias;
414
415         if (!(sp->flags & GS_HASGOTSLOT))
416                 errx(1, "internal error: "
417                         "%s: claim_rrs_gotslot: %s: no reservation",
418                         get_file_name(entry), demangle(sp->name));
419
420         if (sp->gotslot_offset != -1) {
421 #ifdef DIAGNOSTIC
422                 if (*GOTP(sp->gotslot_offset) != addend +
423                     ((!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))
424                        ? sp->value : 0))
425                         errx(1, "%s: %s: gotslot at %#x is multiple valued, "
426                                 "*got = %#x, addend = %#x, sp->value = %#x",
427                                 get_file_name(entry), demangle(sp->name),
428                                 sp->gotslot_offset,
429                                 *GOTP(sp->gotslot_offset), addend, sp->value);
430 #endif
431                 /* This symbol already passed here before. */
432                 return sp->gotslot_offset;
433         }
434
435         if (current_got_offset == 0)
436                 /* GOT offset 0 is reserved */
437                 current_got_offset += sizeof(got_t);
438
439         if (current_got_offset > max_got_offset)
440                 errx(1, "%s: GOT overflow on symbol `%s' at %#x",
441                       get_file_name(entry), demangle(sp->name), RELOC_ADDRESS(rp));
442
443         sp->gotslot_offset = current_got_offset;
444         current_got_offset += sizeof(got_t);
445
446 #ifdef DEBUG
447 printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n",
448          demangle(sp->name), sp->rrs_symbolnum, sp->value, sp->gotslot_offset, addend);
449 #endif
450
451         if (sp->defined &&
452             (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) {
453
454                 /*
455                  * Reduce to just a base-relative translation.
456                  */
457
458                 *GOTP(sp->gotslot_offset) = sp->value + addend;
459                 reloc_type = RELTYPE_RELATIVE;
460
461         } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
462                 /*
463                  * SYMBOLIC: all symbols must be known.
464                  * RRS_PARTIAL: we don't link against shared objects,
465                  * so again all symbols must be known.
466                  */
467                 warnx("Cannot reduce symbol \"%s\" in %s",
468                       demangle(sp->name), get_file_name(entry));
469
470         } else {
471
472                 /*
473                  * This gotslot will be updated with symbol value at run-time.
474                  */
475
476                 *GOTP(sp->gotslot_offset) = addend;
477         }
478
479         if (rrs_section_type == RRS_PARTIAL) {
480                 /*
481                  * Base address is known, gotslot should be fully
482                  * relocated by now.
483                  * NOTE: RRS_PARTIAL implies !SHAREABLE.
484                  */
485                 if (!sp->defined)
486                         warnx("Cannot reduce symbol \"%s\" in %s",
487                               demangle(sp->name), get_file_name(entry));
488                 discarded_rrs_relocs++;
489                 return sp->gotslot_offset;
490         }
491
492         /*
493          * Claim a relocation entry.
494          * If symbol is defined and in "main" (!SHAREABLE)
495          * we still put out a relocation as we cannot easily
496          * undo the allocation.
497          * `RELTYPE_RELATIVE' relocations have the external bit off
498          * as no symbol need be looked up at run-time.
499          */
500         r = rrs_next_reloc();
501         r->r_address = got_symbol->value + sp->gotslot_offset;
502         RELOC_SYMBOL(r) = sp->rrs_symbolnum;
503         RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE);
504         md_make_gotreloc(rp, r, reloc_type);
505
506         return sp->gotslot_offset;
507 }
508
509 /*
510  * Claim a GOT entry for a static symbol. Return offset of the
511  * allocated GOT entry. If RELOC_STATICS_THROUGH_GOT_P is in effect,
512  * return the offset of the symbol with respect to the *location* of
513  * the GOT.
514  */
515 long
516 claim_rrs_internal_gotslot(entry, rp, lsp, addend)
517         struct file_entry       *entry;
518         struct relocation_info  *rp;
519         struct localsymbol      *lsp;
520         long                    addend;
521 {
522         struct relocation_info  *r;
523
524         addend += lsp->nzlist.nz_value;
525
526         if (!RELOC_STATICS_THROUGH_GOT_P(r))
527                 return addend - got_symbol->value;
528
529         if (!(lsp->flags & LS_HASGOTSLOT))
530                 errx(1, "internal error: "
531                         "%s: claim_rrs_internal_gotslot at %#x: no reservation",
532                         get_file_name(entry), RELOC_ADDRESS(rp));
533
534         if (lsp->gotslot_offset != -1) {
535                 /* Already claimed */
536                 if (*GOTP(lsp->gotslot_offset) != addend)
537                         errx(1, "%s: gotslot at %#lx is multiple valued",
538                                 get_file_name(entry), lsp->gotslot_offset);
539                 return lsp->gotslot_offset;
540         }
541
542         if (current_got_offset == 0)
543                 /* GOT offset 0 is reserved */
544                 current_got_offset += sizeof(got_t);
545
546         if (current_got_offset > max_got_offset)
547                 errx(1, "%s: GOT overflow for relocation at %#x",
548                       get_file_name(entry), RELOC_ADDRESS(rp));
549
550         lsp->gotslot_offset = current_got_offset;
551         current_got_offset += sizeof(got_t);
552
553         *GOTP(lsp->gotslot_offset) = addend;
554
555 #ifdef DEBUG
556 printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n",
557         get_file_name(entry), lsp->gotslot_offset, addend);
558 #endif
559
560         if (rrs_section_type == RRS_PARTIAL) {
561                 discarded_rrs_relocs++;
562                 return lsp->gotslot_offset;
563         }
564
565         /*
566          * Relocation entry needed for this static GOT entry.
567          */
568         r = rrs_next_reloc();
569         r->r_address = got_symbol->value + lsp->gotslot_offset;
570         RELOC_EXTERN_P(r) = 0;
571         md_make_gotreloc(rp, r, RELTYPE_RELATIVE);
572         return lsp->gotslot_offset;
573 }
574
575 void
576 claim_rrs_cpy_reloc(entry, rp, sp)
577         struct file_entry       *entry;
578         struct relocation_info  *rp;
579         symbol                  *sp;
580 {
581         struct relocation_info  *r;
582
583         if (sp->flags & GS_CPYRELOCCLAIMED)
584                 return;
585
586         if (!(sp->flags & GS_CPYRELOCRESERVED))
587                 errx(1, "internal error: "
588                         "%s: claim_cpy_reloc: %s: no reservation",
589                         get_file_name(entry), demangle(sp->name));
590
591 #ifdef DEBUG
592 printf("claim_rrs_copy: %s: %s -> %x\n",
593         get_file_name(entry), demangle(sp->name), sp->so_defined);
594 #endif
595
596         r = rrs_next_reloc();
597         sp->flags |= GS_CPYRELOCCLAIMED;
598         r->r_address = rp->r_address;
599         RELOC_SYMBOL(r) = sp->rrs_symbolnum;
600         RELOC_EXTERN_P(r) = RELOC_EXTERN_P(rp);
601         md_make_cpyreloc(rp, r);
602 }
603
604 void
605 claim_rrs_segment_reloc(entry, rp)
606         struct file_entry       *entry;
607         struct relocation_info  *rp;
608 {
609         struct relocation_info  *r = rrs_next_reloc();
610
611 #ifdef DEBUG
612 printf("claim_rrs_segment_reloc: %s at %#x\n",
613         get_file_name(entry), rp->r_address);
614 #endif
615
616         r->r_address = rp->r_address;
617         RELOC_TYPE(r) = RELOC_TYPE(rp);
618         RELOC_EXTERN_P(r) = 0;
619         md_make_reloc(rp, r, RELTYPE_RELATIVE);
620
621 }
622
623 /*
624  * Fill the RRS hash table for the given symbol name.
625  * NOTE: the hash value computation must match the one in rtld.
626  */
627 void
628 rrs_insert_hash(cp, index)
629         char    *cp;
630         int     index;
631 {
632         int             hashval = 0;
633         struct rrs_hash *hp;
634
635         for (; *cp; cp++)
636                 hashval = (hashval << 1) + *cp;
637
638         hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets;
639
640         /* Get to the bucket */
641         hp = rrs_hashtab + hashval;
642         if (hp->rh_symbolnum == -1) {
643                 /* Empty bucket, use it */
644                 hp->rh_symbolnum = index;
645                 hp->rh_next = 0;
646                 return;
647         }
648
649         while (hp->rh_next != 0)
650                 hp = rrs_hashtab + hp->rh_next;
651
652         hp->rh_next = current_hash_index++;
653         hp = rrs_hashtab + hp->rh_next;
654         hp->rh_symbolnum = index;
655         hp->rh_next = 0;
656 }
657
658 /*
659  * There are two interesting cases to consider here.
660  *
661  * 1) No shared objects were loaded, but there were PIC input rel files.
662  *    In this case we must output a _GLOBAL_OFFSET_TABLE_ but no other
663  *    RRS data. Also, the entries in the GOT must be fully resolved.
664  *
665  * 2) It's a genuine dynamically linked program, so the whole RRS scoop
666  *    goes into a.out.
667  */
668 void
669 consider_rrs_section_lengths()
670 {
671         int             n;
672         struct shobj    *shp;
673
674 #ifdef notyet
675         struct shobj    **shpp;
676 /* We run into trouble with this as long as shared object symbols
677    are not checked for definitions */
678         /*
679          * First, determine the real number of shared objects we need.
680          */
681         for (shpp = &rrs_shobjs; *shpp; shpp = &(*shpp)->next) {
682                 while (*shpp && !((*shpp)->entry->flags & E_SYMBOLS_USED)) {
683                         if (--number_of_shobjs < 0)
684                                 errx(1, "internal error: number_of_shobjs < 0");
685                         *shpp = (*shpp)->next;
686                 }
687                 if (*shpp == NULL)
688                         break;
689         }
690 #endif
691
692         /* First, determine what of the RRS we want */
693         if (relocatable_output)
694                 rrs_section_type = RRS_NONE;
695         else if (link_mode & SHAREABLE)
696                 rrs_section_type = RRS_FULL;
697         else if (number_of_shobjs == 0 && !(link_mode & FORCEDYNAMIC)) {
698                 /*
699                  * First slots in both tables are reserved
700                  * hence the "> 1" condition
701                  */
702                 if (number_of_gotslots > 1 || number_of_jmpslots > 1)
703                         rrs_section_type = RRS_PARTIAL;
704                 else
705                         rrs_section_type = RRS_NONE;
706         } else
707                 rrs_section_type = RRS_FULL;
708
709         if (rrs_section_type == RRS_NONE) {
710                 got_symbol->defined = 0;
711                 if (reserved_rrs_relocs > 0)
712                         errx(1, "internal error: empty RRS has reservations");
713                 return;
714         }
715
716         rrs_symbol_size = LD_VERSION_NZLIST_P(soversion) ?
717                         sizeof(struct nzlist) : sizeof(struct nlist);
718
719         /*
720          * If there is an entry point, __DYNAMIC must be referenced (usually
721          * from crt0), as this is the method used to determine whether the
722          * run-time linker must be called.
723          */
724         if (!(link_mode & SHAREABLE) && !(dynamic_symbol->flags & GS_REFERENCED))
725                 errx(1, "No reference to __DYNAMIC");
726
727         dynamic_symbol->flags |= GS_REFERENCED;
728
729         if (number_of_gotslots > 1)
730                 got_symbol->flags |= GS_REFERENCED;
731
732
733         /* Next, allocate relocs, got and plt */
734         n = reserved_rrs_relocs * sizeof(struct relocation_info);
735         rrs_reloc = (struct relocation_info *)xmalloc(n);
736         bzero(rrs_reloc, n);
737
738         n = number_of_gotslots * sizeof(got_t);
739         rrs_got = (got_t *)xmalloc(n);
740         bzero(rrs_got, n);
741
742         n = number_of_jmpslots * sizeof(jmpslot_t);
743         rrs_plt = (jmpslot_t *)xmalloc(n);
744         bzero(rrs_plt, n);
745
746         /* Initialize first jmpslot */
747         md_fix_jmpslot(rrs_plt, 0, 0);
748
749         if (rrs_section_type == RRS_PARTIAL) {
750                 rrs_data_size = number_of_gotslots * sizeof(got_t);
751                 rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
752                 return;
753         }
754
755         /*
756          * Walk the symbol table, assign RRS symbol numbers
757          * and calculate string space.
758          * Assign number 0 to __DYNAMIC (!! Sun compatibility)
759          */
760         dynamic_symbol->rrs_symbolnum = number_of_rrs_symbols++;
761         FOR_EACH_SYMBOL(i ,sp) {
762                 if ((link_mode & SHAREABLE) && sp->warning) {
763                         /* Allocate N_WARNING & co */
764                         rrs_strtab_size +=
765                                 2 + strlen(sp->name) + strlen(sp->warning);
766                         number_of_rrs_symbols += 2;
767                 }
768
769                 if (!(sp->flags & GS_REFERENCED))
770                         continue;
771
772                 rrs_strtab_size += 1 + strlen(sp->name);
773                 if (sp != dynamic_symbol)
774                         sp->rrs_symbolnum = number_of_rrs_symbols++;
775                 if (sp->alias) {
776                         /*
777                          * (sigh) Always allocate space to hold the
778                          * indirection. At this point there's not
779                          * enough information to decide whether it's
780                          * actually needed or not.
781                          */
782                         number_of_rrs_symbols++;
783                         rrs_strtab_size += 1 + strlen(sp->alias->name);
784                 }
785         } END_EACH_SYMBOL;
786
787         /*
788          * Now that we know how many RRS symbols there are going to be,
789          * allocate and initialize the RRS symbol hash table.
790          */
791         rrs_sdt.sdt_buckets = number_of_rrs_symbols/4;
792         if (rrs_sdt.sdt_buckets < 4)
793                 rrs_sdt.sdt_buckets = 4;
794
795         number_of_rrs_hash_entries = rrs_sdt.sdt_buckets +
796                                      number_of_rrs_symbols;
797         rrs_hashtab = (struct rrs_hash *)xmalloc(
798                         number_of_rrs_hash_entries * sizeof(struct rrs_hash));
799         for (n = 0; n < rrs_sdt.sdt_buckets; n++)
800                 rrs_hashtab[n].rh_symbolnum = -1;
801         current_hash_index = rrs_sdt.sdt_buckets;
802
803         /*
804          * Get symbols into hash table now, so we can fine tune the size
805          * of the latter. We adjust the value of `number_of_rrs_hash_entries'
806          * to the number of hash link slots actually used.
807          */
808         FOR_EACH_SYMBOL(i ,sp) {
809                 if (sp->flags & GS_REFERENCED)
810                         rrs_insert_hash(sp->name, sp->rrs_symbolnum);
811         } END_EACH_SYMBOL;
812         number_of_rrs_hash_entries = current_hash_index;
813
814         /*
815          * Calculate RRS section sizes.
816          */
817         rrs_data_size = sizeof(struct _dynamic);
818         rrs_data_size += sizeof(struct so_debug);
819         rrs_data_size += sizeof(struct section_dispatch_table);
820         rrs_data_size += number_of_gotslots * sizeof(got_t);
821         rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
822         rrs_data_size = MALIGN(rrs_data_size);
823
824         rrs_text_size = reserved_rrs_relocs * sizeof(struct relocation_info);
825         rrs_text_size += number_of_rrs_hash_entries * sizeof(struct rrs_hash);
826         rrs_text_size += number_of_rrs_symbols * rrs_symbol_size;
827         rrs_search_paths_size = rrs_search_paths
828                                         ? strlen(rrs_search_paths) + 1
829                                         : 0;
830         rrs_search_paths_size = MALIGN(rrs_search_paths_size);
831         rrs_text_size += rrs_search_paths_size;
832
833         /* Align strings size */
834         rrs_strtab_size = MALIGN(rrs_strtab_size);
835         rrs_text_size += rrs_strtab_size;
836
837         /* Process needed shared objects */
838         for (shp = rrs_shobjs; shp; shp = shp->next) {
839                 char    *name = shp->entry->local_sym_name;
840
841                 if (*name == '-' && *(name+1) == 'l')
842                         name += 2;
843
844                 rrs_text_size += sizeof(struct sod);
845                 rrs_text_size += 1 + strlen(name);
846         }
847
848         /* Finally, align size */
849         rrs_text_size = MALIGN(rrs_text_size);
850 }
851
852 void
853 relocate_rrs_addresses()
854 {
855         int gotsize;
856
857         dynamic_symbol->value = 0;
858
859         /*
860          * Get ready to allocate linkage table offsets.
861          * First jmpslot is reserved for the run-time binder
862          * GOT entry at offset 0 is reserved for `__DYNAMIC'.
863          */
864         current_jmpslot_offset = sizeof(jmpslot_t);
865         current_got_offset = 0;
866         max_got_offset = MAX_GOTOFF(pic_type);
867         min_got_offset = MIN_GOTOFF(pic_type);
868         gotsize = number_of_gotslots * sizeof(got_t);
869
870         if (gotsize + min_got_offset - (int)sizeof(got_t) > max_got_offset)
871                 warnx("Global Offset Table overflow (use `-fPIC')");
872
873         if (gotsize > max_got_offset)
874                 /* Position at "two-complements" origin */
875                 current_got_offset += min_got_offset;
876
877         got_origin = -current_got_offset;
878
879         if (rrs_section_type == RRS_NONE)
880                 return;
881
882         if (rrs_section_type == RRS_PARTIAL) {
883                 rrs_sdt.sdt_got = rrs_data_start;
884                 got_symbol->value = rrs_sdt.sdt_got + got_origin;
885                 rrs_sdt.sdt_plt = rrs_sdt.sdt_got +
886                                   number_of_gotslots * sizeof(got_t);
887                 return;
888         }
889
890         /*
891          * RRS data relocations.
892          */
893         rrs_dyn.d_version = soversion;
894         rrs_dyn.d_debug = (struct so_debug *)
895                           (rrs_data_start + sizeof(struct _dynamic));
896         rrs_dyn.d_un.d_sdt = (struct section_dispatch_table *)
897                              ((long)rrs_dyn.d_debug + sizeof(struct so_debug));
898
899         rrs_sdt.sdt_got = (long)rrs_dyn.d_un.d_sdt +
900                           sizeof(struct section_dispatch_table);
901         rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots*sizeof(got_t);
902
903         /*
904          * RRS text relocations.
905          */
906         rrs_sdt.sdt_rel = rrs_text_start;
907         /*
908          * Sun BUG compatibility alert.
909          * Main program's RRS text values are relative to TXTADDR? WHY??
910          */
911 #ifdef SUN_COMPAT
912         if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE))
913                 rrs_sdt.sdt_rel -= N_TXTADDR(outheader);
914 #endif
915
916         rrs_sdt.sdt_hash = rrs_sdt.sdt_rel +
917                         reserved_rrs_relocs * sizeof(struct relocation_info);
918         rrs_sdt.sdt_nzlist = rrs_sdt.sdt_hash +
919                         number_of_rrs_hash_entries * sizeof(struct rrs_hash);
920         rrs_sdt.sdt_strings = rrs_sdt.sdt_nzlist +
921                         number_of_rrs_symbols * rrs_symbol_size;
922         rrs_sdt.sdt_paths = rrs_search_paths
923                                 ? rrs_sdt.sdt_strings + rrs_strtab_size
924                                 : 0;
925         rrs_sdt.sdt_sods = rrs_shobjs
926                                 ? rrs_sdt.sdt_strings + rrs_strtab_size +
927                                   rrs_search_paths_size
928                                 : 0;
929         rrs_sdt.sdt_filler2 = 0;
930         rrs_sdt.sdt_str_sz = rrs_strtab_size;
931         rrs_sdt.sdt_text_sz = text_size;
932         rrs_sdt.sdt_plt_sz = number_of_jmpslots * sizeof(jmpslot_t);
933
934         /*
935          * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC.
936          * The value `&__DYNAMIC' is in the GOT table at offset 0.
937          */
938         got_symbol->value = rrs_sdt.sdt_got + got_origin;
939         *GOTP(0) = dynamic_symbol->value = rrs_data_start;
940
941 }
942
943 void
944 write_rrs_data()
945 {
946         long    pos;
947
948         if (rrs_section_type == RRS_NONE)
949                 return;
950
951         pos = rrs_data_start + N_TXTOFF(outheader) - text_start;
952         if (fseek(outstream, pos, SEEK_SET) != 0)
953                 err(1, "write_rrs_data: fseek");
954
955         if (rrs_section_type == RRS_PARTIAL) {
956                 /*
957                  * Only a GOT and PLT are needed.
958                  */
959                 md_swapout_got(rrs_got, number_of_gotslots);
960                 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
961
962                 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
963                 mywrite(rrs_plt, number_of_jmpslots,
964                         sizeof(jmpslot_t), outstream);
965
966                 return;
967         }
968
969         md_swapout__dynamic(&rrs_dyn);
970         mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outstream);
971
972         md_swapout_so_debug(&rrs_so_debug);
973         mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outstream);
974
975         md_swapout_section_dispatch_table(&rrs_sdt);
976         mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outstream);
977
978         md_swapout_got(rrs_got, number_of_gotslots);
979         mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
980
981         md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
982         mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outstream);
983 }
984
985 void
986 write_rrs_text()
987 {
988         long                    pos;
989         int                     i;
990         int                     symsize;
991         struct nzlist           *nlp;
992         int                     offset = 0;
993         int                     aligned_offset;
994         struct shobj            *shp;
995         struct sod              *sodp;
996         int                     bind;
997
998         if (rrs_section_type == RRS_PARTIAL)
999                 return;
1000
1001         pos = rrs_text_start + N_TXTOFF(outheader) - text_start;
1002         if (fseek(outstream, pos, SEEK_SET) != 0)
1003                 err(1, "write_rrs_text: fseek");
1004
1005         /* Write relocation records */
1006         md_swapout_reloc(rrs_reloc, reserved_rrs_relocs);
1007         mywrite(rrs_reloc, reserved_rrs_relocs,
1008                 sizeof(struct relocation_info), outstream);
1009
1010         /* Write the RRS symbol hash tables */
1011         md_swapout_rrs_hash(rrs_hashtab, number_of_rrs_hash_entries);
1012         mywrite(rrs_hashtab, number_of_rrs_hash_entries,
1013                 sizeof(struct rrs_hash), outstream);
1014
1015         /*
1016          * Determine size of an RRS symbol entry, allocate space
1017          * to collect them in.
1018          */
1019         symsize = number_of_rrs_symbols * rrs_symbol_size;
1020         nlp = rrs_symbols = (struct nzlist *)alloca(symsize);
1021         rrs_strtab = (char *)alloca(rrs_strtab_size);
1022
1023 #define INCR_NLP(p)     ((p) = (struct nzlist *)((long)(p) + rrs_symbol_size))
1024
1025         /* __DYNAMIC symbol *must* be first for Sun compatibility */
1026         nlp->nz_desc = nlp->nz_other = 0;
1027         if (LD_VERSION_NZLIST_P(soversion))
1028                 nlp->nz_size = 0;
1029         nlp->nz_type = dynamic_symbol->defined;
1030         nlp->nz_value = dynamic_symbol->value;
1031         nlp->nz_value = dynamic_symbol->value;
1032         nlp->nz_strx = offset;
1033         strcpy(rrs_strtab + offset, dynamic_symbol->name);
1034         offset += 1 + strlen(dynamic_symbol->name);
1035         INCR_NLP(nlp);
1036
1037         /*
1038          * Now, for each global symbol, construct a nzlist element
1039          * for inclusion in the RRS symbol table.
1040          */
1041         FOR_EACH_SYMBOL(i, sp) {
1042
1043                 if (sp == dynamic_symbol)
1044                         continue;
1045
1046                 if ((link_mode & SHAREABLE) && sp->warning) {
1047                         /*
1048                          * Write a N_WARNING duo.
1049                          */
1050                         nlp->nz_type = N_WARNING;
1051                         nlp->nz_un.n_strx = offset;
1052                         nlp->nz_value = 0;
1053                         nlp->nz_other = 0;
1054                         nlp->nz_desc = 0;
1055                         nlp->nz_size = 0;
1056                         strcpy(rrs_strtab + offset, sp->warning);
1057                         offset += 1 + strlen(sp->warning);
1058                         INCR_NLP(nlp);
1059
1060                         nlp->nz_type = N_UNDF + N_EXT;
1061                         nlp->nz_un.n_strx = offset;
1062                         nlp->nz_value = 0;
1063                         nlp->nz_other = 0;
1064                         nlp->nz_desc = 0;
1065                         nlp->nz_size = 0;
1066                         strcpy(rrs_strtab + offset, sp->name);
1067                         offset += 1 + strlen(sp->name);
1068                         INCR_NLP(nlp);
1069                 }
1070
1071                 if (!(sp->flags & GS_REFERENCED))
1072                         continue;
1073
1074                 if ((long)nlp - (long)rrs_symbols >=
1075                     number_of_rrs_symbols * rrs_symbol_size)
1076                         errx(1, "internal error: "
1077                                 "rrs symbols exceed allocation %d",
1078                                 number_of_rrs_symbols);
1079
1080                 nlp->nz_desc = 0;
1081                 nlp->nz_other = 0;
1082                 if (LD_VERSION_NZLIST_P(soversion))
1083                         nlp->nz_size = 0;
1084
1085                 bind = (sp->flags & GS_WEAK) ? BIND_WEAK : 0;
1086
1087                 if (sp->defined > 1) {
1088                         /* defined with known type */
1089                         if (!(link_mode & SHAREABLE) &&
1090                             sp->alias && sp->alias->defined > 1) {
1091                                 /*
1092                                  * If the target of an indirect symbol has
1093                                  * been defined and we are outputting an
1094                                  * executable, resolve the indirection; it's
1095                                  * no longer needed.
1096                                  */
1097                                 nlp->nz_type = sp->alias->defined;
1098                                 nlp->nz_value = sp->alias->value;
1099                                 nlp->nz_other = N_OTHER(bind, sp->alias->aux);
1100                         } else if (sp->defined == N_SIZE) {
1101                                 /*
1102                                  * Make sure this symbol isn't going
1103                                  * to define anything.
1104                                  */
1105                                 nlp->nz_type = N_UNDF;
1106                                 nlp->nz_value = 0;
1107                         } else {
1108                                 nlp->nz_type = sp->defined;
1109                                 nlp->nz_value = sp->value;
1110                                 nlp->nz_other = N_OTHER(bind, sp->aux);
1111                         }
1112                         if (LD_VERSION_NZLIST_P(soversion))
1113                                 nlp->nz_size = sp->size;
1114                 } else if (sp->common_size) {
1115                         /*
1116                          * A common definition.
1117                          */
1118                         nlp->nz_type = N_UNDF | N_EXT;
1119                         nlp->nz_value = sp->common_size;
1120                         nlp->nz_other = N_OTHER(bind, 0);
1121                 } else if (!sp->defined) {
1122                         /* undefined */
1123                         nlp->nz_type = N_UNDF | N_EXT;
1124                         nlp->nz_value = 0;
1125                         if (sp->so_defined && sp->jmpslot_offset != -1) {
1126                                 /*
1127                                  * A PLT entry. The auxiliary type -- which
1128                                  * must be AUX_FUNC -- is used by the run-time
1129                                  * linker to unambiguously resolve function
1130                                  * address references.
1131                                  */
1132                                 if (sp->aux != AUX_FUNC)
1133                                         errx(1, "%s: non-function jmpslot",
1134                                                 demangle(sp->name));
1135                                 nlp->nz_other = N_OTHER(bind, sp->aux);
1136                                 nlp->nz_value =
1137                                         rrs_sdt.sdt_plt + sp->jmpslot_offset;
1138                         }
1139                 } else
1140                         errx(1, "internal error: %s defined in mysterious way",
1141                              demangle(sp->name));
1142
1143                 /* Set symbol's name */
1144                 nlp->nz_strx = offset;
1145                 strcpy(rrs_strtab + offset, sp->name);
1146                 offset += 1 + strlen(sp->name);
1147
1148                 if (sp->alias) {
1149                         /*
1150                          * Write an extra symbol for indirections (possibly
1151                          * just a dummy).
1152                          */
1153                         int t = (nlp->nz_type == N_INDR + N_EXT);
1154
1155                         INCR_NLP(nlp);
1156                         nlp->nz_type = N_UNDF + (t ? N_EXT : 0);
1157                         nlp->nz_un.n_strx = offset;
1158                         nlp->nz_value = 0;
1159                         nlp->nz_other = 0;
1160                         nlp->nz_desc = 0;
1161                         nlp->nz_size = 0;
1162                         strcpy(rrs_strtab + offset, sp->alias->name);
1163                         offset += 1 + strlen(sp->alias->name);
1164                 }
1165
1166                 INCR_NLP(nlp);
1167
1168         } END_EACH_SYMBOL;
1169
1170         aligned_offset = MALIGN(offset);
1171         while (offset < aligned_offset)         /* Pad deterministically */
1172                 rrs_strtab[offset++] = '\0';
1173         if (offset != rrs_strtab_size)
1174                 errx(1, "internal error: "
1175                         "inconsistent RRS string table length: %d, expected %d",
1176                         offset, rrs_strtab_size);
1177
1178         /* Write the symbol table */
1179         if (rrs_symbol_size == sizeof(struct nlist))
1180                 md_swapout_symbols(rrs_symbols, number_of_rrs_symbols);
1181         else
1182                 md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols);
1183         mywrite(rrs_symbols, symsize, 1, outstream);
1184
1185         /* Write the strings */
1186         mywrite(rrs_strtab, rrs_strtab_size, 1, outstream);
1187
1188         /* Write RT search path */
1189         mywrite(rrs_search_paths, rrs_search_paths_size, 1, outstream);
1190
1191         /*
1192          * Write the names of the shared objects needed at run-time
1193          */
1194         pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod);
1195         sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod));
1196
1197         for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1198                 char    *name = shp->entry->local_sym_name;
1199
1200                 if (i >= number_of_shobjs)
1201                         errx(1, "internal error: # of link objects exceeds %d",
1202                                 number_of_shobjs);
1203
1204                 sodp[i].sod_name = pos;
1205                 sodp[i].sod_major = shp->entry->lib_major;
1206                 sodp[i].sod_minor = shp->entry->lib_minor;
1207
1208                 if (*name == '-' && *(name+1) == 'l') {
1209                         name += 2;
1210                         sodp[i].sod_library = 1;
1211                 } else
1212                         sodp[i].sod_library = 0;
1213                 sodp[i].sod_reserved = 0;
1214
1215                 pos += 1 + strlen(name);
1216                 sodp[i].sod_next = (i == number_of_shobjs - 1) ? 0 :
1217                         (rrs_sdt.sdt_sods + (i+1)*sizeof(struct sod));
1218         }
1219
1220         if (i < number_of_shobjs)
1221                 errx(1, "internal error: "
1222                         "# of link objects less then expected %d",
1223                         number_of_shobjs);
1224
1225         md_swapout_sod(sodp, number_of_shobjs);
1226         mywrite(sodp, number_of_shobjs, sizeof(struct sod), outstream);
1227
1228         for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1229                 char    *name = shp->entry->local_sym_name;
1230
1231                 if (*name == '-' && *(name+1) == 'l') {
1232                         name += 2;
1233                 }
1234
1235                 mywrite(name, strlen(name) + 1, 1, outstream);
1236         }
1237 }
1238
1239 void
1240 write_rrs()
1241 {
1242
1243         /*
1244          * First, do some consistency checks on the RRS segment.
1245          */
1246         if (rrs_section_type == RRS_NONE) {
1247                 if (reserved_rrs_relocs > 1)
1248                         errx(1, "internal error: "
1249                                 "RRS relocs in static program: %d",
1250                                 reserved_rrs_relocs-1);
1251                 return;
1252         }
1253
1254 #ifdef DEBUG
1255 printf("rrs_relocs: reserved %d claimed %d discarded %d, gotslots %d jmpslots %d\n",
1256         reserved_rrs_relocs, claimed_rrs_relocs, discarded_rrs_relocs,
1257         number_of_gotslots-1, number_of_jmpslots-1);
1258 #endif
1259
1260         /* Final consistency check */
1261         if (claimed_rrs_relocs  + discarded_rrs_relocs != reserved_rrs_relocs) {
1262                 errx(1, "internal error: "
1263                         "reserved relocs(%d) != claimed(%d) + discarded(%d)",
1264                         reserved_rrs_relocs,
1265                         claimed_rrs_relocs,
1266                         discarded_rrs_relocs);
1267         }
1268
1269         /* Write the RRS segments. */
1270         write_rrs_text ();
1271         write_rrs_data ();
1272 }