diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index aab5385dad03..b02e1cc2cae1 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1607,12 +1607,22 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, InputSectionDescription *ISD, uint64_t Off) { auto *TS = make(OS, Off); + TS->Partition = OS->Partition; ISD->ThunkSections.push_back({TS, Pass}); return TS; } -std::pair ThunkCreator::getThunk(Symbol &Sym, RelType Type, - uint64_t Src) { +static bool isThunkSectionCompatible(InputSection *Source, + SectionBase *Target) { + // We can't reuse thunks in different loadable partitions because they might + // not be loaded. But partition 1 (the main partition) will always be loaded. + if (Source->Partition != Target->Partition) + return Target->Partition == 1; + return true; +} + +std::pair ThunkCreator::getThunk(InputSection *IS, Symbol &Sym, + RelType Type, uint64_t Src) { std::vector *ThunkVec = nullptr; // We use (section, offset) pair to find the thunk position if possible so @@ -1625,7 +1635,8 @@ std::pair ThunkCreator::getThunk(Symbol &Sym, RelType Type, // Check existing Thunks for Sym to see if they can be reused for (Thunk *T : *ThunkVec) - if (T->isCompatibleWith(Type) && + if (isThunkSectionCompatible(IS, T->getThunkTargetSym()->Section) && + T->isCompatibleWith(Type) && Target->inBranchRange(Type, Src, T->getThunkTargetSym()->getVA())) return std::make_pair(T, false); @@ -1709,7 +1720,7 @@ bool ThunkCreator::createThunks(ArrayRef OutputSections) { Thunk *T; bool IsNew; - std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src); + std::tie(T, IsNew) = getThunk(IS, *Rel.Sym, Rel.Type, Src); if (IsNew) { // Find or create a ThunkSection for the new Thunk diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 923aa4661a39..00156f5c3731 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -136,7 +136,8 @@ private: void createInitialThunkSections(ArrayRef OutputSections); - std::pair getThunk(Symbol &Sym, RelType Type, uint64_t Src); + std::pair getThunk(InputSection *IS, Symbol &Sym, RelType Type, + uint64_t Src); ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *, uint64_t Off); diff --git a/lld/test/ELF/partition-thunk-reuse.s b/lld/test/ELF/partition-thunk-reuse.s new file mode 100644 index 000000000000..6425bdf345b0 --- /dev/null +++ b/lld/test/ELF/partition-thunk-reuse.s @@ -0,0 +1,45 @@ +// REQUIRES: arm +// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=armv7-unknown-linux -arm-add-build-attributes +// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections +// RUN: llvm-nm %t | FileCheck %s + +// CHECK: __Thumbv7ABSLongThunk__start +// CHECK: __Thumbv7ABSLongThunk__start + +// CHECK: __Thumbv7ABSLongThunk_foo +// CHECK-NOT: __Thumbv7ABSLongThunk_foo + +.thumb + +.section .llvm_sympart.g1,"",%llvm_sympart +.asciz "part1" +.4byte f1 + +.section .llvm_sympart.g2,"",%llvm_sympart +.asciz "part2" +.4byte f2 + +.section .text._start,"ax",%progbits +.globl _start +_start: +bx lr +foo: +b f0 +.zero 17*1048576 + +.section .text.f0,"ax",%progbits +.globl f0 +f0: +b foo + +.section .text.f1,"aw",%progbits +.globl f1 +f1: +b _start +b foo + +.section .text.f2,"ax",%progbits +.globl f2 +f2: +b _start +b foo