diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2006-04-05 12:41:59 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2006-04-05 12:41:59 +0000 |
commit | 910600e9c7e78f59a8e89638016b70837a1ea622 (patch) | |
tree | 840539dc31ba9060f47dbfe8d9cc523a607e84b2 /bfd/elfxx-sparc.c | |
parent | 3b6fe0ccfde65852e8aedad01c1aa6953de9ca13 (diff) | |
download | gdb-910600e9c7e78f59a8e89638016b70837a1ea622.zip gdb-910600e9c7e78f59a8e89638016b70837a1ea622.tar.gz gdb-910600e9c7e78f59a8e89638016b70837a1ea622.tar.bz2 |
bfd/
* config.bfd (sparc-*-vxworks*): New stanza.
* configure.in (bfd_elf32_sparc_vxworks_vec): New stanza.
(bfd_elf32_sparc_vec, bfd_elf64_sparc_vec): Add elf-vxworks.lo.
* configure: Regenerate.
* elf32-sparc.c: Include elf-vxworks.h.
(elf32_sparc_vxworks_link_hash_table_create: New.
(elf32_sparc_vxworks_final_write_processing): New.
(TARGET_BIG_SYM): Override for VxWorks.
(TARGET_BIG_NAME, ELF_MINPAGESIZE): Likewise.
(bfd_elf32_bfd_link_hash_table_create): Likewise.
(elf_backend_want_got_plt, elf_backend_plt_readonly): Likewise.
(elf_backend_got_header_size, elf_backend_add_symbol_hook): Likewise.
(elf_backend_link_output_symbol_hook): Likewise.
(elf_backend_emit_relocs): Likewise.
(elf_backend_final_write_processing, elf32_bed): Likewise.
* elfxx-sparc.c: Include libiberty.h and elf-vxworks.h.
(sparc_vxworks_exec_plt0_entry, sparc_vxworks_exec_plt_entry): New.
(sparc_vxworks_shared_plt0_entry, sparc_vxworks_shared_plt_entry): New.
(_bfd_sparc_elf_link_hash_table_create): Don't initialize
build_plt_entry here.
(create_got_section): Initialize sgotplt for VxWorks.
(_bfd_sparc_elf_create_dynamic_sections): Initialize build_plt_entry,
plt_header_size and plt_entry_size, with new VxWorks-specific settings.
Call elf_vxworks_create_dynamic_sections for VxWorks.
(allocate_dynrelocs): Use plt_header_size and plt_entry_size.
Allocate room for .got.plt and .rela.plt.unloaded entries on VxWorks.
(_bfd_sparc_elf_size_dynamic_sections): Don't allocate a nop in .plt
for VxWorks. Check for the .got.plt section.
(sparc_vxworks_build_plt_entry): New function.
(_bfd_sparc_elf_finish_dynamic_symbol): Add handling of VxWorks PLTs.
Don't make _GLOBAL_OFFSET_TABLE_ and _PROCEDURE_LINKAGE_TABLE_
absolute on VxWorks.
(sparc32_finish_dyn): Add special handling for DT_RELASZ
and DT_PLTGOT on VxWorks.
(sparc_vxworks_finish_exec_plt): New.
(sparc_vxworks_finish_shared_plt): New.
(_bfd_sparc_elf_finish_dynamic_sections): Call them.
Use plt_header_size and plt_entry_size.
* elfxx-sparc.h (_bfd_sparc_elf_link_hash_table): Add is_vxworks,
srelplt2, sgotplt, plt_header_size and plt_entry_size fields.
* Makefile.am (elfxx-sparc.lo): Depend on elf-vxworks.h.
(elf32-sparc.lo): Likewise.
* Makefile.in: Regenerate.
* targets.c (bfd_elf32_sparc_vxworks_vec): Declare.
(_bfd_target_vector): Add a pointer to it.
gas/
* config/tc-sparc.c (sparc_target_format): Handle TE_VXWORKS.
(GOTT_BASE, GOTT_INDEX): New.
(tc_gen_reloc): Don't alter relocations against GOTT_BASE and
GOTT_INDEX when generating VxWorks PIC.
* configure.tgt (sparc*-*-vxworks*): Remove this special case;
use the generic *-*-vxworks* stanza instead.
gas/testsuite/
* gas/sparc/vxworks-pic.s, gas/sparc/vxworks-pic.d: New test.
* gas/sparc/sparc.exp: Run it. Remove sparc*-*-vxworks* XFAILs.
ld/
* configure.tgt (sparc*-*-vxworks*): New stanza.
* emulparams/elf32_sparc_vxworks.sh: New file.
* Makefile.am (ALL_EMULATIONS): Add eelf32_sparc_vxworks.o.
(eelf32_sparc_vxworks.c): New rule.
* Makefile.in: Regenerate.
ld/testsuite/
* ld-sparc/vxworks1.dd, ld-sparc/vxworks1.ld, ld-sparc/vxworks1-lib.dd,
* ld-sparc/vxworks1-lib.nd, ld-sparc/vxworks1-lib.rd,
* ld-sparc/vxworks1-lib.s, ld-sparc/vxworks1.rd, ld-sparc/vxworks1.s,
* ld-sparc/vxworks1-static.d, ld-sparc/vxworks2.s,
* ld-sparc/vxworks2.sd, ld-sparc/vxworks2-static.sd: New tests.
* ld-sparc/sparc.exp: Run them.
Diffstat (limited to 'bfd/elfxx-sparc.c')
-rw-r--r-- | bfd/elfxx-sparc.c | 440 |
1 files changed, 392 insertions, 48 deletions
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index cb5f7cb..ef7ff48 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -23,10 +23,12 @@ #include "sysdep.h" #include "bfdlink.h" #include "libbfd.h" +#include "libiberty.h" #include "elf-bfd.h" #include "elf/sparc.h" #include "opcode/sparc.h" #include "elfxx-sparc.h" +#include "elf-vxworks.h" /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) @@ -697,6 +699,50 @@ sparc64_plt_entry_build (bfd *output_bfd, asection *splt, bfd_vma offset, return index - 4; } +/* The format of the first PLT entry in a VxWorks executable. */ +static const bfd_vma sparc_vxworks_exec_plt0_entry[] = + { + 0x05000000, /* sethi %hi(_GLOBAL_OFFSET_TABLE_+8), %g2 */ + 0x8410a000, /* or %g2, %lo(_GLOBAL_OFFSET_TABLE_+8), %g2 */ + 0xc4008000, /* ld [ %g2 ], %g2 */ + 0x81c08000, /* jmp %g2 */ + 0x01000000 /* nop */ + }; + +/* The format of subsequent PLT entries. */ +static const bfd_vma sparc_vxworks_exec_plt_entry[] = + { + 0x03000000, /* sethi %hi(_GLOBAL_OFFSET_TABLE_+f@got), %g1 */ + 0x82106000, /* or %g1, %lo(_GLOBAL_OFFSET_TABLE_+f@got), %g1 */ + 0xc2004000, /* ld [ %g1 ], %g1 */ + 0x81c04000, /* jmp %g1 */ + 0x01000000, /* nop */ + 0x03000000, /* sethi %hi(f@pltindex), %g1 */ + 0x10800000, /* b _PLT_resolve */ + 0x82106000 /* or %g1, %lo(f@pltindex), %g1 */ + }; + +/* The format of the first PLT entry in a VxWorks shared object. */ +static const bfd_vma sparc_vxworks_shared_plt0_entry[] = + { + 0xc405e008, /* ld [ %l7 + 8 ], %g2 */ + 0x81c08000, /* jmp %g2 */ + 0x01000000 /* nop */ + }; + +/* The format of subsequent PLT entries. */ +static const bfd_vma sparc_vxworks_shared_plt_entry[] = + { + 0x03000000, /* sethi %hi(f@got), %g1 */ + 0x82106000, /* or %g1, %lo(f@got), %g1 */ + 0xc205c001, /* ld [ %l7 + %g1 ], %g1 */ + 0x81c04000, /* jmp %g1 */ + 0x01000000, /* nop */ + 0x03000000, /* sethi %hi(f@pltindex), %g1 */ + 0x10800000, /* b _PLT_resolve */ + 0x82106000 /* or %g1, %lo(f@pltindex), %g1 */ + }; + #define SPARC_ELF_PUT_WORD(htab, bfd, val, ptr) \ htab->put_word(bfd, val, ptr) @@ -781,7 +827,6 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd) ret->append_rela = sparc_elf_append_rela_64; ret->r_info = sparc_elf_r_info_64; ret->r_symndx = sparc_elf_r_symndx_64; - ret->build_plt_entry = sparc64_plt_entry_build; ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF64; ret->dtpmod_reloc = R_SPARC_TLS_DTPMOD64; ret->tpoff_reloc = R_SPARC_TLS_TPOFF64; @@ -798,7 +843,6 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd) ret->append_rela = sparc_elf_append_rela_32; ret->r_info = sparc_elf_r_info_32; ret->r_symndx = sparc_elf_r_symndx_32; - ret->build_plt_entry = sparc32_plt_entry_build; ret->dtpoff_reloc = R_SPARC_TLS_DTPOFF32; ret->dtpmod_reloc = R_SPARC_TLS_DTPMOD32; ret->tpoff_reloc = R_SPARC_TLS_TPOFF32; @@ -846,6 +890,14 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info) || ! bfd_set_section_alignment (dynobj, htab->srelgot, htab->word_align_power)) return FALSE; + + if (htab->is_vxworks) + { + htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); + if (!htab->sgotplt) + return FALSE; + } + return TRUE; } @@ -872,6 +924,41 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj, if (!info->shared) htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss"); + if (htab->is_vxworks) + { + if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) + return FALSE; + if (info->shared) + { + htab->plt_header_size + = 4 * ARRAY_SIZE (sparc_vxworks_shared_plt0_entry); + htab->plt_entry_size + = 4 * ARRAY_SIZE (sparc_vxworks_shared_plt_entry); + } + else + { + htab->plt_header_size + = 4 * ARRAY_SIZE (sparc_vxworks_exec_plt0_entry); + htab->plt_entry_size + = 4 * ARRAY_SIZE (sparc_vxworks_exec_plt_entry); + } + } + else + { + if (ABI_64_P (dynobj)) + { + htab->build_plt_entry = sparc64_plt_entry_build; + htab->plt_header_size = PLT64_HEADER_SIZE; + htab->plt_entry_size = PLT64_ENTRY_SIZE; + } + else + { + htab->build_plt_entry = sparc32_plt_entry_build; + htab->plt_header_size = PLT32_HEADER_SIZE; + htab->plt_entry_size = PLT32_ENTRY_SIZE; + } + } + if (!htab->splt || !htab->srelplt || !htab->sdynbss || (!info->shared && !htab->srelbss)) abort (); @@ -1807,10 +1894,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) { asection *s = htab->splt; - /* The first four entries in .plt is reserved. */ + /* Allocate room for the header. */ if (s->size == 0) - s->size = (SPARC_ELF_WORD_BYTES(htab) == 8 ? - PLT64_HEADER_SIZE : PLT32_HEADER_SIZE); + { + s->size = htab->plt_header_size; + + /* Allocate space for the .rela.plt.unloaded relocations. */ + if (htab->is_vxworks && !info->shared) + htab->srelplt2->size = sizeof (Elf32_External_Rela) * 2; + } /* The procedure linkage table size is bounded by the magnitude of the offset we can describe in the entry. */ @@ -1847,11 +1939,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf) } /* Make room for this entry. */ - s->size += (SPARC_ELF_WORD_BYTES(htab) == 8 ? - PLT64_ENTRY_SIZE : PLT32_ENTRY_SIZE); + s->size += htab->plt_entry_size; /* We also need to make an entry in the .rela.plt section. */ htab->srelplt->size += SPARC_ELF_RELA_BYTES (htab); + + if (htab->is_vxworks) + { + /* Allocate space for the .got.plt entry. */ + htab->sgotplt->size += 4; + + /* ...and for the .rela.plt.unloaded relocations. */ + if (!info->shared) + htab->srelplt2->size += sizeof (Elf32_External_Rela) * 3; + } } else { @@ -2153,6 +2254,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); if (! ABI_64_P (output_bfd) + && !htab->is_vxworks && elf_hash_table (info)->dynamic_sections_created) { /* Make space for the trailing nop in .plt. */ @@ -2179,7 +2281,8 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd, if (s == htab->splt || s == htab->sgot - || s == htab->sdynbss) + || s == htab->sdynbss + || s == htab->sgotplt) { /* Strip this section if we don't need it; see the comment below. */ @@ -3428,6 +3531,97 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, return TRUE; } +/* Build a VxWorks PLT entry. PLT_INDEX is the index of the PLT entry + and PLT_OFFSET is the byte offset from the start of .plt. GOT_OFFSET + is the offset of the associated .got.plt entry from + _GLOBAL_OFFSET_TABLE_. */ + +static void +sparc_vxworks_build_plt_entry (bfd *output_bfd, struct bfd_link_info *info, + bfd_vma plt_offset, bfd_vma plt_index, + bfd_vma got_offset) +{ + bfd_vma got_base; + const bfd_vma *plt_entry; + struct _bfd_sparc_elf_link_hash_table *htab; + bfd_byte *loc; + Elf_Internal_Rela rela; + + htab = _bfd_sparc_elf_hash_table (info); + if (info->shared) + { + plt_entry = sparc_vxworks_shared_plt_entry; + got_base = 0; + } + else + { + plt_entry = sparc_vxworks_exec_plt_entry; + got_base = (htab->elf.hgot->root.u.def.value + + htab->elf.hgot->root.u.def.section->output_offset + + htab->elf.hgot->root.u.def.section->output_section->vma); + } + + /* Fill in the entry in the procedure linkage table. */ + bfd_put_32 (output_bfd, plt_entry[0] + ((got_base + got_offset) >> 10), + htab->splt->contents + plt_offset); + bfd_put_32 (output_bfd, plt_entry[1] + ((got_base + got_offset) & 0x3ff), + htab->splt->contents + plt_offset + 4); + bfd_put_32 (output_bfd, plt_entry[2], + htab->splt->contents + plt_offset + 8); + bfd_put_32 (output_bfd, plt_entry[3], + htab->splt->contents + plt_offset + 12); + bfd_put_32 (output_bfd, plt_entry[4], + htab->splt->contents + plt_offset + 16); + bfd_put_32 (output_bfd, plt_entry[5] + (plt_index >> 10), + htab->splt->contents + plt_offset + 20); + /* PC-relative displacement for a branch to the start of + the PLT section. */ + bfd_put_32 (output_bfd, plt_entry[6] + (((-plt_offset - 24) >> 2) + & 0x003fffff), + htab->splt->contents + plt_offset + 24); + bfd_put_32 (output_bfd, plt_entry[7] + (plt_index & 0x3ff), + htab->splt->contents + plt_offset + 28); + + /* Fill in the .got.plt entry, pointing initially at the + second half of the PLT entry. */ + BFD_ASSERT (htab->sgotplt != NULL); + bfd_put_32 (output_bfd, + htab->splt->output_section->vma + + htab->splt->output_offset + + plt_offset + 20, + htab->sgotplt->contents + got_offset); + + /* Add relocations to .rela.plt.unloaded. */ + if (!info->shared) + { + loc = (htab->srelplt2->contents + + (2 + 3 * plt_index) * sizeof (Elf32_External_Rela)); + + /* Relocate the initial sethi. */ + rela.r_offset = (htab->splt->output_section->vma + + htab->splt->output_offset + + plt_offset); + rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22); + rela.r_addend = got_offset; + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Likewise the following or. */ + rela.r_offset += 4; + rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Relocate the .got.plt entry. */ + rela.r_offset = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + got_offset); + rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_SPARC_32); + rela.r_addend = plt_offset + 20; + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + } +} + /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ @@ -3449,7 +3643,7 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, asection *srela; Elf_Internal_Rela rela; bfd_byte *loc; - bfd_vma r_offset; + bfd_vma r_offset, got_offset; int rela_index; /* This symbol has an entry in the PLT. Set it up. */ @@ -3460,23 +3654,48 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, srela = htab->srelplt; BFD_ASSERT (splt != NULL && srela != NULL); - /* Fill in the entry in the procedure linkage table. */ - rela_index = SPARC_ELF_BUILD_PLT_ENTRY (htab, output_bfd, splt, - h->plt.offset, splt->size, - &r_offset); - /* Fill in the entry in the .rela.plt section. */ - rela.r_offset = r_offset - + (splt->output_section->vma + splt->output_offset); - if (! ABI_64_P (output_bfd) - || h->plt.offset < (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE)) + if (htab->is_vxworks) { + /* Work out the index of this PLT entry. */ + rela_index = ((h->plt.offset - htab->plt_header_size) + / htab->plt_entry_size); + + /* Calculate the offset of the associated .got.plt entry. + The first three entries are reserved. */ + got_offset = (rela_index + 3) * 4; + + sparc_vxworks_build_plt_entry (output_bfd, info, h->plt.offset, + rela_index, got_offset); + + + /* On VxWorks, the relocation points to the .got.plt entry, + not the .plt entry. */ + rela.r_offset = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + got_offset); rela.r_addend = 0; } else { - rela.r_addend = -(h->plt.offset + 4) - -(splt->output_section->vma + splt->output_offset); + /* Fill in the entry in the procedure linkage table. */ + rela_index = SPARC_ELF_BUILD_PLT_ENTRY (htab, output_bfd, splt, + h->plt.offset, splt->size, + &r_offset); + + rela.r_offset = r_offset + + (splt->output_section->vma + splt->output_offset); + if (! ABI_64_P (output_bfd) + || h->plt.offset < (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE)) + { + rela.r_addend = 0; + } + else + { + rela.r_addend = (-(h->plt.offset + 4) + - splt->output_section->vma + - splt->output_offset); + } } rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_JMP_SLOT); @@ -3577,10 +3796,12 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd, SPARC_ELF_APPEND_RELA (htab, output_bfd, s, &rela); } - /* Mark some specially defined symbols as absolute. */ + /* Mark some specially defined symbols as absolute. On VxWorks, + _GLOBAL_OFFSET_TABLE_ is not absolute: it is relative to the + ".got" section. Likewise _PROCEDURE_LINKAGE_TABLE_ and ".plt". */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || h == htab->elf.hgot - || h == htab->elf.hplt) + || (!htab->is_vxworks + && (h == htab->elf.hgot || h == htab->elf.hplt))) sym->st_shndx = SHN_ABS; return TRUE; @@ -3648,13 +3869,14 @@ sparc64_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, #endif static bfd_boolean -sparc32_finish_dyn (bfd *output_bfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED, +sparc32_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj, asection *sdyn, asection *splt ATTRIBUTE_UNUSED) { Elf32_External_Dyn *dyncon, *dynconend; + struct _bfd_sparc_elf_link_hash_table *htab; + htab = _bfd_sparc_elf_hash_table (info); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) @@ -3665,34 +3887,150 @@ sparc32_finish_dyn (bfd *output_bfd, bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); - switch (dyn.d_tag) + if (htab->is_vxworks && dyn.d_tag == DT_RELASZ) { - case DT_PLTGOT: name = ".plt"; size = FALSE; break; - case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break; - case DT_JMPREL: name = ".rela.plt"; size = FALSE; break; - default: name = NULL; size = FALSE; break; + /* On VxWorks, DT_RELASZ should not include the relocations + in .rela.plt. */ + if (htab->srelplt) + { + dyn.d_un.d_val -= htab->srelplt->size; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + } } - - if (name != NULL) + else if (htab->is_vxworks && dyn.d_tag == DT_PLTGOT) { - asection *s; + /* On VxWorks, DT_PLTGOT should point to the start of the GOT, + not to the start of the PLT. */ + if (htab->sgotplt) + { + dyn.d_un.d_val = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset); + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + } + } + else + { + switch (dyn.d_tag) + { + case DT_PLTGOT: name = ".plt"; size = FALSE; break; + case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break; + case DT_JMPREL: name = ".rela.plt"; size = FALSE; break; + default: name = NULL; size = FALSE; break; + } - s = bfd_get_section_by_name (output_bfd, name); - if (s == NULL) - dyn.d_un.d_val = 0; - else + if (name != NULL) { - if (! size) - dyn.d_un.d_ptr = s->vma; + asection *s; + + s = bfd_get_section_by_name (output_bfd, name); + if (s == NULL) + dyn.d_un.d_val = 0; else - dyn.d_un.d_val = s->size; + { + if (! size) + dyn.d_un.d_ptr = s->vma; + else + dyn.d_un.d_val = s->size; + } + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); } - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); } } return TRUE; } +/* Install the first PLT entry in a VxWorks executable and make sure that + .rela.plt.unloaded relocations have the correct symbol indexes. */ + +static void +sparc_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) +{ + struct _bfd_sparc_elf_link_hash_table *htab; + Elf_Internal_Rela rela; + bfd_vma got_base; + bfd_byte *loc; + + htab = _bfd_sparc_elf_hash_table (info); + + /* Calculate the absolute value of _GLOBAL_OFFSET_TABLE_. */ + got_base = (htab->elf.hgot->root.u.def.section->output_section->vma + + htab->elf.hgot->root.u.def.section->output_offset + + htab->elf.hgot->root.u.def.value); + + /* Install the initial PLT entry. */ + bfd_put_32 (output_bfd, + sparc_vxworks_exec_plt0_entry[0] + ((got_base + 8) >> 10), + htab->splt->contents); + bfd_put_32 (output_bfd, + sparc_vxworks_exec_plt0_entry[1] + ((got_base + 8) & 0x3ff), + htab->splt->contents + 4); + bfd_put_32 (output_bfd, + sparc_vxworks_exec_plt0_entry[2], + htab->splt->contents + 8); + bfd_put_32 (output_bfd, + sparc_vxworks_exec_plt0_entry[3], + htab->splt->contents + 12); + bfd_put_32 (output_bfd, + sparc_vxworks_exec_plt0_entry[4], + htab->splt->contents + 16); + + loc = htab->srelplt2->contents; + + /* Add an unloaded relocation for the initial entry's "sethi". */ + rela.r_offset = (htab->splt->output_section->vma + + htab->splt->output_offset); + rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22); + rela.r_addend = 8; + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Likewise the following "or". */ + rela.r_offset += 4; + rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + loc += sizeof (Elf32_External_Rela); + + /* Fix up the remaining .rela.plt.unloaded relocations. They may have + the wrong symbol index for _G_O_T_ or _P_L_T_ depending on the order + in which symbols were output. */ + while (loc < htab->srelplt2->contents + htab->srelplt2->size) + { + Elf_Internal_Rela rel; + + /* The entry's initial "sethi" (against _G_O_T_). */ + bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_HI22); + bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + + /* The following "or" (also against _G_O_T_). */ + bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_SPARC_LO10); + bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + + /* The .got.plt entry (against _P_L_T_). */ + bfd_elf32_swap_reloc_in (output_bfd, loc, &rel); + rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_SPARC_32); + bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + loc += sizeof (Elf32_External_Rela); + } +} + +/* Install the first PLT entry in a VxWorks shared object. */ + +static void +sparc_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info) +{ + struct _bfd_sparc_elf_link_hash_table *htab; + unsigned int i; + + htab = _bfd_sparc_elf_hash_table (info); + for (i = 0; i < ARRAY_SIZE (sparc_vxworks_shared_plt0_entry); i++) + bfd_put_32 (output_bfd, sparc_vxworks_shared_plt0_entry[i], + htab->splt->contents + i * 4); +} + bfd_boolean _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { @@ -3726,18 +4064,24 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i /* Initialize the contents of the .plt section. */ if (splt->size > 0) { - if (ABI_64_P (output_bfd)) - memset (splt->contents, 0, 4 * PLT64_ENTRY_SIZE); + if (htab->is_vxworks) + { + if (info->shared) + sparc_vxworks_finish_shared_plt (output_bfd, info); + else + sparc_vxworks_finish_exec_plt (output_bfd, info); + } else { - memset (splt->contents, 0, 4 * PLT32_ENTRY_SIZE); - bfd_put_32 (output_bfd, (bfd_vma) SPARC_NOP, - splt->contents + splt->size - 4); + memset (splt->contents, 0, htab->plt_header_size); + if (!ABI_64_P (output_bfd)) + bfd_put_32 (output_bfd, (bfd_vma) SPARC_NOP, + splt->contents + splt->size - 4); } } - elf_section_data (splt->output_section)->this_hdr.sh_entsize = - (ABI_64_P (output_bfd) ? PLT64_ENTRY_SIZE : PLT32_ENTRY_SIZE); + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = htab->plt_entry_size; } /* Set the first entry in the global offset table to the address of |