summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp36
1 files changed, 8 insertions, 28 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:
OpenPOWER on IntegriCloud