diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-05-20 21:23:52 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-05-20 21:23:52 +0000 |
| commit | ebed1fe0de88ef664f9f51d079f5b22eb7f996fe (patch) | |
| tree | aa95c42f09a31ff2d56bd4461c7de614a686ff6c | |
| parent | 14d965166c7166a109bdd75333a4a8f8cf668299 (diff) | |
| download | bcm5719-llvm-ebed1fe0de88ef664f9f51d079f5b22eb7f996fe.tar.gz bcm5719-llvm-ebed1fe0de88ef664f9f51d079f5b22eb7f996fe.zip | |
Refactor R_RELAX_TLS_* value computation.
This makes it explicit that each R_RELAX_TLS_* is equivalent to some
other expression.
With this I think we are at a sweet spot for how much is done in
Target.cpp. I did experiment with moving *all* the value math out of it.
It has the advantage that we know the final value in target independent
code, but it gets quite verbose.
llvm-svn: 270277
| -rw-r--r-- | lld/ELF/InputSection.cpp | 35 | ||||
| -rw-r--r-- | lld/ELF/InputSection.h | 1 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 2 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 5 |
4 files changed, 32 insertions, 11 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 9393bf5c70e..c4b50625236 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -135,15 +135,44 @@ static uint64_t getAArch64Page(uint64_t Expr) { return Expr & (~static_cast<uint64_t>(0xFFF)); } +// For computing values, each R_RELAX_TLS_* corresponds to whatever expression +// the target uses in the mode this is being relaxed into. For example, anything +// that relaxes to LE just needs an R_TLS since that is what is used if we +// had a local exec expression to begin with. +static RelExpr getRelaxedExpr(RelExpr Expr) { + switch (Expr) { + default: + return Expr; + case R_RELAX_TLS_GD_TO_LE: + if (Config->EMachine == EM_386) + return R_NEG_TLS; + return R_TLS; + case R_RELAX_TLS_GD_TO_IE: + if (Config->EMachine == EM_386) + return R_GOT_FROM_END; + return R_GOT_PC; + case R_RELAX_TLS_IE_TO_LE: + case R_RELAX_TLS_LD_TO_LE: + return R_TLS; + } +} + template <class ELFT> static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, const SymbolBody &Body, uint8_t *BufLoc, const elf::ObjectFile<ELFT> &File, RelExpr Expr) { typedef typename ELFT::uint uintX_t; + Expr = getRelaxedExpr(Expr); + switch (Expr) { case R_HINT: llvm_unreachable("cannot relocate hint relocs"); + case R_RELAX_TLS_GD_TO_LE: + case R_RELAX_TLS_GD_TO_IE: + case R_RELAX_TLS_IE_TO_LE: + case R_RELAX_TLS_LD_TO_LE: + llvm_unreachable("Should have been mapped"); case R_TLSLD: return Out<ELFT>::Got->getTlsIndexOff() + A - Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); @@ -168,7 +197,6 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, case R_GOTREL: return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA(); case R_GOT_FROM_END: - case R_RELAX_TLS_GD_TO_IE: return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); case R_GOT: @@ -176,13 +204,9 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, case R_GOT_PAGE_PC: return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P); case R_GOT_PC: - case R_RELAX_TLS_GD_TO_IE_PC: return Body.getGotVA<ELFT>() + A - P; case R_GOTONLY_PC: return Out<ELFT>::Got->getVA() + A - P; - case R_RELAX_TLS_GD_TO_LE: - case R_RELAX_TLS_IE_TO_LE: - case R_RELAX_TLS_LD_TO_LE: case R_TLS: if (Target->TcbSize) return Body.getVA<ELFT>(A) + @@ -308,7 +332,6 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) { case R_RELAX_TLS_GD_TO_LE: Target->relaxTlsGdToLe(BufLoc, Type, SymVA); break; - case R_RELAX_TLS_GD_TO_IE_PC: case R_RELAX_TLS_GD_TO_IE: Target->relaxTlsGdToIe(BufLoc, Type, SymVA); break; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index f50ae72157c..84a48dcfbcd 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -47,7 +47,6 @@ enum RelExpr { R_PPC_PLT_OPD, R_PPC_TOC, R_RELAX_TLS_GD_TO_IE, - R_RELAX_TLS_GD_TO_IE_PC, R_RELAX_TLS_GD_TO_LE, R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 071f442fe5d..ec88ec0774c 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -400,7 +400,7 @@ void X86TargetInfo::relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax }; memcpy(Loc - 3, Inst, sizeof(Inst)); - relocateOne(Loc + 5, R_386_32, -Val); + relocateOne(Loc + 5, R_386_32, Val); } void X86TargetInfo::relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index aa24f1a099a..60181c9628a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -336,9 +336,8 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec // depending on the symbol being locally defined or not. if (Body.isPreemptible()) { - Expr = - Expr == R_TLSGD_PC ? R_RELAX_TLS_GD_TO_IE_PC : R_RELAX_TLS_GD_TO_IE; - C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); + C.Relocations.push_back( + {R_RELAX_TLS_GD_TO_IE, Type, Offset, Addend, &Body}); if (!Body.isInGot()) { Out<ELFT>::Got->addEntry(Body); Out<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, Out<ELFT>::Got, |

