about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2014-09-05 14:40:23 -0400
committerChris Metcalf <cmetcalf@tilera.com>2014-09-06 12:24:03 -0400
commit8622092d584962801e4248cd4bb4bef6e71827b0 (patch)
tree59a1913ca848fa3818327716497d4355afb667fa /sysdeps
parent41488498b6d9440ee66ab033808cce8323bba7ac (diff)
downloadglibc-8622092d584962801e4248cd4bb4bef6e71827b0.tar.gz
glibc-8622092d584962801e4248cd4bb4bef6e71827b0.tar.xz
glibc-8622092d584962801e4248cd4bb4bef6e71827b0.zip
[BZ #17354] tile: Fix up corner cases with signed relocations
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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/tile/dl-machine.h41
1 files changed, 23 insertions, 18 deletions
diff --git a/sysdeps/tile/dl-machine.h b/sysdeps/tile/dl-machine.h
index 8be6758675..a96f23fd1a 100644
--- a/sysdeps/tile/dl-machine.h
+++ b/sysdeps/tile/dl-machine.h
@@ -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);