diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp index 035d7600587b..1966d798e9a9 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp @@ -474,10 +474,15 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation( relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(loc, reloc, target, addend); break; case R_AARCH64_TLSLE_ADD_TPREL_HI12: - return relocR_AARCH64_TLSLE_ADD_TPREL_HI12(loc, reloc, target, addend); - case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: - relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(loc, reloc, target, addend); - break; + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: { + _tlsSize = _layout.getAlignedTLSSize(); + if (ref.kindValue() == R_AARCH64_TLSLE_ADD_TPREL_HI12) + return relocR_AARCH64_TLSLE_ADD_TPREL_HI12(loc, reloc, target + _tlsSize, + addend); + else + relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(loc, reloc, target + _tlsSize, + addend); + } break; default: return make_unhandled_reloc_error(); } diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h index a11a02e97bbb..751551da8b62 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h @@ -15,11 +15,21 @@ namespace lld { namespace elf { +class AArch64TargetLayout; + class AArch64TargetRelocationHandler final : public TargetRelocationHandler { public: + AArch64TargetRelocationHandler(AArch64TargetLayout &layout) + : _layout(layout) {} + std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const AtomLayout &, const Reference &) const override; + +private: + // Cached size of the TLS segment. + mutable uint64_t _tlsSize = 0; + AArch64TargetLayout &_layout; }; } // end namespace elf diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp index e5bb5ef16dc6..1d8b7add1153 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp @@ -17,8 +17,8 @@ using namespace lld; using namespace elf; AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &ctx) - : _ctx(ctx), _targetLayout(new TargetLayout(ctx)), - _relocationHandler(new AArch64TargetRelocationHandler()) {} + : _ctx(ctx), _targetLayout(new AArch64TargetLayout(ctx)), + _relocationHandler(new AArch64TargetRelocationHandler(*_targetLayout)) {} std::unique_ptr AArch64TargetHandler::getWriter() { switch (this->_ctx.getOutputELFType()) { diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h index e19fc6be1d36..fb6eec285e0b 100644 --- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h @@ -19,6 +19,19 @@ namespace lld { namespace elf { class AArch64LinkingContext; +class AArch64TargetLayout final : public TargetLayout { +public: + AArch64TargetLayout(ELFLinkingContext &ctx) : TargetLayout(ctx) {} + + uint64_t getAlignedTLSSize() const { + return llvm::RoundUpToAlignment(TCB_ALIGNMENT, this->getTLSSize()); + } + +private: + // Alignment requirement for TCB. + enum { TCB_ALIGNMENT = 0x10 }; +}; + class AArch64TargetHandler final : public TargetHandler { public: AArch64TargetHandler(AArch64LinkingContext &ctx); @@ -39,7 +52,7 @@ public: private: AArch64LinkingContext &_ctx; - std::unique_ptr> _targetLayout; + std::unique_ptr _targetLayout; std::unique_ptr _relocationHandler; }; diff --git a/lld/test/elf/AArch64/local-tls.test b/lld/test/elf/AArch64/local-tls.test new file mode 100644 index 000000000000..6bf73e0d1dae --- /dev/null +++ b/lld/test/elf/AArch64/local-tls.test @@ -0,0 +1,102 @@ +# Check for correct offsets when handling relocations for local TLS +# access (R_AARCH64_TLSLE_ADD_TPREL_HI12, R_AARCH64_TLSLE_ADD_TPREL_LO12_NC) +# RUN: yaml2obj -format=elf %s > %t-obj +# RUN: lld -flavor gnu -target arm64 --noinhibit-exec -o %t-exe %t-obj +# RUN: llvm-objdump -s -t %t-exe | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK-NEXT: 4001dc 48d03bd5 08010091 08410091 090140b9 H.;......A....@. +# \_ | add x8, x8, #0x0 (R_AARCH64_TLSLE_ADD_TPREL_HI12) +# \_ add x8, x8, #0x10 (R_AARCH64_TLSLE_ADD_TPREL_LO12_NC) + +--- +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_GNU + Type: ET_REL + Machine: EM_AARCH64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 48D03BD50801009108010091090140B9E003092AC0035FD6FD7BBFA9FD030091FF4300D1BFC31FB8F6FFFF97BF030091FD7BC1A8C0035FD6 + - Name: .rela.text + Type: SHT_RELA + Link: .symtab + AddressAlign: 0x0000000000000008 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: a + Type: R_AARCH64_TLSLE_ADD_TPREL_HI12 + - Offset: 0x0000000000000008 + Symbol: a + Type: R_AARCH64_TLSLE_ADD_TPREL_LO12_NC + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '' + - Name: .tdata + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ] + AddressAlign: 0x0000000000000004 + Content: '04000000' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742039636664333732343263346635623866393362636462343536366163636565373962306563653666292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420653262383764656531656531393835396561383334313565616365333533666130323362646462302900 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$d.1' + Type: STT_TLS + Section: .tdata + - Name: '$d.2' + Section: .comment + - Name: '$x.0' + Section: .text + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .tdata + Type: STT_SECTION + Section: .tdata + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .note.GNU-stack + Type: STT_SECTION + Section: .note.GNU-stack + Global: + - Name: a + Type: STT_TLS + Section: .tdata + Size: 0x0000000000000004 + - Name: foo + Type: STT_FUNC + Section: .text + Size: 0x0000000000000018 + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000018 + Size: 0x0000000000000020 +...