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.
This commit is contained in:
Maciej W. Rozycki 2016-05-16 08:51:26 +01:00
parent fcdad592cd
commit a43942db49
19 changed files with 104 additions and 83 deletions

View file

@ -1,3 +1,22 @@
2016-05-17 Maciej W. Rozycki <macro@imgtec.com>
* 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 <macro@imgtec.com> 2016-05-16 Maciej W. Rozycki <macro@imgtec.com>
* elf32-v850.c (v850_elf_copy_notes): New function, factored out * elf32-v850.c (v850_elf_copy_notes): New function, factored out

View file

@ -236,11 +236,10 @@ elf_s390_add_symbol_hook (bfd *abfd,
asection **secp ATTRIBUTE_UNUSED, asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED) bfd_vma *valp ATTRIBUTE_UNUSED)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -2742,11 +2742,10 @@ elf_arc_add_symbol_hook (bfd * abfd,
asection ** secp ATTRIBUTE_UNUSED, asection ** secp ATTRIBUTE_UNUSED,
bfd_vma * valp ATTRIBUTE_UNUSED) bfd_vma * valp ATTRIBUTE_UNUSED)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -17725,11 +17725,10 @@ elf32_arm_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
Elf_Internal_Sym *sym, const char **namep, Elf_Internal_Sym *sym, const char **namep,
flagword *flagsp, asection **secp, bfd_vma *valp) flagword *flagsp, asection **secp, bfd_vma *valp)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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) if (elf32_arm_hash_table (info) == NULL)
return FALSE; return FALSE;

View file

@ -5795,27 +5795,6 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
return _bfd_elf_hash_symbol (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_SYM i386_elf32_vec
#define TARGET_LITTLE_NAME "elf32-i386" #define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386 #define ELF_ARCH bfd_arch_i386
@ -5863,7 +5842,6 @@ elf_i386_add_symbol_hook (bfd * abfd,
#define elf_backend_omit_section_dynsym \ #define elf_backend_omit_section_dynsym \
((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_hash_symbol elf_i386_hash_symbol #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 #define elf_backend_fixup_symbol elf_i386_fixup_symbol
#include "elf32-target.h" #include "elf32-target.h"
@ -6053,9 +6031,6 @@ elf32_iamcu_elf_object_p (bfd *abfd)
#undef elf_backend_strtab_flags #undef elf_backend_strtab_flags
#undef elf_backend_copy_special_section_fields #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" #include "elf32-target.h"
/* Restore defaults. */ /* Restore defaults. */

View file

@ -4839,11 +4839,10 @@ elf_m68k_add_symbol_hook (bfd *abfd,
asection **secp ATTRIBUTE_UNUSED, asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED) bfd_vma *valp ATTRIBUTE_UNUSED)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -3674,11 +3674,10 @@ ppc_elf_add_symbol_hook (bfd *abfd,
*valp = sym->st_size; *valp = sym->st_size;
} }
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -180,11 +180,10 @@ elf32_sparc_add_symbol_hook (bfd * abfd,
asection ** secp ATTRIBUTE_UNUSED, asection ** secp ATTRIBUTE_UNUSED,
bfd_vma * valp ATTRIBUTE_UNUSED) bfd_vma * valp ATTRIBUTE_UNUSED)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -4894,11 +4894,10 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
asection **sec, asection **sec,
bfd_vma *value) bfd_vma *value)
{ {
if ((ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
&& (ibfd->flags & DYNAMIC) == 0 && (ibfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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 if (*sec != NULL
&& strcmp ((*sec)->name, ".opd") == 0) && strcmp ((*sec)->name, ".opd") == 0)

View file

@ -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" }; static const char *const stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" };
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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) if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER)
{ {

View file

@ -6277,7 +6277,7 @@ elf_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
static bfd_boolean static bfd_boolean
elf_x86_64_add_symbol_hook (bfd *abfd, elf_x86_64_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info, struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Sym *sym, Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED, const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED, flagword *flagsp ATTRIBUTE_UNUSED,
@ -6306,12 +6306,6 @@ elf_x86_64_add_symbol_hook (bfd *abfd,
return TRUE; 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; return TRUE;
} }

View file

@ -4380,6 +4380,11 @@ error_free_dyn:
(struct bfd_link_hash_entry **) sym_hash))) (struct bfd_link_hash_entry **) sym_hash)))
goto error_free_vers; 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; h = *sym_hash;
/* We need to make sure that indirect symbol dynamic flags are /* We need to make sure that indirect symbol dynamic flags are
updated. */ updated. */

