This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH][gold] Mips: Correct the definition of _gp and _GLOBAL_OFFSET_TABLE_
- From: Vladimir Radosavljevic <Vladimir dot Radosavljevic at imgtec dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: "ccoutant at gmail dot com" <ccoutant at gmail dot com>, Petar Jovanovic <Petar dot Jovanovic at imgtec dot com>
- Date: Fri, 10 Mar 2017 16:55:00 +0000
- Subject: [PATCH][gold] Mips: Correct the definition of _gp and _GLOBAL_OFFSET_TABLE_
- Authentication-results: sourceware.org; auth=none
This patch corrects the definition of _gp and _GLOBAL_OFFSET_TABLE_ symbols.
With this patch, all _gp scope tests from GNU ld testsuite are passing.
Depends on https://sourceware.org/ml/binutils/2017-03/msg00146.html.
Regards,
Vladimir
ChangeLog -
* mips.cc (symbol_refs_local): Return false if a symbol
is from a dynamic object.
(Target_mips::got_section): Make _GLOBAL_OFFSET_TABLE_ STV_HIDDEN.
(Target_mips::set_gp): Refactor. Make _gp STT_NOTYPE and
STB_LOCAL.
(Target_mips::do_finalize_sections): Set _gp after all the checks
for creating .got are done.
(Target_mips::Scan::global): Remove unused code.
diff --git a/gold/mips.cc b/gold/mips.cc
index 52edeac..75470a7 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -2959,8 +2959,7 @@ symbol_refs_local(const Symbol* sym, bool has_dynsym_entry,
// If we don't have a definition in a regular file, then we can't
// resolve locally. The sym is either undefined or dynamic.
- if (sym->source() != Symbol::FROM_OBJECT || sym->object()->is_dynamic()
- || sym->is_undefined())
+ if (sym->is_from_dynobj() || sym->is_undefined())
return false;
// Forced local symbols resolve locally.
@@ -8463,7 +8462,7 @@ Target_mips<size, big_endian>::got_section(Symbol_table* symtab,
this->got_,
0, 0, elfcpp::STT_OBJECT,
elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT, 0,
+ elfcpp::STV_HIDDEN, 0,
false, false);
}
@@ -8476,52 +8475,27 @@ template<int size, bool big_endian>
void
Target_mips<size, big_endian>::set_gp(Layout* layout, Symbol_table* symtab)
{
- if (this->gp_ != NULL)
- return;
-
- Output_data* section = layout->find_output_section(".got");
- if (section == NULL)
- {
- // If there is no .got section, gp should be based on .sdata.
- // TODO(sasa): This is probably not needed. This was needed for older
- // MIPS architectures which accessed both GOT and .sdata section using
- // gp-relative addressing. Modern Mips Linux ELF architectures don't
- // access .sdata using gp-relative addressing.
- for (Layout::Section_list::const_iterator
- p = layout->section_list().begin();
- p != layout->section_list().end();
- ++p)
- {
- if (strcmp((*p)->name(), ".sdata") == 0)
- {
- section = *p;
- break;
- }
- }
- }
+ gold_assert(this->gp_ == NULL);
Sized_symbol<size>* gp =
static_cast<Sized_symbol<size>*>(symtab->lookup("_gp"));
- if (gp != NULL)
- {
- if (gp->source() != Symbol::IS_CONSTANT && section != NULL)
- gp->init_output_data(gp->name(), NULL, section, MIPS_GP_OFFSET, 0,
- elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT, 0,
- false, false);
- this->gp_ = gp;
- }
- else if (section != NULL)
+
+ // Set _gp symbol if the linker script hasn't created it.
+ if (gp == NULL || gp->source() != Symbol::IS_CONSTANT)
{
- gp = static_cast<Sized_symbol<size>*>(symtab->define_in_output_data(
- "_gp", NULL, Symbol_table::PREDEFINED,
- section, MIPS_GP_OFFSET, 0,
- elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT,
- 0, false, false));
- this->gp_ = gp;
+ // If there is no .got section, gp should be based on .sdata.
+ Output_data* gp_section = (this->got_ != NULL
+ ? this->got_->output_section()
+ : layout->find_output_section(".sdata"));
+
+ if (gp_section != NULL)
+ gp = static_cast<Sized_symbol<size>*>(symtab->define_in_output_data(
+ "_gp", NULL, Symbol_table::PREDEFINED,
+ gp_section, MIPS_GP_OFFSET, 0,
+ elfcpp::STT_NOTYPE,
+ elfcpp::STB_LOCAL,
+ elfcpp::STV_DEFAULT,
+ 0, false, false));
}
if (parameters->options().relocatable())
@@ -8531,15 +8505,16 @@ Target_mips<size, big_endian>::set_gp(Layout* layout, Symbol_table* symtab)
gp = static_cast<Sized_symbol<size>*>(symtab->define_as_constant(
"_gp", NULL, Symbol_table::PREDEFINED,
MIPS_GP_OFFSET, 0,
- elfcpp::STT_OBJECT,
- elfcpp::STB_GLOBAL,
+ elfcpp::STT_NOTYPE,
+ elfcpp::STB_LOCAL,
elfcpp::STV_DEFAULT,
0, false, false));
// Don't add _gp to the final symtab, because the value of the _gp symbol
// will be stored into .reginfo/.MIPS.options section.
gp->set_symtab_index(-1U);
- this->gp_ = gp;
}
+
+ this->gp_ = gp;
}
// Set the dynamic symbol indexes. INDEX is the index of the first
@@ -9680,9 +9655,6 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
if (this->got16_addends_.size() > 0)
gold_error("Can't find matching LO16 reloc");
- // Set _gp value.
- this->set_gp(layout, symtab);
-
// Check for any mips16 stub sections that we can discard.
if (!parameters->options().relocatable())
{
@@ -9849,6 +9821,9 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
this->copy_relocs_.emit_mips(this->rel_dyn_section(layout), symtab, layout,
this);
+ // Set _gp value.
+ this->set_gp(layout, symtab);
+
// Emit dynamic relocs.
for (typename std::vector<Dyn_reloc>::iterator p = this->dyn_relocs_.begin();
p != this->dyn_relocs_.end();
@@ -11069,13 +11044,6 @@ Target_mips<size, big_endian>::Scan::global(
// looking for relocs that would need to refer to MIPS16 stubs.
mips_sym->set_need_fn_stub();
- // A reference to _GLOBAL_OFFSET_TABLE_ implies that we need a got
- // section. We check here to avoid creating a dynamic reloc against
- // _GLOBAL_OFFSET_TABLE_.
- if (!target->has_got_section()
- && strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0)
- target->got_section(symtab, layout);
-
// We need PLT entries if there are static-only relocations against
// an externally-defined function. This can technically occur for
// shared libraries if there are branches to the symbol, although it