From 3acfe400a2d9bbc00c8c5eb7ae0cc205209d4338 Mon Sep 17 00:00:00 2001 From: Sean Fertile Date: Thu, 18 Oct 2018 15:43:41 +0000 Subject: [PATCH] [PPC64] Fix offset checks on rel24 call relocations. Adjusted the range check on a call instruction from 24 bits signed to 26 bits signed. While the instruction only encodes 24 bits, the target is assumed to be 4 byte aligned, and the value that is encoded in the instruction gets shifted left by 2 to form the offset. Also added a check that the offset is indeed at least 4 byte aligned. Differential Revision: https://reviews.llvm.org/D53401 llvm-svn: 344747 --- lld/ELF/Arch/PPC64.cpp | 3 +- lld/test/ELF/ppc64-call-reach.s | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/ppc64-call-reach.s diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index b6408af..d19264f 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -697,7 +697,8 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { break; case R_PPC64_REL24: { uint32_t Mask = 0x03FFFFFC; - checkInt(Loc, Val, 24, Type); + checkInt(Loc, Val, 26, Type); + checkAlignment(Loc, Val, 4, Type); write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); break; } diff --git a/lld/test/ELF/ppc64-call-reach.s b/lld/test/ELF/ppc64-call-reach.s new file mode 100644 index 0000000..3e655a1 --- /dev/null +++ b/lld/test/ELF/ppc64-call-reach.s @@ -0,0 +1,66 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s +# RUN: not ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ +# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=OVERFLOW %s +# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ +# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s + +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o +# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ +# RUN: %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s +# RUN: not ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ +# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=OVERFLOW %s +# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ +# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s + +# OVERFLOW: ld.lld: error: {{.*}}.o:(.text+0x14): relocation R_PPC64_REL24 out of range: 33554436 is not in [-33554432, 33554431] +# OVERFLOW: ld.lld: error: {{.*}}.o:(.text+0x24): relocation R_PPC64_REL24 out of range: 33554436 is not in [-33554432, 33554431] + +# MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x14): improper alignment for relocation R_PPC64_REL24: 0x19 is not aligned to 4 bytes +# MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x24): improper alignment for relocation R_PPC64_REL24: 0xB is not aligned to 4 bytes + + .global test + .p2align 4 + .type test,@function +test: +.Lgep: + addis 2, 12, .TOC.-.Lgep@ha + addi 2, 2, .TOC.-.Lgep@l +.Llep: + .localentry test, .Llep-.Lgep + mflr 0 + std 0, 16(1) + stdu 1, 32(1) + bl callee + addi 1, 1, 32 + ld 0, 16(1) + mtlr 0 + b tail_callee + +# Check that we are branching to the definitions, and not range-extending +# thunks. +# CHECK-LABEL: test +# CHECK: 10010014: {{.*}} bl .+33554428 +# CHECK: 10010024: {{.*}} b .+33554428 + +# NEGOFFSET-LABEL: test +# NEGOFFSET: 10010014: {{.*}} bl .+33554432 +# NEGOFFSET: 10010024: {{.*}} b .+33554432 + -- 2.7.4