Fix internal error caused by IFUNC patch.
authorCary Coutant <ccoutant@gmail.com>
Mon, 7 Sep 2015 16:44:11 +0000 (09:44 -0700)
committerCary Coutant <ccoutant@gmail.com>
Mon, 7 Sep 2015 16:44:11 +0000 (09:44 -0700)
The previous commit to fix PR gold/18886 converted STT_IFUNC
to STT_FUNC when resolving to a symbol defined in a shared library.
This leads to an internal error if the shared library symbol is
seen first, as we do not convert the symbol at all.

We need to override the STT_IFUNC in add_from_dynobj() instead of
in override_base().

gold/
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.

gold/ChangeLog
gold/resolve.cc
gold/symtab.cc

index cd24883b3a41146bc8ca40c9ac3c2a0842fc4255..49ce2fea8aa13c193a9e4b80b2b0bac6cf8993e1 100644 (file)
@@ -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
index dd5b6b6afa619600bbbd1bb694671613f5bcfc9b..2dcf7b5b1e8c6431029fe3f53f4b43d41d841bc2 100644 (file)
@@ -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();
index c0d21d6ff6ca63c3222fca3b9a9ca331507eba53..6d107a8b634c1aed3f82f2347689f4a28b5f2b70 100644 (file)
@@ -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;
        }