summaryrefslogtreecommitdiff
path: root/gold
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
commite78b3cdac056ec0b4a0152fa4024277a79149e55 (patch)
tree0861ce017c9d41ccabe593fe36f0b44878adb3c7 /gold
parentd72860765a8a32c6391b56893fa01646933aa61e (diff)
downloadbinutils-redhat-e78b3cdac056ec0b4a0152fa4024277a79149e55.tar.gz
Fix handling of RELA relative relocs against local symbols in merge
sections.
Diffstat (limited to 'gold')
-rw-r--r--gold/object.cc11
-rw-r--r--gold/object.h5
-rw-r--r--gold/output.cc25
-rw-r--r--gold/output.h6
-rw-r--r--gold/testsuite/two_file_test.h4
-rw-r--r--gold/testsuite/two_file_test_1.cc16
-rw-r--r--gold/testsuite/two_file_test_2.cc7
-rw-r--r--gold/testsuite/two_file_test_main.cc1
8 files changed, 48 insertions, 27 deletions
diff --git a/gold/object.cc b/gold/object.cc
index 795fa8bf1b..ed7917bf4c 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -1052,17 +1052,6 @@ Sized_relobj<size, big_endian>::do_set_local_dynsym_offset(off_t off)
return this->output_local_dynsym_count_;
}
-// Return the value of the local symbol symndx.
-template<int size, bool big_endian>
-typename elfcpp::Elf_types<size>::Elf_Addr
-Sized_relobj<size, big_endian>::local_symbol_value(unsigned int symndx) const
-{
- gold_assert(symndx < this->local_symbol_count_);
- gold_assert(symndx < this->local_values_.size());
- const Symbol_value<size>& lv(this->local_values_[symndx]);
- return lv.value(this, 0);
-}
-
// Write out the local symbols.
template<int size, bool big_endian>
diff --git a/gold/object.h b/gold/object.h
index 1f9b7536bc..3a74685943 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -1056,10 +1056,7 @@ class Sized_relobj : public Relobj
sized_target()
{ return this->Object::sized_target<size, big_endian>(); }
- // Return the value of the local symbol symndx.
- Address
- local_symbol_value(unsigned int symndx) const;
-
+ // Record that local symbol SYM needs a dynamic symbol entry.
void
set_needs_output_dynsym_entry(unsigned int sym)
{
diff --git a/gold/output.cc b/gold/output.cc
index bea1542b49..ba4f6c8421 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;
}
diff --git a/gold/output.h b/gold/output.h
index 42c53335cb..ac812a0ab1 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -839,10 +839,10 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
section_offset_type
local_section_offset() const;
- // Get the value of the symbol referred to by a Rel relocation.
-
+ // Get the value of the symbol referred to by a Rel relocation when
+ // we are adding the given ADDEND.
Address
- symbol_value() const;
+ symbol_value(Address addend) const;
// Write the reloc entry to an output view.
void
diff --git a/gold/testsuite/two_file_test.h b/gold/testsuite/two_file_test.h
index 88aa234ffa..32a247f192 100644
--- a/gold/testsuite/two_file_test.h
+++ b/gold/testsuite/two_file_test.h
@@ -69,3 +69,7 @@ extern const wchar_t* f15();
extern bool t16();
extern bool t16a();
+
+extern bool t17();
+extern const char* t17data[];
+#define T17_COUNT 5
diff --git a/gold/testsuite/two_file_test_1.cc b/gold/testsuite/two_file_test_1.cc
index 2c3b9c9b0a..7646838cdb 100644
--- a/gold/testsuite/two_file_test_1.cc
+++ b/gold/testsuite/two_file_test_1.cc
@@ -47,6 +47,7 @@
// 14 Compare string constants in file 1 and file 2.
// 15 Compare wide string constants in file 1 and file 2.
// 16 Call a function directly after its address has been taken.
+// 17 File 1 checks array of string constants defined in file 2.
#include "two_file_test.h"
@@ -203,3 +204,18 @@ t16()
{
return f10() == 135;
}
+
+// 17 File 1 checks array of string constants defined in file 2.
+
+bool
+t17()
+{
+ char c = 'a';
+ for (int i = 0; i < T17_COUNT; ++i)
+ {
+ if (t17data[i][0] != c || t17data[i][1] != '\0')
+ return false;
+ ++c;
+ }
+ return true;
+}
diff --git a/gold/testsuite/two_file_test_2.cc b/gold/testsuite/two_file_test_2.cc
index b92285633a..3888befb73 100644
--- a/gold/testsuite/two_file_test_2.cc
+++ b/gold/testsuite/two_file_test_2.cc
@@ -114,3 +114,10 @@ f15()
{
return TEST_WIDE_STRING_CONSTANT;
}
+
+// 17 File 1 checks array of string constants defined in file 2.
+
+const char* t17data[T17_COUNT] =
+{
+ "a", "b", "c", "d", "e"
+};
diff --git a/gold/testsuite/two_file_test_main.cc b/gold/testsuite/two_file_test_main.cc
index 5f2ff5629d..c69d6e0970 100644
--- a/gold/testsuite/two_file_test_main.cc
+++ b/gold/testsuite/two_file_test_main.cc
@@ -51,5 +51,6 @@ main()
assert(t13());
assert(t16());
assert(t16a());
+ assert(t17());
return 0;
}