[GOLD] powerpc .got symbol

Alan Modra amodra@gmail.com
Fri Nov 30 04:48:00 GMT 2012


Powerpc32 relocations may refer to the "_GLOBAL_OFFSET_TABLE_" symbol
before we have created a .got section.  That can result in
Scan::global() wrongly deciding to create dynamic relocations against
the symbol.  One approach (as used by arm.cc) is to check for the
symbol on every relocation.  I chose instead to define the symbol
early, checking once per object file.  However, making the early
_GLOBAL_OFFSET_TABLE_ weak as I did ran into problems with symbol
versioning.  So this patch makes the early definition local, and
simply updates its value later.  Committed.

	* powerpc.cc (Powerpc_relobj::do_scan_relocs): Make STB_LOCAL
	_GLOBAL_OFFSET_TABLE_ rather than STB_WEAK.
	(Output_data_got_powerpc::make_header): Update _GLOBAL_OFFSET_TABLE_
	value if it already exists.

Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.68
diff -u -p -r1.68 powerpc.cc
--- gold/powerpc.cc	5 Nov 2012 03:29:58 -0000	1.68
+++ gold/powerpc.cc	30 Nov 2012 03:25:22 -0000
@@ -1391,8 +1391,8 @@ Powerpc_relobj<size, big_endian>::do_sca
 {
   if (size == 32)
     {
-      // Define a weak hidden _GLOBAL_OFFSET_TABLE_ to ensure it isn't
-      // seen as undefined when scanning relocs (and thus requires
+      // Define _GLOBAL_OFFSET_TABLE_ to ensure it isn't seen as
+      // undefined when scanning relocs (and thus requires
       // non-relative dynamic relocs).  The proper value will be
       // updated later.
       Symbol *gotsym = symtab->lookup("_GLOBAL_OFFSET_TABLE_", NULL);
@@ -1407,7 +1407,7 @@ Powerpc_relobj<size, big_endian>::do_sca
 					Symbol_table::PREDEFINED,
 					got, 0, 0,
 					elfcpp::STT_OBJECT,
-					elfcpp::STB_WEAK,
+					elfcpp::STB_LOCAL,
 					elfcpp::STV_HIDDEN, 0,
 					false, false);
 	}
@@ -1574,13 +1574,20 @@ private:
 	Output_data_got<size, big_endian>::add_constant(0);
 
 	// Define _GLOBAL_OFFSET_TABLE_ at the header
-	this->symtab_->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
-					     Symbol_table::PREDEFINED,
-					     this, this->g_o_t(), 0,
-					     elfcpp::STT_OBJECT,
-					     elfcpp::STB_LOCAL,
-					     elfcpp::STV_HIDDEN,
-					     0, false, false);
+	Symbol *gotsym = this->symtab_->lookup("_GLOBAL_OFFSET_TABLE_", NULL);
+	if (gotsym != NULL)
+	  {
+	    Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(gotsym);
+	    sym->set_value(this->g_o_t());
+	  }
+	else
+	  this->symtab_->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
+					       Symbol_table::PREDEFINED,
+					       this, this->g_o_t(), 0,
+					       elfcpp::STT_OBJECT,
+					       elfcpp::STB_LOCAL,
+					       elfcpp::STV_HIDDEN, 0,
+					       false, false);
       }
     else
       Output_data_got<size, big_endian>::add_constant(0);

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list