diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2019-02-07 17:04:31 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2019-02-07 17:10:35 +0100 |
commit | afbdeb58468604ede2d51fb00c4ea9850fcf2617 (patch) | |
tree | fcc97300896b93d81cdccbe0c593aef0247922de | |
parent | Visium: fix bogus overflow check on 32-bit hosts (diff) | |
download | binutils-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/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf32-sparc.c | 33 | ||||
-rw-r--r-- | bfd/elf64-sparc.c | 33 |
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: |