View file

@ -538,11 +538,10 @@ _bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
asection **secp ATTRIBUTE_UNUSED, asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED) bfd_vma *valp ATTRIBUTE_UNUSED)
{ {
if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0 && (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) && 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; return TRUE;
} }

View file

@ -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; 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 /* 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 odd. This will cause something like .word SYM to come up with
the right value when it is loaded into the PC. */ the right value when it is loaded into the PC. */

View file

@ -1,3 +1,10 @@
2016-05-17 Maciej W. Rozycki <macro@imgtec.com>
* 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 <macro@imgtec.com> 2016-05-16 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/binutils-all/objcopy.exp: Don't skip the `strip-10' * testsuite/binutils-all/objcopy.exp: Don't skip the `strip-10'

View file

@ -1060,11 +1060,8 @@ if [is_elf_format] {
run_dump_test "strip-8" run_dump_test "strip-8"
run_dump_test "strip-9" run_dump_test "strip-9"
run_dump_test "strip-12" run_dump_test "strip-12"
# Non-EABI ARM targets will set OSABI to ARM # This requires STB_GNU_UNIQUE support with OSABI set to GNU.
if { ![istarget "*-*-hpux*"] if { [supports_gnu_unique] } {
&& ![istarget "msp*-*-*"]
&& ![istarget "visium-*-*"]
&& !([istarget "arm*-*-*"] && ![istarget "arm-*-*eabi*"])} {
run_dump_test "strip-10" run_dump_test "strip-10"
} }
set extra_strip11 "" set extra_strip11 ""

View file

@ -162,6 +162,46 @@ proc is_elf64 { binary_file } {
return 0 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 # 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. # is the expected output. Ignore blank lines in either file.
# #

View file

@ -1,3 +1,8 @@
2016-05-17 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/ld-unique/unique.exp: Use `is_elf_format' and
`supports_gnu_unique' to qualify testing.
2016-05-16 Maciej W. Rozycki <macro@imgtec.com> 2016-05-16 Maciej W. Rozycki <macro@imgtec.com>
* testsuite/ld-elf/flags1.d: Update the xfail list. * testsuite/ld-elf/flags1.d: Update the xfail list.

View file

@ -24,20 +24,13 @@
# Adapted for unique checking by Mark J. Wielaard <mjw@redhat.com> # Adapted for unique checking by Mark J. Wielaard <mjw@redhat.com>
# STB_GNU_UNIQUE support has only been implemented for the ix86, x86_64, # Exclude non-ELF targets.
# arm, mips, powerpc, and sparc so far. if { ![is_elf_format] } {
if {!(([istarget "i?86-*-*"] return
|| [istarget "x86_64-*-*"] }
|| [istarget "arm*-*-*"]
|| [istarget "mips*-*-*"] # Require STB_GNU_UNIQUE support with OSABI set to GNU.
|| [istarget "powerpc*-*-*"] if { ![supports_gnu_unique] } {
|| [istarget "sparc*-*-*"])
&& ([istarget "*-*-elf*"]
|| [istarget "*-*-nacl*"]
|| (([istarget "*-*-linux*"]
|| [istarget "*-*-gnu*"])
&& ![istarget "*-*-*aout*"]
&& ![istarget "*-*-*oldld*"]))) } {
verbose "UNIQUE tests not run - target does not support UNIQUE" verbose "UNIQUE tests not run - target does not support UNIQUE"
return return
} }