From: Ian Lance Taylor Date: Sun, 16 Mar 2008 23:51:19 +0000 (+0000) Subject: Fix handling of RELA relative relocs against local symbols in merge X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d1f003c610e39314803fa3fd4f311230729d3616;p=binutils-gdb.git Fix handling of RELA relative relocs against local symbols in merge sections. --- diff --git a/gold/object.cc b/gold/object.cc index 795fa8bf1b0..ed7917bf4cf 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1052,17 +1052,6 @@ Sized_relobj::do_set_local_dynsym_offset(off_t off) return this->output_local_dynsym_count_; } -// Return the value of the local symbol symndx. -template -typename elfcpp::Elf_types::Elf_Addr -Sized_relobj::local_symbol_value(unsigned int symndx) const -{ - gold_assert(symndx < this->local_symbol_count_); - gold_assert(symndx < this->local_values_.size()); - const Symbol_value& lv(this->local_values_[symndx]); - return lv.value(this, 0); -} - // Write out the local symbols. template diff --git a/gold/object.h b/gold/object.h index 1f9b7536bce..3a74685943b 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(); } - // 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 bea1542b492..ba4f6c8421f 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -800,7 +800,7 @@ Output_reloc:: 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::write( template typename elfcpp::Elf_types::Elf_Addr -Output_reloc::symbol_value() const +Output_reloc::symbol_value( + Address addend) const { if (this->local_sym_index_ == GSYM_CODE) { const Sized_symbol* sym; sym = static_cast*>(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* 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* 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::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::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* 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 42c53335cb1..ac812a0ab19 100644 --- a/gold/output.h +++ b/gold/output.h @@ -839,10 +839,10 @@ class Output_reloc 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 88aa234ffa5..32a247f1929 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 2c3b9c9b0a4..7646838cdb7 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 b92285633a3..3888befb732 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 5f2ff5629d9..c69d6e0970e 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; }