gold: Ignore def/ref from a dynamic object for special symbols
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 8 Nov 2017 23:56:54 +0000 (15:56 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 9 Nov 2017 00:02:50 +0000 (16:02 -0800)
Since special symbol must be defined in a regular object, definition
from a dynamic object should be ignored.  If special symbol has the
hidden or internal visibility, reference from a dynamic object should
also be ignored.  Also __start and __stop symbols in a dynamic object
shouldn't be preempted.

PR gold/22291
* layout.cc (Layout::define_section_symbols): Use STV_PROTECTED
for __start and __stop symbols.
* symtab.cc (Symbol_table::define_special_symbol): Add an
argument, visibility.  Ignore definition and reference from
a dynamic object, depending on visibility.
(Symbol_table::do_define_in_output_data): Pass visibility to
define_special_symbol.
(Symbol_table::do_define_in_output_segment): Likewise.
(Symbol_table::do_define_as_constant): Likewise.
(Symbol_table::add_undefined_symbol_from_command_line): Pass
STV_DEFAULT to define_special_symbol.
* symtab.h (Symbol_table::define_special_symbol): Add an
argument, visibility.

gold/ChangeLog
gold/layout.cc
gold/symtab.cc
gold/symtab.h

index c4c171d..bd842a6 100644 (file)
@@ -1,3 +1,20 @@
+2017-11-08  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR gold/22291
+       * layout.cc (Layout::define_section_symbols): Use STV_PROTECTED
+       for __start and __stop symbols.
+       * symtab.cc (Symbol_table::define_special_symbol): Add an
+       argument, visibility.  Ignore definition and reference from
+       a dynamic object, depending on visibility.
+       (Symbol_table::do_define_in_output_data): Pass visibility to
+       define_special_symbol.
+       (Symbol_table::do_define_in_output_segment): Likewise.
+       (Symbol_table::do_define_as_constant): Likewise.
+       (Symbol_table::add_undefined_symbol_from_command_line): Pass
+       STV_DEFAULT to define_special_symbol.
+       * symtab.h (Symbol_table::define_special_symbol): Add an
+       argument, visibility.
+
 2017-11-08  James Clarke  <jrtc27@jrtc27.com>
 
        PR gold/22266
index 15c5434..351c4b4 100644 (file)
@@ -2252,7 +2252,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_DEFAULT,
+                                       elfcpp::STV_PROTECTED,
                                        0, // nonvis
                                        false, // offset_is_from_end
                                        true); // only_if_ref
@@ -2265,7 +2265,7 @@ Layout::define_section_symbols(Symbol_table* symtab)
                                        0, // symsize
                                        elfcpp::STT_NOTYPE,
                                        elfcpp::STB_GLOBAL,
-                                       elfcpp::STV_DEFAULT,
+                                       elfcpp::STV_PROTECTED,
                                        0, // nonvis
                                        true, // offset_is_from_end
                                        true); // only_if_ref
index 7ebcd6b..d1f71e0 100644 (file)
@@ -1761,6 +1761,7 @@ template<int size, bool big_endian>
 Sized_symbol<size>*
 Symbol_table::define_special_symbol(const char** pname, const char** pversion,
                                    bool only_if_ref,
+                                   elfcpp::STV visibility,
                                     Sized_symbol<size>** poldsym,
                                    bool* resolve_oldsym, bool is_forced_local)
 {
@@ -1799,8 +1800,21 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion,
       oldsym = this->lookup(*pname, *pversion);
       if (oldsym == NULL && is_default_version)
        oldsym = this->lookup(*pname, NULL);
-      if (oldsym == NULL || !oldsym->is_undefined())
+      if (oldsym == NULL)
        return NULL;
+      if (!oldsym->is_undefined())
+       {
+         // Skip if the old definition is from a regular object.
+         if (!oldsym->is_from_dynobj())
+           return NULL;
+
+         // If the symbol has hidden or internal visibility, ignore
+         // definition and reference from a dynamic object.
+         if ((visibility == elfcpp::STV_HIDDEN
+              || visibility == elfcpp::STV_INTERNAL)
+             && !oldsym->in_reg())
+           return NULL;
+       }
 
       *pname = oldsym->name();
       if (is_default_version)
@@ -1975,7 +1989,9 @@ Symbol_table::do_define_in_output_data(
     {
 #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
       sym = this->define_special_symbol<size, true>(&name, &version,
-                                                   only_if_ref, &oldsym,
+                                                   only_if_ref,
+                                                   visibility,
+                                                   &oldsym,
                                                    &resolve_oldsym,
                                                    is_forced_local);
 #else
@@ -1986,7 +2002,9 @@ Symbol_table::do_define_in_output_data(
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
       sym = this->define_special_symbol<size, false>(&name, &version,
-                                                    only_if_ref, &oldsym,
+                                                    only_if_ref,
+                                                    visibility,
+                                                    &oldsym,
                                                     &resolve_oldsym,
                                                     is_forced_local);
 #else
@@ -2094,7 +2112,9 @@ Symbol_table::do_define_in_output_segment(
     {
 #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
       sym = this->define_special_symbol<size, true>(&name, &version,
-                                                   only_if_ref, &oldsym,
+                                                   only_if_ref,
+                                                   visibility,
+                                                   &oldsym,
                                                    &resolve_oldsym,
                                                    is_forced_local);
 #else
@@ -2105,7 +2125,9 @@ Symbol_table::do_define_in_output_segment(
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
       sym = this->define_special_symbol<size, false>(&name, &version,
-                                                    only_if_ref, &oldsym,
+                                                    only_if_ref,
+                                                    visibility,
+                                                    &oldsym,
                                                     &resolve_oldsym,
                                                     is_forced_local);
 #else
@@ -2211,7 +2233,9 @@ Symbol_table::do_define_as_constant(
     {
 #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
       sym = this->define_special_symbol<size, true>(&name, &version,
-                                                   only_if_ref, &oldsym,
+                                                   only_if_ref,
+                                                   visibility,
+                                                   &oldsym,
                                                    &resolve_oldsym,
                                                    is_forced_local);
 #else
@@ -2222,7 +2246,9 @@ Symbol_table::do_define_as_constant(
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
       sym = this->define_special_symbol<size, false>(&name, &version,
-                                                    only_if_ref, &oldsym,
+                                                    only_if_ref,
+                                                    visibility,
+                                                    &oldsym,
                                                     &resolve_oldsym,
                                                     is_forced_local);
 #else
@@ -2449,7 +2475,9 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name)
     {
 #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
       sym = this->define_special_symbol<size, true>(&name, &version,
-                                                   false, &oldsym,
+                                                   false,
+                                                   elfcpp::STV_DEFAULT,
+                                                   &oldsym,
                                                    &resolve_oldsym,
                                                    false);
 #else
@@ -2460,7 +2488,9 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name)
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
       sym = this->define_special_symbol<size, false>(&name, &version,
-                                                    false, &oldsym,
+                                                    false,
+                                                    elfcpp::STV_DEFAULT,
+                                                    &oldsym,
                                                     &resolve_oldsym,
                                                     false);
 #else
index a67d5eb..edf1c17 100644 (file)
@@ -1830,7 +1830,8 @@ class Symbol_table
   template<int size, bool big_endian>
   Sized_symbol<size>*
   define_special_symbol(const char** pname, const char** pversion,
-                       bool only_if_ref, Sized_symbol<size>** poldsym,
+                       bool only_if_ref, elfcpp::STV visibility,
+                       Sized_symbol<size>** poldsym,
                        bool* resolve_oldsym, bool is_forced_local);
 
   // Define a symbol in an Output_data, sized version.