This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] tile: Fix up corner cases with signed relocations
- From: Chris Metcalf <cmetcalf at tilera dot com>
- To: libc-alpha at sourceware dot org
- Date: Fri, 5 Sep 2014 14:40:23 -0400
- Subject: [PATCH] tile: Fix up corner cases with signed relocations
- Authentication-results: sourceware.org; auth=none
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.
---
sysdeps/tile/dl-machine.h | 40 ++++++++++++++++++++++------------------
1 files changed, 22 insertions(+), 18 deletions(-)
This is the change I wanted to push before 2.20 froze. It turns out
not to be a regression, so arguably the conservative thing may to wait
until after 2.21 opens. I've done reasonable internal testing (and
will have more results by Saturday morning after a full rebuild and
test suite run) but could easily be swayed one way or the other.
diff --git a/sysdeps/tile/dl-machine.h b/sysdeps/tile/dl-machine.h
index 8be6758..ecd1eff 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,17 @@ 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 = (long) get_##func (bits) \
+ << (__WORDSIZE - length) >> (__WORDSIZE - length); \
+ 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 +704,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 +750,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 +774,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 +796,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 +838,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 +858,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);
--
1.7.1