[BZ #17354] tile: Fix up corner cases with signed relocations
authorChris Metcalf <cmetcalf@tilera.com>
Fri, 5 Sep 2014 18:40:23 +0000 (14:40 -0400)
committerChris Metcalf <cmetcalf@tilera.com>
Sat, 6 Sep 2014 16:24:03 +0000 (12:24 -0400)
Some types of relocations technically need to be signed rather than
unsigned: in particular ones that are used with moveli or movei,
or for jump and branch.  This is almost never a problem.  Jump and
branch opcodes are pretty much uniformly resolved by the static linker
(unless you omit -fpic for a shared library, which is not recommended).
The moveli and movei opcodes that need to be sign-extended generally
are for positive displacements, like the construction of the address of
main() from _start().  However, tst-pie1 ends up with main below _start
(in a different module) and the test failed due to signedness issues in
relocation handling.

This commit treats the value as signed when shifting (to preserve the
high bit) and also sign-extends the value generated from the updated
bundle when comparing with the desired bundle, which we do to make sure
no overflow occurred.  As a result, the tst-pie1 test now passes.

ChangeLog
NEWS
sysdeps/tile/dl-machine.h

index 498e493659a6b126a6bcce9ecd454ae3fcbb0ce2..393d03cb9b8087820b81e73e45c83a23d8d0f7e7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-09-06  Chris Metcalf  <cmetcalf@tilera.com>
+
+       [BZ #17354]
+       * sysdeps/tile/dl-machine.h (elf_machine_rela): Add a MUNGE_SIGNED
+       macro for handling signed relocations.
+
 2014-09-03  Florian Weimer  <fweimer@redhat.com>
 
        [BZ #17325]
diff --git a/NEWS b/NEWS
index 17b75825fa517ed428e92a898fe9fa4ba20b358d..721b457a8b3fd37ce5fe13a03d00d580a84d9b5c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.20
   16966, 16967, 16977, 16978, 16984, 16990, 16996, 17009, 17022, 17031,
   17042, 17048, 17050, 17058, 17061, 17062, 17069, 17075, 17078, 17079,
   17084, 17086, 17088, 17092, 17097, 17125, 17135, 17137, 17150, 17153,
-  17187, 17213, 17259, 17261, 17262, 17263, 17319, 17325.
+  17187, 17213, 17259, 17261, 17262, 17263, 17319, 17325, 17354.
 
 * Reverted change of ABI data structures for s390 and s390x:
   On s390 and s390x the size of struct ucontext and jmp_buf was increased in
index 8be6758675f9fe17292fdc408b2c5215c68ab8c2..a96f23fd1aa6c3d7b99f6e601ff8bc7c20c1beeb 100644 (file)
@@ -657,7 +657,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     value += 0x8000;
 #endif
 
-  value >>= h->right_shift;
+  value = ((long) value) >> h->right_shift;
 
   switch (h->byte_size)
     {
@@ -686,13 +686,18 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
   tile_bundle_bits *p = (tile_bundle_bits *) reloc_addr;
   tile_bundle_bits bits = *p;
 
-#define MUNGE(func) do {                                            \
+#define MUNGE_SIGNED(func, length) do {                             \
     bits = ((bits & ~create_##func (-1)) | create_##func (value));  \
-    if (get_##func (bits) != value)                                 \
+    ElfW(Addr) result = get_##func (bits);                          \
+    int signbits = __WORDSIZE - length;                             \
+    result = (long) (result << signbits) >> signbits;               \
+    if (result != value)                                            \
       _dl_signal_error (0, map->l_name, NULL,                       \
                         "relocation value too large for " #func);   \
   } while (0)
 
+#define MUNGE(func) MUNGE_SIGNED(func, __WORDSIZE)
+
 #define MUNGE_NOCHECK(func)                                     \
   bits = ((bits & ~create_##func (-1)) | create_##func (value))
 
@@ -700,23 +705,23 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     {
 #ifdef __tilegx__
     case R_TILEGX_BROFF_X1:
-      MUNGE (BrOff_X1);
+      MUNGE_SIGNED (BrOff_X1, 17);
       break;
     case R_TILEGX_JUMPOFF_X1:
     case R_TILEGX_JUMPOFF_X1_PLT:
-      MUNGE (JumpOff_X1);
+      MUNGE_SIGNED (JumpOff_X1, 27);
       break;
     case R_TILEGX_IMM8_X0:
-      MUNGE (Imm8_X0);
+      MUNGE_SIGNED (Imm8_X0, 8);
       break;
     case R_TILEGX_IMM8_Y0:
-      MUNGE (Imm8_Y0);
+      MUNGE_SIGNED (Imm8_Y0, 8);
       break;
     case R_TILEGX_IMM8_X1:
-      MUNGE (Imm8_X1);
+      MUNGE_SIGNED (Imm8_X1, 8);
       break;
     case R_TILEGX_IMM8_Y1:
-      MUNGE (Imm8_Y1);
+      MUNGE_SIGNED (Imm8_Y1, 8);
       break;
     case R_TILEGX_MT_IMM14_X1:
       MUNGE (MT_Imm14_X1);
@@ -746,7 +751,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD:
     case R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE:
     case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE:
-      MUNGE (Imm16_X0);
+      MUNGE_SIGNED (Imm16_X0, 16);
       break;
     case R_TILEGX_IMM16_X1_HW0:
     case R_TILEGX_IMM16_X1_HW1:
@@ -770,7 +775,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD:
     case R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE:
     case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE:
-      MUNGE (Imm16_X1);
+      MUNGE_SIGNED (Imm16_X1, 16);
       break;
     case R_TILEGX_MMSTART_X0:
       MUNGE (BFStart_X0);
@@ -792,23 +797,23 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
       break;
 #else
     case R_TILEPRO_BROFF_X1:
-      MUNGE (BrOff_X1);
+      MUNGE_SIGNED (BrOff_X1, 17);
       break;
     case R_TILEPRO_JOFFLONG_X1:
     case R_TILEPRO_JOFFLONG_X1_PLT:
       MUNGE_NOCHECK (JOffLong_X1);   /* holds full 32-bit value */
       break;
     case R_TILEPRO_IMM8_X0:
-      MUNGE (Imm8_X0);
+      MUNGE_SIGNED (Imm8_X0, 8);
       break;
     case R_TILEPRO_IMM8_Y0:
-      MUNGE (Imm8_Y0);
+      MUNGE_SIGNED (Imm8_Y0, 8);
       break;
     case R_TILEPRO_IMM8_X1:
-      MUNGE (Imm8_X1);
+      MUNGE_SIGNED (Imm8_X1, 8);
       break;
     case R_TILEPRO_IMM8_Y1:
-      MUNGE (Imm8_Y1);
+      MUNGE_SIGNED (Imm8_Y1, 8);
       break;
     case R_TILEPRO_MT_IMM15_X1:
       MUNGE (MT_Imm15_X1);
@@ -834,7 +839,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     case R_TILEPRO_IMM16_X0_PCREL:
     case R_TILEPRO_IMM16_X0_TLS_GD:
     case R_TILEPRO_IMM16_X0_TLS_IE:
-      MUNGE (Imm16_X0);
+      MUNGE_SIGNED (Imm16_X0, 16);
       break;
     case R_TILEPRO_IMM16_X1_LO:
     case R_TILEPRO_IMM16_X1_HI:
@@ -854,7 +859,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     case R_TILEPRO_IMM16_X1_PCREL:
     case R_TILEPRO_IMM16_X1_TLS_GD:
     case R_TILEPRO_IMM16_X1_TLS_IE:
-      MUNGE (Imm16_X1);
+      MUNGE_SIGNED (Imm16_X1, 16);
       break;
     case R_TILEPRO_MMSTART_X0:
       MUNGE (MMStart_X0);