forked from OSchip/llvm-project
Revert "[ORC] Initial MachO debugging support (via GDB JIT debug..."
This reverts commit e1933a0488
until I can look
into bot failures.
This commit is contained in:
parent
7505b7045f
commit
f55ba3525e
|
@ -343,12 +343,6 @@ private:
|
|||
std::vector<Edge> Edges;
|
||||
};
|
||||
|
||||
// Align a JITTargetAddress to conform with block alignment requirements.
|
||||
inline JITTargetAddress alignToBlock(JITTargetAddress Addr, Block &B) {
|
||||
uint64_t Delta = (B.getAlignmentOffset() - Addr) % B.getAlignment();
|
||||
return Addr + Delta;
|
||||
}
|
||||
|
||||
/// Describes symbol linkage. This can be used to make resolve definition
|
||||
/// clashes.
|
||||
enum class Linkage : uint8_t {
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
//===--- DebugerSupportPlugin.h -- Utils for debugger support ---*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Generates debug objects and registers them using the jit-loader-gdb protocol.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_DEBUGGERSUPPORT_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_DEBUGGERSUPPORT_H
|
||||
|
||||
#include "llvm/ExecutionEngine/Orc/Core.h"
|
||||
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
/// For each object containing debug info, installs JITLink passes to synthesize
|
||||
/// a debug object and then register it via the GDB JIT-registration interface.
|
||||
///
|
||||
/// Currently MachO only. For ELF use DebugObjectManagerPlugin. These two
|
||||
/// plugins will be merged in the near future.
|
||||
class GDBJITDebugInfoRegistrationPlugin : public ObjectLinkingLayer::Plugin {
|
||||
public:
|
||||
class DebugSectionSynthesizer {
|
||||
public:
|
||||
virtual ~DebugSectionSynthesizer() {}
|
||||
virtual Error startSynthesis() = 0;
|
||||
virtual Error completeSynthesisAndRegister() = 0;
|
||||
};
|
||||
|
||||
static Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>>
|
||||
Create(ExecutionSession &ES, JITDylib &ProcessJD, const Triple &TT);
|
||||
|
||||
GDBJITDebugInfoRegistrationPlugin(ExecutorAddr RegisterActionAddr)
|
||||
: RegisterActionAddr(RegisterActionAddr) {}
|
||||
|
||||
Error notifyFailed(MaterializationResponsibility &MR) override;
|
||||
Error notifyRemovingResources(ResourceKey K) override;
|
||||
|
||||
void notifyTransferringResources(ResourceKey DstKey,
|
||||
ResourceKey SrcKey) override;
|
||||
|
||||
void modifyPassConfig(MaterializationResponsibility &MR,
|
||||
jitlink::LinkGraph &LG,
|
||||
jitlink::PassConfiguration &PassConfig) override;
|
||||
|
||||
private:
|
||||
void modifyPassConfigForMachO(MaterializationResponsibility &MR,
|
||||
jitlink::LinkGraph &LG,
|
||||
jitlink::PassConfiguration &PassConfig);
|
||||
|
||||
ExecutorAddr RegisterActionAddr;
|
||||
};
|
||||
|
||||
} // namespace orc
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_DEBUGGERSUPPORT_H
|
|
@ -72,6 +72,12 @@ static Error runAllocAction(JITLinkMemoryManager::AllocActionCall &C) {
|
|||
static_cast<size_t>(C.CtxSize)));
|
||||
}
|
||||
|
||||
// Align a JITTargetAddress to conform with block alignment requirements.
|
||||
static JITTargetAddress alignToBlock(JITTargetAddress Addr, Block &B) {
|
||||
uint64_t Delta = (B.getAlignmentOffset() - Addr) % B.getAlignment();
|
||||
return Addr + Delta;
|
||||
}
|
||||
|
||||
BasicLayout::BasicLayout(LinkGraph &G) : G(G) {
|
||||
|
||||
for (auto &Sec : G.sections()) {
|
||||
|
|
|
@ -180,10 +180,17 @@ Error MachOLinkGraphBuilder::createNormalizedSections() {
|
|||
else
|
||||
Prot = MemProt::Read | MemProt::Write;
|
||||
|
||||
auto FullyQualifiedName =
|
||||
G->allocateString(StringRef(NSec.SegName) + "," + NSec.SectName);
|
||||
NSec.GraphSection = &G->createSection(
|
||||
StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()), Prot);
|
||||
if (!isDebugSection(NSec)) {
|
||||
auto FullyQualifiedName =
|
||||
G->allocateString(StringRef(NSec.SegName) + "," + NSec.SectName);
|
||||
NSec.GraphSection = &G->createSection(
|
||||
StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()),
|
||||
Prot);
|
||||
} else
|
||||
LLVM_DEBUG({
|
||||
dbgs() << " " << NSec.SegName << "," << NSec.SectName
|
||||
<< " is a debug section: No graph section will be created.\n";
|
||||
});
|
||||
|
||||
IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ add_llvm_component_library(LLVMOrcJIT
|
|||
CompileUtils.cpp
|
||||
Core.cpp
|
||||
DebugObjectManagerPlugin.cpp
|
||||
DebuggerSupportPlugin.cpp
|
||||
DebugUtils.cpp
|
||||
EPCDynamicLibrarySearchGenerator.cpp
|
||||
EPCDebugObjectRegistrar.cpp
|
||||
|
|
|
@ -1,450 +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() {}
|
||||
|
||||
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;
|
||||
JITTargetAddress Alignment = 0;
|
||||
JITTargetAddress StartAddr = 0;
|
||||
uint64_t Size = 0;
|
||||
};
|
||||
|
||||
SmallVector<DebugSectionInfo, 12> DebugSecInfos;
|
||||
size_t NumSections = 0;
|
||||
for (auto &Sec : G.sections()) {
|
||||
if (llvm::empty(Sec.blocks()))
|
||||
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, 0});
|
||||
} else
|
||||
NonDebugSections.push_back(&Sec);
|
||||
}
|
||||
|
||||
// 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, 0, 8, 0);
|
||||
|
||||
// Copy debug section blocks and symbols.
|
||||
JITTargetAddress NextBlockAddr = MachOContainerBlock->getSize();
|
||||
for (auto &SI : DebugSecInfos) {
|
||||
assert(!llvm::empty(SI.Sec->blocks()) && "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 - 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;
|
||||
Sec.size = SI.Size;
|
||||
Sec.offset = SI.StartAddr;
|
||||
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();
|
||||
SecCmd.size = R.getSize();
|
||||
SecCmd.offset = 0;
|
||||
SecCmd.align = R.getFirstBlock()->getAlignment();
|
||||
SecCmd.reloff = 0;
|
||||
SecCmd.nreloc = 0;
|
||||
SecCmd.flags = 0;
|
||||
Writer.write(SecCmd);
|
||||
}
|
||||
|
||||
SectionRange R(MachOContainerBlock->getSection());
|
||||
G.allocActions().push_back(
|
||||
{{RegisterActionAddr.getValue(), R.getStart(), R.getSize()}, {}});
|
||||
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 Addr = ES.lookup({&ProcessJD}, RegisterActionAddr))
|
||||
return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
|
||||
ExecutorAddr(Addr->getAddress()));
|
||||
else
|
||||
return Addr.takeError();
|
||||
}
|
||||
|
||||
Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
|
||||
MaterializationResponsibility &MR) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
|
||||
ResourceKey K) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
|
||||
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
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/Support/BinaryStreamReader.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
@ -71,18 +70,10 @@ using namespace llvm::orc;
|
|||
ManagedStatic<std::mutex> JITDebugLock;
|
||||
|
||||
// Register debug object, return error message or null for success.
|
||||
static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "Registering debug object with GDB JIT interface "
|
||||
<< formatv("([{0:x16} -- {1:x16}])",
|
||||
reinterpret_cast<uintptr_t>(ObjAddr),
|
||||
reinterpret_cast<uintptr_t>(ObjAddr + Size))
|
||||
<< "\n";
|
||||
});
|
||||
|
||||
static void registerJITLoaderGDBImpl(ExecutorAddrRange DebugObjRange) {
|
||||
jit_code_entry *E = new jit_code_entry;
|
||||
E->symfile_addr = ObjAddr;
|
||||
E->symfile_size = Size;
|
||||
E->symfile_addr = DebugObjRange.Start.toPtr<const char *>();
|
||||
E->symfile_size = DebugObjRange.size().getValue();
|
||||
E->prev_entry = nullptr;
|
||||
|
||||
std::lock_guard<std::mutex> Lock(*JITDebugLock);
|
||||
|
@ -102,26 +93,10 @@ static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
|
|||
__jit_debug_register_code();
|
||||
}
|
||||
|
||||
extern "C" orc::shared::CWrapperFunctionResult
|
||||
llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
|
||||
using namespace orc::shared;
|
||||
return WrapperFunction<SPSError()>::handle(nullptr, 0,
|
||||
[=]() -> Error {
|
||||
registerJITLoaderGDBImpl(Data,
|
||||
Size);
|
||||
return Error::success();
|
||||
})
|
||||
.release();
|
||||
}
|
||||
|
||||
extern "C" orc::shared::CWrapperFunctionResult
|
||||
llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
|
||||
using namespace orc::shared;
|
||||
return WrapperFunction<void(SPSExecutorAddrRange)>::handle(
|
||||
Data, Size,
|
||||
[](ExecutorAddrRange R) {
|
||||
registerJITLoaderGDBImpl(R.Start.toPtr<char *>(),
|
||||
R.size().getValue());
|
||||
})
|
||||
Data, Size, registerJITLoaderGDBImpl)
|
||||
.release();
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# REQUIRES: asserts
|
||||
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t %s
|
||||
# RUN: llvm-jitlink -debug-only=orc -noexec %t 2>&1 | FileCheck %s
|
||||
#
|
||||
# Check that presence of a "__DWARF" section triggers the
|
||||
# GDBJITDebugInfoRegistrationPlugin.
|
||||
#
|
||||
# CHECK: Registering debug object with GDB JIT interface
|
||||
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.globl _main
|
||||
.p2align 4, 0x90
|
||||
_main:
|
||||
xorl %eax, %eax
|
||||
retq
|
||||
|
||||
.section __DWARF,__debug_str,regular,debug
|
||||
Linfo_string:
|
||||
.asciz "test dwarf string"
|
||||
|
||||
.subsections_via_symbols
|
|
@ -0,0 +1,21 @@
|
|||
# REQUIRES: asserts
|
||||
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t %s
|
||||
# RUN: llvm-jitlink -debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
|
||||
#
|
||||
# Check that debug sections are not emitted, and consequently that we don't
|
||||
# error out due to buggy past-the-end anonymous relocations in __debug_ranges.
|
||||
#
|
||||
# CHECK: __debug_ranges is a debug section: No graph section will be created.
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.macosx_version_min 10, 15
|
||||
.globl _main
|
||||
.p2align 4, 0x90
|
||||
_main:
|
||||
retq
|
||||
Lpast_the_end:
|
||||
|
||||
.section __DWARF,__debug_ranges
|
||||
.p2align 4
|
||||
.quad Lpast_the_end
|
||||
|
||||
.subsections_via_symbols
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
|
||||
#include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
|
||||
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
|
||||
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
|
||||
|
@ -988,13 +987,8 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
|
|||
ExitOnErr(loadProcessSymbols(*this));
|
||||
ExitOnErr(loadDylibs(*this));
|
||||
|
||||
auto &TT = ES.getExecutorProcessControl().getTargetTriple();
|
||||
|
||||
if (TT.isOSBinFormatMachO())
|
||||
ObjLayer.addPlugin(ExitOnErr(
|
||||
GDBJITDebugInfoRegistrationPlugin::Create(this->ES, *MainJD, TT)));
|
||||
|
||||
// Set up the platform.
|
||||
auto &TT = ES.getExecutorProcessControl().getTargetTriple();
|
||||
if (TT.isOSBinFormatMachO() && !OrcRuntime.empty()) {
|
||||
if (auto P =
|
||||
MachOPlatform::Create(ES, ObjLayer, *MainJD, OrcRuntime.c_str()))
|
||||
|
|
Loading…
Reference in New Issue