[binutils-gdb] Fix incorrect handling of STT_COMMON symbols in shared libraries.

Cary Coutant ccoutant@sourceware.org
Sun Jun 7 21:04:00 GMT 2015


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b8cf50755b573140aae71f7247b604373fcdfbeb

commit b8cf50755b573140aae71f7247b604373fcdfbeb
Author: Cary Coutant <ccoutant@gmail.com>
Date:   Sun Jun 7 14:03:09 2015 -0700

    Fix incorrect handling of STT_COMMON symbols in shared libraries.
    
    The gABI allows STT_COMMON symbols to appear in executables and shared
    objects, so that the dynamic loader can resolve commons across modules.
    When reading a shared object, however, an STT_COMMON symbol should be
    treated as a regular definition at link time.
    
    In a relocatable object, the gABI requires that any STT_COMMON symbols
    must also be defined in the special SHN_COMMON section (which we extend
    to include target-specific small and large common sections). Thus,
    there is no need for gold to treat STT_COMMON symbols as common unless
    the st_shndx field is also set to a common section.
    
    gold/
    	PR gold/18288
    	* resolve.cc (symbol_to_bits): Remove type parameter; adjust all
    	callers. Don't use STT_COMMON to check for common symbols.
    	(Symbol_table::resolve): Warn if relocatable object has STT_COMMON
    	symbol that's not in a common section.
    	* symtab.h (Symbol::is_common): Don't use STT_COMMON to check for
    	common symbols.

Diff:
---
 gold/ChangeLog  | 10 ++++++++++
 gold/resolve.cc | 30 +++++++++++++++++-------------
 gold/symtab.h   |  2 --
 3 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 8d9f414..30bd0a8 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,13 @@
+2015-06-07  Cary Coutant  <ccoutant@gmail.com>
+
+	PR gold/18288
+	* resolve.cc (symbol_to_bits): Remove type parameter; adjust all
+	callers. Don't use STT_COMMON to check for common symbols.
+	(Symbol_table::resolve): Warn if relocatable object has STT_COMMON
+	symbol that's not in a common section.
+	* symtab.h (Symbol::is_common): Don't use STT_COMMON to check for
+	common symbols.
+
 2015-06-04  Cary Coutant  <ccoutant@gmail.com>
 
 	PR gold/18200
diff --git a/gold/resolve.cc b/gold/resolve.cc
index 1c0344c..fdae0ba 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -173,7 +173,7 @@ static const unsigned int common_flag = 2 << def_undef_or_common_shift;
 
 static unsigned int
 symbol_to_bits(elfcpp::STB binding, bool is_dynamic,
-	       unsigned int shndx, bool is_ordinary, elfcpp::STT type)
+	       unsigned int shndx, bool is_ordinary)
 {
   unsigned int bits;
 
@@ -218,9 +218,7 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic,
       break;
 
     default:
-      if (type == elfcpp::STT_COMMON)
-	bits |= common_flag;
-      else if (!is_ordinary && Symbol::is_common_shndx(shndx))
+      if (!is_ordinary && Symbol::is_common_shndx(shndx))
 	bits |= common_flag;
       else
         bits |= def_flag;
@@ -272,6 +270,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
 
   if (!object->is_dynamic())
     {
+      if (sym.get_st_type() == elfcpp::STT_COMMON
+	  && (is_ordinary || !Symbol::is_common_shndx(st_shndx)))
+	{
+	  gold_warning(_("STT_COMMON symbol '%s' in %s "
+			 "is not in a common section"),
+		       to->demangled_name().c_str(),
+		       to->object()->name().c_str());
+	  return;
+	}
       // Record that we've seen this symbol in a regular object.
       to->set_in_reg();
     }
@@ -314,7 +321,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
 	  bool adjust_common = false;
 	  typename Sized_symbol<size>::Size_type tosize = 0;
 	  typename Sized_symbol<size>::Value_type tovalue = 0;
-	  if (to->is_common() && !is_ordinary && st_shndx == elfcpp::SHN_COMMON)
+	  if (to->is_common()
+	      && !is_ordinary && Symbol::is_common_shndx(st_shndx))
 	    {
 	      adjust_common = true;
 	      tosize = to->symsize();
@@ -370,8 +378,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
 			  : sym.get_st_type());
   unsigned int frombits = symbol_to_bits(sym.get_st_bind(),
                                          object->is_dynamic(),
-					 st_shndx, is_ordinary,
-                                         fromtype);
+					 st_shndx, is_ordinary);
 
   bool adjust_common_sizes;
   bool adjust_dyndef;
@@ -454,11 +461,9 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
 
   unsigned int tobits;
   if (to->source() == Symbol::IS_UNDEFINED)
-    tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true,
-			    to->type());
+    tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_UNDEF, true);
   else if (to->source() != Symbol::FROM_OBJECT)
-    tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false,
-			    to->type());
+    tobits = symbol_to_bits(to->binding(), false, elfcpp::SHN_ABS, false);
   else
     {
       bool is_ordinary;
@@ -466,8 +471,7 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
       tobits = symbol_to_bits(to->binding(),
 			      to->object()->is_dynamic(),
 			      shndx,
-			      is_ordinary,
-			      to->type());
+			      is_ordinary);
     }
 
   if ((to->type() == elfcpp::STT_TLS) ^ (fromtype == elfcpp::STT_TLS)
diff --git a/gold/symtab.h b/gold/symtab.h
index f6c0ac6..2c9aa32 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -557,8 +557,6 @@ class Symbol
   {
     if (this->source_ != FROM_OBJECT)
       return false;
-    if (this->type_ == elfcpp::STT_COMMON)
-      return true;
     bool is_ordinary;
     unsigned int shndx = this->shndx(&is_ordinary);
     return !is_ordinary && Symbol::is_common_shndx(shndx);



More information about the Binutils-cvs mailing list