2 * Copyright (c) 1993 Paul Kranenburg
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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.
30 * $FreeBSD: src/gnu/usr.bin/ld/rrs.c,v 1.24 1999/08/27 23:36:01 peter Exp $
33 #include <sys/param.h>
34 #include <sys/types.h>
38 #include <sys/resource.h>
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;
67 static int reserved_rrs_relocs;
68 static int claimed_rrs_relocs;
69 static int discarded_rrs_relocs;
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;
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;
87 /* Convert a GOT offset into a table entry */
88 #define GOTP(off) ((got_t *)((long)rrs_got + got_origin + (off)))
92 struct file_entry *entry;
97 +-------------------+ <-- sdt_rel (rrs_text_start)
101 +-------------------+ <-- <sdt>.sdt_hash
105 +-------------------+ <-- <sdt>.sdt_nzlist
109 +-------------------+ <-- <sdt>.sdt_strings
113 +-------------------+ <-- <sdt>.sdt_sods
117 +-------------------+
119 | shobjs strings | <-- <shobj>.sod_name
121 +-------------------+
126 +-------------------+ <-- __DYNAMIC (rrs_data_start)
130 +-------------------+ <-- __DYNAMIC.d_debug
134 +-------------------+ <-- __DYNAMIC.d_un.d_sdt
138 +-------------------+ <-- sdt_got
140 | _GOT_ | <-- _GLOBAL_OFFSET_TABLE_
141 | | ( == sdt_got + got_origin)
143 +-------------------+ <-- sdt_plt
147 +-------------------+
151 * Add NAME to the list of needed run-time objects.
152 * Return 1 if ENTRY was added to the list.
156 struct file_entry *entry;
160 for (p = &rrs_shobjs; *p != NULL; p = &(*p)->next)
161 if (strcmp((*p)->entry->filename, entry->filename) == 0)
163 *p = (struct shobj *)xmalloc(sizeof(struct shobj));
172 alloc_rrs_reloc(entry, sp)
173 struct file_entry *entry;
177 printf("alloc_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
179 reserved_rrs_relocs++;
183 alloc_rrs_segment_reloc(entry, r)
184 struct file_entry *entry;
185 struct relocation_info *r;
188 printf("alloc_rrs_segment_reloc at %#x in %s\n",
189 r->r_address, get_file_name(entry));
191 reserved_rrs_relocs++;
195 alloc_rrs_jmpslot(entry, sp)
196 struct file_entry *entry;
199 if (sp->flags & GS_HASJMPSLOT)
202 sp->flags |= GS_HASJMPSLOT;
203 number_of_jmpslots++;
204 reserved_rrs_relocs++;
208 alloc_rrs_gotslot(entry, r, lsp)
209 struct file_entry *entry;
210 struct relocation_info *r;
211 struct localsymbol *lsp;
213 symbol *sp = lsp->symbol;
215 if (!RELOC_EXTERN_P(r)) {
218 warnx("%s: relocation for internal symbol "
220 get_file_name(entry), RELOC_ADDRESS(r));
224 if (!RELOC_STATICS_THROUGH_GOT_P(r))
225 /* No need for a GOT slot */
228 if (lsp->flags & LS_HASGOTSLOT)
231 lsp->flags |= LS_HASGOTSLOT;
236 warnx("%s: relocation must refer "
237 "to global symbol at %#x",
238 get_file_name(entry), RELOC_ADDRESS(r));
245 if (sp->flags & GS_HASGOTSLOT)
248 sp->flags |= GS_HASGOTSLOT;
251 number_of_gotslots++;
252 reserved_rrs_relocs++;
256 alloc_rrs_cpy_reloc(entry, sp)
257 struct file_entry *entry;
260 if (sp->flags & GS_CPYRELOCRESERVED)
263 printf("alloc_rrs_copy: %s in %s\n", demangle(sp->name), get_file_name(entry));
265 sp->flags |= GS_CPYRELOCRESERVED;
266 reserved_rrs_relocs++;
269 static struct relocation_info *
272 struct relocation_info *r;
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);
282 * Claim a RRS relocation as a result of a regular (ie. non-PIC)
283 * relocation record in a rel file.
285 * Return 1 if the output file needs no further updating.
286 * Return 0 if the relocation value pointed to by RELOCATION must
290 claim_rrs_reloc(entry, rp, sp, relocation)
291 struct file_entry *entry;
292 struct relocation_info *rp;
296 struct relocation_info *r = rrs_next_reloc();
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));
304 printf("claim_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
306 r->r_address = rp->r_address;
307 r->r_symbolnum = sp->rrs_symbolnum;
309 if (link_mode & SYMBOLIC) {
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);
318 RELOC_EXTERN_P(r) = 1;
319 return md_make_reloc(rp, r, RELTYPE_EXTERN);
324 * Claim a jmpslot. Setup RRS relocation if claimed for the first time.
327 claim_rrs_jmpslot(entry, rp, sp, addend)
328 struct file_entry *entry;
329 struct relocation_info *rp;
333 struct relocation_info *r;
335 if (!(sp->flags & GS_HASJMPSLOT))
336 errx(1, "internal error: "
337 "%s: claim_rrs_jmpslot: %s: no reservation",
338 get_file_name(entry),
341 if (sp->jmpslot_offset != -1)
342 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
344 sp->jmpslot_offset = current_jmpslot_offset;
345 current_jmpslot_offset += sizeof(jmpslot_t);
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);
353 if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
355 warnx("Cannot reduce symbol \"%s\" in %s",
356 demangle(sp->name), get_file_name(entry));
358 md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
359 rrs_sdt.sdt_plt + sp->jmpslot_offset,
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;
367 md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
373 * Install a run-time relocation for this PLT entry.
375 r = rrs_next_reloc();
377 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
379 r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset;
381 if (link_mode & SYMBOLIC) {
382 RELOC_EXTERN_P(r) = 0;
383 md_make_jmpreloc(rp, r, RELTYPE_RELATIVE);
385 RELOC_EXTERN_P(r) = 1;
386 md_make_jmpreloc(rp, r, 0);
389 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
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.
398 claim_rrs_gotslot(entry, rp, lsp, addend)
399 struct file_entry *entry;
400 struct relocation_info *rp;
401 struct localsymbol *lsp;
404 struct relocation_info *r;
405 symbol *sp = lsp->symbol;
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));
420 if (sp->gotslot_offset != -1) {
422 if (*GOTP(sp->gotslot_offset) != addend +
423 ((!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))
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),
429 *GOTP(sp->gotslot_offset), addend, sp->value);
431 /* This symbol already passed here before. */
432 return sp->gotslot_offset;
435 if (current_got_offset == 0)
436 /* GOT offset 0 is reserved */
437 current_got_offset += sizeof(got_t);
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));
443 sp->gotslot_offset = current_got_offset;
444 current_got_offset += sizeof(got_t);
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);
452 (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) {
455 * Reduce to just a base-relative translation.
458 *GOTP(sp->gotslot_offset) = sp->value + addend;
459 reloc_type = RELTYPE_RELATIVE;
461 } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
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.
467 warnx("Cannot reduce symbol \"%s\" in %s",
468 demangle(sp->name), get_file_name(entry));
473 * This gotslot will be updated with symbol value at run-time.
476 *GOTP(sp->gotslot_offset) = addend;
479 if (rrs_section_type == RRS_PARTIAL) {
481 * Base address is known, gotslot should be fully
483 * NOTE: RRS_PARTIAL implies !SHAREABLE.
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;
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.
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);
506 return sp->gotslot_offset;
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
516 claim_rrs_internal_gotslot(entry, rp, lsp, addend)
517 struct file_entry *entry;
518 struct relocation_info *rp;
519 struct localsymbol *lsp;
522 struct relocation_info *r;
524 addend += lsp->nzlist.nz_value;
526 if (!RELOC_STATICS_THROUGH_GOT_P(r))
527 return addend - got_symbol->value;
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));
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;
542 if (current_got_offset == 0)
543 /* GOT offset 0 is reserved */
544 current_got_offset += sizeof(got_t);
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));
550 lsp->gotslot_offset = current_got_offset;
551 current_got_offset += sizeof(got_t);
553 *GOTP(lsp->gotslot_offset) = addend;
556 printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n",
557 get_file_name(entry), lsp->gotslot_offset, addend);
560 if (rrs_section_type == RRS_PARTIAL) {
561 discarded_rrs_relocs++;
562 return lsp->gotslot_offset;
566 * Relocation entry needed for this static GOT entry.
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;
576 claim_rrs_cpy_reloc(entry, rp, sp)
577 struct file_entry *entry;
578 struct relocation_info *rp;
581 struct relocation_info *r;
583 if (sp->flags & GS_CPYRELOCCLAIMED)
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));
592 printf("claim_rrs_copy: %s: %s -> %x\n",
593 get_file_name(entry), demangle(sp->name), sp->so_defined);
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);
605 claim_rrs_segment_reloc(entry, rp)
606 struct file_entry *entry;
607 struct relocation_info *rp;
609 struct relocation_info *r = rrs_next_reloc();
612 printf("claim_rrs_segment_reloc: %s at %#x\n",
613 get_file_name(entry), rp->r_address);
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);
624 * Fill the RRS hash table for the given symbol name.
625 * NOTE: the hash value computation must match the one in rtld.
628 rrs_insert_hash(cp, index)
636 hashval = (hashval << 1) + *cp;
638 hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets;
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;
649 while (hp->rh_next != 0)
650 hp = rrs_hashtab + hp->rh_next;
652 hp->rh_next = current_hash_index++;
653 hp = rrs_hashtab + hp->rh_next;
654 hp->rh_symbolnum = index;
659 * There are two interesting cases to consider here.
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.
665 * 2) It's a genuine dynamically linked program, so the whole RRS scoop
669 consider_rrs_section_lengths()
676 /* We run into trouble with this as long as shared object symbols
677 are not checked for definitions */
679 * First, determine the real number of shared objects we need.
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;
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)) {
699 * First slots in both tables are reserved
700 * hence the "> 1" condition
702 if (number_of_gotslots > 1 || number_of_jmpslots > 1)
703 rrs_section_type = RRS_PARTIAL;
705 rrs_section_type = RRS_NONE;
707 rrs_section_type = RRS_FULL;
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");
716 rrs_symbol_size = LD_VERSION_NZLIST_P(soversion) ?
717 sizeof(struct nzlist) : sizeof(struct nlist);
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.
724 if (!(link_mode & SHAREABLE) && !(dynamic_symbol->flags & GS_REFERENCED))
725 errx(1, "No reference to __DYNAMIC");
727 dynamic_symbol->flags |= GS_REFERENCED;
729 if (number_of_gotslots > 1)
730 got_symbol->flags |= GS_REFERENCED;
733 /* Next, allocate relocs, got and plt */
734 n = reserved_rrs_relocs * sizeof(struct relocation_info);
735 rrs_reloc = (struct relocation_info *)xmalloc(n);
738 n = number_of_gotslots * sizeof(got_t);
739 rrs_got = (got_t *)xmalloc(n);
742 n = number_of_jmpslots * sizeof(jmpslot_t);
743 rrs_plt = (jmpslot_t *)xmalloc(n);
746 /* Initialize first jmpslot */
747 md_fix_jmpslot(rrs_plt, 0, 0);
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);
756 * Walk the symbol table, assign RRS symbol numbers
757 * and calculate string space.
758 * Assign number 0 to __DYNAMIC (!! Sun compatibility)
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 */
765 2 + strlen(sp->name) + strlen(sp->warning);
766 number_of_rrs_symbols += 2;
769 if (!(sp->flags & GS_REFERENCED))
772 rrs_strtab_size += 1 + strlen(sp->name);
773 if (sp != dynamic_symbol)
774 sp->rrs_symbolnum = number_of_rrs_symbols++;
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.
782 number_of_rrs_symbols++;
783 rrs_strtab_size += 1 + strlen(sp->alias->name);
788 * Now that we know how many RRS symbols there are going to be,
789 * allocate and initialize the RRS symbol hash table.
791 rrs_sdt.sdt_buckets = number_of_rrs_symbols/4;
792 if (rrs_sdt.sdt_buckets < 4)
793 rrs_sdt.sdt_buckets = 4;
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;
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.
808 FOR_EACH_SYMBOL(i ,sp) {
809 if (sp->flags & GS_REFERENCED)
810 rrs_insert_hash(sp->name, sp->rrs_symbolnum);
812 number_of_rrs_hash_entries = current_hash_index;
815 * Calculate RRS section sizes.
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);
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
830 rrs_search_paths_size = MALIGN(rrs_search_paths_size);
831 rrs_text_size += rrs_search_paths_size;
833 /* Align strings size */
834 rrs_strtab_size = MALIGN(rrs_strtab_size);
835 rrs_text_size += rrs_strtab_size;
837 /* Process needed shared objects */
838 for (shp = rrs_shobjs; shp; shp = shp->next) {
839 char *name = shp->entry->local_sym_name;
841 if (*name == '-' && *(name+1) == 'l')
844 rrs_text_size += sizeof(struct sod);
845 rrs_text_size += 1 + strlen(name);
848 /* Finally, align size */
849 rrs_text_size = MALIGN(rrs_text_size);
853 relocate_rrs_addresses()
857 dynamic_symbol->value = 0;
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'.
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);
870 if (gotsize + min_got_offset - (int)sizeof(got_t) > max_got_offset)
871 warnx("Global Offset Table overflow (use `-fPIC')");
873 if (gotsize > max_got_offset)
874 /* Position at "two-complements" origin */
875 current_got_offset += min_got_offset;
877 got_origin = -current_got_offset;
879 if (rrs_section_type == RRS_NONE)
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);
891 * RRS data relocations.
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));
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);
904 * RRS text relocations.
906 rrs_sdt.sdt_rel = rrs_text_start;
908 * Sun BUG compatibility alert.
909 * Main program's RRS text values are relative to TXTADDR? WHY??
912 if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE))
913 rrs_sdt.sdt_rel -= N_TXTADDR(outheader);
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
925 rrs_sdt.sdt_sods = rrs_shobjs
926 ? rrs_sdt.sdt_strings + rrs_strtab_size +
927 rrs_search_paths_size
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);
935 * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC.
936 * The value `&__DYNAMIC' is in the GOT table at offset 0.
938 got_symbol->value = rrs_sdt.sdt_got + got_origin;
939 *GOTP(0) = dynamic_symbol->value = rrs_data_start;
948 if (rrs_section_type == RRS_NONE)
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");
955 if (rrs_section_type == RRS_PARTIAL) {
957 * Only a GOT and PLT are needed.
959 md_swapout_got(rrs_got, number_of_gotslots);
960 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
962 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
963 mywrite(rrs_plt, number_of_jmpslots,
964 sizeof(jmpslot_t), outstream);
969 md_swapout__dynamic(&rrs_dyn);
970 mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outstream);
972 md_swapout_so_debug(&rrs_so_debug);
973 mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outstream);
975 md_swapout_section_dispatch_table(&rrs_sdt);
976 mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outstream);
978 md_swapout_got(rrs_got, number_of_gotslots);
979 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
981 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
982 mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outstream);
998 if (rrs_section_type == RRS_PARTIAL)
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");
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);
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);
1016 * Determine size of an RRS symbol entry, allocate space
1017 * to collect them in.
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);
1023 #define INCR_NLP(p) ((p) = (struct nzlist *)((long)(p) + rrs_symbol_size))
1025 /* __DYNAMIC symbol *must* be first for Sun compatibility */
1026 nlp->nz_desc = nlp->nz_other = 0;
1027 if (LD_VERSION_NZLIST_P(soversion))
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);
1038 * Now, for each global symbol, construct a nzlist element
1039 * for inclusion in the RRS symbol table.
1041 FOR_EACH_SYMBOL(i, sp) {
1043 if (sp == dynamic_symbol)
1046 if ((link_mode & SHAREABLE) && sp->warning) {
1048 * Write a N_WARNING duo.
1050 nlp->nz_type = N_WARNING;
1051 nlp->nz_un.n_strx = offset;
1056 strcpy(rrs_strtab + offset, sp->warning);
1057 offset += 1 + strlen(sp->warning);
1060 nlp->nz_type = N_UNDF + N_EXT;
1061 nlp->nz_un.n_strx = offset;
1066 strcpy(rrs_strtab + offset, sp->name);
1067 offset += 1 + strlen(sp->name);
1071 if (!(sp->flags & GS_REFERENCED))
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);
1082 if (LD_VERSION_NZLIST_P(soversion))
1085 bind = (sp->flags & GS_WEAK) ? BIND_WEAK : 0;
1087 if (sp->defined > 1) {
1088 /* defined with known type */
1089 if (!(link_mode & SHAREABLE) &&
1090 sp->alias && sp->alias->defined > 1) {
1092 * If the target of an indirect symbol has
1093 * been defined and we are outputting an
1094 * executable, resolve the indirection; it's
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) {
1102 * Make sure this symbol isn't going
1103 * to define anything.
1105 nlp->nz_type = N_UNDF;
1108 nlp->nz_type = sp->defined;
1109 nlp->nz_value = sp->value;
1110 nlp->nz_other = N_OTHER(bind, sp->aux);
1112 if (LD_VERSION_NZLIST_P(soversion))
1113 nlp->nz_size = sp->size;
1114 } else if (sp->common_size) {
1116 * A common definition.
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) {
1123 nlp->nz_type = N_UNDF | N_EXT;
1125 if (sp->so_defined && sp->jmpslot_offset != -1) {
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.
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);
1137 rrs_sdt.sdt_plt + sp->jmpslot_offset;
1140 errx(1, "internal error: %s defined in mysterious way",
1141 demangle(sp->name));
1143 /* Set symbol's name */
1144 nlp->nz_strx = offset;
1145 strcpy(rrs_strtab + offset, sp->name);
1146 offset += 1 + strlen(sp->name);
1150 * Write an extra symbol for indirections (possibly
1153 int t = (nlp->nz_type == N_INDR + N_EXT);
1156 nlp->nz_type = N_UNDF + (t ? N_EXT : 0);
1157 nlp->nz_un.n_strx = offset;
1162 strcpy(rrs_strtab + offset, sp->alias->name);
1163 offset += 1 + strlen(sp->alias->name);
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);
1178 /* Write the symbol table */
1179 if (rrs_symbol_size == sizeof(struct nlist))
1180 md_swapout_symbols(rrs_symbols, number_of_rrs_symbols);
1182 md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols);
1183 mywrite(rrs_symbols, symsize, 1, outstream);
1185 /* Write the strings */
1186 mywrite(rrs_strtab, rrs_strtab_size, 1, outstream);
1188 /* Write RT search path */
1189 mywrite(rrs_search_paths, rrs_search_paths_size, 1, outstream);
1192 * Write the names of the shared objects needed at run-time
1194 pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod);
1195 sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod));
1197 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1198 char *name = shp->entry->local_sym_name;
1200 if (i >= number_of_shobjs)
1201 errx(1, "internal error: # of link objects exceeds %d",
1204 sodp[i].sod_name = pos;
1205 sodp[i].sod_major = shp->entry->lib_major;
1206 sodp[i].sod_minor = shp->entry->lib_minor;
1208 if (*name == '-' && *(name+1) == 'l') {
1210 sodp[i].sod_library = 1;
1212 sodp[i].sod_library = 0;
1213 sodp[i].sod_reserved = 0;
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));
1220 if (i < number_of_shobjs)
1221 errx(1, "internal error: "
1222 "# of link objects less then expected %d",
1225 md_swapout_sod(sodp, number_of_shobjs);
1226 mywrite(sodp, number_of_shobjs, sizeof(struct sod), outstream);
1228 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1229 char *name = shp->entry->local_sym_name;
1231 if (*name == '-' && *(name+1) == 'l') {
1235 mywrite(name, strlen(name) + 1, 1, outstream);
1244 * First, do some consistency checks on the RRS segment.
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);
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);
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,
1266 discarded_rrs_relocs);
1269 /* Write the RRS segments. */