summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
authorMichael J. Spencer <bigcheesegs@gmail.com>2015-11-03 22:39:09 +0000
committerMichael J. Spencer <bigcheesegs@gmail.com>2015-11-03 22:39:09 +0000
commitd77f0d2526e28611b09121324540e8faaa5cab1a (patch)
tree3f48354bb665064aff8c66de78cac0ab8efab906 /lld/ELF
parent3bd1def3ecd425757373b44b01675eb1397bd58e (diff)
downloadbcm5719-llvm-d77f0d2526e28611b09121324540e8faaa5cab1a.tar.gz
bcm5719-llvm-d77f0d2526e28611b09121324540e8faaa5cab1a.zip
[elf2] Implement R_X86_64_TPOFF32.
This does not support TPOFF32 relocations to local symbols as the address calculations are separate. Support for this will be a separate patch. llvm-svn: 251998
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/OutputSections.cpp3
-rw-r--r--lld/ELF/OutputSections.h3
-rw-r--r--lld/ELF/Target.cpp3
-rw-r--r--lld/ELF/Writer.cpp4
4 files changed, 12 insertions, 1 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index e3e3fef8be5..5007ba003fa 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -644,6 +644,9 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
case SymbolBody::DefinedRegularKind: {
const auto &DR = cast<DefinedRegular<ELFT>>(S);
InputSectionBase<ELFT> &SC = DR.Section;
+ if (DR.Sym.getType() == STT_TLS)
+ return SC.OutSec->getVA() + SC.getOffset(DR.Sym) -
+ Out<ELFT>::TlsInitImageVA;
return SC.OutSec->getVA() + SC.getOffset(DR.Sym);
}
case SymbolBody::DefinedCommonKind:
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 5a23c86411c..df173361da2 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -353,6 +353,7 @@ private:
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
template <class ELFT> struct Out {
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
static DynamicSection<ELFT> *Dynamic;
static GnuHashTableSection<ELFT> *GnuHashTab;
static GotPltSection<ELFT> *GotPlt;
@@ -370,6 +371,7 @@ template <class ELFT> struct Out {
static StringTableSection<ELFT> *StrTab;
static SymbolTableSection<ELFT> *DynSymTab;
static SymbolTableSection<ELFT> *SymTab;
+ static uintX_t TlsInitImageVA;
};
template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
@@ -389,6 +391,7 @@ template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::ShStrTab;
template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::SymTab;
+template <class ELFT> typename Out<ELFT>::uintX_t Out<ELFT>::TlsInitImageVA;
}
}
#endif
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 0ebcf827d9d..7adc5c6de43 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -339,6 +339,9 @@ void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
error("R_X86_64_32S out of range");
write32le(Loc, SA);
break;
+ case R_X86_64_TPOFF32:
+ write32le(Loc, SA);
+ break;
default:
error("unrecognized reloc " + Twine(Type));
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 4f8f623c740..fe87d926067 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -716,8 +716,10 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
if ((Sec->getFlags() & SHF_ALLOC) && (Sec->getFlags() & SHF_TLS)) {
- if (!TlsPhdr.p_vaddr)
+ if (!TlsPhdr.p_vaddr) {
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
+ Out<ELFT>::TlsInitImageVA = VA;
+ }
if (Sec->getType() != SHT_NOBITS)
VA = RoundUpToAlignment(VA, Sec->getAlign());
uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
OpenPOWER on IntegriCloud