Fix handling of RELA relative relocs against local symbols in merge
authorIan Lance Taylor <iant@google.com>
Sun, 16 Mar 2008 23:51:19 +0000 (23:51 +0000)
committerIan Lance Taylor <iant@google.com>
Sun, 16 Mar 2008 23:51:19 +0000 (23:51 +0000)
sections.

gold/object.cc
gold/object.h
gold/output.cc
gold/output.h
gold/testsuite/two_file_test.h
gold/testsuite/two_file_test_1.cc
gold/testsuite/two_file_test_2.cc
gold/testsuite/two_file_test_main.cc

index 795fa8bf1b0b96410084adb01bed77ede6f27892..ed7917bf4cf0ec30f430e5f7229f9b71e50818e8 100644 (file)
@@ -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>
index 1f9b7536bcec2574ef05459441f2ed6809f9132b..3a74685943b9a0742587822b6cc7a682003c2209 100644 (file)
@@ -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)
   {
index bea1542b492d120791db35b60028831ff85bf9c8..ba4f6c8421fa3ddd8fd2f077d02be2a78d66f0ac 100644 (file)
@@ -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;
     }
 
index 42c53335cb1e090682ae666e36a29a4e83aeb36c..ac812a0ab19d560c0dcbdd89e42585db59ebe359 100644 (file)
@@ -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
index 88aa234ffa58c428c257421cfb62e997fff79448..32a247f1929abbedca18aecf85671c19fc1735c5 100644 (file)
@@ -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
index 2c3b9c9b0a4cd39fedf524fa7c983c48cf36f561..7646838cdb753df95069fe30872ac6b6ab83ca99 100644 (file)
@@ -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;
+}
index b92285633a38be329548ca6935df8b5fc34c8c97..3888befb732cdb1754f898c53eb488038ffdf6a1 100644 (file)
@@ -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"
+};
index 5f2ff5629d95fb7dcc716a69ee88eaea70b0d59a..c69d6e0970e78ab8d3bf362ceb5d0227cda8612b 100644 (file)
@@ -51,5 +51,6 @@ main()
   assert(t13());
   assert(t16());
   assert(t16a());
+  assert(t17());
   return 0;
 }