forked from OSchip/llvm-project
[ELF] Fix the branch range computation when reusing a thunk
Notation: dst is `t->getThunkTargetSym()->getVA()` On AArch64, when `src-0x8000000-r_addend <= dst < src-0x8000000`, the condition `target->inBranchRange(rel.type, src, rel.sym->getVA(rel.addend))` may incorrectly consider a thunk reusable. `rel.addend = -getPCBias(rel.type)` resets the addend to 0 for AArch64/PPC and the zero addend is used by `rel.sym->getVA(rel.addend)` to check out-of-range relocations. See the test for a case this computation is wrong: `error: a.o:(.text_high+0x4): relocation R_AARCH64_JUMP26 out of range: -134217732 is not in [-134217728, 134217727]` I have seen a real world case with r_addend=19960. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D117734
This commit is contained in:
parent
6997f4d07f
commit
c03fdd3403
|
@ -2042,7 +2042,8 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
|
|||
// out in the relocation addend. We compensate for the PC bias so that
|
||||
// an Arm and Thumb relocation to the same destination get the same keyAddend,
|
||||
// which is usually 0.
|
||||
int64_t keyAddend = rel.addend + getPCBias(rel.type);
|
||||
const int64_t pcBias = getPCBias(rel.type);
|
||||
const int64_t keyAddend = rel.addend + pcBias;
|
||||
|
||||
// We use a ((section, offset), addend) pair to find the thunk position if
|
||||
// possible so that we create only one thunk for aliased symbols or ICFed
|
||||
|
@ -2061,7 +2062,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
|
|||
if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) &&
|
||||
t->isCompatibleWith(*isec, rel) &&
|
||||
target->inBranchRange(rel.type, src,
|
||||
t->getThunkTargetSym()->getVA(rel.addend)))
|
||||
t->getThunkTargetSym()->getVA(-pcBias)))
|
||||
return std::make_pair(t, false);
|
||||
|
||||
// No existing compatible Thunk in range, create a new one
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# REQUIRES: aarch64
|
||||
# RUN: rm -rf %t && split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64 %t/a.s -o %t/a.o
|
||||
# RUN: ld.lld -pie -T %t/lds %t/a.o -o %t/a
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn %t/a | FileCheck %s
|
||||
|
||||
## We create a thunk for dest.
|
||||
# CHECK-LABEL: <mid>:
|
||||
# CHECK-NEXT: 8010008: b 0x801000c <__AArch64ADRPThunk_>
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <__AArch64ADRPThunk_>:
|
||||
# CHECK-NEXT: 801000c: adrp x16, 0x10000
|
||||
# CHECK-NEXT: add x16, x16, #4
|
||||
# CHECK-NEXT: br x16
|
||||
|
||||
## The first instruction can reuse the thunk but the second can't.
|
||||
## If we reuse the thunk for b, we will get an "out of range" error.
|
||||
# CHECK-LABEL: <high>:
|
||||
# CHECK-NEXT: 1001000c: bl 0x801000c <__AArch64ADRPThunk_>
|
||||
# CHECK-NEXT: b 0x10010014 <__AArch64ADRPThunk_>
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <__AArch64ADRPThunk_>:
|
||||
# CHECK-NEXT: 10010014: adrp x16, 0x10000
|
||||
# CHECK-NEXT: add x16, x16, #4
|
||||
# CHECK-NEXT: br x16
|
||||
|
||||
#--- a.s
|
||||
.section .text_low, "ax", %progbits
|
||||
.globl _start
|
||||
_start:
|
||||
nop
|
||||
dest:
|
||||
ret
|
||||
|
||||
.section .text_mid, "ax", %progbits
|
||||
mid:
|
||||
b dest
|
||||
|
||||
.section .text_high, "ax", %progbits
|
||||
high:
|
||||
bl dest
|
||||
b dest
|
||||
|
||||
#--- lds
|
||||
SECTIONS {
|
||||
.text_low 0x10000: { *(.text_low) }
|
||||
.text_mid 0x8010008 : { *(.text_mid) }
|
||||
.text_high 0x1001000c : { *(.text_high) }
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
# REQUIRES: arm
|
||||
# RUN: rm -rf %t && split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=armv7-a-none-eabi --arm-add-build-attributes %t/a.s -o %t/a.o
|
||||
# RUN: ld.lld -pie -T %t/lds %t/a.o -o %t/a
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn %t/a | FileCheck %s
|
||||
|
||||
## We create a thunk for dest.
|
||||
# CHECK-LABEL: <mid>:
|
||||
# CHECK-NEXT: 2010004: b 0x2010008 <__ARMV7PILongThunk_dest>
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <__ARMV7PILongThunk_dest>:
|
||||
# CHECK-NEXT: 2010008: movw r12, #65516
|
||||
# CHECK-NEXT: movt r12, #65023
|
||||
# CHECK-NEXT: add r12, r12, pc
|
||||
# CHECK-NEXT: bx r12
|
||||
|
||||
## The first instruction can reuse the thunk but the second can't.
|
||||
## If we reuse the thunk for b, we will get an "out of range" error.
|
||||
# CHECK-LABEL: <high>:
|
||||
# CHECK-NEXT: 4010000: bl 0x2010008 <__ARMV7PILongThunk_dest>
|
||||
# CHECK-NEXT: b 0x4010008 <__ARMV7PILongThunk_dest>
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: <__ARMV7PILongThunk_dest>:
|
||||
# CHECK-NEXT: 4010008: movw r12, #65516
|
||||
# CHECK-NEXT: movt r12, #64511
|
||||
# CHECK-NEXT: add r12, r12, pc
|
||||
# CHECK-NEXT: bx r12
|
||||
|
||||
#--- a.s
|
||||
.section .text_low, "ax", %progbits
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
nop
|
||||
dest:
|
||||
bx lr
|
||||
|
||||
.section .text_mid, "ax", %progbits
|
||||
mid:
|
||||
b dest
|
||||
|
||||
.section .text_high, "ax", %progbits
|
||||
high:
|
||||
bl dest
|
||||
b dest
|
||||
|
||||
#--- lds
|
||||
SECTIONS {
|
||||
.text_low 0x10000: { *(.text_low) }
|
||||
.text_mid 0x2010004 : { *(.text_mid) }
|
||||
.text_high 0x4010000 : { *(.text_high) }
|
||||
}
|
Loading…
Reference in New Issue