summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-06-04 23:22:34 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-06-04 23:22:34 +0000
commit69f5402b263d5bfcccda8cdb6db669eb34f82f35 (patch)
treef933b2c80239bbe22ca72df77bc7597e25e7e5e7
parentf807d47164176352b8314526884664fefa5e3b51 (diff)
downloadbcm5719-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.cpp36
-rw-r--r--lld/ELF/Relocations.cpp6
-rw-r--r--lld/ELF/Relocations.h2
-rw-r--r--lld/ELF/Target.cpp14
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());
}
OpenPOWER on IntegriCloud