From patchwork Fri Sep 5 18:40:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Metcalf X-Patchwork-Id: 2657 Received: (qmail 5963 invoked by alias); 5 Sep 2014 18:54:48 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 5929 invoked by uid 89); 5 Sep 2014 18:54:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=AWL, BAYES_00, NO_DNS_FOR_FROM, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: gx-1.internal.tilera.com Message-Id: <201409051854.s85IsfM0024659@gx-1.internal.tilera.com> From: Chris Metcalf Date: Fri, 5 Sep 2014 14:40:23 -0400 Subject: [PATCH] tile: Fix up corner cases with signed relocations To: libc-alpha@sourceware.org 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);