Properly hide hidden versioned symbol in executable

A hidden versioned symbol in executable should be forced local if it is
locally defined, not referenced by shared library and not exported.  We
must do it before _bfd_elf_link_renumber_dynsyms.

bfd/

	* elflink.c (_bfd_elf_fix_symbol_flags): Hide hidden versioned
	symbol in executable.
	(elf_link_output_extsym): Don't change bind from global to
	local when linking executable.

ld/

	* testsuite/ld-elf/indirect.exp: Add a test for PR 18720.
	* testsuite/ld-elf/pr18720.rd: New file.
This commit is contained in:
H.J. Lu
2016-11-28 08:03:46 -08:00
parent 9e27646a6d
commit 4deb8f714d
5 changed files with 46 additions and 28 deletions

View File

@ -1,3 +1,10 @@
2016-11-28 H.J. Lu <hongjiu.lu@intel.com>
* elflink.c (_bfd_elf_fix_symbol_flags): Hide hidden versioned
symbol in executable.
(elf_link_output_extsym): Don't change bind from global to
local when linking executable.
2016-11-25 Jon Turney <jon.turney@dronecode.org.uk> 2016-11-25 Jon Turney <jon.turney@dronecode.org.uk>
PR ld/20193 PR ld/20193

View File

@ -2654,13 +2654,30 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
&& (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0) && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
h->def_regular = 1; h->def_regular = 1;
/* If a weak undefined symbol has non-default visibility, we also
hide it from the dynamic linker. */
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
&& h->root.type == bfd_link_hash_undefweak)
(*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
/* A hidden versioned symbol in executable should be forced local if
it is is locally defined, not referenced by shared library and not
exported. */
else if (bfd_link_executable (eif->info)
&& h->versioned == versioned_hidden
&& !eif->info->export_dynamic
&& !h->dynamic
&& !h->ref_dynamic
&& h->def_regular)
(*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
/* If -Bsymbolic was used (which means to bind references to global /* If -Bsymbolic was used (which means to bind references to global
symbols to the definition within the shared object), and this symbols to the definition within the shared object), and this
symbol was defined in a regular object, then it actually doesn't symbol was defined in a regular object, then it actually doesn't
need a PLT entry. Likewise, if the symbol has non-default need a PLT entry. Likewise, if the symbol has non-default
visibility. If the symbol has hidden or internal visibility, we visibility. If the symbol has hidden or internal visibility, we
will force it local. */ will force it local. */
if (h->needs_plt else if (h->needs_plt
&& bfd_link_pic (eif->info) && bfd_link_pic (eif->info)
&& is_elf_hash_table (eif->info->hash) && is_elf_hash_table (eif->info->hash)
&& (SYMBOLIC_BIND (eif->info, h) && (SYMBOLIC_BIND (eif->info, h)
@ -2674,12 +2691,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
(*bed->elf_backend_hide_symbol) (eif->info, h, force_local); (*bed->elf_backend_hide_symbol) (eif->info, h, force_local);
} }
/* If a weak undefined symbol has non-default visibility, we also
hide it from the dynamic linker. */
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
&& h->root.type == bfd_link_hash_undefweak)
(*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
/* If this is a weak defined symbol in a dynamic object, and we know /* If this is a weak defined symbol in a dynamic object, and we know
the real definition in the dynamic object, copy interesting flags the real definition in the dynamic object, copy interesting flags
over to the real definition. */ over to the real definition. */
@ -9249,16 +9260,6 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
long indx; long indx;
int ret; int ret;
unsigned int type; unsigned int type;
/* A symbol is bound locally if it is forced local or it is locally
defined, hidden versioned, not referenced by shared library and
not exported when linking executable. */
bfd_boolean local_bind = (h->forced_local
|| (bfd_link_executable (flinfo->info)
&& !flinfo->info->export_dynamic
&& !h->dynamic
&& !h->ref_dynamic
&& h->def_regular
&& h->versioned == versioned_hidden));
if (h->root.type == bfd_link_hash_warning) if (h->root.type == bfd_link_hash_warning)
{ {
@ -9270,12 +9271,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
/* Decide whether to output this symbol in this pass. */ /* Decide whether to output this symbol in this pass. */
if (eoinfo->localsyms) if (eoinfo->localsyms)
{ {
if (!local_bind) if (!h->forced_local)
return TRUE; return TRUE;
} }
else else
{ {
if (local_bind) if (h->forced_local)
return TRUE; return TRUE;
} }
@ -9492,7 +9493,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
abort (); abort ();
} }
if (local_bind) if (h->forced_local)
{ {
sym.st_info = ELF_ST_INFO (STB_LOCAL, type); sym.st_info = ELF_ST_INFO (STB_LOCAL, type);
/* Turn off visibility on local symbol. */ /* Turn off visibility on local symbol. */
@ -9603,10 +9604,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
/* Since there is no version information in the dynamic string, /* Since there is no version information in the dynamic string,
if there is no version info in symbol version section, we will if there is no version info in symbol version section, we will
have a run-time problem if not linking executable, referenced have a run-time problem if not linking executable, referenced
by shared library, not locally defined, or not bound locally. by shared library, or not bound locally. */
*/
if (h->verinfo.verdef == NULL if (h->verinfo.verdef == NULL
&& !local_bind
&& (!bfd_link_executable (flinfo->info) && (!bfd_link_executable (flinfo->info)
|| h->ref_dynamic || h->ref_dynamic
|| !h->def_regular)) || !h->def_regular))

View File

@ -1,3 +1,8 @@
2016-11-28 H.J. Lu <hongjiu.lu@intel.com>
* testsuite/ld-elf/indirect.exp: Add a test for PR 18720.
* testsuite/ld-elf/pr18720.rd: New file.
2016-11-27 Alan Modra <amodra@gmail.com> 2016-11-27 Alan Modra <amodra@gmail.com>
PR 20815 PR 20815

View File

@ -91,6 +91,9 @@ set build_tests {
{"Build pr18720b1.o" {"Build pr18720b1.o"
"-r -nostdlib tmpdir/pr18720b.o" "" "-r -nostdlib tmpdir/pr18720b.o" ""
{dummy.c} {} "pr18720b1.o"} {dummy.c} {} "pr18720b1.o"}
{"Build pr18720a"
"tmpdir/pr18720a.o tmpdir/pr18720b.o tmpdir/libpr18720c.so" ""
{check-ptr-eq.c} {{readelf {--dyn-syms} pr18720.rd}} "pr18720a"}
{"Build libpr19553b.so" {"Build libpr19553b.so"
"-shared -Wl,--version-script=pr19553.map" "-fPIC" "-shared -Wl,--version-script=pr19553.map" "-fPIC"
{pr19553b.c} {} "libpr19553b.so"} {pr19553b.c} {} "libpr19553b.so"}

View File

@ -0,0 +1,4 @@
#failif
#...
.* found at index >= .dynsym's sh_info value .*
#...