aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-03-16 23:51:19 +0000
committerIan Lance Taylor <iant@google.com>2008-03-16 23:51:19 +0000
commitd1f003c610e39314803fa3fd4f311230729d3616 (patch)
tree221e357d029f9eb1bbd14c02ffbdf37cf5d2d8e0 /gold/output.cc
parentda6b876ee6e7599e1fd07514b77f1c4a6ae7dca6 (diff)
downloadfsf-binutils-gdb-d1f003c610e39314803fa3fd4f311230729d3616.zip
fsf-binutils-gdb-d1f003c610e39314803fa3fd4f311230729d3616.tar.gz
fsf-binutils-gdb-d1f003c610e39314803fa3fd4f311230729d3616.tar.bz2
Fix handling of RELA relative relocs against local symbols in merge
sections.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc25
1 files changed, 16 insertions, 9 deletions
diff --git a/gold/output.cc b/gold/output.cc
index bea1542..ba4f6c8 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -800,7 +800,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
const unsigned int lsi = this->local_sym_index_;
section_offset_type offset;
Output_section* os = this->u1_.relobj->output_section(lsi, &offset);
- gold_assert(os != NULL);
+ gold_assert(os != NULL && offset != -1);
return offset;
}
@@ -851,18 +851,21 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write(
template<bool dynamic, int size, bool big_endian>
typename elfcpp::Elf_types<size>::Elf_Addr
-Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value() const
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
+ Address addend) const
{
if (this->local_sym_index_ == GSYM_CODE)
{
const Sized_symbol<size>* sym;
sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
- return sym->value();
+ return sym->value() + addend;
}
gold_assert(this->local_sym_index_ != SECTION_CODE
- && this->local_sym_index_ != INVALID_CODE);
- const Sized_relobj<size, big_endian>* relobj = this->u1_.relobj;
- return relobj->local_symbol_value(this->local_sym_index_);
+ && this->local_sym_index_ != INVALID_CODE
+ && !this->is_section_symbol_);
+ const unsigned int lsi = this->local_sym_index_;
+ const Symbol_value<size>* symval = this->u1_.relobj->local_symbol(lsi);
+ return symval->value(this->u1_.relobj, addend);
}
// Write out a Rela relocation.
@@ -876,8 +879,8 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
this->rel_.write_rel(&orel);
Addend addend = this->addend_;
if (this->rel_.is_relative())
- addend += this->rel_.symbol_value();
- if (this->rel_.is_local_section_symbol())
+ addend = this->rel_.symbol_value(addend);
+ else if (this->rel_.is_local_section_symbol())
addend += this->rel_.local_section_offset();
orel.put_r_addend(addend);
}
@@ -1037,7 +1040,11 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
break;
default:
- val = this->u_.object->local_symbol_value(this->local_sym_index_);
+ {
+ const unsigned int lsi = this->local_sym_index_;
+ const Symbol_value<size>* symval = this->u_.object->local_symbol(lsi);
+ val = symval->value(this->u_.object, 0);
+ }
break;
}