include/
* elf/sparc.h (R_SPARC_JMP_IREL, R_SPARC_IRELATIVE): Define. bfd/ * reloc.c (BFD_RELOC_SPARC_JMP_IREL): New. (BFD_RELOC_SPARC_IRELATIVE): Likewise. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. * elfxx-sparc.h (_bfd_sparc_elf_link_hash_table): Add loc_hash_table and loc_hash_memory. (_bfd_sparc_elf_link_hash_table_free): Declare. * elf32-sparc.c (elf32_sparc_add_symbol_hook): New. (elf_backend_add_symbol_hook, elf_backend_post_process_headers, bfd_elf32_bfd_link_hash_table_free): Define. * elf64-sparc.c (elf64_sparc_add_symbol_hook): Set has_ifunc_symbols if STT_GNU_IFUNC. (bfd_elf64_bfd_link_hash_table_free): Define. (elf_backend_post_process_headers): Define always. * elfxx-sparc.c (sparc_jmp_irel_howto, sparc_irelative_howto): New. (sparc_reloc_map): Add entries for new IFUNC relocs. (_bfd_sparc_elf_reloc_type_lookup): Handle new IFUNC relocs. (_bfd_sparc_elf_info_to_howto_ptr): Likewise. (elf_sparc_local_htab_hash, elf_sparc_local_htab_eq, elf_sparc_get_local_sym_hash): New. (_bfd_sparc_elf_create_dynamic_sections): Move PLT ops initialization from here... (_bfd_sparc_elf_link_hash_table_create): ... to here. Allocate local hash table. (_bfd_sparc_elf_link_hash_table_free): New. (create_ifunc_sections): New. (_bfd_sparc_elf_check_relocs): Unconditionally assign htab->elf.dynobj and call create_ifunc_sections(). For local STT_GNU_IFUNC symbols cons up a fake local hash table entry for it. Unconditionally add a PLT refcount for STT_GNU_IFUNC symbols when h->def_regular. Count dyn relocs for ifunc. (_bfd_sparc_elf_adjust_dynamic_symbol): Handle ifunc. (allocate_dynrelocs): Unconditionally emit a PLT entry when STT_GNU_IFUNC and h->def_regular. Count GOT dyn relocs for ifunc. (allocate_local_dynrelocs): New function. (_bfd_sparc_elf_size_dynamic_sections): Invoke it over the local hash table. Emit dynamic relocs to irelplt when not shared. Treat iplt like splt. (_bfd_sparc_elf_relocate_section): Handle ifunc relocations by hand. (_bfd_sparc_elf_finish_dynamic_symbol): Adjust for non-dynamic ifunc plt in iplt/irelplt. ld/testsuite/ * ld-ifunc/ifunc.exp: Run for sparc.
This commit is contained in:
parent
72fbc6e5ab
commit
d0c9aeb3fc
12 changed files with 579 additions and 64 deletions
|
@ -32,6 +32,49 @@
|
|||
* elfxx-sparc.c (_bfd_sparc_elf_adjust_dynamic_symbol): Handle
|
||||
nocopyreloc.
|
||||
|
||||
* reloc.c (BFD_RELOC_SPARC_JMP_IREL): New.
|
||||
(BFD_RELOC_SPARC_IRELATIVE): Likewise.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* libbfd.h: Regenerate.
|
||||
|
||||
* elfxx-sparc.h (_bfd_sparc_elf_link_hash_table): Add loc_hash_table
|
||||
and loc_hash_memory.
|
||||
(_bfd_sparc_elf_link_hash_table_free): Declare.
|
||||
* elf32-sparc.c (elf32_sparc_add_symbol_hook): New.
|
||||
(elf_backend_add_symbol_hook, elf_backend_post_process_headers,
|
||||
bfd_elf32_bfd_link_hash_table_free): Define.
|
||||
* elf64-sparc.c (elf64_sparc_add_symbol_hook): Set
|
||||
has_ifunc_symbols if STT_GNU_IFUNC.
|
||||
(bfd_elf64_bfd_link_hash_table_free): Define.
|
||||
(elf_backend_post_process_headers): Define always.
|
||||
* elfxx-sparc.c (sparc_jmp_irel_howto, sparc_irelative_howto): New.
|
||||
(sparc_reloc_map): Add entries for new IFUNC relocs.
|
||||
(_bfd_sparc_elf_reloc_type_lookup): Handle new IFUNC relocs.
|
||||
(_bfd_sparc_elf_info_to_howto_ptr): Likewise.
|
||||
(elf_sparc_local_htab_hash, elf_sparc_local_htab_eq,
|
||||
elf_sparc_get_local_sym_hash): New.
|
||||
(_bfd_sparc_elf_create_dynamic_sections): Move PLT ops initialization
|
||||
from here...
|
||||
(_bfd_sparc_elf_link_hash_table_create): ... to here. Allocate
|
||||
local hash table.
|
||||
(_bfd_sparc_elf_link_hash_table_free): New.
|
||||
(create_ifunc_sections): New.
|
||||
(_bfd_sparc_elf_check_relocs): Unconditionally assign htab->elf.dynobj
|
||||
and call create_ifunc_sections(). For local STT_GNU_IFUNC symbols
|
||||
cons up a fake local hash table entry for it. Unconditionally add
|
||||
a PLT refcount for STT_GNU_IFUNC symbols when h->def_regular. Count
|
||||
dyn relocs for ifunc.
|
||||
(_bfd_sparc_elf_adjust_dynamic_symbol): Handle ifunc.
|
||||
(allocate_dynrelocs): Unconditionally emit a PLT entry when
|
||||
STT_GNU_IFUNC and h->def_regular. Count GOT dyn relocs for ifunc.
|
||||
(allocate_local_dynrelocs): New function.
|
||||
(_bfd_sparc_elf_size_dynamic_sections): Invoke it over the local hash
|
||||
table. Emit dynamic relocs to irelplt when not shared. Treat iplt
|
||||
like splt.
|
||||
(_bfd_sparc_elf_relocate_section): Handle ifunc relocations by hand.
|
||||
(_bfd_sparc_elf_finish_dynamic_symbol): Adjust for non-dynamic ifunc
|
||||
plt in iplt/irelplt.
|
||||
|
||||
2010-02-08 Richard Sandiford <r.sandiford@uk.ibm.com>
|
||||
|
||||
* xcofflink.c (_bfd_xcoff_bfd_final_link): When calculating
|
||||
|
|
|
@ -2496,6 +2496,8 @@ relocation types already defined. */
|
|||
BFD_RELOC_SPARC_GOTDATA_OP_HIX22,
|
||||
BFD_RELOC_SPARC_GOTDATA_OP_LOX10,
|
||||
BFD_RELOC_SPARC_GOTDATA_OP,
|
||||
BFD_RELOC_SPARC_JMP_IREL,
|
||||
BFD_RELOC_SPARC_IRELATIVE,
|
||||
|
||||
/* I think these are specific to SPARC a.out (e.g., Sun 4). */
|
||||
BFD_RELOC_SPARC_BASE13,
|
||||
|
|
|
@ -167,6 +167,23 @@ elf32_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
|
|||
}
|
||||
}
|
||||
|
||||
/* Hook called by the linker routine which adds symbols from an object
|
||||
file. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_sparc_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info * info ATTRIBUTE_UNUSED,
|
||||
Elf_Internal_Sym * sym,
|
||||
const char ** namep ATTRIBUTE_UNUSED,
|
||||
flagword * flagsp ATTRIBUTE_UNUSED,
|
||||
asection ** secp ATTRIBUTE_UNUSED,
|
||||
bfd_vma * valp ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||
elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define TARGET_BIG_SYM bfd_elf32_sparc_vec
|
||||
#define TARGET_BIG_NAME "elf32-sparc"
|
||||
#define ELF_ARCH bfd_arch_sparc
|
||||
|
@ -188,6 +205,8 @@ elf32_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
|
|||
_bfd_sparc_elf_reloc_name_lookup
|
||||
#define bfd_elf32_bfd_link_hash_table_create \
|
||||
_bfd_sparc_elf_link_hash_table_create
|
||||
#define bfd_elf32_bfd_link_hash_table_free \
|
||||
_bfd_sparc_elf_link_hash_table_free
|
||||
#define bfd_elf32_bfd_relax_section _bfd_sparc_elf_relax_section
|
||||
#define bfd_elf32_new_section_hook _bfd_sparc_elf_new_section_hook
|
||||
#define elf_backend_copy_indirect_symbol \
|
||||
|
@ -220,6 +239,9 @@ elf32_sparc_reloc_type_class (const Elf_Internal_Rela *rela)
|
|||
#define elf_backend_got_header_size 4
|
||||
#define elf_backend_rela_normal 1
|
||||
|
||||
#define elf_backend_post_process_headers _bfd_elf_set_osabi
|
||||
#define elf_backend_add_symbol_hook elf32_sparc_add_symbol_hook
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
||||
/* A wrapper around _bfd_sparc_elf_link_hash_table_create that identifies
|
||||
|
|
|
@ -424,6 +424,9 @@ elf64_sparc_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
|
|||
{
|
||||
static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
|
||||
|
||||
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||
elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
|
||||
|
||||
if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
|
||||
{
|
||||
int reg;
|
||||
|
@ -856,6 +859,8 @@ const struct elf_size_info elf64_sparc_size_info =
|
|||
_bfd_sparc_elf_plt_sym_val
|
||||
#define bfd_elf64_bfd_link_hash_table_create \
|
||||
_bfd_sparc_elf_link_hash_table_create
|
||||
#define bfd_elf64_bfd_link_hash_table_free \
|
||||
_bfd_sparc_elf_link_hash_table_free
|
||||
#define elf_info_to_howto \
|
||||
_bfd_sparc_elf_info_to_howto
|
||||
#define elf_backend_copy_indirect_symbol \
|
||||
|
@ -910,6 +915,8 @@ const struct elf_size_info elf64_sparc_size_info =
|
|||
/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */
|
||||
#define elf_backend_plt_alignment 8
|
||||
|
||||
#define elf_backend_post_process_headers _bfd_elf_set_osabi
|
||||
|
||||
#include "elf64-target.h"
|
||||
|
||||
/* FreeBSD support */
|
||||
|
@ -920,8 +927,6 @@ const struct elf_size_info elf64_sparc_size_info =
|
|||
#undef ELF_OSABI
|
||||
#define ELF_OSABI ELFOSABI_FREEBSD
|
||||
|
||||
#undef elf_backend_post_process_headers
|
||||
#define elf_backend_post_process_headers _bfd_elf_set_osabi
|
||||
#undef elf64_bed
|
||||
#define elf64_bed elf64_sparc_fbsd_bed
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "opcode/sparc.h"
|
||||
#include "elfxx-sparc.h"
|
||||
#include "elf-vxworks.h"
|
||||
#include "objalloc.h"
|
||||
#include "hashtab.h"
|
||||
|
||||
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */
|
||||
#define MINUS_ONE (~ (bfd_vma) 0)
|
||||
|
@ -265,6 +267,10 @@ static reloc_howto_type _bfd_sparc_elf_howto_table[] =
|
|||
HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont, sparc_elf_lox10_reloc, "R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff, FALSE),
|
||||
HOWTO(R_SPARC_GOTDATA_OP,0,0, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE),
|
||||
};
|
||||
static reloc_howto_type sparc_jmp_irel_howto =
|
||||
HOWTO(R_SPARC_JMP_IREL, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_IREL",FALSE,0,0x00000000,TRUE);
|
||||
static reloc_howto_type sparc_irelative_howto =
|
||||
HOWTO(R_SPARC_IRELATIVE, 0,0,00,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_IRELATIVE",FALSE,0,0x00000000,TRUE);
|
||||
static reloc_howto_type sparc_vtinherit_howto =
|
||||
HOWTO (R_SPARC_GNU_VTINHERIT, 0,2,0,FALSE,0,complain_overflow_dont, NULL, "R_SPARC_GNU_VTINHERIT", FALSE,0, 0, FALSE);
|
||||
static reloc_howto_type sparc_vtentry_howto =
|
||||
|
@ -360,6 +366,8 @@ static const struct elf_reloc_map sparc_reloc_map[] =
|
|||
{ BFD_RELOC_SPARC_GOTDATA_OP_LOX10, R_SPARC_GOTDATA_OP_LOX10 },
|
||||
{ BFD_RELOC_SPARC_GOTDATA_OP, R_SPARC_GOTDATA_OP },
|
||||
{ BFD_RELOC_SPARC_REGISTER, R_SPARC_REGISTER },
|
||||
{ BFD_RELOC_SPARC_JMP_IREL, R_SPARC_JMP_IREL },
|
||||
{ BFD_RELOC_SPARC_IRELATIVE, R_SPARC_IRELATIVE },
|
||||
{ BFD_RELOC_VTABLE_INHERIT, R_SPARC_GNU_VTINHERIT },
|
||||
{ BFD_RELOC_VTABLE_ENTRY, R_SPARC_GNU_VTENTRY },
|
||||
{ BFD_RELOC_SPARC_REV32, R_SPARC_REV32 },
|
||||
|
@ -373,6 +381,12 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|||
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_SPARC_JMP_IREL:
|
||||
return &sparc_jmp_irel_howto;
|
||||
|
||||
case BFD_RELOC_SPARC_IRELATIVE:
|
||||
return &sparc_irelative_howto;
|
||||
|
||||
case BFD_RELOC_VTABLE_INHERIT:
|
||||
return &sparc_vtinherit_howto;
|
||||
|
||||
|
@ -425,6 +439,12 @@ _bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type)
|
|||
{
|
||||
switch (r_type)
|
||||
{
|
||||
case R_SPARC_JMP_IREL:
|
||||
return &sparc_jmp_irel_howto;
|
||||
|
||||
case R_SPARC_IRELATIVE:
|
||||
return &sparc_irelative_howto;
|
||||
|
||||
case R_SPARC_GNU_VTINHERIT:
|
||||
return &sparc_vtinherit_howto;
|
||||
|
||||
|
@ -831,6 +851,78 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
#define ELF32_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
||||
#define ELF64_DYNAMIC_INTERPRETER "/usr/lib/sparcv9/ld.so.1"
|
||||
|
||||
/* Compute a hash of a local hash entry. We use elf_link_hash_entry
|
||||
for local symbol so that we can handle local STT_GNU_IFUNC symbols
|
||||
as global symbol. We reuse indx and dynstr_index for local symbol
|
||||
hash since they aren't used by global symbols in this backend. */
|
||||
|
||||
static hashval_t
|
||||
elf_sparc_local_htab_hash (const void *ptr)
|
||||
{
|
||||
struct elf_link_hash_entry *h
|
||||
= (struct elf_link_hash_entry *) ptr;
|
||||
return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
|
||||
}
|
||||
|
||||
/* Compare local hash entries. */
|
||||
|
||||
static int
|
||||
elf_sparc_local_htab_eq (const void *ptr1, const void *ptr2)
|
||||
{
|
||||
struct elf_link_hash_entry *h1
|
||||
= (struct elf_link_hash_entry *) ptr1;
|
||||
struct elf_link_hash_entry *h2
|
||||
= (struct elf_link_hash_entry *) ptr2;
|
||||
|
||||
return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
|
||||
}
|
||||
|
||||
/* Find and/or create a hash entry for local symbol. */
|
||||
|
||||
static struct elf_link_hash_entry *
|
||||
elf_sparc_get_local_sym_hash (struct _bfd_sparc_elf_link_hash_table *htab,
|
||||
bfd *abfd, const Elf_Internal_Rela *rel,
|
||||
bfd_boolean create)
|
||||
{
|
||||
struct _bfd_sparc_elf_link_hash_entry e, *ret;
|
||||
asection *sec = abfd->sections;
|
||||
unsigned long r_symndx;
|
||||
hashval_t h;
|
||||
void **slot;
|
||||
|
||||
r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
|
||||
h = ELF_LOCAL_SYMBOL_HASH (sec->id, r_symndx);
|
||||
|
||||
e.elf.indx = sec->id;
|
||||
e.elf.dynstr_index = r_symndx;
|
||||
slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
|
||||
create ? INSERT : NO_INSERT);
|
||||
|
||||
if (!slot)
|
||||
return NULL;
|
||||
|
||||
if (*slot)
|
||||
{
|
||||
ret = (struct _bfd_sparc_elf_link_hash_entry *) *slot;
|
||||
return &ret->elf;
|
||||
}
|
||||
|
||||
ret = (struct _bfd_sparc_elf_link_hash_entry *)
|
||||
objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
|
||||
sizeof (struct _bfd_sparc_elf_link_hash_entry));
|
||||
if (ret)
|
||||
{
|
||||
memset (ret, 0, sizeof (*ret));
|
||||
ret->elf.indx = sec->id;
|
||||
ret->elf.dynstr_index = r_symndx;
|
||||
ret->elf.dynindx = -1;
|
||||
ret->elf.plt.offset = (bfd_vma) -1;
|
||||
ret->elf.got.offset = (bfd_vma) -1;
|
||||
*slot = ret;
|
||||
}
|
||||
return &ret->elf;
|
||||
}
|
||||
|
||||
/* Create a SPARC ELF linker hash table. */
|
||||
|
||||
struct bfd_link_hash_table *
|
||||
|
@ -857,6 +949,10 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd)
|
|||
ret->bytes_per_rela = sizeof (Elf64_External_Rela);
|
||||
ret->dynamic_interpreter = ELF64_DYNAMIC_INTERPRETER;
|
||||
ret->dynamic_interpreter_size = sizeof ELF64_DYNAMIC_INTERPRETER;
|
||||
|
||||
ret->build_plt_entry = sparc64_plt_entry_build;
|
||||
ret->plt_header_size = PLT64_HEADER_SIZE;
|
||||
ret->plt_entry_size = PLT64_ENTRY_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -872,6 +968,10 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd)
|
|||
ret->bytes_per_rela = sizeof (Elf32_External_Rela);
|
||||
ret->dynamic_interpreter = ELF32_DYNAMIC_INTERPRETER;
|
||||
ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER;
|
||||
|
||||
ret->build_plt_entry = sparc32_plt_entry_build;
|
||||
ret->plt_header_size = PLT32_HEADER_SIZE;
|
||||
ret->plt_entry_size = PLT32_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
|
||||
|
@ -882,9 +982,35 @@ _bfd_sparc_elf_link_hash_table_create (bfd *abfd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ret->loc_hash_table = htab_try_create (1024,
|
||||
elf_sparc_local_htab_hash,
|
||||
elf_sparc_local_htab_eq,
|
||||
NULL);
|
||||
ret->loc_hash_memory = objalloc_create ();
|
||||
if (!ret->loc_hash_table || !ret->loc_hash_memory)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &ret->elf.root;
|
||||
}
|
||||
|
||||
/* Destroy a SPARC ELF linker hash table. */
|
||||
|
||||
void
|
||||
_bfd_sparc_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
|
||||
{
|
||||
struct _bfd_sparc_elf_link_hash_table *htab
|
||||
= (struct _bfd_sparc_elf_link_hash_table *) hash;
|
||||
|
||||
if (htab->loc_hash_table)
|
||||
htab_delete (htab->loc_hash_table);
|
||||
if (htab->loc_hash_memory)
|
||||
objalloc_free ((struct objalloc *) htab->loc_hash_memory);
|
||||
_bfd_generic_link_hash_table_free (hash);
|
||||
}
|
||||
|
||||
/* Create .plt, .rela.plt, .got, .rela.got, .dynbss, and
|
||||
.rela.bss sections in DYNOBJ, and set up shortcuts to them in our
|
||||
hash table. */
|
||||
|
@ -924,21 +1050,6 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj,
|
|||
= 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->elf.splt || !htab->elf.srelplt || !htab->sdynbss
|
||||
|| (!info->shared && !htab->srelbss))
|
||||
|
@ -947,6 +1058,37 @@ _bfd_sparc_elf_create_dynamic_sections (bfd *dynobj,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
struct elf_link_hash_table *htab = elf_hash_table (info);
|
||||
flagword flags, pltflags;
|
||||
asection *s;
|
||||
|
||||
if (htab->irelifunc != NULL || htab->iplt != NULL)
|
||||
return TRUE;
|
||||
|
||||
flags = bed->dynamic_sec_flags;
|
||||
pltflags = flags | SEC_ALLOC | SEC_CODE | SEC_LOAD;
|
||||
|
||||
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
|
||||
return FALSE;
|
||||
htab->iplt = s;
|
||||
|
||||
s = bfd_make_section_with_flags (abfd, ".rela.iplt",
|
||||
flags | SEC_READONLY);
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s,
|
||||
bed->s->log_file_align))
|
||||
return FALSE;
|
||||
htab->irelplt = s;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Copy the extra info we tack onto an elf_link_hash_entry. */
|
||||
|
||||
void
|
||||
|
@ -1074,12 +1216,18 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
|
||||
BFD_ASSERT (is_sparc_elf (abfd) || num_relocs == 0);
|
||||
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (!create_ifunc_sections (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
|
||||
rel_end = relocs + num_relocs;
|
||||
for (rel = relocs; rel < rel_end; rel++)
|
||||
{
|
||||
unsigned int r_type;
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *isym;
|
||||
|
||||
r_symndx = SPARC_ELF_R_SYMNDX (htab, rel->r_info);
|
||||
r_type = SPARC_ELF_R_TYPE (rel->r_info);
|
||||
|
@ -1091,8 +1239,33 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
isym = NULL;
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = NULL;
|
||||
{
|
||||
/* A local symbol. */
|
||||
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
|
||||
abfd, r_symndx);
|
||||
if (isym == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Check relocation against local STT_GNU_IFUNC symbol. */
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
h = elf_sparc_get_local_sym_hash (htab, abfd, rel,
|
||||
TRUE);
|
||||
if (h == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Fake a STT_GNU_IFUNC symbol. */
|
||||
h->type = STT_GNU_IFUNC;
|
||||
h->def_regular = 1;
|
||||
h->ref_regular = 1;
|
||||
h->forced_local = 1;
|
||||
h->root.type = bfd_link_hash_defined;
|
||||
}
|
||||
else
|
||||
h = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
|
@ -1101,6 +1274,12 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
|
||||
if (h && h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
if (h->def_regular)
|
||||
h->plt.refcount += 1;
|
||||
}
|
||||
|
||||
/* Compatibility with old R_SPARC_REV32 reloc conflicting
|
||||
with R_SPARC_TLS_GD_HI22. */
|
||||
if (! ABI_64_P (abfd) && ! checked_tlsgd)
|
||||
|
@ -1239,8 +1418,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
|
||||
if (htab->elf.sgot == NULL)
|
||||
{
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1403,7 +1580,10 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
&& (sec->flags & SEC_ALLOC) != 0
|
||||
&& h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defweak
|
||||
|| !h->def_regular)))
|
||||
|| !h->def_regular))
|
||||
|| (!info->shared
|
||||
&& h != NULL
|
||||
&& h->type == STT_GNU_IFUNC))
|
||||
{
|
||||
struct _bfd_sparc_elf_dyn_relocs *p;
|
||||
struct _bfd_sparc_elf_dyn_relocs **head;
|
||||
|
@ -1413,9 +1593,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
section in dynobj and make room for the reloc. */
|
||||
if (sreloc == NULL)
|
||||
{
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
|
||||
sreloc = _bfd_elf_make_dynamic_reloc_section
|
||||
(sec, htab->elf.dynobj, htab->word_align_power,
|
||||
abfd, /*rela?*/ TRUE);
|
||||
|
@ -1435,13 +1612,8 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
easily. Oh well. */
|
||||
asection *s;
|
||||
void *vpp;
|
||||
Elf_Internal_Sym *isym;
|
||||
|
||||
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
|
||||
abfd, r_symndx);
|
||||
if (isym == NULL)
|
||||
return FALSE;
|
||||
|
||||
BFD_ASSERT (isym != NULL);
|
||||
s = bfd_section_from_elf_index (abfd, isym->st_shndx);
|
||||
if (s == NULL)
|
||||
s = sec;
|
||||
|
@ -1684,6 +1856,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
/* Make sure we know what is going on here. */
|
||||
BFD_ASSERT (htab->elf.dynobj != NULL
|
||||
&& (h->needs_plt
|
||||
|| h->type == STT_GNU_IFUNC
|
||||
|| h->u.weakdef != NULL
|
||||
|| (h->def_dynamic
|
||||
&& h->ref_regular
|
||||
|
@ -1697,6 +1870,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
some of their functions as STT_NOTYPE when they really should be
|
||||
STT_FUNC. */
|
||||
if (h->type == STT_FUNC
|
||||
|| h->type == STT_GNU_IFUNC
|
||||
|| h->needs_plt
|
||||
|| (h->type == STT_NOTYPE
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|
@ -1704,9 +1878,10 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
&& (h->root.u.def.section->flags & SEC_CODE) != 0))
|
||||
{
|
||||
if (h->plt.refcount <= 0
|
||||
|| SYMBOL_CALLS_LOCAL (info, h)
|
||||
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
||||
&& h->root.type == bfd_link_hash_undefweak))
|
||||
|| (h->type != STT_GNU_IFUNC
|
||||
&& (SYMBOL_CALLS_LOCAL (info, h)
|
||||
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
||||
&& h->root.type == bfd_link_hash_undefweak))))
|
||||
{
|
||||
/* This case can occur if we saw a WPLT30 reloc in an input
|
||||
file, but the symbol was never referred to by a dynamic
|
||||
|
@ -1828,8 +2003,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
|
|||
htab = _bfd_sparc_elf_hash_table (info);
|
||||
BFD_ASSERT (htab != NULL);
|
||||
|
||||
if (htab->elf.dynamic_sections_created
|
||||
&& h->plt.refcount > 0)
|
||||
if ((htab->elf.dynamic_sections_created
|
||||
&& h->plt.refcount > 0)
|
||||
|| (h->type == STT_GNU_IFUNC
|
||||
&& h->def_regular))
|
||||
{
|
||||
/* Make sure this symbol is output as a dynamic symbol.
|
||||
Undefined weak syms won't yet be marked as dynamic. */
|
||||
|
@ -1840,10 +2017,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
|
||||
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)
|
||||
|| h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
asection *s = htab->elf.splt;
|
||||
|
||||
if (s == NULL)
|
||||
s = htab->elf.iplt;
|
||||
|
||||
/* Allocate room for the header. */
|
||||
if (s->size == 0)
|
||||
{
|
||||
|
@ -1892,7 +2073,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
|
|||
s->size += htab->plt_entry_size;
|
||||
|
||||
/* We also need to make an entry in the .rela.plt section. */
|
||||
htab->elf.srelplt->size += SPARC_ELF_RELA_BYTES (htab);
|
||||
if (s == htab->elf.splt)
|
||||
htab->elf.srelplt->size += SPARC_ELF_RELA_BYTES (htab);
|
||||
else
|
||||
htab->elf.irelplt->size += SPARC_ELF_RELA_BYTES (htab);
|
||||
|
||||
if (htab->is_vxworks)
|
||||
{
|
||||
|
@ -1949,7 +2133,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
|
|||
R_SPARC_TLS_GD_{HI22,LO10} needs one if local symbol and two if
|
||||
global. */
|
||||
if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
|
||||
|| tls_type == GOT_TLS_IE)
|
||||
|| tls_type == GOT_TLS_IE
|
||||
|| h->type == STT_GNU_IFUNC)
|
||||
htab->elf.srelgot->size += SPARC_ELF_RELA_BYTES (htab);
|
||||
else if (tls_type == GOT_TLS_GD)
|
||||
htab->elf.srelgot->size += 2 * SPARC_ELF_RELA_BYTES (htab);
|
||||
|
@ -2060,6 +2245,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Allocate space in .plt, .got and associated reloc sections for
|
||||
local dynamic relocs. */
|
||||
|
||||
static bfd_boolean
|
||||
allocate_local_dynrelocs (void **slot, void *inf)
|
||||
{
|
||||
struct elf_link_hash_entry *h
|
||||
= (struct elf_link_hash_entry *) *slot;
|
||||
|
||||
if (h->type != STT_GNU_IFUNC
|
||||
|| !h->def_regular
|
||||
|| !h->ref_regular
|
||||
|| !h->forced_local
|
||||
|| h->root.type != bfd_link_hash_defined)
|
||||
abort ();
|
||||
|
||||
return allocate_dynrelocs (h, inf);
|
||||
}
|
||||
|
||||
/* Find any dynamic relocs that apply to read-only sections. */
|
||||
|
||||
static bfd_boolean
|
||||
|
@ -2172,6 +2376,8 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
else if (p->count != 0)
|
||||
{
|
||||
srel = elf_section_data (p->sec)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
srel = htab->elf.irelplt;
|
||||
srel->size += p->count * SPARC_ELF_RELA_BYTES (htab);
|
||||
if ((p->sec->output_section->flags & SEC_READONLY) != 0)
|
||||
info->flags |= DF_TEXTREL;
|
||||
|
@ -2222,6 +2428,9 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
sym dynamic relocs. */
|
||||
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
|
||||
|
||||
/* Allocate .plt and .got entries, and space for local symbols. */
|
||||
htab_traverse (htab->loc_hash_table, allocate_local_dynrelocs, info);
|
||||
|
||||
if (! ABI_64_P (output_bfd)
|
||||
&& !htab->is_vxworks
|
||||
&& elf_hash_table (info)->dynamic_sections_created)
|
||||
|
@ -2251,6 +2460,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
if (s == htab->elf.splt
|
||||
|| s == htab->elf.sgot
|
||||
|| s == htab->sdynbss
|
||||
|| s == htab->elf.iplt
|
||||
|| s == htab->elf.sgotplt)
|
||||
{
|
||||
/* Strip this section if we don't need it; see the
|
||||
|
@ -2544,6 +2754,20 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
|
|||
sym = local_syms + r_symndx;
|
||||
sec = local_sections[r_symndx];
|
||||
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
|
||||
|
||||
if (!info->relocatable
|
||||
&& ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
/* Relocate against local STT_GNU_IFUNC symbol. */
|
||||
h = elf_sparc_get_local_sym_hash (htab, input_bfd,
|
||||
rel, FALSE);
|
||||
if (h == NULL)
|
||||
abort ();
|
||||
|
||||
/* Set STT_GNU_IFUNC symbol value. */
|
||||
h->root.u.def.value = sym->st_value;
|
||||
h->root.u.def.section = sec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2580,6 +2804,111 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
|
|||
if (info->relocatable)
|
||||
continue;
|
||||
|
||||
if (h != NULL
|
||||
&& h->type == STT_GNU_IFUNC
|
||||
&& h->def_regular)
|
||||
{
|
||||
asection *plt_sec;
|
||||
const char *name;
|
||||
|
||||
if ((input_section->flags & SEC_ALLOC) == 0
|
||||
|| h->plt.offset == (bfd_vma) -1)
|
||||
abort ();
|
||||
|
||||
plt_sec = htab->elf.splt;
|
||||
if (! plt_sec)
|
||||
plt_sec =htab->elf.iplt;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_SPARC_GOTDATA_HIX22:
|
||||
case R_SPARC_GOTDATA_LOX10:
|
||||
case R_SPARC_GOTDATA_OP_HIX22:
|
||||
case R_SPARC_GOTDATA_OP_LOX10:
|
||||
case R_SPARC_GOT10:
|
||||
case R_SPARC_GOT13:
|
||||
case R_SPARC_GOT22:
|
||||
if (htab->elf.sgot == NULL)
|
||||
abort ();
|
||||
off = h->got.offset;
|
||||
if (off == (bfd_vma) -1)
|
||||
abort();
|
||||
relocation = htab->elf.sgot->output_offset + off - got_base;
|
||||
goto do_relocation;
|
||||
|
||||
case R_SPARC_WPLT30:
|
||||
case R_SPARC_WDISP30:
|
||||
relocation = (plt_sec->output_section->vma
|
||||
+ plt_sec->output_offset + h->plt.offset);
|
||||
goto do_relocation;
|
||||
|
||||
case R_SPARC_32:
|
||||
case R_SPARC_64:
|
||||
if (info->shared && h->non_got_ref)
|
||||
{
|
||||
Elf_Internal_Rela outrel;
|
||||
bfd_vma offset;
|
||||
|
||||
offset = _bfd_elf_section_offset (output_bfd, info,
|
||||
input_section,
|
||||
rel->r_offset);
|
||||
if (offset == (bfd_vma) -1
|
||||
|| offset == (bfd_vma) -2)
|
||||
abort();
|
||||
|
||||
outrel.r_offset = (input_section->output_section->vma
|
||||
+ input_section->output_offset
|
||||
+ offset);
|
||||
|
||||
if (h->dynindx == -1
|
||||
|| h->forced_local
|
||||
|| info->executable)
|
||||
{
|
||||
outrel.r_info = SPARC_ELF_R_INFO (htab, NULL,
|
||||
0, R_SPARC_IRELATIVE);
|
||||
outrel.r_addend = relocation + rel->r_addend;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h->dynindx == -1)
|
||||
abort();
|
||||
outrel.r_info = SPARC_ELF_R_INFO (htab, rel, h->dynindx, r_type);
|
||||
outrel.r_addend = rel->r_addend;
|
||||
}
|
||||
|
||||
sparc_elf_append_rela (output_bfd, sreloc, &outrel);
|
||||
continue;
|
||||
}
|
||||
|
||||
relocation = (plt_sec->output_section->vma
|
||||
+ plt_sec->output_offset + h->plt.offset);
|
||||
goto do_relocation;
|
||||
|
||||
case R_SPARC_HI22:
|
||||
case R_SPARC_LO10:
|
||||
/* We should only see such relocs in static links. */
|
||||
if (info->shared)
|
||||
abort();
|
||||
relocation = (plt_sec->output_section->vma
|
||||
+ plt_sec->output_offset + h->plt.offset);
|
||||
goto do_relocation;
|
||||
|
||||
default:
|
||||
if (h->root.root.string)
|
||||
name = h->root.root.string;
|
||||
else
|
||||
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
|
||||
NULL);
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: relocation %s against STT_GNU_IFUNC "
|
||||
"symbol `%s' isn't handled by %s"), input_bfd,
|
||||
_bfd_sparc_elf_howto_table[r_type].name,
|
||||
name, __FUNCTION__);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_SPARC_GOTDATA_HIX22:
|
||||
|
@ -3496,10 +3825,12 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
|
|||
}
|
||||
|
||||
if (r == bfd_reloc_continue)
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel->r_offset,
|
||||
relocation, rel->r_addend);
|
||||
|
||||
{
|
||||
do_relocation:
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel->r_offset,
|
||||
relocation, rel->r_addend);
|
||||
}
|
||||
if (r != bfd_reloc_ok)
|
||||
{
|
||||
switch (r)
|
||||
|
@ -3681,13 +4012,21 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
bfd_vma r_offset, got_offset;
|
||||
int rela_index;
|
||||
|
||||
/* This symbol has an entry in the PLT. Set it up. */
|
||||
/* When building a static executable, use .iplt and
|
||||
.rela.iplt sections for STT_GNU_IFUNC symbols. */
|
||||
if (htab->elf.splt != NULL)
|
||||
{
|
||||
splt = htab->elf.splt;
|
||||
srela = htab->elf.srelplt;
|
||||
}
|
||||
else
|
||||
{
|
||||
splt = htab->elf.iplt;
|
||||
srela = htab->elf.irelplt;
|
||||
}
|
||||
|
||||
BFD_ASSERT (h->dynindx != -1);
|
||||
|
||||
splt = htab->elf.splt;
|
||||
srela = htab->elf.srelplt;
|
||||
BFD_ASSERT (splt != NULL && srela != NULL);
|
||||
if (splt == NULL || srela == NULL)
|
||||
abort ();
|
||||
|
||||
/* Fill in the entry in the .rela.plt section. */
|
||||
if (htab->is_vxworks)
|
||||
|
@ -3710,29 +4049,73 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
+ htab->elf.sgotplt->output_offset
|
||||
+ got_offset);
|
||||
rela.r_addend = 0;
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx,
|
||||
R_SPARC_JMP_SLOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_boolean ifunc = FALSE;
|
||||
|
||||
/* 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);
|
||||
|
||||
if (h == NULL
|
||||
|| h->dynindx == -1
|
||||
|| ((info->executable
|
||||
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
|
||||
&& h->def_regular
|
||||
&& h->type == STT_GNU_IFUNC))
|
||||
{
|
||||
ifunc = TRUE;
|
||||
BFD_ASSERT (h == NULL
|
||||
|| (h->type == STT_GNU_IFUNC
|
||||
&& h->def_regular
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)));
|
||||
}
|
||||
|
||||
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 (ABI_64_P (output_bfd)
|
||||
&& h->plt.offset >= (PLT64_LARGE_THRESHOLD * PLT64_ENTRY_SIZE))
|
||||
{
|
||||
rela.r_addend = 0;
|
||||
if (ifunc)
|
||||
{
|
||||
rela.r_addend = (h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset
|
||||
+ h->root.u.def.value);
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0,
|
||||
R_SPARC_IRELATIVE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rela.r_addend = (-(h->plt.offset + 4)
|
||||
- splt->output_section->vma
|
||||
- splt->output_offset);
|
||||
if (ifunc)
|
||||
{
|
||||
rela.r_addend = (h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset
|
||||
+ h->root.u.def.value);
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0,
|
||||
R_SPARC_JMP_IREL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rela.r_addend = 0;
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx,
|
||||
R_SPARC_JMP_SLOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_JMP_SLOT);
|
||||
|
||||
/* Adjust for the first 4 reserved elements in the .plt section
|
||||
when setting the offset in the .rela.plt section.
|
||||
|
@ -3780,11 +4163,29 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
the symbol was forced to be local because of a version file.
|
||||
The entry in the global offset table will already have been
|
||||
initialized in the relocate_section function. */
|
||||
if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if (! info->shared
|
||||
&& h->type == STT_GNU_IFUNC
|
||||
&& h->def_regular)
|
||||
{
|
||||
asection *plt;
|
||||
|
||||
/* We load the GOT entry with the PLT entry. */
|
||||
plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
|
||||
SPARC_ELF_PUT_WORD (htab, output_bfd,
|
||||
(plt->output_section->vma
|
||||
+ plt->output_offset + h->plt.offset),
|
||||
htab->elf.sgot->contents
|
||||
+ (h->got.offset & ~(bfd_vma) 1));
|
||||
return TRUE;
|
||||
}
|
||||
else if (info->shared
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
{
|
||||
asection *sec = h->root.u.def.section;
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_RELATIVE);
|
||||
if (h->type == STT_GNU_IFUNC)
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_IRELATIVE);
|
||||
else
|
||||
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, 0, R_SPARC_RELATIVE);
|
||||
rela.r_addend = (h->root.u.def.value
|
||||
+ sec->output_section->vma
|
||||
+ sec->output_offset);
|
||||
|
@ -3823,9 +4224,10 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
/* 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
|
||||
|| (!htab->is_vxworks
|
||||
&& (h == htab->elf.hgot || h == htab->elf.hplt)))
|
||||
if (sym != NULL
|
||||
&& (strcmp (h->root.root.string, "_DYNAMIC") == 0
|
||||
|| (!htab->is_vxworks
|
||||
&& (h == htab->elf.hgot || h == htab->elf.hplt))))
|
||||
sym->st_shndx = SHN_ABS;
|
||||
|
||||
return TRUE;
|
||||
|
@ -4021,6 +4423,21 @@ sparc_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info)
|
|||
htab->elf.splt->contents + i * 4);
|
||||
}
|
||||
|
||||
/* Finish up local dynamic symbol handling. We set the contents of
|
||||
various dynamic sections here. */
|
||||
|
||||
static bfd_boolean
|
||||
finish_local_dynamic_symbol (void **slot, void *inf)
|
||||
{
|
||||
struct elf_link_hash_entry *h
|
||||
= (struct elf_link_hash_entry *) *slot;
|
||||
struct bfd_link_info *info
|
||||
= (struct bfd_link_info *) inf;
|
||||
|
||||
return _bfd_sparc_elf_finish_dynamic_symbol (info->output_bfd, info,
|
||||
h, NULL);
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
_bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
|
||||
{
|
||||
|
@ -4083,6 +4500,9 @@ _bfd_sparc_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *i
|
|||
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize =
|
||||
SPARC_ELF_WORD_BYTES (htab);
|
||||
|
||||
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
|
||||
htab_traverse (htab->loc_hash_table, finish_local_dynamic_symbol, info);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,10 @@ struct _bfd_sparc_elf_link_hash_table
|
|||
/* Small local sym cache. */
|
||||
struct sym_cache sym_cache;
|
||||
|
||||
/* Used by local STT_GNU_IFUNC symbols. */
|
||||
htab_t loc_hash_table;
|
||||
void *loc_hash_memory;
|
||||
|
||||
/* True if the target system is VxWorks. */
|
||||
int is_vxworks;
|
||||
|
||||
|
@ -102,6 +106,8 @@ extern bfd_boolean _bfd_sparc_elf_mkobject
|
|||
(bfd *);
|
||||
extern struct bfd_link_hash_table *_bfd_sparc_elf_link_hash_table_create
|
||||
(bfd *);
|
||||
extern void _bfd_sparc_elf_link_hash_table_free
|
||||
(struct bfd_link_hash_table *);
|
||||
extern bfd_boolean _bfd_sparc_elf_create_dynamic_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
extern void _bfd_sparc_elf_copy_indirect_symbol
|
||||
|
|
|
@ -928,6 +928,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
|||
"BFD_RELOC_SPARC_GOTDATA_OP_HIX22",
|
||||
"BFD_RELOC_SPARC_GOTDATA_OP_LOX10",
|
||||
"BFD_RELOC_SPARC_GOTDATA_OP",
|
||||
"BFD_RELOC_SPARC_JMP_IREL",
|
||||
"BFD_RELOC_SPARC_IRELATIVE",
|
||||
"BFD_RELOC_SPARC_BASE13",
|
||||
"BFD_RELOC_SPARC_BASE22",
|
||||
"BFD_RELOC_SPARC_10",
|
||||
|
|
|
@ -1870,6 +1870,10 @@ ENUMX
|
|||
BFD_RELOC_SPARC_GOTDATA_OP_LOX10
|
||||
ENUMX
|
||||
BFD_RELOC_SPARC_GOTDATA_OP
|
||||
ENUMX
|
||||
BFD_RELOC_SPARC_JMP_IREL
|
||||
ENUMX
|
||||
BFD_RELOC_SPARC_IRELATIVE
|
||||
ENUMDOC
|
||||
SPARC ELF relocations. There is probably some overlap with other
|
||||
relocation types already defined.
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-02-08 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* elf/sparc.h (R_SPARC_JMP_IREL, R_SPARC_IRELATIVE): Define.
|
||||
|
||||
2010-01-13 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
Add new DW_AT_use_GNAT_descriptive_type CU attribute.
|
||||
|
|
|
@ -164,6 +164,8 @@ START_RELOC_NUMBERS (elf_sparc_reloc_type)
|
|||
|
||||
EMPTY_RELOC (R_SPARC_max_std)
|
||||
|
||||
RELOC_NUMBER (R_SPARC_JMP_IREL, 248)
|
||||
RELOC_NUMBER (R_SPARC_IRELATIVE, 249)
|
||||
RELOC_NUMBER (R_SPARC_GNU_VTINHERIT, 250)
|
||||
RELOC_NUMBER (R_SPARC_GNU_VTENTRY, 251)
|
||||
RELOC_NUMBER (R_SPARC_REV32, 252)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2010-02-08 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* ld-ifunc/ifunc.exp: Run for sparc.
|
||||
|
||||
2010-02-08 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* ld-powerpc/apuinfo-nul.s: New.
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
# Written by Nick Clifton <nickc@redhat.com>
|
||||
|
||||
|
||||
# IFUNC support has only been implemented for the ix86, x86_64 and powerpc
|
||||
# so far.
|
||||
# IFUNC support has only been implemented for the ix86, x86_64, powerpc,
|
||||
# and sparc so far.
|
||||
if {!(([istarget "i?86-*-*"]
|
||||
|| [istarget "x86_64-*-*"]
|
||||
|| [istarget "powerpc*-*-*"])
|
||||
|| [istarget "powerpc*-*-*"]
|
||||
|| [istarget "sparc*-*-*"])
|
||||
&& ([istarget "*-*-elf*"]
|
||||
|| ([istarget "*-*-linux*"]
|
||||
&& ![istarget "*-*-*aout*"]
|
||||
|
|
Loading…
Reference in a new issue