gold --emit-relocs
authorAlan Modra <amodra@gmail.com>
Thu, 20 Aug 2015 02:32:45 +0000 (12:02 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 20 Aug 2015 02:32:45 +0000 (12:02 +0930)
A symbol value in an ELF final linked binary is absolute, in contrast
to a relocatable object file where the value is section relative.  For
--emit-relocs it is therefore incorrect to use the value of a section
symbol as the addend when adjusting relocs against input section
symbols to output section symbols.

PR gold/18846
* target-reloc.h (relocate_relocs <RELOC_ADJUST_FOR_SECTION_RELA>):
Subtract os->address() from addend.
* powerpc.cc (relocate_relocs): Likewise.

gold/ChangeLog
gold/powerpc.cc
gold/target-reloc.h

index 0c5a40c3e2927815cd4257c82a2ae5efbc3e43b1..b3417b2149dd41c7d8d8f0350d2673da1231a4a6 100644 (file)
@@ -1,3 +1,10 @@
+2015-08-20  Alan Modra  <amodra@gmail.com>
+
+       PR gold/18846
+       * target-reloc.h (relocate_relocs <RELOC_ADJUST_FOR_SECTION_RELA>):
+       Subtract os->address() from addend.
+       * powerpc.cc (relocate_relocs): Likewise.
+
 2015-08-12  Simon Dardis  <simon.dardis@imgtec.com>
 
        * mips.cc (plt0_entry_o32, plt0_entry_n32, plt0_entry_n64,
index 540e1977c62df0ae9ddb3aa8ff87459ca6cbb07e..3311a1d51261b9d6777c8834f494e1471474c80d 100644 (file)
@@ -8110,6 +8110,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
        }
 
       // Get the new symbol index.
+      Output_section* os = NULL;
       if (r_sym < local_count)
        {
          switch (strategy)
@@ -8134,7 +8135,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
                unsigned int shndx =
                  object->local_symbol_input_shndx(r_sym, &is_ordinary);
                gold_assert(is_ordinary);
-               Output_section* os = object->output_section(shndx);
+               os = object->output_section(shndx);
                gold_assert(os != NULL);
                gold_assert(os->needs_symtab_index());
                r_sym = os->symtab_index();
@@ -8187,7 +8188,8 @@ Target_powerpc<size, big_endian>::relocate_relocs(
       else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA)
        {
          const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym);
-         addend = psymval->value(object, addend);
+         gold_assert(os != NULL);
+         addend = psymval->value(object, addend) - os->address();
        }
       else if (strategy == Relocatable_relocs::RELOC_SPECIAL)
        {
index c13545942aad6750e8654a6a82d30467fb799446..89906af2b4a5298b04442f138de001ef47893e42 100644 (file)
@@ -666,6 +666,7 @@ relocate_relocs(
 
       // Get the new symbol index.
 
+      Output_section* os = NULL;
       unsigned int new_symndx;
       if (r_sym < local_count)
        {
@@ -698,7 +699,7 @@ relocate_relocs(
                unsigned int shndx =
                  object->local_symbol_input_shndx(r_sym, &is_ordinary);
                gold_assert(is_ordinary);
-               Output_section* os = object->output_section(shndx);
+               os = object->output_section(shndx);
                gold_assert(os != NULL);
                gold_assert(os->needs_symtab_index());
                new_symndx = os->symtab_index();
@@ -780,7 +781,8 @@ relocate_relocs(
                typename elfcpp::Elf_types<size>::Elf_Swxword addend;
                addend = Reloc_types<sh_type, size, big_endian>::
                           get_reloc_addend(&reloc);
-               addend = psymval->value(object, addend);
+               gold_assert(os != NULL);
+               addend = psymval->value(object, addend) - os->address();
                Reloc_types<sh_type, size, big_endian>::
                  set_reloc_addend(&reloc_write, addend);
              }