From: Lang Hames Date: Fri, 10 May 2019 22:24:37 +0000 (+0000) Subject: [JITLink][MachO] Mark atoms in sections 'no-dead-strip' set live by default. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=77ebf7c3a9871e89b24cc75c3bba0e8e5267e4e5;p=llvm [JITLink][MachO] Mark atoms in sections 'no-dead-strip' set live by default. If a MachO section has the no-dead-strip attribute set then its atoms should be preserved, regardless of whether they're public or referenced elsewhere in the object. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360477 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.cpp b/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.cpp index 215742c0e52..0c19f8fee0d 100644 --- a/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.cpp +++ b/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.cpp @@ -100,27 +100,8 @@ Error MachOAtomGraphBuilder::parseSections() { if (auto EC = SecRef.getName(Name)) return errorCodeToError(EC); - StringRef Content; - - // If this is a virtual section, leave its content empty. - if (!SecRef.isVirtual()) { - if (auto EC = SecRef.getContents(Content)) - return errorCodeToError(EC); - if (Content.size() != SecRef.getSize()) - return make_error("Section content size does not match " - "declared size for " + - Name); - } - unsigned SectionIndex = SecRef.getIndex() + 1; - LLVM_DEBUG({ - dbgs() << "Adding section " << Name << ": " - << format("0x%016" PRIx64, SecRef.getAddress()) - << ", size: " << Content.size() - << ", align: " << SecRef.getAlignment() << "\n"; - }); - // FIXME: Get real section permissions // How, exactly, on MachO? sys::Memory::ProtectionFlags Prot; @@ -132,12 +113,41 @@ Error MachOAtomGraphBuilder::parseSections() { sys::Memory::MF_WRITE); auto &GenericSection = G->createSection(Name, Prot, SecRef.isBSS()); - if (SecRef.isVirtual()) - Sections[SectionIndex] = - MachOSection(GenericSection, SecRef.getAddress(), - SecRef.getAlignment(), SecRef.getSize()); - Sections[SectionIndex] = MachOSection(GenericSection, SecRef.getAddress(), - SecRef.getAlignment(), Content); + + LLVM_DEBUG({ + dbgs() << "Adding section " << Name << ": " + << format("0x%016" PRIx64, SecRef.getAddress()) + << ", align: " << SecRef.getAlignment() << "\n"; + }); + + assert(!Sections.count(SectionIndex) && "Section index already in use"); + + auto &MachOSec = + Sections + .try_emplace(SectionIndex, GenericSection, SecRef.getAddress(), + SecRef.getAlignment()) + .first->second; + + if (!SecRef.isVirtual()) { + // If this section has content then record it. + StringRef Content; + if (auto EC = SecRef.getContents(Content)) + return errorCodeToError(EC); + if (Content.size() != SecRef.getSize()) + return make_error("Section content size does not match " + "declared size for " + + Name); + MachOSec.setContent(Content); + } else { + // If this is a zero-fill section then just record the size. + MachOSec.setZeroFill(SecRef.getSize()); + } + + uint32_t SectionFlags = + Obj.is64Bit() ? Obj.getSection64(SecRef.getRawDataRefImpl()).flags + : Obj.getSection(SecRef.getRawDataRefImpl()).flags; + + MachOSec.setNoDeadStrip(SectionFlags & MachO::S_ATTR_NO_DEAD_STRIP); } return Error::success(); @@ -290,7 +300,7 @@ Error MachOAtomGraphBuilder::addNonCustomAtoms() { LLVM_DEBUG(dbgs() << "MachOGraphBuilder setting atom content\n"); - // Set atom contents. + // Set atom contents and any section-based flags. for (auto &KV : SecToAtoms) { auto &S = *KV.first; auto &SecAtoms = KV.second; @@ -304,10 +314,16 @@ Error MachOAtomGraphBuilder::addNonCustomAtoms() { dbgs() << " " << A << " to [ " << S.getAddress() + Offset << " .. " << S.getAddress() + LastAtomAddr << " ]\n"; }); + if (S.isZeroFill()) A.setZeroFill(LastAtomAddr - Offset); else A.setContent(S.getContent().substr(Offset, LastAtomAddr - Offset)); + + // If the section has no-dead-strip set then mark the atom as live. + if (S.isNoDeadStrip()) + A.setLive(true); + LastAtomAddr = Offset; } } diff --git a/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.h b/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.h index 540e2c366f0..f5cd0ea1853 100644 --- a/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.h +++ b/lib/ExecutionEngine/JITLink/MachOAtomGraphBuilder.h @@ -34,17 +34,10 @@ protected: public: MachOSection() = default; - /// Create a MachO section with the given content. + /// Create a MachO section with the given address and alignment. MachOSection(Section &GenericSection, JITTargetAddress Address, - unsigned Alignment, StringRef Content) + unsigned Alignment) : Address(Address), GenericSection(&GenericSection), - ContentPtr(Content.data()), Size(Content.size()), - Alignment(Alignment) {} - - /// Create a zero-fill MachO section with the given size. - MachOSection(Section &GenericSection, JITTargetAddress Address, - unsigned Alignment, size_t ZeroFillSize) - : Address(Address), GenericSection(&GenericSection), Size(ZeroFillSize), Alignment(Alignment) {} /// Create a section without address, content or size (used for common @@ -61,6 +54,19 @@ protected: return GenericSection->getName(); } + MachOSection &setContent(StringRef Content) { + assert(!ContentPtr && !Size && "Content/zeroFill already set"); + ContentPtr = Content.data(); + Size = Content.size(); + return *this; + } + + MachOSection &setZeroFill(uint64_t Size) { + assert(!ContentPtr && !Size && "Content/zeroFill already set"); + this->Size = Size; + return *this; + } + bool isZeroFill() const { return !ContentPtr; } bool empty() const { return getSize() == 0; } @@ -76,12 +82,20 @@ protected: unsigned getAlignment() const { return Alignment; } + MachOSection &setNoDeadStrip(bool NoDeadStrip) { + this->NoDeadStrip = NoDeadStrip; + return *this; + } + + bool isNoDeadStrip() const { return NoDeadStrip; } + private: JITTargetAddress Address = 0; Section *GenericSection = nullptr; const char *ContentPtr = nullptr; - size_t Size = 0; + uint64_t Size = 0; unsigned Alignment = 0; + bool NoDeadStrip = false; }; using CustomAtomizeFunction = std::function; diff --git a/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s b/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s index a6aa72327c9..6c3d9036363 100644 --- a/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s +++ b/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s @@ -263,4 +263,13 @@ subtractor_with_alt_entry_subtrahend_quad: subtractor_with_alt_entry_subtrahend_quad_B: .quad 0 +# Check that unreferenced atoms in no-dead-strip sections are not dead stripped. +# We need to use a local symbol for this as any named symbol will end up in the +# ORC responsibility set, which is automatically marked live and would couse +# spurious passes. +# +# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_sect) = 0 + .section __DATA,__nds_test_sect,regular,no_dead_strip + .quad 0 + .subsections_via_symbols