diff options
| -rw-r--r-- | lld/ELF/InputSection.cpp | 5 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 30 | ||||
| -rw-r--r-- | lld/ELF/Relocations.h | 2 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 24 | ||||
| -rw-r--r-- | lld/ELF/Target.h | 1 | ||||
| -rw-r--r-- | lld/test/ELF/aarch64-tlsdesc.s | 24 |
6 files changed, 70 insertions, 16 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 54b6f5e29f5..fe76388ae76 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -193,6 +193,11 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); case R_TLSGD_PC: return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P; + case R_TLSDESC: + return Out<ELFT>::Got->getGlobalDynAddr(Body) + A; + case R_TLSDESC_PAGE: + return getAArch64Page(Out<ELFT>::Got->getGlobalDynAddr(Body) + A) - + getAArch64Page(P); case R_PLT: return Body.getPltVA<ELFT>() + A; case R_PLT_PC: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 53149ba3faf..48fb403b50e 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -62,7 +62,7 @@ static bool refersToGotEntry(RelExpr Expr) { return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL || Expr == R_MIPS_GOT_LOCAL_PAGE || Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || Expr == R_GOT_FROM_END || Expr == R_TLSGD || - Expr == R_TLSGD_PC; + Expr == R_TLSGD_PC || Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE; } static bool isPreemptible(const SymbolBody &Body, uint32_t Type) { @@ -94,6 +94,19 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, return 0; typedef typename ELFT::uint uintX_t; + + if ((Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE || Expr == R_HINT) && + Config->Shared) { + if (Out<ELFT>::Got->addDynTlsEntry(Body)) { + uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body); + Out<ELFT>::RelaDyn->addReloc( + {Target->TlsDescRel, Out<ELFT>::Got, Off, false, &Body, 0}); + } + if (Expr != R_HINT) + C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); + return 1; + } + if (Expr == R_TLSLD_PC || Expr == R_TLSLD) { // Local-Dynamic relocs can be relaxed to Local-Exec. if (!Config->Shared) { @@ -116,7 +129,8 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, return 1; } - if (Target->isTlsGlobalDynamicRel(Type)) { + if (Expr == R_TLSDESC_PAGE || Expr == R_TLSDESC || Expr == R_HINT || + Target->isTlsGlobalDynamicRel(Type)) { if (Config->Shared) { if (Out<ELFT>::Got->addDynTlsEntry(Body)) { uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body); @@ -254,12 +268,12 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF || E == R_MIPS_GOT_LOCAL || E == R_MIPS_GOT_LOCAL_PAGE || E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC || - E == R_TLSGD || E == R_PPC_PLT_OPD) + E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E == R_HINT) return true; // These never do, except if the entire file is position dependent or if // only the low bits are used. - if (E == R_GOT || E == R_PLT) + if (E == R_GOT || E == R_PLT || E == R_TLSDESC) return Target->usesOnlyLowPageBits(Type) || !Config->Pic; if (isPreemptible(Body, Type)) @@ -493,10 +507,6 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { uint32_t Type = RI.getType(Config->Mips64EL); RelExpr Expr = Target->getRelExpr(Type, Body); - // Ignore "hint" relocation because it is for optional code optimization. - if (Expr == R_HINT) - continue; - uintX_t Offset = C.getOffset(RI.r_offset); if (Offset == (uintX_t)-1) continue; @@ -519,6 +529,10 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { continue; } + // Ignore "hint" relocation because it is for optional code optimization. + if (Expr == R_HINT) + continue; + if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) || !isPreemptible(Body, Type)) { // If the relocation points to something in the file, we can process it. diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index e682c579c86..57f0318359d 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -47,6 +47,8 @@ enum RelExpr { R_SIZE, R_THUNK, R_TLS, + R_TLSDESC, + R_TLSDESC_PAGE, R_TLSGD, R_TLSGD_PC, R_TLSLD, diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 4891f04b0a9..c18e45b615c 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -147,7 +147,6 @@ public: AArch64TargetInfo(); RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override; uint32_t getDynRel(uint32_t Type) const override; - bool isTlsGlobalDynamicRel(uint32_t Type) const override; bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override; void writePltZero(uint8_t *Buf) const override; @@ -1076,6 +1075,7 @@ AArch64TargetInfo::AArch64TargetInfo() { IRelativeRel = R_AARCH64_IRELATIVE; GotRel = R_AARCH64_GLOB_DAT; PltRel = R_AARCH64_JUMP_SLOT; + TlsDescRel = R_AARCH64_TLSDESC; TlsGotRel = R_AARCH64_TLS_TPREL64; PltEntrySize = 16; PltZeroSize = 32; @@ -1091,6 +1091,16 @@ RelExpr AArch64TargetInfo::getRelExpr(uint32_t Type, default: return R_ABS; + case R_AARCH64_TLSDESC_ADR_PAGE21: + return R_TLSDESC_PAGE; + + case R_AARCH64_TLSDESC_LD64_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12_NC: + return R_TLSDESC; + + case R_AARCH64_TLSDESC_CALL: + return R_HINT; + case R_AARCH64_TLSLE_ADD_TPREL_HI12: case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: return R_TLS; @@ -1128,18 +1138,13 @@ bool AArch64TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { case R_AARCH64_LDST32_ABS_LO12_NC: case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12_NC: + case R_AARCH64_TLSDESC_LD64_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: return true; } } -bool AArch64TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const { - return Type == R_AARCH64_TLSDESC_ADR_PAGE21 || - Type == R_AARCH64_TLSDESC_LD64_LO12_NC || - Type == R_AARCH64_TLSDESC_ADD_LO12_NC || - Type == R_AARCH64_TLSDESC_CALL; -} - bool AArch64TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC; @@ -1239,6 +1244,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_TLSDESC_ADR_PAGE21: checkInt<33>(Val, Type); updateAArch64Addr(Loc, Val >> 12); break; @@ -1257,6 +1263,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, break; case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSDESC_LD64_LO12_NC: checkAlignment<8>(Val, Type); or32le(Loc, (Val & 0xFF8) << 7); break; @@ -1284,6 +1291,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, updateAArch64Add(Loc, Val >> 12); break; case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12_NC: updateAArch64Add(Loc, Val); break; default: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index f572c73685e..5fa1181f54f 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -73,6 +73,7 @@ public: uint32_t PltRel; uint32_t RelativeRel; uint32_t IRelativeRel; + uint32_t TlsDescRel; uint32_t TlsGotRel = 0; uint32_t TlsModuleIndexRel; uint32_t TlsOffsetRel; diff --git a/lld/test/ELF/aarch64-tlsdesc.s b/lld/test/ELF/aarch64-tlsdesc.s new file mode 100644 index 00000000000..f8c73aff243 --- /dev/null +++ b/lld/test/ELF/aarch64-tlsdesc.s @@ -0,0 +1,24 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.so +// RUN: llvm-objdump -d %t.so | FileCheck %s +// RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=REL %s + + adrp x0, :tlsdesc:a + ldr x1, [x0, :tlsdesc_lo12:a] + add x0, x0, :tlsdesc_lo12:a + .tlsdesccall a + blr x1 + +// CHECK: 1000: {{.*}} adrp x0, #4096 +// CHECK-NEXT: 1004: {{.*}} ldr x1, [x0, #144] +// CHECK-NEXT: 1008: {{.*}} add x0, x0, #144 +// CHECK-NEXT: 100c: {{.*}} blr x1 + +// 0x1000 + 4096 + 144 = 0x2090 + +// REL: Relocations [ +// REL-NEXT: Section (4) .rela.dyn { +// REL-NEXT: 0x2090 R_AARCH64_TLSDESC a 0x0 +// REL-NEXT: } +// REL-NEXT: ] |

