summaryrefslogtreecommitdiff
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
authorSean Fertile <sfertile@ca.ibm.com>2018-06-26 19:38:18 +0000
committerSean Fertile <sfertile@ca.ibm.com>2018-06-26 19:38:18 +0000
commitbf96e9826c0ba67fb2893b139951120a13591589 (patch)
tree203677dbfad5afb6efb0d3caef0543f4e38c75e1 /lld/ELF/InputSection.cpp
parent728a3e98fcd2df55264367d0865e785403cfe8d5 (diff)
[PPC64] Thread-local storage general-dynamic to initial-exec relaxation.
Patch adds support for relaxing the general-dynamic tls sequence to initial-exec. the relaxation performs the following transformation: addis r3, r2, x@got@tlsgd@ha --> addis r3, r2, x@got@tprel@ha addi r3, r3, x@got@tlsgd@l --> ld r3, x@got@tprel@l(r3) bl __tls_get_addr(x@tlsgd) --> nop nop --> add r3, r3, r13 and instead of emitting a DTPMOD64/DTPREL64 pair for x, we emit a single R_PPC64_TPREL64. Differential Revision: https://reviews.llvm.org/D48090
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp8
1 files changed, 8 insertions, 0 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 33f4f25658f..aec9cd1af23 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -504,6 +504,7 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
case R_RELAX_TLS_GD_TO_IE_END:
return Sym.getGotOffset() + A - InX::Got->getSize();
case R_GOT_OFF:
+ case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return Sym.getGotOffset() + A;
case R_GOT_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
@@ -773,11 +774,18 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
break;
case R_RELAX_TLS_GD_TO_IE:
case R_RELAX_TLS_GD_TO_IE_ABS:
+ case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
case R_RELAX_TLS_GD_TO_IE_END:
Target->relaxTlsGdToIe(BufLoc, Type, TargetVA);
break;
case R_PPC_CALL:
+ // If this is a call to __tls_get_addr, it may be part of a TLS
+ // sequence that has been relaxed and turned into a nop. In this
+ // case, we don't want to handle it as a call.
+ if (read32(BufLoc) == 0x60000000) // nop
+ break;
+
// Patch a nop (0x60000000) to a ld.
if (Rel.Sym->NeedsTocRestore) {
if (BufLoc + 8 > BufEnd || read32(BufLoc + 4) != 0x60000000) {