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 $
31 * $DragonFly: src/gnu/usr.bin/ld/Attic/rrs.c,v 1.2 2003/06/17 04:25:46 dillon Exp $
34 #include <sys/param.h>
35 #include <sys/types.h>
39 #include <sys/resource.h>
55 static struct _dynamic rrs_dyn; /* defined in link.h */
56 static struct so_debug rrs_so_debug; /* defined in link.h */
57 static struct section_dispatch_table rrs_sdt; /* defined in link.h */
58 static got_t *rrs_got;
59 static jmpslot_t *rrs_plt; /* defined in md.h */
60 static struct relocation_info *rrs_reloc;
61 static struct nzlist *rrs_symbols; /* RRS symbol table */
62 static char *rrs_strtab; /* RRS strings */
63 static struct rrs_hash *rrs_hashtab; /* RT hash table */
64 static struct shobj *rrs_shobjs;
65 char *rrs_search_paths; /* `-L' RT search */
66 static int rrs_search_paths_size;
68 static int reserved_rrs_relocs;
69 static int claimed_rrs_relocs;
70 static int discarded_rrs_relocs;
72 static int number_of_gotslots = 1;
73 static int number_of_jmpslots = 1;
74 static int number_of_rrs_hash_entries;
75 static int number_of_rrs_symbols;
76 static int rrs_strtab_size;
77 static int rrs_symbol_size;
79 static int current_jmpslot_offset;
80 static int current_got_offset;
81 static int max_got_offset;
82 static int min_got_offset;
83 static int got_origin;
84 static int current_reloc_offset;
85 static int current_hash_index;
88 /* Convert a GOT offset into a table entry */
89 #define GOTP(off) ((got_t *)((long)rrs_got + got_origin + (off)))
93 struct file_entry *entry;
98 +-------------------+ <-- sdt_rel (rrs_text_start)
102 +-------------------+ <-- <sdt>.sdt_hash
106 +-------------------+ <-- <sdt>.sdt_nzlist
110 +-------------------+ <-- <sdt>.sdt_strings
114 +-------------------+ <-- <sdt>.sdt_sods
118 +-------------------+
120 | shobjs strings | <-- <shobj>.sod_name
122 +-------------------+
127 +-------------------+ <-- __DYNAMIC (rrs_data_start)
131 +-------------------+ <-- __DYNAMIC.d_debug
135 +-------------------+ <-- __DYNAMIC.d_un.d_sdt
139 +-------------------+ <-- sdt_got
141 | _GOT_ | <-- _GLOBAL_OFFSET_TABLE_
142 | | ( == sdt_got + got_origin)
144 +-------------------+ <-- sdt_plt
148 +-------------------+
152 * Add NAME to the list of needed run-time objects.
153 * Return 1 if ENTRY was added to the list.
157 struct file_entry *entry;
161 for (p = &rrs_shobjs; *p != NULL; p = &(*p)->next)
162 if (strcmp((*p)->entry->filename, entry->filename) == 0)
164 *p = (struct shobj *)xmalloc(sizeof(struct shobj));
173 alloc_rrs_reloc(entry, sp)
174 struct file_entry *entry;
178 printf("alloc_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
180 reserved_rrs_relocs++;
184 alloc_rrs_segment_reloc(entry, r)
185 struct file_entry *entry;
186 struct relocation_info *r;
189 printf("alloc_rrs_segment_reloc at %#x in %s\n",
190 r->r_address, get_file_name(entry));
192 reserved_rrs_relocs++;
196 alloc_rrs_jmpslot(entry, sp)
197 struct file_entry *entry;
200 if (sp->flags & GS_HASJMPSLOT)
203 sp->flags |= GS_HASJMPSLOT;
204 number_of_jmpslots++;
205 reserved_rrs_relocs++;
209 alloc_rrs_gotslot(entry, r, lsp)
210 struct file_entry *entry;
211 struct relocation_info *r;
212 struct localsymbol *lsp;
214 symbol *sp = lsp->symbol;
216 if (!RELOC_EXTERN_P(r)) {
219 warnx("%s: relocation for internal symbol "
221 get_file_name(entry), RELOC_ADDRESS(r));
225 if (!RELOC_STATICS_THROUGH_GOT_P(r))
226 /* No need for a GOT slot */
229 if (lsp->flags & LS_HASGOTSLOT)
232 lsp->flags |= LS_HASGOTSLOT;
237 warnx("%s: relocation must refer "
238 "to global symbol at %#x",
239 get_file_name(entry), RELOC_ADDRESS(r));
246 if (sp->flags & GS_HASGOTSLOT)
249 sp->flags |= GS_HASGOTSLOT;
252 number_of_gotslots++;
253 reserved_rrs_relocs++;
257 alloc_rrs_cpy_reloc(entry, sp)
258 struct file_entry *entry;
261 if (sp->flags & GS_CPYRELOCRESERVED)
264 printf("alloc_rrs_copy: %s in %s\n", demangle(sp->name), get_file_name(entry));
266 sp->flags |= GS_CPYRELOCRESERVED;
267 reserved_rrs_relocs++;
270 static struct relocation_info *
273 struct relocation_info *r;
275 r = rrs_reloc + claimed_rrs_relocs++;
276 if (claimed_rrs_relocs > reserved_rrs_relocs)
277 errx(1, "internal error: RRS relocs exceed allocation %d",
278 reserved_rrs_relocs);
283 * Claim a RRS relocation as a result of a regular (ie. non-PIC)
284 * relocation record in a rel file.
286 * Return 1 if the output file needs no further updating.
287 * Return 0 if the relocation value pointed to by RELOCATION must
291 claim_rrs_reloc(entry, rp, sp, relocation)
292 struct file_entry *entry;
293 struct relocation_info *rp;
297 struct relocation_info *r = rrs_next_reloc();
299 if (rp->r_address < text_start + text_size
300 && (link_mode & WARNRRSTEXT))
301 warnx("%s: RRS text relocation at %#x for \"%s\"",
302 get_file_name(entry), rp->r_address, demangle(sp->name));
305 printf("claim_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
307 r->r_address = rp->r_address;
308 r->r_symbolnum = sp->rrs_symbolnum;
310 if (link_mode & SYMBOLIC) {
312 warnx("Cannot reduce symbol \"%s\" in %s",
313 demangle(sp->name), get_file_name(entry));
314 RELOC_EXTERN_P(r) = 0;
315 *relocation += sp->value;
316 (void) md_make_reloc(rp, r, RELTYPE_RELATIVE);
319 RELOC_EXTERN_P(r) = 1;
320 return md_make_reloc(rp, r, RELTYPE_EXTERN);
325 * Claim a jmpslot. Setup RRS relocation if claimed for the first time.
328 claim_rrs_jmpslot(entry, rp, sp, addend)
329 struct file_entry *entry;
330 struct relocation_info *rp;
334 struct relocation_info *r;
336 if (!(sp->flags & GS_HASJMPSLOT))
337 errx(1, "internal error: "
338 "%s: claim_rrs_jmpslot: %s: no reservation",
339 get_file_name(entry),
342 if (sp->jmpslot_offset != -1)
343 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
345 sp->jmpslot_offset = current_jmpslot_offset;
346 current_jmpslot_offset += sizeof(jmpslot_t);
349 printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n",
350 get_file_name(entry),
351 demangle(sp->name), sp->rrs_symbolnum, sp->jmpslot_offset);
354 if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
356 warnx("Cannot reduce symbol \"%s\" in %s",
357 demangle(sp->name), get_file_name(entry));
359 md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
360 rrs_sdt.sdt_plt + sp->jmpslot_offset,
362 if (rrs_section_type == RRS_PARTIAL || !JMPSLOT_NEEDS_RELOC) {
363 /* PLT is self-contained */
364 discarded_rrs_relocs++;
365 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
368 md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
374 * Install a run-time relocation for this PLT entry.
376 r = rrs_next_reloc();
378 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
380 r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset;
382 if (link_mode & SYMBOLIC) {
383 RELOC_EXTERN_P(r) = 0;
384 md_make_jmpreloc(rp, r, RELTYPE_RELATIVE);
386 RELOC_EXTERN_P(r) = 1;
387 md_make_jmpreloc(rp, r, 0);
390 return rrs_sdt.sdt_plt + sp->jmpslot_offset;
394 * Claim GOT entry for a global symbol. If this is the first relocation
395 * claiming the entry, setup a RRS relocation for it.
396 * Return offset into the GOT allocated to this symbol.
399 claim_rrs_gotslot(entry, rp, lsp, addend)
400 struct file_entry *entry;
401 struct relocation_info *rp;
402 struct localsymbol *lsp;
405 struct relocation_info *r;
406 symbol *sp = lsp->symbol;
416 if (!(sp->flags & GS_HASGOTSLOT))
417 errx(1, "internal error: "
418 "%s: claim_rrs_gotslot: %s: no reservation",
419 get_file_name(entry), demangle(sp->name));
421 if (sp->gotslot_offset != -1) {
423 if (*GOTP(sp->gotslot_offset) != addend +
424 ((!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))
426 errx(1, "%s: %s: gotslot at %#x is multiple valued, "
427 "*got = %#x, addend = %#x, sp->value = %#x",
428 get_file_name(entry), demangle(sp->name),
430 *GOTP(sp->gotslot_offset), addend, sp->value);
432 /* This symbol already passed here before. */
433 return sp->gotslot_offset;
436 if (current_got_offset == 0)
437 /* GOT offset 0 is reserved */
438 current_got_offset += sizeof(got_t);
440 if (current_got_offset > max_got_offset)
441 errx(1, "%s: GOT overflow on symbol `%s' at %#x",
442 get_file_name(entry), demangle(sp->name), RELOC_ADDRESS(rp));
444 sp->gotslot_offset = current_got_offset;
445 current_got_offset += sizeof(got_t);
448 printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n",
449 demangle(sp->name), sp->rrs_symbolnum, sp->value, sp->gotslot_offset, addend);
453 (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) {
456 * Reduce to just a base-relative translation.
459 *GOTP(sp->gotslot_offset) = sp->value + addend;
460 reloc_type = RELTYPE_RELATIVE;
462 } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
464 * SYMBOLIC: all symbols must be known.
465 * RRS_PARTIAL: we don't link against shared objects,
466 * so again all symbols must be known.
468 warnx("Cannot reduce symbol \"%s\" in %s",
469 demangle(sp->name), get_file_name(entry));
474 * This gotslot will be updated with symbol value at run-time.
477 *GOTP(sp->gotslot_offset) = addend;
480 if (rrs_section_type == RRS_PARTIAL) {
482 * Base address is known, gotslot should be fully
484 * NOTE: RRS_PARTIAL implies !SHAREABLE.
487 warnx("Cannot reduce symbol \"%s\" in %s",
488 demangle(sp->name), get_file_name(entry));
489 discarded_rrs_relocs++;
490 return sp->gotslot_offset;
494 * Claim a relocation entry.
495 * If symbol is defined and in "main" (!SHAREABLE)
496 * we still put out a relocation as we cannot easily
497 * undo the allocation.
498 * `RELTYPE_RELATIVE' relocations have the external bit off
499 * as no symbol need be looked up at run-time.
501 r = rrs_next_reloc();
502 r->r_address = got_symbol->value + sp->gotslot_offset;
503 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
504 RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE);
505 md_make_gotreloc(rp, r, reloc_type);
507 return sp->gotslot_offset;
511 * Claim a GOT entry for a static symbol. Return offset of the
512 * allocated GOT entry. If RELOC_STATICS_THROUGH_GOT_P is in effect,
513 * return the offset of the symbol with respect to the *location* of
517 claim_rrs_internal_gotslot(entry, rp, lsp, addend)
518 struct file_entry *entry;
519 struct relocation_info *rp;
520 struct localsymbol *lsp;
523 struct relocation_info *r;
525 addend += lsp->nzlist.nz_value;
527 if (!RELOC_STATICS_THROUGH_GOT_P(r))
528 return addend - got_symbol->value;
530 if (!(lsp->flags & LS_HASGOTSLOT))
531 errx(1, "internal error: "
532 "%s: claim_rrs_internal_gotslot at %#x: no reservation",
533 get_file_name(entry), RELOC_ADDRESS(rp));
535 if (lsp->gotslot_offset != -1) {
536 /* Already claimed */
537 if (*GOTP(lsp->gotslot_offset) != addend)
538 errx(1, "%s: gotslot at %#lx is multiple valued",
539 get_file_name(entry), lsp->gotslot_offset);
540 return lsp->gotslot_offset;
543 if (current_got_offset == 0)
544 /* GOT offset 0 is reserved */
545 current_got_offset += sizeof(got_t);
547 if (current_got_offset > max_got_offset)
548 errx(1, "%s: GOT overflow for relocation at %#x",
549 get_file_name(entry), RELOC_ADDRESS(rp));
551 lsp->gotslot_offset = current_got_offset;
552 current_got_offset += sizeof(got_t);
554 *GOTP(lsp->gotslot_offset) = addend;
557 printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n",
558 get_file_name(entry), lsp->gotslot_offset, addend);
561 if (rrs_section_type == RRS_PARTIAL) {
562 discarded_rrs_relocs++;
563 return lsp->gotslot_offset;
567 * Relocation entry needed for this static GOT entry.
569 r = rrs_next_reloc();
570 r->r_address = got_symbol->value + lsp->gotslot_offset;
571 RELOC_EXTERN_P(r) = 0;
572 md_make_gotreloc(rp, r, RELTYPE_RELATIVE);
573 return lsp->gotslot_offset;
577 claim_rrs_cpy_reloc(entry, rp, sp)
578 struct file_entry *entry;
579 struct relocation_info *rp;
582 struct relocation_info *r;
584 if (sp->flags & GS_CPYRELOCCLAIMED)
587 if (!(sp->flags & GS_CPYRELOCRESERVED))
588 errx(1, "internal error: "
589 "%s: claim_cpy_reloc: %s: no reservation",
590 get_file_name(entry), demangle(sp->name));
593 printf("claim_rrs_copy: %s: %s -> %x\n",
594 get_file_name(entry), demangle(sp->name), sp->so_defined);
597 r = rrs_next_reloc();
598 sp->flags |= GS_CPYRELOCCLAIMED;
599 r->r_address = rp->r_address;
600 RELOC_SYMBOL(r) = sp->rrs_symbolnum;
601 RELOC_EXTERN_P(r) = RELOC_EXTERN_P(rp);
602 md_make_cpyreloc(rp, r);
606 claim_rrs_segment_reloc(entry, rp)
607 struct file_entry *entry;
608 struct relocation_info *rp;
610 struct relocation_info *r = rrs_next_reloc();
613 printf("claim_rrs_segment_reloc: %s at %#x\n",
614 get_file_name(entry), rp->r_address);
617 r->r_address = rp->r_address;
618 RELOC_TYPE(r) = RELOC_TYPE(rp);
619 RELOC_EXTERN_P(r) = 0;
620 md_make_reloc(rp, r, RELTYPE_RELATIVE);
625 * Fill the RRS hash table for the given symbol name.
626 * NOTE: the hash value computation must match the one in rtld.
629 rrs_insert_hash(cp, index)
637 hashval = (hashval << 1) + *cp;
639 hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets;
641 /* Get to the bucket */
642 hp = rrs_hashtab + hashval;
643 if (hp->rh_symbolnum == -1) {
644 /* Empty bucket, use it */
645 hp->rh_symbolnum = index;
650 while (hp->rh_next != 0)
651 hp = rrs_hashtab + hp->rh_next;
653 hp->rh_next = current_hash_index++;
654 hp = rrs_hashtab + hp->rh_next;
655 hp->rh_symbolnum = index;
660 * There are two interesting cases to consider here.
662 * 1) No shared objects were loaded, but there were PIC input rel files.
663 * In this case we must output a _GLOBAL_OFFSET_TABLE_ but no other
664 * RRS data. Also, the entries in the GOT must be fully resolved.
666 * 2) It's a genuine dynamically linked program, so the whole RRS scoop
670 consider_rrs_section_lengths()
677 /* We run into trouble with this as long as shared object symbols
678 are not checked for definitions */
680 * First, determine the real number of shared objects we need.
682 for (shpp = &rrs_shobjs; *shpp; shpp = &(*shpp)->next) {
683 while (*shpp && !((*shpp)->entry->flags & E_SYMBOLS_USED)) {
684 if (--number_of_shobjs < 0)
685 errx(1, "internal error: number_of_shobjs < 0");
686 *shpp = (*shpp)->next;
693 /* First, determine what of the RRS we want */
694 if (relocatable_output)
695 rrs_section_type = RRS_NONE;
696 else if (link_mode & SHAREABLE)
697 rrs_section_type = RRS_FULL;
698 else if (number_of_shobjs == 0 && !(link_mode & FORCEDYNAMIC)) {
700 * First slots in both tables are reserved
701 * hence the "> 1" condition
703 if (number_of_gotslots > 1 || number_of_jmpslots > 1)
704 rrs_section_type = RRS_PARTIAL;
706 rrs_section_type = RRS_NONE;
708 rrs_section_type = RRS_FULL;
710 if (rrs_section_type == RRS_NONE) {
711 got_symbol->defined = 0;
712 if (reserved_rrs_relocs > 0)
713 errx(1, "internal error: empty RRS has reservations");
717 rrs_symbol_size = LD_VERSION_NZLIST_P(soversion) ?
718 sizeof(struct nzlist) : sizeof(struct nlist);
721 * If there is an entry point, __DYNAMIC must be referenced (usually
722 * from crt0), as this is the method used to determine whether the
723 * run-time linker must be called.
725 if (!(link_mode & SHAREABLE) && !(dynamic_symbol->flags & GS_REFERENCED))
726 errx(1, "No reference to __DYNAMIC");
728 dynamic_symbol->flags |= GS_REFERENCED;
730 if (number_of_gotslots > 1)
731 got_symbol->flags |= GS_REFERENCED;
734 /* Next, allocate relocs, got and plt */
735 n = reserved_rrs_relocs * sizeof(struct relocation_info);
736 rrs_reloc = (struct relocation_info *)xmalloc(n);
739 n = number_of_gotslots * sizeof(got_t);
740 rrs_got = (got_t *)xmalloc(n);
743 n = number_of_jmpslots * sizeof(jmpslot_t);
744 rrs_plt = (jmpslot_t *)xmalloc(n);
747 /* Initialize first jmpslot */
748 md_fix_jmpslot(rrs_plt, 0, 0);
750 if (rrs_section_type == RRS_PARTIAL) {
751 rrs_data_size = number_of_gotslots * sizeof(got_t);
752 rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
757 * Walk the symbol table, assign RRS symbol numbers
758 * and calculate string space.
759 * Assign number 0 to __DYNAMIC (!! Sun compatibility)
761 dynamic_symbol->rrs_symbolnum = number_of_rrs_symbols++;
762 FOR_EACH_SYMBOL(i ,sp) {
763 if ((link_mode & SHAREABLE) && sp->warning) {
764 /* Allocate N_WARNING & co */
766 2 + strlen(sp->name) + strlen(sp->warning);
767 number_of_rrs_symbols += 2;
770 if (!(sp->flags & GS_REFERENCED))
773 rrs_strtab_size += 1 + strlen(sp->name);
774 if (sp != dynamic_symbol)
775 sp->rrs_symbolnum = number_of_rrs_symbols++;
778 * (sigh) Always allocate space to hold the
779 * indirection. At this point there's not
780 * enough information to decide whether it's
781 * actually needed or not.
783 number_of_rrs_symbols++;
784 rrs_strtab_size += 1 + strlen(sp->alias->name);
789 * Now that we know how many RRS symbols there are going to be,
790 * allocate and initialize the RRS symbol hash table.
792 rrs_sdt.sdt_buckets = number_of_rrs_symbols/4;
793 if (rrs_sdt.sdt_buckets < 4)
794 rrs_sdt.sdt_buckets = 4;
796 number_of_rrs_hash_entries = rrs_sdt.sdt_buckets +
797 number_of_rrs_symbols;
798 rrs_hashtab = (struct rrs_hash *)xmalloc(
799 number_of_rrs_hash_entries * sizeof(struct rrs_hash));
800 for (n = 0; n < rrs_sdt.sdt_buckets; n++)
801 rrs_hashtab[n].rh_symbolnum = -1;
802 current_hash_index = rrs_sdt.sdt_buckets;
805 * Get symbols into hash table now, so we can fine tune the size
806 * of the latter. We adjust the value of `number_of_rrs_hash_entries'
807 * to the number of hash link slots actually used.
809 FOR_EACH_SYMBOL(i ,sp) {
810 if (sp->flags & GS_REFERENCED)
811 rrs_insert_hash(sp->name, sp->rrs_symbolnum);
813 number_of_rrs_hash_entries = current_hash_index;
816 * Calculate RRS section sizes.
818 rrs_data_size = sizeof(struct _dynamic);
819 rrs_data_size += sizeof(struct so_debug);
820 rrs_data_size += sizeof(struct section_dispatch_table);
821 rrs_data_size += number_of_gotslots * sizeof(got_t);
822 rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
823 rrs_data_size = MALIGN(rrs_data_size);
825 rrs_text_size = reserved_rrs_relocs * sizeof(struct relocation_info);
826 rrs_text_size += number_of_rrs_hash_entries * sizeof(struct rrs_hash);
827 rrs_text_size += number_of_rrs_symbols * rrs_symbol_size;
828 rrs_search_paths_size = rrs_search_paths
829 ? strlen(rrs_search_paths) + 1
831 rrs_search_paths_size = MALIGN(rrs_search_paths_size);
832 rrs_text_size += rrs_search_paths_size;
834 /* Align strings size */
835 rrs_strtab_size = MALIGN(rrs_strtab_size);
836 rrs_text_size += rrs_strtab_size;
838 /* Process needed shared objects */
839 for (shp = rrs_shobjs; shp; shp = shp->next) {
840 char *name = shp->entry->local_sym_name;
842 if (*name == '-' && *(name+1) == 'l')
845 rrs_text_size += sizeof(struct sod);
846 rrs_text_size += 1 + strlen(name);
849 /* Finally, align size */
850 rrs_text_size = MALIGN(rrs_text_size);
854 relocate_rrs_addresses()
858 dynamic_symbol->value = 0;
861 * Get ready to allocate linkage table offsets.
862 * First jmpslot is reserved for the run-time binder
863 * GOT entry at offset 0 is reserved for `__DYNAMIC'.
865 current_jmpslot_offset = sizeof(jmpslot_t);
866 current_got_offset = 0;
867 max_got_offset = MAX_GOTOFF(pic_type);
868 min_got_offset = MIN_GOTOFF(pic_type);
869 gotsize = number_of_gotslots * sizeof(got_t);
871 if (gotsize + min_got_offset - (int)sizeof(got_t) > max_got_offset)
872 warnx("Global Offset Table overflow (use `-fPIC')");
874 if (gotsize > max_got_offset)
875 /* Position at "two-complements" origin */
876 current_got_offset += min_got_offset;
878 got_origin = -current_got_offset;
880 if (rrs_section_type == RRS_NONE)
883 if (rrs_section_type == RRS_PARTIAL) {
884 rrs_sdt.sdt_got = rrs_data_start;
885 got_symbol->value = rrs_sdt.sdt_got + got_origin;
886 rrs_sdt.sdt_plt = rrs_sdt.sdt_got +
887 number_of_gotslots * sizeof(got_t);
892 * RRS data relocations.
894 rrs_dyn.d_version = soversion;
895 rrs_dyn.d_debug = (struct so_debug *)
896 (rrs_data_start + sizeof(struct _dynamic));
897 rrs_dyn.d_un.d_sdt = (struct section_dispatch_table *)
898 ((long)rrs_dyn.d_debug + sizeof(struct so_debug));
900 rrs_sdt.sdt_got = (long)rrs_dyn.d_un.d_sdt +
901 sizeof(struct section_dispatch_table);
902 rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots*sizeof(got_t);
905 * RRS text relocations.
907 rrs_sdt.sdt_rel = rrs_text_start;
909 * Sun BUG compatibility alert.
910 * Main program's RRS text values are relative to TXTADDR? WHY??
913 if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE))
914 rrs_sdt.sdt_rel -= N_TXTADDR(outheader);
917 rrs_sdt.sdt_hash = rrs_sdt.sdt_rel +
918 reserved_rrs_relocs * sizeof(struct relocation_info);
919 rrs_sdt.sdt_nzlist = rrs_sdt.sdt_hash +
920 number_of_rrs_hash_entries * sizeof(struct rrs_hash);
921 rrs_sdt.sdt_strings = rrs_sdt.sdt_nzlist +
922 number_of_rrs_symbols * rrs_symbol_size;
923 rrs_sdt.sdt_paths = rrs_search_paths
924 ? rrs_sdt.sdt_strings + rrs_strtab_size
926 rrs_sdt.sdt_sods = rrs_shobjs
927 ? rrs_sdt.sdt_strings + rrs_strtab_size +
928 rrs_search_paths_size
930 rrs_sdt.sdt_filler2 = 0;
931 rrs_sdt.sdt_str_sz = rrs_strtab_size;
932 rrs_sdt.sdt_text_sz = text_size;
933 rrs_sdt.sdt_plt_sz = number_of_jmpslots * sizeof(jmpslot_t);
936 * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC.
937 * The value `&__DYNAMIC' is in the GOT table at offset 0.
939 got_symbol->value = rrs_sdt.sdt_got + got_origin;
940 *GOTP(0) = dynamic_symbol->value = rrs_data_start;
949 if (rrs_section_type == RRS_NONE)
952 pos = rrs_data_start + N_TXTOFF(outheader) - text_start;
953 if (fseek(outstream, pos, SEEK_SET) != 0)
954 err(1, "write_rrs_data: fseek");
956 if (rrs_section_type == RRS_PARTIAL) {
958 * Only a GOT and PLT are needed.
960 md_swapout_got(rrs_got, number_of_gotslots);
961 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
963 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
964 mywrite(rrs_plt, number_of_jmpslots,
965 sizeof(jmpslot_t), outstream);
970 md_swapout__dynamic(&rrs_dyn);
971 mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outstream);
973 md_swapout_so_debug(&rrs_so_debug);
974 mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outstream);
976 md_swapout_section_dispatch_table(&rrs_sdt);
977 mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outstream);
979 md_swapout_got(rrs_got, number_of_gotslots);
980 mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
982 md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
983 mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outstream);
999 if (rrs_section_type == RRS_PARTIAL)
1002 pos = rrs_text_start + N_TXTOFF(outheader) - text_start;
1003 if (fseek(outstream, pos, SEEK_SET) != 0)
1004 err(1, "write_rrs_text: fseek");
1006 /* Write relocation records */
1007 md_swapout_reloc(rrs_reloc, reserved_rrs_relocs);
1008 mywrite(rrs_reloc, reserved_rrs_relocs,
1009 sizeof(struct relocation_info), outstream);
1011 /* Write the RRS symbol hash tables */
1012 md_swapout_rrs_hash(rrs_hashtab, number_of_rrs_hash_entries);
1013 mywrite(rrs_hashtab, number_of_rrs_hash_entries,
1014 sizeof(struct rrs_hash), outstream);
1017 * Determine size of an RRS symbol entry, allocate space
1018 * to collect them in.
1020 symsize = number_of_rrs_symbols * rrs_symbol_size;
1021 nlp = rrs_symbols = (struct nzlist *)alloca(symsize);
1022 rrs_strtab = (char *)alloca(rrs_strtab_size);
1024 #define INCR_NLP(p) ((p) = (struct nzlist *)((long)(p) + rrs_symbol_size))
1026 /* __DYNAMIC symbol *must* be first for Sun compatibility */
1027 nlp->nz_desc = nlp->nz_other = 0;
1028 if (LD_VERSION_NZLIST_P(soversion))
1030 nlp->nz_type = dynamic_symbol->defined;
1031 nlp->nz_value = dynamic_symbol->value;
1032 nlp->nz_value = dynamic_symbol->value;
1033 nlp->nz_strx = offset;
1034 strcpy(rrs_strtab + offset, dynamic_symbol->name);
1035 offset += 1 + strlen(dynamic_symbol->name);
1039 * Now, for each global symbol, construct a nzlist element
1040 * for inclusion in the RRS symbol table.
1042 FOR_EACH_SYMBOL(i, sp) {
1044 if (sp == dynamic_symbol)
1047 if ((link_mode & SHAREABLE) && sp->warning) {
1049 * Write a N_WARNING duo.
1051 nlp->nz_type = N_WARNING;
1052 nlp->nz_un.n_strx = offset;
1057 strcpy(rrs_strtab + offset, sp->warning);
1058 offset += 1 + strlen(sp->warning);
1061 nlp->nz_type = N_UNDF + N_EXT;
1062 nlp->nz_un.n_strx = offset;
1067 strcpy(rrs_strtab + offset, sp->name);
1068 offset += 1 + strlen(sp->name);
1072 if (!(sp->flags & GS_REFERENCED))
1075 if ((long)nlp - (long)rrs_symbols >=
1076 number_of_rrs_symbols * rrs_symbol_size)
1077 errx(1, "internal error: "
1078 "rrs symbols exceed allocation %d",
1079 number_of_rrs_symbols);
1083 if (LD_VERSION_NZLIST_P(soversion))
1086 bind = (sp->flags & GS_WEAK) ? BIND_WEAK : 0;
1088 if (sp->defined > 1) {
1089 /* defined with known type */
1090 if (!(link_mode & SHAREABLE) &&
1091 sp->alias && sp->alias->defined > 1) {
1093 * If the target of an indirect symbol has
1094 * been defined and we are outputting an
1095 * executable, resolve the indirection; it's
1098 nlp->nz_type = sp->alias->defined;
1099 nlp->nz_value = sp->alias->value;
1100 nlp->nz_other = N_OTHER(bind, sp->alias->aux);
1101 } else if (sp->defined == N_SIZE) {
1103 * Make sure this symbol isn't going
1104 * to define anything.
1106 nlp->nz_type = N_UNDF;
1109 nlp->nz_type = sp->defined;
1110 nlp->nz_value = sp->value;
1111 nlp->nz_other = N_OTHER(bind, sp->aux);
1113 if (LD_VERSION_NZLIST_P(soversion))
1114 nlp->nz_size = sp->size;
1115 } else if (sp->common_size) {
1117 * A common definition.
1119 nlp->nz_type = N_UNDF | N_EXT;
1120 nlp->nz_value = sp->common_size;
1121 nlp->nz_other = N_OTHER(bind, 0);
1122 } else if (!sp->defined) {
1124 nlp->nz_type = N_UNDF | N_EXT;
1126 if (sp->so_defined && sp->jmpslot_offset != -1) {
1128 * A PLT entry. The auxiliary type -- which
1129 * must be AUX_FUNC -- is used by the run-time
1130 * linker to unambiguously resolve function
1131 * address references.
1133 if (sp->aux != AUX_FUNC)
1134 errx(1, "%s: non-function jmpslot",
1135 demangle(sp->name));
1136 nlp->nz_other = N_OTHER(bind, sp->aux);
1138 rrs_sdt.sdt_plt + sp->jmpslot_offset;
1141 errx(1, "internal error: %s defined in mysterious way",
1142 demangle(sp->name));
1144 /* Set symbol's name */
1145 nlp->nz_strx = offset;
1146 strcpy(rrs_strtab + offset, sp->name);
1147 offset += 1 + strlen(sp->name);
1151 * Write an extra symbol for indirections (possibly
1154 int t = (nlp->nz_type == N_INDR + N_EXT);
1157 nlp->nz_type = N_UNDF + (t ? N_EXT : 0);
1158 nlp->nz_un.n_strx = offset;
1163 strcpy(rrs_strtab + offset, sp->alias->name);
1164 offset += 1 + strlen(sp->alias->name);
1171 aligned_offset = MALIGN(offset);
1172 while (offset < aligned_offset) /* Pad deterministically */
1173 rrs_strtab[offset++] = '\0';
1174 if (offset != rrs_strtab_size)
1175 errx(1, "internal error: "
1176 "inconsistent RRS string table length: %d, expected %d",
1177 offset, rrs_strtab_size);
1179 /* Write the symbol table */
1180 if (rrs_symbol_size == sizeof(struct nlist))
1181 md_swapout_symbols(rrs_symbols, number_of_rrs_symbols);
1183 md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols);
1184 mywrite(rrs_symbols, symsize, 1, outstream);
1186 /* Write the strings */
1187 mywrite(rrs_strtab, rrs_strtab_size, 1, outstream);
1189 /* Write RT search path */
1190 mywrite(rrs_search_paths, rrs_search_paths_size, 1, outstream);
1193 * Write the names of the shared objects needed at run-time
1195 pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod);
1196 sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod));
1198 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1199 char *name = shp->entry->local_sym_name;
1201 if (i >= number_of_shobjs)
1202 errx(1, "internal error: # of link objects exceeds %d",
1205 sodp[i].sod_name = pos;
1206 sodp[i].sod_major = shp->entry->lib_major;
1207 sodp[i].sod_minor = shp->entry->lib_minor;
1209 if (*name == '-' && *(name+1) == 'l') {
1211 sodp[i].sod_library = 1;
1213 sodp[i].sod_library = 0;
1214 sodp[i].sod_reserved = 0;
1216 pos += 1 + strlen(name);
1217 sodp[i].sod_next = (i == number_of_shobjs - 1) ? 0 :
1218 (rrs_sdt.sdt_sods + (i+1)*sizeof(struct sod));
1221 if (i < number_of_shobjs)
1222 errx(1, "internal error: "
1223 "# of link objects less then expected %d",
1226 md_swapout_sod(sodp, number_of_shobjs);
1227 mywrite(sodp, number_of_shobjs, sizeof(struct sod), outstream);
1229 for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
1230 char *name = shp->entry->local_sym_name;
1232 if (*name == '-' && *(name+1) == 'l') {
1236 mywrite(name, strlen(name) + 1, 1, outstream);
1245 * First, do some consistency checks on the RRS segment.
1247 if (rrs_section_type == RRS_NONE) {
1248 if (reserved_rrs_relocs > 1)
1249 errx(1, "internal error: "
1250 "RRS relocs in static program: %d",
1251 reserved_rrs_relocs-1);
1256 printf("rrs_relocs: reserved %d claimed %d discarded %d, gotslots %d jmpslots %d\n",
1257 reserved_rrs_relocs, claimed_rrs_relocs, discarded_rrs_relocs,
1258 number_of_gotslots-1, number_of_jmpslots-1);
1261 /* Final consistency check */
1262 if (claimed_rrs_relocs + discarded_rrs_relocs != reserved_rrs_relocs) {
1263 errx(1, "internal error: "
1264 "reserved relocs(%d) != claimed(%d) + discarded(%d)",
1265 reserved_rrs_relocs,
1267 discarded_rrs_relocs);
1270 /* Write the RRS segments. */