[lld] r335732 - [PPC64] Add support for R_PPC64_GOT_DTPREL16* relocations
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 27 06:55:41 PDT 2018
Author: syzaara
Date: Wed Jun 27 06:55:41 2018
New Revision: 335732
URL: http://llvm.org/viewvc/llvm-project?rev=335732&view=rev
Log:
[PPC64] Add support for R_PPC64_GOT_DTPREL16* relocations
The local dynamic TLS access on PPC64 ELF v2 ABI uses R_PPC64_GOT_DTPREL16*
relocations when a TLS variables falls outside 2 GB of the thread storage
block. This patch adds support for these relocations by adding a new RelExpr
called R_TLSLD_GOT_OFF which emits a got entry for the TLS variable relative
to the dynamic thread pointer using the relocation R_PPC64_DTPREL64. It then
evaluates the R_PPC64_GOT_DTPREL16* relocations as the got offset for the
R_PPC64_DTPREL64 got entries.
Differential Revision: https://reviews.llvm.org/D48484
Modified:
lld/trunk/ELF/Arch/PPC64.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/test/ELF/ppc64-dtprel.s
Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Wed Jun 27 06:55:41 2018
@@ -230,6 +230,11 @@ RelExpr PPC64::getRelExpr(RelType Type,
case R_PPC64_GOT_TPREL16_DS:
case R_PPC64_GOT_TPREL16_HI:
return R_GOT_OFF;
+ case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ return R_TLSLD_GOT_OFF;
case R_PPC64_TPREL16:
case R_PPC64_TPREL16_HA:
case R_PPC64_TPREL16_LO:
@@ -312,15 +317,18 @@ static std::pair<RelType, uint64_t> toAd
return {R_PPC64_ADDR16, TocBiasedVal};
case R_PPC64_TOC16_DS:
case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
return {R_PPC64_ADDR16_DS, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_HA:
case R_PPC64_GOT_TLSLD16_HA:
case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_HA:
case R_PPC64_TOC16_HA:
return {R_PPC64_ADDR16_HA, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_HI:
case R_PPC64_GOT_TLSLD16_HI:
case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_DTPREL16_HI:
case R_PPC64_TOC16_HI:
return {R_PPC64_ADDR16_HI, TocBiasedVal};
case R_PPC64_GOT_TLSGD16_LO:
@@ -329,6 +337,7 @@ static std::pair<RelType, uint64_t> toAd
return {R_PPC64_ADDR16_LO, TocBiasedVal};
case R_PPC64_TOC16_LO_DS:
case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
return {R_PPC64_ADDR16_LO_DS, TocBiasedVal};
// Dynamic Thread pointer biased relocation types.
@@ -434,6 +443,9 @@ void PPC64::relocateOne(uint8_t *Loc, Re
write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
break;
}
+ case R_PPC64_DTPREL64:
+ write64(Loc, Val - DynamicThreadPointerOffset);
+ break;
default:
error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
}
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Jun 27 06:55:41 2018
@@ -503,6 +503,7 @@ static uint64_t getRelocTargetVA(const I
case R_GOT_FROM_END:
case R_RELAX_TLS_GD_TO_IE_END:
return Sym.getGotOffset() + A - InX::Got->getSize();
+ case R_TLSLD_GOT_OFF:
case R_GOT_OFF:
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return Sym.getGotOffset() + A;
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Jun 27 06:55:41 2018
@@ -209,6 +209,23 @@ handleTlsRelocation(RelType Type, Symbol
return 1;
}
+ // Local-Dynamic sequence where offset of tls variable relative to dynamic
+ // thread pointer is stored in the got.
+ if (Expr == R_TLSLD_GOT_OFF) {
+ // Local-Dynamic relocs can be relaxed to local-exec
+ if (!Config->Shared) {
+ C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});
+ return 1;
+ }
+ if (!Sym.isInGot()) {
+ InX::Got->addEntry(Sym);
+ uint64_t Off = Sym.getGotOffset();
+ InX::Got->Relocations.push_back({R_ABS, Target->TlsOffsetRel, Off, 0, &Sym});
+ }
+ C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
+ return 1;
+ }
+
if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD_GOT,
R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) {
if (Config->Shared) {
@@ -335,12 +352,13 @@ static bool isRelExpr(RelExpr Expr) {
static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
InputSectionBase &S, uint64_t RelOff) {
// These expressions always compute a constant
- if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
- R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32,
- R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC,
- R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT,
- R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT,
- R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
+ if (isRelExprOneOf<
+ R_GOT_FROM_END, R_GOT_OFF, R_TLSLD_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+ R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+ R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
+ R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END,
+ R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(
+ E))
return true;
// These never do, except if the entire file is position dependent or if
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Wed Jun 27 06:55:41 2018
@@ -81,8 +81,9 @@ enum RelExpr {
R_TLSGD_GOT,
R_TLSGD_GOT_FROM_END,
R_TLSGD_PC,
- R_TLSLD_GOT_FROM_END,
R_TLSLD_GOT,
+ R_TLSLD_GOT_FROM_END,
+ R_TLSLD_GOT_OFF,
R_TLSLD_PC,
};
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Jun 27 06:55:41 2018
@@ -633,7 +633,6 @@ void GotSection::writeTo(uint8_t *Buf) {
// whereas InputSectionBase::relocateAlloc() expects its argument
// to point to the start of the output section.
Target->writeGotHeader(Buf);
- Buf += Target->GotHeaderEntriesNum * Target->GotEntrySize;
relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
}
Modified: lld/trunk/test/ELF/ppc64-dtprel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/ppc64-dtprel.s?rev=335732&r1=335731&r2=335732&view=diff
==============================================================================
--- lld/trunk/test/ELF/ppc64-dtprel.s (original)
+++ lld/trunk/test/ELF/ppc64-dtprel.s Wed Jun 27 06:55:41 2018
@@ -5,12 +5,14 @@
// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s
// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s
+// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisLE %s
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: ld.lld -shared %t.o -o %t.so
// RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s
// RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s
// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s
+// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisBE %s
.text
.abiversion 2
@@ -95,6 +97,15 @@ test_not_adjusted:
mtlr 0
blr
+ .globl test_got_dtprel
+ .p2align 4
+ .type test_got_dtprel, at function
+test_got_dtprel:
+ addis 3, 2, i at got@dtprel at ha
+ ld 3, i at got@dtprel at l(3)
+ addis 3, 2, i at got@dtprel at h
+ addi 3, 2, i at got@dtprel
+
.section .debug_addr,"", at progbits
.quad i at dtprel+32768
@@ -126,6 +137,10 @@ k:
// InputRelocs: R_PPC64_DTPREL16_HIGHER {{[0-9a-f]+}} k + 0
// InputRelocs: R_PPC64_DTPREL16_HI {{[0-9a-f]+}} k + 0
// InputRelocs: R_PPC64_DTPREL16_LO {{[0-9a-f]+}} k + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_HA {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_LO_DS {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_HI {{[0-9a-f]+}} i + 0
+// InputRelocs: R_PPC64_GOT_DTPREL16_DS {{[0-9a-f]+}} i + 0
// InputRelocs: Relocation section '.rela.debug_addr'
// InputRelocs: R_PPC64_DTPREL64 {{[0-9a-f]+}} i + 8000
@@ -161,3 +176,29 @@ k:
// Dis: ori 4, 4, 0
// Dis: oris 4, 4, 63
// Dis: ori 4, 4, 33796
+
+// Check for GOT entry for i. There should be a got entry which holds the offset
+// of i relative to the dynamic thread pointer.
+// i at dtprel -> (1024 - 0x8000) = 0xffff8400
+// GotDisBE: Disassembly of section .got:
+// GotDisBE: 4204f8: 00 00 00 00
+// GotDisBE: 4204fc: 00 42 84 f8
+// GotDisBE: 420510: ff ff ff ff
+// GotDisBE: 420514: ff ff 84 00
+
+// GotDisLE: Disassembly of section .got:
+// GotDisLE: 4204f8: f8 84 42 00
+// GotDisLE: 420510: 00 84 ff ff
+// GotDisLE: 420514: ff ff ff ff
+
+// Check that we have the correct offset to the got entry for i at got@dtprel
+// The got entry for i is 0x420510, and the TOC pointer is 0x4284f8.
+// #ha(i at got@dtprel) --> ((0x420510 - 0x4284f8 + 0x8000) >> 16) & 0xffff = 0
+// #lo(i at got@dtprel) --> (0x420510 - 0x4284f8) & 0xffff = -32744
+// #hi(i at got@dtprel) --> ((0x420510 - 0x4284f8) >> 16) & 0xffff = -1
+// i at got@dtprel --> 0x420510 - 0x4284f8 = -32744
+// Dis: test_got_dtprel:
+// Dis: addis 3, 2, 0
+// Dis: ld 3, -32744(3)
+// Dis: addis 3, 2, -1
+// Dis: addi 3, 2, -32744
More information about the llvm-commits
mailing list