5de29b
#
5de29b
# commit f8e3e9f31bfd71641418897228fa1732170b69cc
5de29b
# Author: Alan Modra <amodra@gmail.com>
5de29b
# Date:   Thu Oct 3 13:51:52 2013 +0930
5de29b
# 
5de29b
#     Correct little-endian relocation of UADDR64,32,16.
5de29b
# 
5de29b
#         * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
5de29b
#         Correct handling of unaligned relocs for little-endian.
5de29b
#         * sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.
5de29b
# 
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/dl-machine.c glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/dl-machine.c
5de29b
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/dl-machine.c	2012-12-24 22:02:13.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/dl-machine.c	2014-11-11 18:51:36.140570654 -0500
5de29b
@@ -423,6 +423,12 @@
5de29b
 			Elf32_Addr const finaladdr,
5de29b
 			int rinfo)
5de29b
 {
5de29b
+  union unaligned
5de29b
+    {
5de29b
+      unsigned u2 __attribute__ ((mode (HI)));
5de29b
+      unsigned u4 __attribute__ ((mode (SI)));
5de29b
+    } __attribute__((__packed__));
5de29b
+
5de29b
   switch (rinfo)
5de29b
     {
5de29b
     case R_PPC_NONE:
5de29b
@@ -439,10 +445,7 @@
5de29b
       return;
5de29b
 
5de29b
     case R_PPC_UADDR32:
5de29b
-      ((char *) reloc_addr)[0] = finaladdr >> 24;
5de29b
-      ((char *) reloc_addr)[1] = finaladdr >> 16;
5de29b
-      ((char *) reloc_addr)[2] = finaladdr >> 8;
5de29b
-      ((char *) reloc_addr)[3] = finaladdr;
5de29b
+      ((union unaligned *) reloc_addr)->u4 = finaladdr;
5de29b
       break;
5de29b
 
5de29b
     case R_PPC_ADDR24:
5de29b
@@ -460,8 +463,7 @@
5de29b
     case R_PPC_UADDR16:
5de29b
       if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0))
5de29b
 	_dl_reloc_overflow (map,  "R_PPC_UADDR16", reloc_addr, refsym);
5de29b
-      ((char *) reloc_addr)[0] = finaladdr >> 8;
5de29b
-      ((char *) reloc_addr)[1] = finaladdr;
5de29b
+      ((union unaligned *) reloc_addr)->u2 = finaladdr;
5de29b
       break;
5de29b
 
5de29b
     case R_PPC_ADDR16_LO:
12745e
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h
5de29b
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2012-12-24 22:02:13.000000000 -0500
12745e
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h	2014-11-11 18:51:36.141570651 -0500
5de29b
@@ -561,6 +561,12 @@
5de29b
   Elf64_Addr *const reloc_addr = reloc_addr_arg;
5de29b
   const int r_type = ELF64_R_TYPE (reloc->r_info);
5de29b
   const Elf64_Sym *const refsym = sym;
5de29b
+  union unaligned
5de29b
+    {
5de29b
+      unsigned u2 __attribute__ ((mode (HI)));
5de29b
+      unsigned u4 __attribute__ ((mode (SI)));
5de29b
+      unsigned u8 __attribute__ ((mode (DI)));
5de29b
+    } __attribute__((__packed__));
5de29b
 
5de29b
   if (r_type == R_PPC64_RELATIVE)
5de29b
     {
5de29b
@@ -742,23 +748,11 @@
5de29b
       return;
5de29b
 
5de29b
     case R_PPC64_UADDR64:
5de29b
-      /* We are big-endian.  */
5de29b
-      ((char *) reloc_addr_arg)[0] = (value >> 56) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[1] = (value >> 48) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[2] = (value >> 40) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[3] = (value >> 32) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[4] = (value >> 24) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[5] = (value >> 16) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[6] = (value >> 8) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[7] = (value >> 0) & 0xff;
5de29b
+      ((union unaligned *) reloc_addr)->u8 = value;
5de29b
       return;
5de29b
 
5de29b
     case R_PPC64_UADDR32:
5de29b
-      /* We are big-endian.  */
5de29b
-      ((char *) reloc_addr_arg)[0] = (value >> 24) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[1] = (value >> 16) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[2] = (value >> 8) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[3] = (value >> 0) & 0xff;
5de29b
+      ((union unaligned *) reloc_addr)->u4 = value;
5de29b
       return;
5de29b
 
5de29b
     case R_PPC64_ADDR32:
5de29b
@@ -782,10 +776,8 @@
5de29b
     case R_PPC64_UADDR16:
5de29b
       if (dont_expect ((value + 0x8000) >= 0x10000))
5de29b
 	_dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym);
5de29b
-      /* We are big-endian.  */
5de29b
-      ((char *) reloc_addr_arg)[0] = (value >> 8) & 0xff;
5de29b
-      ((char *) reloc_addr_arg)[1] = (value >> 0) & 0xff;
5de29b
-      break;
5de29b
+      ((union unaligned *) reloc_addr)->u2 = value;
5de29b
+      return;
5de29b
 
5de29b
     case R_PPC64_ADDR16_DS:
5de29b
       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))