aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog7
-rw-r--r--gold/resolve.cc8
-rw-r--r--gold/symtab.cc10
3 files changed, 16 insertions, 9 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index cd24883..49ce2fe 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,10 @@
+2015-09-07 Cary Coutant <ccoutant@gmail.com>
+
+ PR gold/18930
+ PR gold/18886
+ * resolve.cc (Symbol::override_base): Don't convert IFUNC symbols here.
+ * symtab.cc (Symbol_table::add_from_dynobj): Convert them here instead.
+
2015-09-02 H.J. Lu <hongjiu.lu@intel.com>
PR gold/18886
diff --git a/gold/resolve.cc b/gold/resolve.cc
index dd5b6b6..2dcf7b5 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -98,13 +98,7 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym,
this->is_ordinary_shndx_ = is_ordinary;
// Don't override st_type from plugin placeholder symbols.
if (object->pluginobj() == NULL)
- {
- // Turn IFUNC symbols from shared libraries into normal FUNC symbols.
- elfcpp::STT type = sym.get_st_type();
- if (object->is_dynamic() && type == elfcpp::STT_GNU_IFUNC)
- type = elfcpp::STT_FUNC;
- this->type_ = type;
- }
+ this->type_ = sym.get_st_type();
this->binding_ = sym.get_st_bind();
this->override_visibility(sym.get_st_visibility());
this->nonvis_ = sym.get_st_nonvis();
diff --git a/gold/symtab.cc b/gold/symtab.cc
index c0d21d6..6d107a8 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1468,14 +1468,20 @@ Symbol_table::add_from_dynobj(
// A protected symbol in a shared library must be treated as a
// normal symbol when viewed from outside the shared library.
// Implement this by overriding the visibility here.
+ // Likewise, an IFUNC symbol in a shared library must be treated
+ // as a normal FUNC symbol.
elfcpp::Sym<size, big_endian>* psym = &sym;
unsigned char symbuf[sym_size];
elfcpp::Sym<size, big_endian> sym2(symbuf);
- if (sym.get_st_visibility() == elfcpp::STV_PROTECTED)
+ if (sym.get_st_visibility() == elfcpp::STV_PROTECTED
+ || sym.get_st_type() == elfcpp::STT_GNU_IFUNC)
{
memcpy(symbuf, p, sym_size);
elfcpp::Sym_write<size, big_endian> sw(symbuf);
- sw.put_st_other(elfcpp::STV_DEFAULT, sym.get_st_nonvis());
+ if (sym.get_st_visibility() == elfcpp::STV_PROTECTED)
+ sw.put_st_other(elfcpp::STV_DEFAULT, sym.get_st_nonvis());
+ if (sym.get_st_type() == elfcpp::STT_GNU_IFUNC)
+ sw.put_st_info(sym.get_st_bind(), elfcpp::STT_FUNC);
psym = &sym2;
}