From 87575f6501dc4c1ae27e3bd6a469fa0391964a2b Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 29 May 2019 04:06:01 +0000 Subject: [PATCH] ELF: Don't reuse a thunk in a different loadable partition. There's no guarantee that the other partition will be loaded, so it can't be reused. Differential Revision: https://reviews.llvm.org/D62365 llvm-svn: 361926 --- lld/ELF/Relocations.cpp | 19 +++++++++++---- lld/ELF/Relocations.h | 3 ++- lld/test/ELF/partition-thunk-reuse.s | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 lld/test/ELF/partition-thunk-reuse.s diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index aab5385..b02e1cc 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 923aa46..00156f5 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 0000000..6425bdf --- /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 -- 2.7.4