summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/OutputSections.cpp2
-rw-r--r--lld/ELF/OutputSections.h4
-rw-r--r--lld/ELF/Target.cpp11
-rw-r--r--lld/ELF/Target.h1
-rw-r--r--lld/ELF/Writer.cpp14
5 files changed, 30 insertions, 2 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 9b5fad15016..4d72f5e1b0d 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -21,6 +21,8 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
+bool lld::elf2::HasGotOffRel = false;
+
template <class ELFT>
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
uintX_t sh_flags)
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index d01eb7355ae..66dad5e67a1 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -37,6 +37,10 @@ template <class ELFT> class ObjectFile;
template <class ELFT> class DefinedRegular;
template <class ELFT> class ELFSymbolBody;
+// Flag to force GOT to be in output if we have relocations
+// that relies on its address.
+extern bool HasGotOffRel;
+
template <class ELFT>
static inline typename llvm::object::ELFFile<ELFT>::uintX_t
getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 2ea6c65b2f5..c540e552b84 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -95,6 +95,7 @@ public:
unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
uint64_t P, uint64_t SA,
const SymbolBody &S) const override;
+ bool isGotRelative(uint32_t Type) const override;
private:
void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
@@ -232,6 +233,8 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
return false;
}
+bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
+
unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; }
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
@@ -358,6 +361,13 @@ bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
(Type == R_386_PC32 && S.isShared());
}
+bool X86TargetInfo::isGotRelative(uint32_t Type) const {
+ // This relocation does not require got entry,
+ // but it is relative to got and needs it to be created.
+ // Here we request for that.
+ return Type == R_386_GOTOFF;
+}
+
void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
uint64_t P, uint64_t SA, uint64_t ZA,
uint8_t *PairedLoc) const {
@@ -366,6 +376,7 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
add32le(Loc, SA);
break;
case R_386_GOT32:
+ case R_386_GOTOFF:
add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
break;
case R_386_GOTPC:
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 8b24e461e81..f2ca0f092bb 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -64,6 +64,7 @@ public:
virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
uint64_t P, uint64_t SA, uint64_t ZA = 0,
uint8_t *PairedLoc = nullptr) const = 0;
+ virtual bool isGotRelative(uint32_t Type) const;
virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const;
virtual bool needsCopyRel(uint32_t Type, const SymbolBody &S) const;
virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index b5fa2b94741..3fc272e4230 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -209,6 +209,9 @@ void Writer<ELFT>::scanRelocs(
SymbolBody *Body = File.getSymbolBody(SymIndex);
uint32_t Type = RI.getType(Config->Mips64EL);
+ if (Target->isGotRelative(Type))
+ HasGotOffRel = true;
+
if (Target->isTlsLocalDynamicReloc(Type)) {
if (Target->isTlsOptimized(Type, nullptr))
continue;
@@ -774,10 +777,17 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
}
+ bool needsGot = !Out<ELFT>::Got->empty();
// We add the .got section to the result for dynamic MIPS target because
// its address and properties are mentioned in the .dynamic section.
- if (!Out<ELFT>::Got->empty() ||
- (isOutputDynamic() && Config->EMachine == EM_MIPS))
+ if (Config->EMachine == EM_MIPS)
+ needsGot |= isOutputDynamic();
+ // If we have a relocation that is relative to GOT (such as GOTOFFREL),
+ // we need to emit a GOT even if it's empty.
+ if (HasGotOffRel)
+ needsGot = true;
+
+ if (needsGot)
OutputSections.push_back(Out<ELFT>::Got);
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
OutputSections.push_back(Out<ELFT>::GotPlt);
OpenPOWER on IntegriCloud