summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp5
-rw-r--r--lld/ELF/Relocations.cpp30
-rw-r--r--lld/ELF/Relocations.h2
-rw-r--r--lld/ELF/Target.cpp24
-rw-r--r--lld/ELF/Target.h1
-rw-r--r--lld/test/ELF/aarch64-tlsdesc.s24
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: ]
OpenPOWER on IntegriCloud