diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-06-04 23:22:34 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-06-04 23:22:34 +0000 |
| commit | 69f5402b263d5bfcccda8cdb6db669eb34f82f35 (patch) | |
| tree | f933b2c80239bbe22ca72df77bc7597e25e7e5e7 | |
| parent | f807d47164176352b8314526884664fefa5e3b51 (diff) | |
| download | bcm5719-llvm-69f5402b263d5bfcccda8cdb6db669eb34f82f35.tar.gz bcm5719-llvm-69f5402b263d5bfcccda8cdb6db669eb34f82f35.zip | |
Use adjustRelaxExpr for tls relaxations too.
This remove some EM_386 specific code from InputSection.cpp and opens
the way for more relaxations.
llvm-svn: 271814
| -rw-r--r-- | lld/ELF/InputSection.cpp | 36 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Relocations.h | 2 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 14 |
4 files changed, 28 insertions, 30 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index b6b09db506a..a90b3098a27 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -141,44 +141,16 @@ 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); @@ -207,6 +179,7 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, return Body.getSize<ELFT>() + A; case R_GOTREL: return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA(); + case R_RELAX_TLS_GD_TO_IE_END: case R_GOT_FROM_END: return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t); @@ -214,15 +187,20 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, return Body.getGotVA<ELFT>() + A; case R_GOT_PAGE_PC: return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P); + case R_RELAX_TLS_GD_TO_IE: case R_GOT_PC: return Body.getGotVA<ELFT>() + A - P; case R_GOTONLY_PC: return Out<ELFT>::Got->getVA() + A - P; + case R_RELAX_TLS_LD_TO_LE: + case R_RELAX_TLS_IE_TO_LE: + case R_RELAX_TLS_GD_TO_LE: case R_TLS: if (Target->TcbSize) return Body.getVA<ELFT>(A) + alignTo(Target->TcbSize, Out<ELFT>::TlsPhdr->p_align); return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz; + case R_RELAX_TLS_GD_TO_LE_NEG: case R_NEG_TLS: return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A); case R_ABS: @@ -342,9 +320,11 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) { Target->relaxTlsLdToLe(BufLoc, Type, SymVA); break; case R_RELAX_TLS_GD_TO_LE: + case R_RELAX_TLS_GD_TO_LE_NEG: Target->relaxTlsGdToLe(BufLoc, Type, SymVA); break; case R_RELAX_TLS_GD_TO_IE: + case R_RELAX_TLS_GD_TO_IE_END: Target->relaxTlsGdToIe(BufLoc, Type, SymVA); break; case R_PPC_PLT_OPD: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 5a13ef0166e..736e447484a 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -148,7 +148,8 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, // depending on the symbol being locally defined or not. if (isPreemptible(Body, Type)) { C.Relocations.push_back( - {R_RELAX_TLS_GD_TO_IE, Type, Offset, Addend, &Body}); + {Target->adjustRelaxExpr(Type, nullptr, 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, @@ -158,7 +159,8 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body, return 2; } C.Relocations.push_back( - {R_RELAX_TLS_GD_TO_LE, Type, Offset, Addend, &Body}); + {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, + Offset, Addend, &Body}); return Target->TlsGdRelaxSkip; } diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 1c24e617003..8f6a5ce75c2 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -42,7 +42,9 @@ enum RelExpr { R_RELAX_GOT_PC, R_RELAX_GOT_PC_NOPIC, R_RELAX_TLS_GD_TO_IE, + R_RELAX_TLS_GD_TO_IE_END, R_RELAX_TLS_GD_TO_LE, + R_RELAX_TLS_GD_TO_LE_NEG, R_RELAX_TLS_IE_TO_LE, R_RELAX_TLS_LD_TO_LE, R_SIZE, diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 2d871ceef7d..073e613b3ad 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -92,6 +92,8 @@ public: int32_t Index, unsigned RelOff) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; + RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const override; void relaxTlsGdToIe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; void relaxTlsGdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; void relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; @@ -309,6 +311,18 @@ RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { } } +RelExpr X86TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data, + RelExpr Expr) const { + switch (Expr) { + default: + return Expr; + case R_RELAX_TLS_GD_TO_IE: + return R_RELAX_TLS_GD_TO_IE_END; + case R_RELAX_TLS_GD_TO_LE: + return R_RELAX_TLS_GD_TO_LE_NEG; + } +} + void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const { write32le(Buf, Out<ELF32LE>::Dynamic->getVA()); } |

