]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Correct little-endian relocation of UADDR64,32,16.
authorAlan Modra <amodra@gmail.com>
Thu, 3 Oct 2013 04:21:52 +0000 (13:51 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 4 Oct 2013 02:03:12 +0000 (11:33 +0930)
* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
Correct handling of unaligned relocs for little-endian.
* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.

ChangeLog
sysdeps/powerpc/powerpc32/dl-machine.c
sysdeps/powerpc/powerpc64/dl-machine.h

index e86a0ab27f7827ab7e8592ce3fd2512f778ee961..52bfa8ac7f0886e0514536a54a37757d6d21d60f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+       * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
+       Correct handling of unaligned relocs for little-endian.
+       * sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.
+
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
        * configure.in: Map powerpc64le and powerpcle to base_machine/machine.
index 3e7202d86944f7a30c41d25c4b8dac1439f26fe8..f81899a0ac522d7fd5fc180338421cb1a6428c1c 100644 (file)
@@ -416,6 +416,12 @@ __process_machine_rela (struct link_map *map,
                        Elf32_Addr const finaladdr,
                        int rinfo)
 {
+  union unaligned
+    {
+      unsigned u2 __attribute__ ((mode (HI)));
+      unsigned u4 __attribute__ ((mode (SI)));
+    } __attribute__((__packed__));
+
   switch (rinfo)
     {
     case R_PPC_NONE:
@@ -432,10 +438,7 @@ __process_machine_rela (struct link_map *map,
       return;
 
     case R_PPC_UADDR32:
-      ((char *) reloc_addr)[0] = finaladdr >> 24;
-      ((char *) reloc_addr)[1] = finaladdr >> 16;
-      ((char *) reloc_addr)[2] = finaladdr >> 8;
-      ((char *) reloc_addr)[3] = finaladdr;
+      ((union unaligned *) reloc_addr)->u4 = finaladdr;
       break;
 
     case R_PPC_ADDR24:
@@ -453,8 +456,7 @@ __process_machine_rela (struct link_map *map,
     case R_PPC_UADDR16:
       if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0))
        _dl_reloc_overflow (map,  "R_PPC_UADDR16", reloc_addr, refsym);
-      ((char *) reloc_addr)[0] = finaladdr >> 8;
-      ((char *) reloc_addr)[1] = finaladdr;
+      ((union unaligned *) reloc_addr)->u2 = finaladdr;
       break;
 
     case R_PPC_ADDR16_LO:
index 059fdafd53b9b3880009d0210bbc7704f6f1f32e..b69a1ce06fed2022e64b4e8f1f19c25b57f49678 100644 (file)
@@ -561,6 +561,12 @@ elf_machine_rela (struct link_map *map,
   Elf64_Addr *const reloc_addr = reloc_addr_arg;
   const int r_type = ELF64_R_TYPE (reloc->r_info);
   const Elf64_Sym *const refsym = sym;
+  union unaligned
+    {
+      unsigned u2 __attribute__ ((mode (HI)));
+      unsigned u4 __attribute__ ((mode (SI)));
+      unsigned u8 __attribute__ ((mode (DI)));
+    } __attribute__((__packed__));
 
   if (r_type == R_PPC64_RELATIVE)
     {
@@ -741,23 +747,11 @@ elf_machine_rela (struct link_map *map,
       return;
 
     case R_PPC64_UADDR64:
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 56) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 48) & 0xff;
-      ((char *) reloc_addr_arg)[2] = (value >> 40) & 0xff;
-      ((char *) reloc_addr_arg)[3] = (value >> 32) & 0xff;
-      ((char *) reloc_addr_arg)[4] = (value >> 24) & 0xff;
-      ((char *) reloc_addr_arg)[5] = (value >> 16) & 0xff;
-      ((char *) reloc_addr_arg)[6] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[7] = (value >> 0) & 0xff;
+      ((union unaligned *) reloc_addr)->u8 = value;
       return;
 
     case R_PPC64_UADDR32:
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 24) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 16) & 0xff;
-      ((char *) reloc_addr_arg)[2] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[3] = (value >> 0) & 0xff;
+      ((union unaligned *) reloc_addr)->u4 = value;
       return;
 
     case R_PPC64_ADDR32:
@@ -781,10 +775,8 @@ elf_machine_rela (struct link_map *map,
     case R_PPC64_UADDR16:
       if (dont_expect ((value + 0x8000) >= 0x10000))
        _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym);
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 0) & 0xff;
-      break;
+      ((union unaligned *) reloc_addr)->u2 = value;
+      return;
 
     case R_PPC64_ADDR16_DS:
       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))