diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1862,6 +1862,19 @@ }); } +static int64_t getPCBias(RelType type) { + if (config->emachine != EM_ARM) + return 0; + switch (type) { + case R_ARM_THM_JUMP19: + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + return 4; + default: + return 8; + } +} + // Find or create a ThunkSection within the InputSectionDescription (ISD) that // is in range of Src. An ISD maps to a range of InputSections described by a // linker script section pattern such as { .text .text.* }. @@ -1870,10 +1883,12 @@ InputSectionDescription *isd, const Relocation &rel, uint64_t src) { + // See the comment in getThunk for -pcBias below. + const int64_t pcBias = getPCBias(rel.type); for (std::pair tp : isd->thunkSections) { ThunkSection *ts = tp.first; - uint64_t tsBase = os->addr + ts->outSecOff + rel.addend; - uint64_t tsLimit = tsBase + ts->getSize() + rel.addend; + uint64_t tsBase = os->addr + ts->outSecOff - pcBias; + uint64_t tsLimit = tsBase + ts->getSize(); if (target->inBranchRange(rel.type, src, (src > tsLimit) ? tsBase : tsLimit)) return ts; @@ -2024,19 +2039,6 @@ return true; } -static int64_t getPCBias(RelType type) { - if (config->emachine != EM_ARM) - return 0; - switch (type) { - case R_ARM_THM_JUMP19: - case R_ARM_THM_JUMP24: - case R_ARM_THM_CALL: - return 4; - default: - return 8; - } -} - std::pair ThunkCreator::getThunk(InputSection *isec, Relocation &rel, uint64_t src) { std::vector *thunkVec = nullptr; diff --git a/lld/test/ELF/aarch64-thunk-reuse2.s b/lld/test/ELF/aarch64-thunk-reuse2.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-thunk-reuse2.s @@ -0,0 +1,38 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: ld.lld -pie -Ttext=0x10300 %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn --disassemble-symbols=dest,__AArch64ADRPThunk_,high %t | FileCheck %s + +## We create initial ThunkSection before the gap. Because the ThunkSection +## selection code isn't so precise, we may create an unused thunk there (0x10704). +## In the next pass we will create a ThunkSection after the gap. There used to be +## a bug reusing the first ThunkSection (unreachable) due to the large r_addend. +# CHECK: : +# CHECK-NEXT: 10700: ret +# CHECK: <__AArch64ADRPThunk_>: +# CHECK-NEXT: 10704: adrp x16, 0x10000 +# CHECK-NEXT: add x16, x16, #1792 +# CHECK-NEXT: br x16 +# CHECK-EMPTY: +# CHECK: <__AArch64ADRPThunk_>: +# CHECK-NEXT: 8010710: adrp x16, 0x10000 +# CHECK-NEXT: add x16, x16, #1792 +# CHECK-NEXT: br x16 +# CHECK-LABEL: : +# CHECK-NEXT: 801071c: bl 0x8010710 <__AArch64ADRPThunk_> +# CHECK-NEXT: b 0x8010710 <__AArch64ADRPThunk_> + +.section .text._start, "ax", %progbits +.globl _start +_start: +.space 0x400 +dest: + ret + +.section .text.gap, "ax", %progbits +.space 0x8000000 + +.section .text.high, "ax", %progbits +high: + bl dest + b dest