PowerPC64: Report overflow on @h and @ha relocations
authorAlan Modra <amodra@gmail.com>
Wed, 4 Dec 2013 12:44:06 +0000 (06:44 -0600)
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>
Wed, 4 Dec 2013 13:41:37 +0000 (07:41 -0600)
This patch updates glibc in accordance with the binutils patch checked in here:
https://sourceware.org/ml/binutils/2013-10/msg00372.html

This changes the various R_PPC64_..._HI and _HA relocations to report
32-bit overflows.  The motivation is that existing uses of @h / @ha
are to build up 32-bit offsets (for the "medium model" TOC access
that GCC now defaults to), and we'd really like to see failures at
link / load time rather than silent truncations.

For those rare cases where a modifier is needed to build up a 64-bit
constant, new relocations _HIGH / _HIGHA are supported.

The patch also fixes a bug in overflow checking for the R_PPC64_ADDR30
and R_PPC64_ADDR32 relocations.

ChangeLog
elf/elf.h
sysdeps/powerpc/powerpc64/dl-machine.h

index 80b0a75..4ac3396 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-12-04  Alan Modra  <amodra@gmail.com>
+
+       * elf/elf.h (R_PPC64_TLSGD, R_PPC64_TLSLD, R_PPC64_TOCSAVE): Define.
+       (R_PPC64_ADDR16_HIGH, R_PPC64_ADDR16_HIGHA): Likewise.
+       (R_PPC64_TPREL16_HIGH, R_PPC64_TPREL16_HIGHA): Likewise.
+       (R_PPC64_DTPREL16_HIGH, R_PPC64_DTPREL16_HIGHA): Likewise.
+
+       * sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Add
+       overflow checking for R_PPC64_ADDR16_HI, R_PPC64_ADDR16_HA,
+       R_PPC64_TPREL16_HI, and R_PPC64_TPREL16_HA.
+       Support new R_PPC64_ADDR16_HIGH, R_PPC64_ADDR16_HIGHA,
+       R_PPC64_TPREL16_HIGH, and R_PPC64_TPREL16_HIGHA relocations.
+       Fix overflow checking for R_PPC64_ADDR30 and R_PPC64_ADDR32.
+
 2013-12-04  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
        * sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
index a05ea3b..6e2552e 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2252,6 +2252,17 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
 #define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
 #define R_PPC64_DTPREL16_HIGHESTA 106 /* half16        (sym+add)@dtprel@highesta */
+#define R_PPC64_TLSGD          107 /* none     (sym+add)@tlsgd */
+#define R_PPC64_TLSLD          108 /* none     (sym+add)@tlsld */
+#define R_PPC64_TOCSAVE                109 /* none */
+
+/* Added when HA and HI relocs were changed to report overflows.  */
+#define R_PPC64_ADDR16_HIGH    110
+#define R_PPC64_ADDR16_HIGHA   111
+#define R_PPC64_TPREL16_HIGH   112
+#define R_PPC64_TPREL16_HIGHA  113
+#define R_PPC64_DTPREL16_HIGH  114
+#define R_PPC64_DTPREL16_HIGHA 115
 
 /* GNU extension to support local ifunc.  */
 #define R_PPC64_JMP_IREL       247
index 18cf157..19fa4fa 100644 (file)
@@ -669,11 +669,25 @@ elf_machine_rela (struct link_map *map,
 
     case R_PPC64_TPREL16_HI:
       value = elf_machine_tprel (map, sym_map, sym, reloc);
+      if (dont_expect (value + 0x80000000 >= 0x100000000LL))
+       _dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym);
+      *(Elf64_Half *) reloc_addr = PPC_HI (value);
+      break;
+
+    case R_PPC64_TPREL16_HIGH:
+      value = elf_machine_tprel (map, sym_map, sym, reloc);
       *(Elf64_Half *) reloc_addr = PPC_HI (value);
       break;
 
     case R_PPC64_TPREL16_HA:
       value = elf_machine_tprel (map, sym_map, sym, reloc);
+      if (dont_expect (value + 0x80008000 >= 0x100000000LL))
+       _dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym);
+      *(Elf64_Half *) reloc_addr = PPC_HA (value);
+      break;
+
+    case R_PPC64_TPREL16_HIGHA:
+      value = elf_machine_tprel (map, sym_map, sym, reloc);
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
@@ -709,17 +723,23 @@ elf_machine_rela (struct link_map *map,
       break;
 
     case R_PPC64_ADDR16_HI:
+      if (dont_expect (value + 0x80000000 >= 0x100000000LL))
+       _dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym);
+    case R_PPC64_ADDR16_HIGH:
       *(Elf64_Half *) reloc_addr = PPC_HI (value);
       break;
 
     case R_PPC64_ADDR16_HA:
+      if (dont_expect (value + 0x80008000 >= 0x100000000LL))
+       _dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym);
+    case R_PPC64_ADDR16_HIGHA:
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
     case R_PPC64_ADDR30:
       {
        Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
-       if (dont_expect ((delta + 0x80000000) >= 0x10000000
+       if (dont_expect ((delta + 0x80000000) >= 0x100000000LL
                         || (delta & 3) != 0))
          _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym);
        BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc);
@@ -755,7 +775,7 @@ elf_machine_rela (struct link_map *map,
       return;
 
     case R_PPC64_ADDR32:
-      if (dont_expect ((value + 0x80000000) >= 0x10000000))
+      if (dont_expect ((value + 0x80000000) >= 0x100000000LL))
        _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym);
       *(Elf64_Word *) reloc_addr = value;
       return;