2011-11-10 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Thu, 10 Nov 2011 20:53:36 +0000 (20:53 +0000)
committerDoug Kwan <dougkwan@google.com>
Thu, 10 Nov 2011 20:53:36 +0000 (20:53 +0000)
PR gold/13362
* arm.cc (Target_arm::Relocate::relocate_tls): Do unaligned accesses
when processing data relocs.
* reloc.h (Relocate_functions::rel_unaligned): New method.
(Relocate_functions::pcrel_unaligned): Ditto.
(Relocate_functions::rel32_unaligned): Ditto.
(Relocate_functions::pcrel32_unaligned): Ditto.

gold/ChangeLog
gold/arm.cc
gold/reloc.h

index f3707ae910749d27faa2ead73260fde392bc367a..0b17438b8b8206a36f2bf0932fc6b434fa066fb2 100644 (file)
@@ -1,3 +1,13 @@
+2011-11-10  Doug Kwan  <dougkwan@google.com>
+
+       PR gold/13362
+       * arm.cc (Target_arm::Relocate::relocate_tls): Do unaligned accesses
+       when processing data relocs.
+       * reloc.h (Relocate_functions::rel_unaligned): New method.
+       (Relocate_functions::pcrel_unaligned): Ditto.
+       (Relocate_functions::rel32_unaligned): Ditto.
+       (Relocate_functions::pcrel32_unaligned): Ditto.
+
 2011-11-09  Doug Kwan  <dougkwan@google.com>
 
        PR gold/13362
index a17469b2c9f255bd3a55e4eb41956b128eb7289e..3ee2224d631983ffd03814df611ceb7b702cc154 100644 (file)
@@ -9348,7 +9348,7 @@ Target_arm<big_endian>::Relocate::relocate_tls(
              
               // Relocate the field with the PC relative offset of the pair of
               // GOT entries.
-             RelocFuncs::pcrel32(view, got_entry, address);
+             RelocFuncs::pcrel32_unaligned(view, got_entry, address);
               return ArmRelocFuncs::STATUS_OKAY;
             }
         }
@@ -9367,13 +9367,13 @@ Target_arm<big_endian>::Relocate::relocate_tls(
 
           // Relocate the field with the PC relative offset of the pair of
           // GOT entries.
-          RelocFuncs::pcrel32(view, got_entry, address);
+          RelocFuncs::pcrel32_unaligned(view, got_entry, address);
          return ArmRelocFuncs::STATUS_OKAY;
         }
       break;
 
     case elfcpp::R_ARM_TLS_LDO32:      // Alternate local-dynamic
-      RelocFuncs::rel32(view, value);
+      RelocFuncs::rel32_unaligned(view, value);
       return ArmRelocFuncs::STATUS_OKAY;
 
     case elfcpp::R_ARM_TLS_IE32:       // Initial-exec
@@ -9402,7 +9402,7 @@ Target_arm<big_endian>::Relocate::relocate_tls(
            target->got_plt_section()->address() + got_offset;
 
           // Relocate the field with the PC relative offset of the GOT entry.
-         RelocFuncs::pcrel32(view, got_entry, address);
+         RelocFuncs::pcrel32_unaligned(view, got_entry, address);
          return ArmRelocFuncs::STATUS_OKAY;
         }
       break;
@@ -9418,7 +9418,7 @@ Target_arm<big_endian>::Relocate::relocate_tls(
          // need to add TCB size to the offset.
          Arm_address aligned_tcb_size =
            align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
-          RelocFuncs::rel32(view, value + aligned_tcb_size);
+          RelocFuncs::rel32_unaligned(view, value + aligned_tcb_size);
 
         }
       return ArmRelocFuncs::STATUS_OKAY;
index fefcb3f1e2841a0f38ca54e149d9de38ee163d54..02f91a43353c03a7b2fd22bbb528303c8b483993 100644 (file)
@@ -333,6 +333,18 @@ private:
     elfcpp::Swap<valsize, big_endian>::writeval(wv, x + value);
   }
 
+  // Like the above but for relocs at unaligned addresses.
+  template<int valsize>
+  static inline void
+  rel_unaligned(unsigned char* view,
+               typename elfcpp::Swap<valsize, big_endian>::Valtype value)
+  {
+    typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
+       Valtype;
+    Valtype x = elfcpp::Swap_unaligned<valsize, big_endian>::readval(view);
+    elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view, x + value);
+  }
+
   // Do a simple relocation using a Symbol_value with the addend in
   // the section contents.  VALSIZE is the size of the value to
   // relocate.
@@ -405,6 +417,19 @@ private:
     elfcpp::Swap<valsize, big_endian>::writeval(wv, x + value - address);
   }
 
+  // Like the above but for relocs at unaligned addresses.
+  template<int valsize>
+  static inline void
+  pcrel_unaligned(unsigned char* view,
+                 typename elfcpp::Swap<valsize, big_endian>::Valtype value,
+                 typename elfcpp::Elf_types<size>::Elf_Addr address)
+  {
+    typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
+    Valtype x = elfcpp::Swap_unaligned<valsize, big_endian>::readval(view);
+    elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view,
+                                                         x + value - address);
+  }
+
   // Do a simple PC relative relocation with a Symbol_value with the
   // addend in the section contents.  VALSIZE is the size of the
   // value.
@@ -568,6 +593,11 @@ public:
   rel32(unsigned char* view, elfcpp::Elf_Word value)
   { This::template rel<32>(view, value); }
 
+  // Like above but for relocs at unaligned addresses.
+  static inline void
+  rel32_unaligned(unsigned char* view, elfcpp::Elf_Word value)
+  { This::template rel_unaligned<32>(view, value); }
+
   static inline void
   rel32(unsigned char* view,
        const Sized_relobj_file<size, big_endian>* object,
@@ -600,6 +630,12 @@ public:
          typename elfcpp::Elf_types<size>::Elf_Addr address)
   { This::template pcrel<32>(view, value, address); }
 
+  // Unaligned version of the above.
+  static inline void
+  pcrel32_unaligned(unsigned char* view, elfcpp::Elf_Word value,
+                   typename elfcpp::Elf_types<size>::Elf_Addr address)
+  { This::template pcrel_unaligned<32>(view, value, address); }
+
   static inline void
   pcrel32(unsigned char* view,
          const Sized_relobj_file<size, big_endian>* object,