diff options
author | Sean Fertile <sfertile@ca.ibm.com> | 2018-06-26 19:38:18 +0000 |
---|---|---|
committer | Sean Fertile <sfertile@ca.ibm.com> | 2018-06-26 19:38:18 +0000 |
commit | bf96e9826c0ba67fb2893b139951120a13591589 (patch) | |
tree | 203677dbfad5afb6efb0d3caef0543f4e38c75e1 /lld/ELF/InputSection.cpp | |
parent | 728a3e98fcd2df55264367d0865e785403cfe8d5 (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.cpp | 8 |
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) { |