diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-19 21:12:03 +0000 |
| commit | c9157d925c489f07ba9c0b2ce47e5149b75969a5 (patch) | |
| tree | 08bc4a3d9cad3f9ebffa558ddf140b9d9257b219 /contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp | |
| parent | 2a66844f606a35d68ad8a8061f4bea204274b3bc (diff) | |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp | 472 |
1 files changed, 0 insertions, 472 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp deleted file mode 100644 index 830582bb3649..000000000000 --- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp +++ /dev/null @@ -1,472 +0,0 @@ -//===------- DebuggerSupportPlugin.cpp - Utils for debugger support -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h" - -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/BinaryFormat/MachO.h" - -#define DEBUG_TYPE "orc" - -using namespace llvm; -using namespace llvm::jitlink; -using namespace llvm::orc; - -static const char *SynthDebugSectionName = "__jitlink_synth_debug_object"; - -namespace { - -struct MachO64LE { - using UIntPtr = uint64_t; - - using Header = MachO::mach_header_64; - using SegmentLC = MachO::segment_command_64; - using Section = MachO::section_64; - using NList = MachO::nlist_64; - - static constexpr support::endianness Endianness = support::little; - static constexpr const uint32_t Magic = MachO::MH_MAGIC_64; - static constexpr const uint32_t SegmentCmd = MachO::LC_SEGMENT_64; -}; - -class MachODebugObjectSynthesizerBase - : public GDBJITDebugInfoRegistrationPlugin::DebugSectionSynthesizer { -public: - static bool isDebugSection(Section &Sec) { - return Sec.getName().startswith("__DWARF,"); - } - - MachODebugObjectSynthesizerBase(LinkGraph &G, ExecutorAddr RegisterActionAddr) - : G(G), RegisterActionAddr(RegisterActionAddr) {} - virtual ~MachODebugObjectSynthesizerBase() = default; - - Error preserveDebugSections() { - if (G.findSectionByName(SynthDebugSectionName)) { - LLVM_DEBUG({ - dbgs() << "MachODebugObjectSynthesizer skipping graph " << G.getName() - << " which contains an unexpected existing " - << SynthDebugSectionName << " section.\n"; - }); - return Error::success(); - } - - LLVM_DEBUG({ - dbgs() << "MachODebugObjectSynthesizer visiting graph " << G.getName() - << "\n"; - }); - for (auto &Sec : G.sections()) { - if (!isDebugSection(Sec)) - continue; - // Preserve blocks in this debug section by marking one existing symbol - // live for each block, and introducing a new live, anonymous symbol for - // each currently unreferenced block. - LLVM_DEBUG({ - dbgs() << " Preserving debug section " << Sec.getName() << "\n"; - }); - SmallSet<Block *, 8> PreservedBlocks; - for (auto *Sym : Sec.symbols()) { - bool NewPreservedBlock = - PreservedBlocks.insert(&Sym->getBlock()).second; - if (NewPreservedBlock) - Sym->setLive(true); - } - for (auto *B : Sec.blocks()) - if (!PreservedBlocks.count(B)) - G.addAnonymousSymbol(*B, 0, 0, false, true); - } - return Error::success(); - } - -protected: - LinkGraph &G; - ExecutorAddr RegisterActionAddr; -}; - -template <typename MachOTraits> -class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase { -private: - class MachOStructWriter { - public: - MachOStructWriter(MutableArrayRef<char> Buffer) : Buffer(Buffer) {} - - size_t getOffset() const { return Offset; } - - template <typename MachOStruct> void write(MachOStruct S) { - assert(Offset + sizeof(S) <= Buffer.size() && - "Container block overflow while constructing debug MachO"); - if (MachOTraits::Endianness != support::endian::system_endianness()) - MachO::swapStruct(S); - memcpy(Buffer.data() + Offset, &S, sizeof(S)); - Offset += sizeof(S); - } - - private: - MutableArrayRef<char> Buffer; - size_t Offset = 0; - }; - -public: - using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase; - - Error startSynthesis() override { - LLVM_DEBUG({ - dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName() - << "\n"; - }); - auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read); - - struct DebugSectionInfo { - Section *Sec = nullptr; - StringRef SegName; - StringRef SecName; - uint64_t Alignment = 0; - orc::ExecutorAddr StartAddr; - uint64_t Size = 0; - }; - - SmallVector<DebugSectionInfo, 12> DebugSecInfos; - size_t NumSections = 0; - for (auto &Sec : G.sections()) { - if (Sec.blocks().empty()) - continue; - - ++NumSections; - if (isDebugSection(Sec)) { - size_t SepPos = Sec.getName().find(','); - if (SepPos > 16 || (Sec.getName().size() - (SepPos + 1) > 16)) { - LLVM_DEBUG({ - dbgs() << "Skipping debug object synthesis for graph " - << G.getName() - << ": encountered non-standard DWARF section name \"" - << Sec.getName() << "\"\n"; - }); - return Error::success(); - } - DebugSecInfos.push_back({&Sec, Sec.getName().substr(0, SepPos), - Sec.getName().substr(SepPos + 1), 0, - orc::ExecutorAddr(), 0}); - } else { - NonDebugSections.push_back(&Sec); - - // If the first block in the section has a non-zero alignment offset - // then we need to add a padding block, since the section command in - // the header doesn't allow for aligment offsets. - SectionRange R(Sec); - if (!R.empty()) { - auto &FB = *R.getFirstBlock(); - if (FB.getAlignmentOffset() != 0) { - auto Padding = G.allocateBuffer(FB.getAlignmentOffset()); - memset(Padding.data(), 0, Padding.size()); - G.createContentBlock(Sec, Padding, - FB.getAddress() - FB.getAlignmentOffset(), - FB.getAlignment(), 0); - } - } - } - } - - // Create container block. - size_t SectionsCmdSize = - sizeof(typename MachOTraits::Section) * NumSections; - size_t SegmentLCSize = - sizeof(typename MachOTraits::SegmentLC) + SectionsCmdSize; - size_t ContainerBlockSize = - sizeof(typename MachOTraits::Header) + SegmentLCSize; - auto ContainerBlockContent = G.allocateBuffer(ContainerBlockSize); - MachOContainerBlock = &G.createMutableContentBlock( - SDOSec, ContainerBlockContent, orc::ExecutorAddr(), 8, 0); - - // Copy debug section blocks and symbols. - orc::ExecutorAddr NextBlockAddr(MachOContainerBlock->getSize()); - for (auto &SI : DebugSecInfos) { - assert(!SI.Sec->blocks().empty() && "Empty debug info section?"); - - // Update addresses in debug section. - LLVM_DEBUG({ - dbgs() << " Appending " << SI.Sec->getName() << " (" - << SI.Sec->blocks_size() << " block(s)) at " - << formatv("{0:x8}", NextBlockAddr) << "\n"; - }); - for (auto *B : SI.Sec->blocks()) { - NextBlockAddr = alignToBlock(NextBlockAddr, *B); - B->setAddress(NextBlockAddr); - NextBlockAddr += B->getSize(); - } - - auto &FirstBlock = **SI.Sec->blocks().begin(); - if (FirstBlock.getAlignmentOffset() != 0) - return make_error<StringError>( - "First block in " + SI.Sec->getName() + - " section has non-zero alignment offset", - inconvertibleErrorCode()); - if (FirstBlock.getAlignment() > std::numeric_limits<uint32_t>::max()) - return make_error<StringError>("First block in " + SI.Sec->getName() + - " has alignment >4Gb", - inconvertibleErrorCode()); - - SI.Alignment = FirstBlock.getAlignment(); - SI.StartAddr = FirstBlock.getAddress(); - SI.Size = NextBlockAddr - SI.StartAddr; - G.mergeSections(SDOSec, *SI.Sec); - SI.Sec = nullptr; - } - size_t DebugSectionsSize = - NextBlockAddr - orc::ExecutorAddr(MachOContainerBlock->getSize()); - - // Write MachO header and debug section load commands. - MachOStructWriter Writer(MachOContainerBlock->getAlreadyMutableContent()); - typename MachOTraits::Header Hdr; - memset(&Hdr, 0, sizeof(Hdr)); - Hdr.magic = MachOTraits::Magic; - switch (G.getTargetTriple().getArch()) { - case Triple::x86_64: - Hdr.cputype = MachO::CPU_TYPE_X86_64; - Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; - break; - case Triple::aarch64: - Hdr.cputype = MachO::CPU_TYPE_ARM64; - Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; - break; - default: - llvm_unreachable("Unsupported architecture"); - } - Hdr.filetype = MachO::MH_OBJECT; - Hdr.ncmds = 1; - Hdr.sizeofcmds = SegmentLCSize; - Hdr.flags = 0; - Writer.write(Hdr); - - typename MachOTraits::SegmentLC SegLC; - memset(&SegLC, 0, sizeof(SegLC)); - SegLC.cmd = MachOTraits::SegmentCmd; - SegLC.cmdsize = SegmentLCSize; - SegLC.vmaddr = ContainerBlockSize; - SegLC.vmsize = DebugSectionsSize; - SegLC.fileoff = ContainerBlockSize; - SegLC.filesize = DebugSectionsSize; - SegLC.maxprot = - MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE; - SegLC.initprot = - MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE; - SegLC.nsects = NumSections; - SegLC.flags = 0; - Writer.write(SegLC); - - StringSet<> ExistingLongNames; - for (auto &SI : DebugSecInfos) { - typename MachOTraits::Section Sec; - memset(&Sec, 0, sizeof(Sec)); - memcpy(Sec.sectname, SI.SecName.data(), SI.SecName.size()); - memcpy(Sec.segname, SI.SegName.data(), SI.SegName.size()); - Sec.addr = SI.StartAddr.getValue(); - Sec.size = SI.Size; - Sec.offset = SI.StartAddr.getValue(); - Sec.align = SI.Alignment; - Sec.reloff = 0; - Sec.nreloc = 0; - Sec.flags = MachO::S_ATTR_DEBUG; - Writer.write(Sec); - } - - // Set MachOContainerBlock to indicate success to - // completeSynthesisAndRegister. - NonDebugSectionsStart = Writer.getOffset(); - return Error::success(); - } - - Error completeSynthesisAndRegister() override { - if (!MachOContainerBlock) { - LLVM_DEBUG({ - dbgs() << "Not writing MachO debug object header for " << G.getName() - << " since createDebugSection failed\n"; - }); - return Error::success(); - } - - LLVM_DEBUG({ - dbgs() << "Writing MachO debug object header for " << G.getName() << "\n"; - }); - - MachOStructWriter Writer( - MachOContainerBlock->getAlreadyMutableContent().drop_front( - NonDebugSectionsStart)); - - unsigned LongSectionNameIdx = 0; - for (auto *Sec : NonDebugSections) { - size_t SepPos = Sec->getName().find(','); - StringRef SegName, SecName; - std::string CustomSecName; - - if ((SepPos == StringRef::npos && Sec->getName().size() <= 16)) { - // No embedded segment name, short section name. - SegName = "__JITLINK_CUSTOM"; - SecName = Sec->getName(); - } else if (SepPos < 16 && (Sec->getName().size() - (SepPos + 1) <= 16)) { - // Canonical embedded segment and section name. - SegName = Sec->getName().substr(0, SepPos); - SecName = Sec->getName().substr(SepPos + 1); - } else { - // Long section name that needs to be truncated. - assert(Sec->getName().size() > 16 && - "Short section name should have been handled above"); - SegName = "__JITLINK_CUSTOM"; - auto IdxStr = std::to_string(++LongSectionNameIdx); - CustomSecName = Sec->getName().substr(0, 15 - IdxStr.size()).str(); - CustomSecName += "."; - CustomSecName += IdxStr; - SecName = StringRef(CustomSecName.data(), 16); - } - - SectionRange R(*Sec); - if (R.getFirstBlock()->getAlignmentOffset() != 0) - return make_error<StringError>( - "While building MachO debug object for " + G.getName() + - " first block has non-zero alignment offset", - inconvertibleErrorCode()); - - typename MachOTraits::Section SecCmd; - memset(&SecCmd, 0, sizeof(SecCmd)); - memcpy(SecCmd.sectname, SecName.data(), SecName.size()); - memcpy(SecCmd.segname, SegName.data(), SegName.size()); - SecCmd.addr = R.getStart().getValue(); - SecCmd.size = R.getSize(); - SecCmd.offset = 0; - SecCmd.align = R.getFirstBlock()->getAlignment(); - SecCmd.reloff = 0; - SecCmd.nreloc = 0; - SecCmd.flags = 0; - Writer.write(SecCmd); - } - - static constexpr bool AutoRegisterCode = true; - SectionRange R(MachOContainerBlock->getSection()); - G.allocActions().push_back( - {cantFail(shared::WrapperFunctionCall::Create< - shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>( - RegisterActionAddr, R.getRange(), AutoRegisterCode)), - {}}); - return Error::success(); - } - -private: - Block *MachOContainerBlock = nullptr; - SmallVector<Section *, 16> NonDebugSections; - size_t NonDebugSectionsStart = 0; -}; - -} // end anonymous namespace - -namespace llvm { -namespace orc { - -Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>> -GDBJITDebugInfoRegistrationPlugin::Create(ExecutionSession &ES, - JITDylib &ProcessJD, - const Triple &TT) { - auto RegisterActionAddr = - TT.isOSBinFormatMachO() - ? ES.intern("_llvm_orc_registerJITLoaderGDBAllocAction") - : ES.intern("llvm_orc_registerJITLoaderGDBAllocAction"); - - if (auto RegisterSym = ES.lookup({&ProcessJD}, RegisterActionAddr)) - return std::make_unique<GDBJITDebugInfoRegistrationPlugin>( - RegisterSym->getAddress()); - else - return RegisterSym.takeError(); -} - -Error GDBJITDebugInfoRegistrationPlugin::notifyFailed( - MaterializationResponsibility &MR) { - return Error::success(); -} - -Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources( - JITDylib &JD, ResourceKey K) { - return Error::success(); -} - -void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources( - JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {} - -void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig( - MaterializationResponsibility &MR, LinkGraph &LG, - PassConfiguration &PassConfig) { - - if (LG.getTargetTriple().getObjectFormat() == Triple::MachO) - modifyPassConfigForMachO(MR, LG, PassConfig); - else { - LLVM_DEBUG({ - dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unspported graph " - << LG.getName() << "(triple = " << LG.getTargetTriple().str() - << "\n"; - }); - } -} - -void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO( - MaterializationResponsibility &MR, jitlink::LinkGraph &LG, - jitlink::PassConfiguration &PassConfig) { - - switch (LG.getTargetTriple().getArch()) { - case Triple::x86_64: - case Triple::aarch64: - // Supported, continue. - assert(LG.getPointerSize() == 8 && "Graph has incorrect pointer size"); - assert(LG.getEndianness() == support::little && - "Graph has incorrect endianness"); - break; - default: - // Unsupported. - LLVM_DEBUG({ - dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unsupported " - << "MachO graph " << LG.getName() - << "(triple = " << LG.getTargetTriple().str() - << ", pointer size = " << LG.getPointerSize() << ", endianness = " - << (LG.getEndianness() == support::big ? "big" : "little") - << ")\n"; - }); - return; - } - - // Scan for debug sections. If we find one then install passes. - bool HasDebugSections = false; - for (auto &Sec : LG.sections()) - if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) { - HasDebugSections = true; - break; - } - - if (HasDebugSections) { - LLVM_DEBUG({ - dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName() - << " contains debug info. Installing debugger support passes.\n"; - }); - - auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>( - LG, RegisterActionAddr); - PassConfig.PrePrunePasses.push_back( - [=](LinkGraph &G) { return MDOS->preserveDebugSections(); }); - PassConfig.PostPrunePasses.push_back( - [=](LinkGraph &G) { return MDOS->startSynthesis(); }); - PassConfig.PreFixupPasses.push_back( - [=](LinkGraph &G) { return MDOS->completeSynthesisAndRegister(); }); - } else { - LLVM_DEBUG({ - dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName() - << " contains no debug info. Skipping.\n"; - }); - } -} - -} // namespace orc -} // namespace llvm |
