From b2abe1bd8149dd9ad64432f620c3a034bf23a5fe Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Thu, 7 Feb 2019 17:04:31 +0100 Subject: [PATCH] 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. --- bfd/ChangeLog | 7 +++++++ bfd/elf32-sparc.c | 33 ++++++++++++++++++++++++++++++++- bfd/elf64-sparc.c | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c0a3a374294..9656c50febf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2019-02-07 Eric Botcazou + + 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 * elf32-visium.c (visium_elf_howto_parity_reloc): Minor tweak. 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: -- 2.30.2