From a43942db49b07a457ee4f960d0f118b23641ec38 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 16 May 2016 08:51:26 +0100 Subject: [PATCH] LD/ELF: Unify STB_GNU_UNIQUE handling Take STB_GNU_UNIQUE handling scattered across targets and gather it in the generic ELF linker. Update test suite infrastructure accordingly. bfd/ * elf-s390-common.c (elf_s390_add_symbol_hook): Remove STB_GNU_UNIQUE handling. * elf32-arc.c (elf_arc_add_symbol_hook): Likewise. * elf32-arm.c (elf32_arm_add_symbol_hook): Likewise. * elf32-m68k.c (elf_m68k_add_symbol_hook): Likewise. * elf32-ppc.c (ppc_elf_add_symbol_hook): Likewise. * elf32-sparc.c (elf32_sparc_add_symbol_hook): Likewise. * elf64-ppc.c (ppc64_elf_add_symbol_hook): Likewise. * elf64-sparc.c (elf64_sparc_add_symbol_hook): Likewise. * elf64-x86-64.c (elf_x86_64_add_symbol_hook): Likewise. * elfxx-aarch64.c (_bfd_aarch64_elf_add_symbol_hook): Likewise. * elfxx-mips.c (_bfd_mips_elf_add_symbol_hook): Likewise. * elf32-i386.c (elf_i386_add_symbol_hook): Remove function. (elf_backend_add_symbol_hook): Remove macro. * elflink.c (elf_link_add_object_symbols): Set `has_gnu_symbols' for STB_GNU_UNIQUE symbols. binutils/ * testsuite/lib/binutils-common.exp (supports_gnu_unique): New procedure. * testsuite/binutils-all/objcopy.exp: Use `supports_gnu_unique' with the `strip-10' test. ld/ * testsuite/ld-unique/unique.exp: Use `is_elf_format' and `supports_gnu_unique' to qualify testing. --- bfd/ChangeLog | 19 ++++++++++++++ bfd/elf-s390-common.c | 5 ++-- bfd/elf32-arc.c | 5 ++-- bfd/elf32-arm.c | 5 ++-- bfd/elf32-i386.c | 25 ------------------ bfd/elf32-m68k.c | 5 ++-- bfd/elf32-ppc.c | 5 ++-- bfd/elf32-sparc.c | 5 ++-- bfd/elf64-ppc.c | 5 ++-- bfd/elf64-sparc.c | 5 ++-- bfd/elf64-x86-64.c | 8 +----- bfd/elflink.c | 5 ++++ bfd/elfxx-aarch64.c | 5 ++-- bfd/elfxx-mips.c | 5 ---- binutils/ChangeLog | 7 +++++ binutils/testsuite/binutils-all/objcopy.exp | 7 ++--- binutils/testsuite/lib/binutils-common.exp | 40 +++++++++++++++++++++++++++++ ld/ChangeLog | 5 ++++ ld/testsuite/ld-unique/unique.exp | 21 +++++---------- 19 files changed, 104 insertions(+), 83 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9f1bb70..57a8189 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2016-05-17 Maciej W. Rozycki + + * elf-s390-common.c (elf_s390_add_symbol_hook): Remove + STB_GNU_UNIQUE handling. + * elf32-arc.c (elf_arc_add_symbol_hook): Likewise. + * elf32-arm.c (elf32_arm_add_symbol_hook): Likewise. + * elf32-m68k.c (elf_m68k_add_symbol_hook): Likewise. + * elf32-ppc.c (ppc_elf_add_symbol_hook): Likewise. + * elf32-sparc.c (elf32_sparc_add_symbol_hook): Likewise. + * elf64-ppc.c (ppc64_elf_add_symbol_hook): Likewise. + * elf64-sparc.c (elf64_sparc_add_symbol_hook): Likewise. + * elf64-x86-64.c (elf_x86_64_add_symbol_hook): Likewise. + * elfxx-aarch64.c (_bfd_aarch64_elf_add_symbol_hook): Likewise. + * elfxx-mips.c (_bfd_mips_elf_add_symbol_hook): Likewise. + * elf32-i386.c (elf_i386_add_symbol_hook): Remove function. + (elf_backend_add_symbol_hook): Remove macro. + * elflink.c (elf_link_add_object_symbols): Set `has_gnu_symbols' + for STB_GNU_UNIQUE symbols. + 2016-05-16 Maciej W. Rozycki * elf32-v850.c (v850_elf_copy_notes): New function, factored out diff --git a/bfd/elf-s390-common.c b/bfd/elf-s390-common.c index 51c8d7e..2170da0 100644 --- a/bfd/elf-s390-common.c +++ b/bfd/elf-s390-common.c @@ -236,11 +236,10 @@ elf_s390_add_symbol_hook (bfd *abfd, asection **secp ATTRIBUTE_UNUSED, bfd_vma *valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index f7b0fff..d765dd4 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -2742,11 +2742,10 @@ elf_arc_add_symbol_hook (bfd * abfd, asection ** secp ATTRIBUTE_UNUSED, bfd_vma * valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 65b593a..c21d45a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -17725,11 +17725,10 @@ elf32_arm_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep, flagword *flagsp, asection **secp, bfd_vma *valp) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; if (elf32_arm_hash_table (info) == NULL) return FALSE; diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index df08dd4..fcb22c4 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -5795,27 +5795,6 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h) return _bfd_elf_hash_symbol (h); } -/* Hook called by the linker routine which adds symbols from an object - file. */ - -static bfd_boolean -elf_i386_add_symbol_hook (bfd * abfd, - struct bfd_link_info * info, - 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_BIND (sym->st_info) == STB_GNU_UNIQUE - && (abfd->flags & DYNAMIC) == 0 - && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_unique; - - return TRUE; -} - #define TARGET_LITTLE_SYM i386_elf32_vec #define TARGET_LITTLE_NAME "elf32-i386" #define ELF_ARCH bfd_arch_i386 @@ -5863,7 +5842,6 @@ elf_i386_add_symbol_hook (bfd * abfd, #define elf_backend_omit_section_dynsym \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_hash_symbol elf_i386_hash_symbol -#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook #define elf_backend_fixup_symbol elf_i386_fixup_symbol #include "elf32-target.h" @@ -6053,9 +6031,6 @@ elf32_iamcu_elf_object_p (bfd *abfd) #undef elf_backend_strtab_flags #undef elf_backend_copy_special_section_fields -#undef elf_backend_add_symbol_hook -#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook - #include "elf32-target.h" /* Restore defaults. */ diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 586f4c9..fa52bc9 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -4839,11 +4839,10 @@ elf_m68k_add_symbol_hook (bfd *abfd, asection **secp ATTRIBUTE_UNUSED, bfd_vma *valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index f3e5e42..856bef1 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -3674,11 +3674,10 @@ ppc_elf_add_symbol_hook (bfd *abfd, *valp = sym->st_size; } - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index 495d55a..5f20846 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -180,11 +180,10 @@ elf32_sparc_add_symbol_hook (bfd * abfd, asection ** secp ATTRIBUTE_UNUSED, bfd_vma * valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index d15f50b..95d98eb 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -4894,11 +4894,10 @@ ppc64_elf_add_symbol_hook (bfd *ibfd, asection **sec, bfd_vma *value) { - if ((ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC && (ibfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; if (*sec != NULL && strcmp ((*sec)->name, ".opd") == 0) diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index 1aa785b..c700b7e 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -426,11 +426,10 @@ 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_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER) { diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 9fc884e..170b61a 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -6277,7 +6277,7 @@ elf_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, static bfd_boolean elf_x86_64_add_symbol_hook (bfd *abfd, - struct bfd_link_info *info, + struct bfd_link_info *info ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym, const char **namep ATTRIBUTE_UNUSED, flagword *flagsp ATTRIBUTE_UNUSED, @@ -6306,12 +6306,6 @@ elf_x86_64_add_symbol_hook (bfd *abfd, return TRUE; } - if (ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE - && (abfd->flags & DYNAMIC) == 0 - && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols - |= elf_gnu_symbol_unique; - return TRUE; } diff --git a/bfd/elflink.c b/bfd/elflink.c index 1223d27..1569e93 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4380,6 +4380,11 @@ error_free_dyn: (struct bfd_link_hash_entry **) sym_hash))) goto error_free_vers; + if ((flags & BSF_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique; + h = *sym_hash; /* We need to make sure that indirect symbol dynamic flags are updated. */ diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c index 498171c..c861170 100644 --- a/bfd/elfxx-aarch64.c +++ b/bfd/elfxx-aarch64.c @@ -538,11 +538,10 @@ _bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, asection **secp ATTRIBUTE_UNUSED, bfd_vma *valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; } diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index f215341..cb775bb 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -7526,11 +7526,6 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, mips_elf_hash_table (info)->rld_symbol = h; } - if (ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE - && (abfd->flags & DYNAMIC) == 0 - && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique; - /* If this is a mips16 text symbol, add 1 to the value to make it odd. This will cause something like .word SYM to come up with the right value when it is loaded into the PC. */ diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 57802e8..faa9b78 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2016-05-17 Maciej W. Rozycki + + * testsuite/lib/binutils-common.exp (supports_gnu_unique): New + procedure. + * testsuite/binutils-all/objcopy.exp: Use `supports_gnu_unique' + with the `strip-10' test. + 2016-05-16 Maciej W. Rozycki * testsuite/binutils-all/objcopy.exp: Don't skip the `strip-10' diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp index 176764a..af333ac 100644 --- a/binutils/testsuite/binutils-all/objcopy.exp +++ b/binutils/testsuite/binutils-all/objcopy.exp @@ -1060,11 +1060,8 @@ if [is_elf_format] { run_dump_test "strip-8" run_dump_test "strip-9" run_dump_test "strip-12" - # Non-EABI ARM targets will set OSABI to ARM - if { ![istarget "*-*-hpux*"] - && ![istarget "msp*-*-*"] - && ![istarget "visium-*-*"] - && !([istarget "arm*-*-*"] && ![istarget "arm-*-*eabi*"])} { + # This requires STB_GNU_UNIQUE support with OSABI set to GNU. + if { [supports_gnu_unique] } { run_dump_test "strip-10" } set extra_strip11 "" diff --git a/binutils/testsuite/lib/binutils-common.exp b/binutils/testsuite/lib/binutils-common.exp index 5f17012..33a0382 100644 --- a/binutils/testsuite/lib/binutils-common.exp +++ b/binutils/testsuite/lib/binutils-common.exp @@ -162,6 +162,46 @@ proc is_elf64 { binary_file } { return 0 } +# True if the ELF target supports STB_GNU_UNIQUE with the ELF header's +# OSABI field set to ELFOSABI_GNU. +# +# This generally depends on the target OS only, however there are a +# number of exceptions for bare metal targets as follows. The MSP430 +# and Visium targets set OSABI to ELFOSABI_STANDALONE and cannot +# support STB_GNU_UNIQUE. Likewise non-EABI ARM targets set OSABI to +# ELFOSABI_ARM, and TI C6X targets to ELFOSABI_C6000_*. Finally +# rather than `bfd_elf_final_link' AM33/2.0, D30V, DLX, i960, and +# picoJava targets use `_bfd_generic_final_link', which does not +# support STB_GNU_UNIQUE symbol binding causing assertion failures. +# +proc supports_gnu_unique {} { + if { [istarget *-*-gnu*] + || [istarget *-*-linux*] + || [istarget *-*-nacl*] } { + return 1 + } + if { [istarget "arm*-*-*eabi*"] } { + return 1 + } + if { ![istarget "*-*-elf*"] } { + return 0 + } + if { [istarget "arm*-*-*"] + || [istarget "msp430-*-*"] + || [istarget "tic6x-*-*"] + || [istarget "visium-*-*"] } { + return 0 + } + if { [istarget "am33_2.0-*-*"] + || [istarget "d30v-*-*"] + || [istarget "dlx-*-*"] + || [istarget "i960-*-*"] + || [istarget "pj*-*-*"] } { + return 0 + } + return 1 +} + # Compare two files line-by-line. FILE_1 is the actual output and FILE_2 # is the expected output. Ignore blank lines in either file. # diff --git a/ld/ChangeLog b/ld/ChangeLog index 3f933e4..783355c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2016-05-17 Maciej W. Rozycki + + * testsuite/ld-unique/unique.exp: Use `is_elf_format' and + `supports_gnu_unique' to qualify testing. + 2016-05-16 Maciej W. Rozycki * testsuite/ld-elf/flags1.d: Update the xfail list. diff --git a/ld/testsuite/ld-unique/unique.exp b/ld/testsuite/ld-unique/unique.exp index a34bc4c..ccddad6 100644 --- a/ld/testsuite/ld-unique/unique.exp +++ b/ld/testsuite/ld-unique/unique.exp @@ -24,20 +24,13 @@ # Adapted for unique checking by Mark J. Wielaard -# STB_GNU_UNIQUE support has only been implemented for the ix86, x86_64, -# arm, mips, powerpc, and sparc so far. -if {!(([istarget "i?86-*-*"] - || [istarget "x86_64-*-*"] - || [istarget "arm*-*-*"] - || [istarget "mips*-*-*"] - || [istarget "powerpc*-*-*"] - || [istarget "sparc*-*-*"]) - && ([istarget "*-*-elf*"] - || [istarget "*-*-nacl*"] - || (([istarget "*-*-linux*"] - || [istarget "*-*-gnu*"]) - && ![istarget "*-*-*aout*"] - && ![istarget "*-*-*oldld*"]))) } { +# Exclude non-ELF targets. +if { ![is_elf_format] } { + return +} + +# Require STB_GNU_UNIQUE support with OSABI set to GNU. +if { ![supports_gnu_unique] } { verbose "UNIQUE tests not run - target does not support UNIQUE" return } -- 2.7.4