diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:39:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:39:25 +0000 |
commit | 1eafc0458f4bb4547fe78c62b78312ad4f719c38 (patch) | |
tree | db247ebc1d3d05750e31ef4b162cf9ab4af9ddef /ELF/Writer.cpp | |
parent | b047fead11133644be3dbae34b85be39ce2819e9 (diff) | |
download | src-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.cpp | 63 |
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(); |