diff options
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h | 12 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp | 17 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp | 2 | ||||
| -rw-r--r-- | lld/test/elf/ARM/rel-tls-ie32.test | 40 |
4 files changed, 59 insertions, 12 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h index a354c2fc415..883180798c3 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h @@ -33,6 +33,18 @@ public: return _baseAddress; } + bool isDynamicRelocation(const Reference &r) const override { + if (r.kindNamespace() != Reference::KindNamespace::ELF) + return false; + assert(r.kindArch() == Reference::KindArch::ARM); + switch (r.kindValue()) { + case llvm::ELF::R_ARM_TLS_TPOFF32: + return true; + default: + return false; + } + } + bool isPLTRelocation(const Reference &r) const override { if (r.kindNamespace() != Reference::KindNamespace::ELF) return false; diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp index ce5f14c95a3..b0dfac20776 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -89,6 +89,7 @@ static Reference::Addend readAddend(const uint8_t *location, case R_ARM_BASE_PREL: case R_ARM_TLS_IE32: case R_ARM_TLS_LE32: + case R_ARM_TLS_TPOFF32: return (int32_t)read32le(location); case R_ARM_PREL31: return (int32_t)(read32le(location) & 0x7FFFFFFF); @@ -427,6 +428,19 @@ static void relocR_ARM_TLS_LE32(uint8_t *location, uint64_t P, uint64_t S, applyArmReloc(location, result); } +/// \brief R_ARM_TLS_TPOFF32 - S + A - tp => S + A (offset within TLS block) +static void relocR_ARM_TLS_TPOFF32(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + uint32_t result = (uint32_t)(S + A); + + DEBUG(llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + applyArmReloc(location, result); +} + template <uint32_t lshift> static void relocR_ARM_ALU_PC_GN_NC(uint8_t *location, uint32_t result) { static_assert(lshift < 32 && lshift % 2 == 0, @@ -571,6 +585,9 @@ std::error_code ARMTargetRelocationHandler::applyRelocation( case R_ARM_TLS_LE32: relocR_ARM_TLS_LE32(loc, reloc, target, addend, _armLayout.getTPOffset()); break; + case R_ARM_TLS_TPOFF32: + relocR_ARM_TLS_TPOFF32(loc, reloc, target, addend); + break; case R_ARM_GOT_BREL: relocR_ARM_GOT_BREL(loc, reloc, target, addend, _armLayout.getGOTSymAddr()); break; diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index bc3456defca..1114ba3eb91 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -870,7 +870,7 @@ public: /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc. const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) { - llvm_unreachable("Handle TLS TPOFF32"); + return getGOTTLSEntry<R_ARM_TLS_TPOFF32>(da); } const PLT0Atom *getPLT0() { diff --git a/lld/test/elf/ARM/rel-tls-ie32.test b/lld/test/elf/ARM/rel-tls-ie32.test index 7b65c2f194c..ec549f04436 100644 --- a/lld/test/elf/ARM/rel-tls-ie32.test +++ b/lld/test/elf/ARM/rel-tls-ie32.test @@ -1,20 +1,38 @@ # Check handling of R_ARM_TLS_IE32 relocation. + # RUN: yaml2obj -format=elf -docnum 1 %s > %t-tls.o # RUN: yaml2obj -format=elf -docnum 2 %s > %t-tlsv.o # RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ # RUN: --noinhibit-exec %t-tls.o %t-tlsv.o -o %t -# RUN: llvm-objdump -s -t %t | FileCheck %s +# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=STATIC %s + +# STATIC: Contents of section .got: +# STATIC-NEXT: 401008 08000000 0c000000 +# tp_off(i) = 0x08 ^^ ^^ tp_off(j) = 0x0c +# tp_off(i) + sizeof(i) = tp_off(j) +# 0x08 + 0x04 = 0x0c +# STATIC: SYMBOL TABLE: +# STATIC: 00400094 g F .text {{[0-9a-f]+}} main +# STATIC: 00000000 g .tdata 00000004 i +# sizeof(i) = 0x04 ^^ +# STATIC: 00000004 g .tdata 00000004 j + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-tls.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-tlsv.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi \ +# RUN: --noinhibit-exec %t-tls.o %t-tlsv.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=EXEC-DYN %s -# CHECK: Contents of section .got: -# CHECK: 401008 08000000 0c000000 -# tp_off(i) = 0x08 ^^ ^^ tp_off(j) = 0x0c -# tp_off(i) + sizeof(i) = tp_off(j) -# 0x08 + 0x04 = 0x0c -# CHECK: SYMBOL TABLE: -# CHECK: 00400094 g F .text {{[0-9a-f]+}} main -# CHECK: 00000000 g .tdata 00000004 i -# sizeof(i) = 0x04 ^^ -# CHECK: 00000004 g .tdata 00000004 j +# EXEC-DYN: Contents of section .rel.dyn: +# EXEC-DYN-NEXT: 400134 08104000 13000000 0c104000 13000000 +# addr(i) = 0x401008 ^^ ^^ addr(j) = 0x40100c +# EXEC-DYN: Contents of section .got: +# EXEC-DYN-NEXT: 401008 00000000 04000000 +# tls_off(i) = 0x00 ^^ ^^ tls_off(j) = 0x04 +# EXEC-DYN: SYMBOL TABLE: +# EXEC-DYN: 00400144 g F .text {{[0-9a-f]+}} main +# EXEC-DYN: 00000000 g .tdata 00000004 i +# EXEC-DYN: 00000004 g .tdata 00000004 j # tls.o --- |

