aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-11-28 08:03:46 -0800
committerH.J. Lu <hjl.tools@gmail.com>2016-11-28 08:03:46 -0800
commit4deb8f714d555a2f530e37c3e7af32bc42fdda58 (patch)
tree4f5c4fc9e7e3347ae4e8cb222032d7e64e9231ad
parent9e27646a6dedd071bdc8a7ba75eca1faaf500366 (diff)
downloadgdb-4deb8f714d555a2f530e37c3e7af32bc42fdda58.zip
gdb-4deb8f714d555a2f530e37c3e7af32bc42fdda58.tar.gz
gdb-4deb8f714d555a2f530e37c3e7af32bc42fdda58.tar.bz2
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.
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elflink.c55
-rw-r--r--ld/ChangeLog5
-rw-r--r--ld/testsuite/ld-elf/indirect.exp3
-rw-r--r--ld/testsuite/ld-elf/pr18720.rd4
5 files changed, 46 insertions, 28 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 0d79764..99b0f8b 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
PR ld/20193
diff --git a/bfd/elflink.c b/bfd/elflink.c
index ddbe801..5f87f87 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2654,18 +2654,35 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
&& (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0)
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
symbols to the definition within the shared object), and this
symbol was defined in a regular object, then it actually doesn't
need a PLT entry. Likewise, if the symbol has non-default
visibility. If the symbol has hidden or internal visibility, we
will force it local. */
- if (h->needs_plt
- && bfd_link_pic (eif->info)
- && is_elf_hash_table (eif->info->hash)
- && (SYMBOLIC_BIND (eif->info, h)
- || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- && h->def_regular)
+ else if (h->needs_plt
+ && bfd_link_pic (eif->info)
+ && is_elf_hash_table (eif->info->hash)
+ && (SYMBOLIC_BIND (eif->info, h)
+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ && h->def_regular)
{
bfd_boolean force_local;
@@ -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);
}
- /* 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
the real definition in the dynamic object, copy interesting flags
over to the real definition. */
@@ -9249,16 +9260,6 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
long indx;
int ret;
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)
{
@@ -9270,12 +9271,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
/* Decide whether to output this symbol in this pass. */
if (eoinfo->localsyms)
{
- if (!local_bind)
+ if (!h->forced_local)
return TRUE;
}
else
{
- if (local_bind)
+ if (h->forced_local)
return TRUE;
}
@@ -9492,7 +9493,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
abort ();
}
- if (local_bind)
+ if (h->forced_local)
{
sym.st_info = ELF_ST_INFO (STB_LOCAL, type);
/* 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,
if there is no version info in symbol version section, we will
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
- && !local_bind
&& (!bfd_link_executable (flinfo->info)
|| h->ref_dynamic
|| !h->def_regular))
diff --git a/ld/ChangeLog b/ld/ChangeLog
index d612849..8040aa0 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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>
PR 20815
diff --git a/ld/testsuite/ld-elf/indirect.exp b/ld/testsuite/ld-elf/indirect.exp
index b4766fd..3176210 100644
--- a/ld/testsuite/ld-elf/indirect.exp
+++ b/ld/testsuite/ld-elf/indirect.exp
@@ -91,6 +91,9 @@ set build_tests {
{"Build pr18720b1.o"
"-r -nostdlib tmpdir/pr18720b.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"
"-shared -Wl,--version-script=pr19553.map" "-fPIC"
{pr19553b.c} {} "libpr19553b.so"}
diff --git a/ld/testsuite/ld-elf/pr18720.rd b/ld/testsuite/ld-elf/pr18720.rd
new file mode 100644
index 0000000..b5e848f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr18720.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+.* found at index >= .dynsym's sh_info value .*
+#...