This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[GOLD] powerpc .got symbol
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Fri, 30 Nov 2012 15:17:54 +1030
- Subject: [GOLD] powerpc .got symbol
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