aboutsummaryrefslogtreecommitdiff
path: root/ELF/Writer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-14 15:39:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-14 15:39:25 +0000
commit1eafc0458f4bb4547fe78c62b78312ad4f719c38 (patch)
treedb247ebc1d3d05750e31ef4b162cf9ab4af9ddef /ELF/Writer.cpp
parentb047fead11133644be3dbae34b85be39ce2819e9 (diff)
downloadsrc-1eafc0458f4bb4547fe78c62b78312ad4f719c38.tar.gz
src-1eafc0458f4bb4547fe78c62b78312ad4f719c38.zip
Vendor import of lld release_40 branch r292009:vendor/lld/lld-release_40-r292009
Notes
Notes: svn path=/vendor/lld/dist/; revision=312181 svn path=/vendor/lld/lld-release_40-r292009/; revision=312182; tag=vendor/lld/lld-release_40-r292009
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r--ELF/Writer.cpp63
1 files changed, 41 insertions, 22 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 154de8cf6d18..bddc42e1acf9 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -250,6 +250,8 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
// Create singleton output sections.
Out<ELFT>::Bss =
make<OutputSection<ELFT>>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
+ Out<ELFT>::BssRelRo = make<OutputSection<ELFT>>(".bss.rel.ro", SHT_NOBITS,
+ SHF_ALLOC | SHF_WRITE);
In<ELFT>::DynStrTab = make<StringTableSection<ELFT>>(".dynstr", true);
In<ELFT>::Dynamic = make<DynamicSection<ELFT>>();
Out<ELFT>::EhFrame = make<EhOutputSection<ELFT>>();
@@ -498,6 +500,8 @@ template <class ELFT> bool elf::isRelroSection(const OutputSectionBase *Sec) {
return true;
if (In<ELFT>::MipsGot && Sec == In<ELFT>::MipsGot->OutSec)
return true;
+ if (Sec == Out<ELFT>::BssRelRo)
+ return true;
StringRef S = Sec->getName();
return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
S == ".eh_frame" || S == ".openbsd.randomdata";
@@ -557,30 +561,38 @@ static bool compareSectionsNonScript(const OutputSectionBase *A,
// If we got here we know that both A and B are in the same PT_LOAD.
- // The TLS initialization block needs to be a single contiguous block in a R/W
- // PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
- // sections are placed here as they don't take up virtual address space in the
- // PT_LOAD.
bool AIsTls = A->Flags & SHF_TLS;
bool BIsTls = B->Flags & SHF_TLS;
- if (AIsTls != BIsTls)
- return AIsTls;
-
- // The next requirement we have is to put nobits sections last. The
- // reason is that the only thing the dynamic linker will see about
- // them is a p_memsz that is larger than p_filesz. Seeing that it
- // zeros the end of the PT_LOAD, so that has to correspond to the
- // nobits sections.
bool AIsNoBits = A->Type == SHT_NOBITS;
bool BIsNoBits = B->Type == SHT_NOBITS;
- if (AIsNoBits != BIsNoBits)
- return BIsNoBits;
- // We place RelRo section before plain r/w ones.
+ // The first requirement we have is to put (non-TLS) nobits sections last. The
+ // reason is that the only thing the dynamic linker will see about them is a
+ // p_memsz that is larger than p_filesz. Seeing that it zeros the end of the
+ // PT_LOAD, so that has to correspond to the nobits sections.
+ bool AIsNonTlsNoBits = AIsNoBits && !AIsTls;
+ bool BIsNonTlsNoBits = BIsNoBits && !BIsTls;
+ if (AIsNonTlsNoBits != BIsNonTlsNoBits)
+ return BIsNonTlsNoBits;
+
+ // We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo
+ // sections after r/w ones, so that the RelRo sections are contiguous.
bool AIsRelRo = isRelroSection<ELFT>(A);
bool BIsRelRo = isRelroSection<ELFT>(B);
if (AIsRelRo != BIsRelRo)
- return AIsRelRo;
+ return AIsNonTlsNoBits ? AIsRelRo : BIsRelRo;
+
+ // The TLS initialization block needs to be a single contiguous block in a R/W
+ // PT_LOAD, so stick TLS sections directly before the other RelRo R/W
+ // sections. The TLS NOBITS sections are placed here as they don't take up
+ // virtual address space in the PT_LOAD.
+ if (AIsTls != BIsTls)
+ return AIsTls;
+
+ // Within the TLS initialization block, the non-nobits sections need to appear
+ // first.
+ if (AIsNoBits != BIsNoBits)
+ return BIsNoBits;
// Some architectures have additional ordering restrictions for sections
// within the same PT_LOAD.
@@ -1071,6 +1083,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
if (Out<ELFT>::Bss->Size > 0)
OutputSections.push_back(Out<ELFT>::Bss);
+ if (Out<ELFT>::BssRelRo->Size > 0)
+ OutputSections.push_back(Out<ELFT>::BssRelRo);
auto OS = dyn_cast_or_null<OutputSection<ELFT>>(findSection(".ARM.exidx"));
if (OS && !OS->Sections.empty() && !Config->Relocatable)
@@ -1272,8 +1286,9 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) {
Phdrs.push_back(ARMExidx);
}
-// The first section of each PT_LOAD and the first section after PT_GNU_RELRO
-// have to be page aligned so that the dynamic linker can set the permissions.
+// The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the
+// first section after PT_GNU_RELRO have to be page aligned so that the dynamic
+// linker can set the permissions.
template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
for (const PhdrEntry &P : Phdrs)
if (P.p_type == PT_LOAD && P.First)
@@ -1282,6 +1297,8 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
for (const PhdrEntry &P : Phdrs) {
if (P.p_type != PT_GNU_RELRO)
continue;
+ if (P.First)
+ P.First->PageAlign = true;
// Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
// have to align it to a page.
auto End = OutputSections.end();
@@ -1635,10 +1652,12 @@ static void unlinkAsync(StringRef Path) {
// Path as a new file. If we do that in a different thread, the new
// thread can remove the new file.
SmallString<128> TempPath;
- if (auto EC = sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath))
- fatal(EC, "createUniqueFile failed");
- if (auto EC = sys::fs::rename(Path, TempPath))
- fatal(EC, "rename failed");
+ if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath))
+ return;
+ if (sys::fs::rename(Path, TempPath)) {
+ sys::fs::remove(TempPath);
+ return;
+ }
// Remove TempPath in background.
std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach();