summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2019-02-07 17:04:31 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2019-02-07 17:10:35 +0100
commitafbdeb58468604ede2d51fb00c4ea9850fcf2617 (patch)
treefcc97300896b93d81cdccbe0c593aef0247922de
parentVisium: fix bogus overflow check on 32-bit hosts (diff)
downloadbinutils-gdb-afbdeb58468604ede2d51fb00c4ea9850fcf2617.tar.gz
binutils-gdb-afbdeb58468604ede2d51fb00c4ea9850fcf2617.tar.bz2
binutils-gdb-afbdeb58468604ede2d51fb00c4ea9850fcf2617.zip
SPARC: fix PR ld/18841
This fixes the last ld failures on SPARC64/Linux: FAIL: Run pr18841 with libpr18841b.so FAIL: Run pr18841 with libpr18841c.so FAIL: Run pr18841 with libpr18841bn.so (-z now) FAIL: Run pr18841 with libpr18841cn.so (-z now) by mimicing what has been done on x86-64 and Aarch64 to fix the PR. bfd/ PR ld/18841 * elf32-sparc.c (elf32_sparc_reloc_type_class): Return reloc_class_ifunc for ifunc symbols. * elf64-sparc.c (elf64_sparc_reloc_type_class): Likewise.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-sparc.c33
-rw-r--r--bfd/elf64-sparc.c33
3 files changed, 71 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3714662700f..3faecb87f17 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,12 @@
2019-02-07 Eric Botcazou <ebotcazou@adacore.com>
+ PR ld/18841
+ * elf32-sparc.c (elf32_sparc_reloc_type_class): Return
+ reloc_class_ifunc for ifunc symbols.
+ * elf64-sparc.c (elf64_sparc_reloc_type_class): Likewise.
+
+2019-02-07 Eric Botcazou <ebotcazou@adacore.com>
+
* elf32-visium.c (visium_elf_howto_parity_reloc): Minor tweak.
<R_VISIUM_PC16>: Use explicit range test to detect an overflow.
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 1873b1ae7cc..f5c58630686 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -157,13 +157,44 @@ elf32_sparc_final_write_processing (bfd *abfd,
}
}
+/* Used to decide how to sort relocs in an optimal manner for the
+ dynamic linker, before writing them out. */
+
static enum elf_reloc_type_class
-elf32_sparc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+elf32_sparc_reloc_type_class (const struct bfd_link_info *info,
const asection *rel_sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *rela)
{
+ bfd *abfd = info->output_bfd;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct _bfd_sparc_elf_link_hash_table *htab
+ = _bfd_sparc_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
+ if (htab->elf.dynsym != NULL
+ && htab->elf.dynsym->contents != NULL)
+ {
+ /* Check relocation against STT_GNU_IFUNC symbol if there are
+ dynamic symbols. */
+ unsigned long r_symndx = htab->r_symndx (rela->r_info);
+ if (r_symndx != STN_UNDEF)
+ {
+ Elf_Internal_Sym sym;
+ if (!bed->s->swap_symbol_in (abfd,
+ (htab->elf.dynsym->contents
+ + r_symndx * bed->s->sizeof_sym),
+ 0, &sym))
+ abort ();
+
+ if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+ return reloc_class_ifunc;
+ }
+ }
+
switch ((int) ELF32_R_TYPE (rela->r_info))
{
+ case R_SPARC_IRELATIVE:
+ return reloc_class_ifunc;
case R_SPARC_RELATIVE:
return reloc_class_relative;
case R_SPARC_JMP_SLOT:
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index 7de32c91926..bd29be3a93c 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -769,13 +769,44 @@ elf64_sparc_print_symbol_all (bfd *abfd ATTRIBUTE_UNUSED, void * filep,
return symbol->name;
}
+/* Used to decide how to sort relocs in an optimal manner for the
+ dynamic linker, before writing them out. */
+
static enum elf_reloc_type_class
-elf64_sparc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+elf64_sparc_reloc_type_class (const struct bfd_link_info *info,
const asection *rel_sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *rela)
{
+ bfd *abfd = info->output_bfd;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct _bfd_sparc_elf_link_hash_table *htab
+ = _bfd_sparc_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
+ if (htab->elf.dynsym != NULL
+ && htab->elf.dynsym->contents != NULL)
+ {
+ /* Check relocation against STT_GNU_IFUNC symbol if there are
+ dynamic symbols. */
+ unsigned long r_symndx = htab->r_symndx (rela->r_info);
+ if (r_symndx != STN_UNDEF)
+ {
+ Elf_Internal_Sym sym;
+ if (!bed->s->swap_symbol_in (abfd,
+ (htab->elf.dynsym->contents
+ + r_symndx * bed->s->sizeof_sym),
+ 0, &sym))
+ abort ();
+
+ if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+ return reloc_class_ifunc;
+ }
+ }
+
switch ((int) ELF64_R_TYPE (rela->r_info))
{
+ case R_SPARC_IRELATIVE:
+ return reloc_class_ifunc;
case R_SPARC_RELATIVE:
return reloc_class_relative;
case R_SPARC_JMP_SLOT: