diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index b6408af07205..d19264fe7857 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 000000000000..3e655a176878 --- /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 +