169be352aSLang Hames //===------- DebuggerSupportPlugin.cpp - Utils for debugger support -------===//
269be352aSLang Hames //
369be352aSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
469be352aSLang Hames // See https://llvm.org/LICENSE.txt for license information.
569be352aSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
669be352aSLang Hames //
769be352aSLang Hames //===----------------------------------------------------------------------===//
869be352aSLang Hames //
969be352aSLang Hames //
1069be352aSLang Hames //===----------------------------------------------------------------------===//
1169be352aSLang Hames
1269be352aSLang Hames #include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h"
1369be352aSLang Hames
1469be352aSLang Hames #include "llvm/ADT/SmallSet.h"
1569be352aSLang Hames #include "llvm/ADT/SmallVector.h"
1669be352aSLang Hames #include "llvm/ADT/StringSet.h"
1769be352aSLang Hames #include "llvm/BinaryFormat/MachO.h"
1869be352aSLang Hames
1969be352aSLang Hames #define DEBUG_TYPE "orc"
2069be352aSLang Hames
2169be352aSLang Hames using namespace llvm;
2269be352aSLang Hames using namespace llvm::jitlink;
2369be352aSLang Hames using namespace llvm::orc;
2469be352aSLang Hames
2569be352aSLang Hames static const char *SynthDebugSectionName = "__jitlink_synth_debug_object";
2669be352aSLang Hames
2769be352aSLang Hames namespace {
2869be352aSLang Hames
2969be352aSLang Hames struct MachO64LE {
3069be352aSLang Hames using UIntPtr = uint64_t;
3169be352aSLang Hames
3269be352aSLang Hames using Header = MachO::mach_header_64;
3369be352aSLang Hames using SegmentLC = MachO::segment_command_64;
3469be352aSLang Hames using Section = MachO::section_64;
3569be352aSLang Hames using NList = MachO::nlist_64;
3669be352aSLang Hames
3769be352aSLang Hames static constexpr support::endianness Endianness = support::little;
3869be352aSLang Hames static constexpr const uint32_t Magic = MachO::MH_MAGIC_64;
3969be352aSLang Hames static constexpr const uint32_t SegmentCmd = MachO::LC_SEGMENT_64;
4069be352aSLang Hames };
4169be352aSLang Hames
4269be352aSLang Hames class MachODebugObjectSynthesizerBase
4369be352aSLang Hames : public GDBJITDebugInfoRegistrationPlugin::DebugSectionSynthesizer {
4469be352aSLang Hames public:
isDebugSection(Section & Sec)4569be352aSLang Hames static bool isDebugSection(Section &Sec) {
4669be352aSLang Hames return Sec.getName().startswith("__DWARF,");
4769be352aSLang Hames }
4869be352aSLang Hames
MachODebugObjectSynthesizerBase(LinkGraph & G,ExecutorAddr RegisterActionAddr)4969be352aSLang Hames MachODebugObjectSynthesizerBase(LinkGraph &G, ExecutorAddr RegisterActionAddr)
5069be352aSLang Hames : G(G), RegisterActionAddr(RegisterActionAddr) {}
513a3cb929SKazu Hirata virtual ~MachODebugObjectSynthesizerBase() = default;
5269be352aSLang Hames
preserveDebugSections()5369be352aSLang Hames Error preserveDebugSections() {
5469be352aSLang Hames if (G.findSectionByName(SynthDebugSectionName)) {
5569be352aSLang Hames LLVM_DEBUG({
5669be352aSLang Hames dbgs() << "MachODebugObjectSynthesizer skipping graph " << G.getName()
5769be352aSLang Hames << " which contains an unexpected existing "
5869be352aSLang Hames << SynthDebugSectionName << " section.\n";
5969be352aSLang Hames });
6069be352aSLang Hames return Error::success();
6169be352aSLang Hames }
6269be352aSLang Hames
6369be352aSLang Hames LLVM_DEBUG({
6469be352aSLang Hames dbgs() << "MachODebugObjectSynthesizer visiting graph " << G.getName()
6569be352aSLang Hames << "\n";
6669be352aSLang Hames });
6769be352aSLang Hames for (auto &Sec : G.sections()) {
6869be352aSLang Hames if (!isDebugSection(Sec))
6969be352aSLang Hames continue;
7069be352aSLang Hames // Preserve blocks in this debug section by marking one existing symbol
7169be352aSLang Hames // live for each block, and introducing a new live, anonymous symbol for
7269be352aSLang Hames // each currently unreferenced block.
7369be352aSLang Hames LLVM_DEBUG({
7469be352aSLang Hames dbgs() << " Preserving debug section " << Sec.getName() << "\n";
7569be352aSLang Hames });
7669be352aSLang Hames SmallSet<Block *, 8> PreservedBlocks;
7769be352aSLang Hames for (auto *Sym : Sec.symbols()) {
7869be352aSLang Hames bool NewPreservedBlock =
7969be352aSLang Hames PreservedBlocks.insert(&Sym->getBlock()).second;
8069be352aSLang Hames if (NewPreservedBlock)
8169be352aSLang Hames Sym->setLive(true);
8269be352aSLang Hames }
8369be352aSLang Hames for (auto *B : Sec.blocks())
8469be352aSLang Hames if (!PreservedBlocks.count(B))
8569be352aSLang Hames G.addAnonymousSymbol(*B, 0, 0, false, true);
8669be352aSLang Hames }
8769be352aSLang Hames return Error::success();
8869be352aSLang Hames }
8969be352aSLang Hames
9069be352aSLang Hames protected:
9169be352aSLang Hames LinkGraph &G;
9269be352aSLang Hames ExecutorAddr RegisterActionAddr;
9369be352aSLang Hames };
9469be352aSLang Hames
9569be352aSLang Hames template <typename MachOTraits>
9669be352aSLang Hames class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
9769be352aSLang Hames private:
9869be352aSLang Hames class MachOStructWriter {
9969be352aSLang Hames public:
MachOStructWriter(MutableArrayRef<char> Buffer)10069be352aSLang Hames MachOStructWriter(MutableArrayRef<char> Buffer) : Buffer(Buffer) {}
10169be352aSLang Hames
getOffset() const10269be352aSLang Hames size_t getOffset() const { return Offset; }
10369be352aSLang Hames
write(MachOStruct S)10469be352aSLang Hames template <typename MachOStruct> void write(MachOStruct S) {
10569be352aSLang Hames assert(Offset + sizeof(S) <= Buffer.size() &&
10669be352aSLang Hames "Container block overflow while constructing debug MachO");
10769be352aSLang Hames if (MachOTraits::Endianness != support::endian::system_endianness())
10869be352aSLang Hames MachO::swapStruct(S);
10969be352aSLang Hames memcpy(Buffer.data() + Offset, &S, sizeof(S));
11069be352aSLang Hames Offset += sizeof(S);
11169be352aSLang Hames }
11269be352aSLang Hames
11369be352aSLang Hames private:
11469be352aSLang Hames MutableArrayRef<char> Buffer;
11569be352aSLang Hames size_t Offset = 0;
11669be352aSLang Hames };
11769be352aSLang Hames
11869be352aSLang Hames public:
11969be352aSLang Hames using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
12069be352aSLang Hames
startSynthesis()12169be352aSLang Hames Error startSynthesis() override {
12269be352aSLang Hames LLVM_DEBUG({
12369be352aSLang Hames dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName()
12469be352aSLang Hames << "\n";
12569be352aSLang Hames });
12669be352aSLang Hames auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
12769be352aSLang Hames
12869be352aSLang Hames struct DebugSectionInfo {
12969be352aSLang Hames Section *Sec = nullptr;
13069be352aSLang Hames StringRef SegName;
13169be352aSLang Hames StringRef SecName;
132118e953bSLang Hames uint64_t Alignment = 0;
133118e953bSLang Hames orc::ExecutorAddr StartAddr;
13469be352aSLang Hames uint64_t Size = 0;
13569be352aSLang Hames };
13669be352aSLang Hames
13769be352aSLang Hames SmallVector<DebugSectionInfo, 12> DebugSecInfos;
13869be352aSLang Hames size_t NumSections = 0;
13969be352aSLang Hames for (auto &Sec : G.sections()) {
14069be352aSLang Hames if (llvm::empty(Sec.blocks()))
14169be352aSLang Hames continue;
14269be352aSLang Hames
14369be352aSLang Hames ++NumSections;
14469be352aSLang Hames if (isDebugSection(Sec)) {
14569be352aSLang Hames size_t SepPos = Sec.getName().find(',');
14669be352aSLang Hames if (SepPos > 16 || (Sec.getName().size() - (SepPos + 1) > 16)) {
14769be352aSLang Hames LLVM_DEBUG({
14869be352aSLang Hames dbgs() << "Skipping debug object synthesis for graph "
14969be352aSLang Hames << G.getName()
15069be352aSLang Hames << ": encountered non-standard DWARF section name \""
15169be352aSLang Hames << Sec.getName() << "\"\n";
15269be352aSLang Hames });
15369be352aSLang Hames return Error::success();
15469be352aSLang Hames }
15569be352aSLang Hames DebugSecInfos.push_back({&Sec, Sec.getName().substr(0, SepPos),
156118e953bSLang Hames Sec.getName().substr(SepPos + 1), 0,
157118e953bSLang Hames orc::ExecutorAddr(), 0});
15802095f2dSLang Hames } else {
15969be352aSLang Hames NonDebugSections.push_back(&Sec);
16002095f2dSLang Hames
16102095f2dSLang Hames // If the first block in the section has a non-zero alignment offset
16202095f2dSLang Hames // then we need to add a padding block, since the section command in
16302095f2dSLang Hames // the header doesn't allow for aligment offsets.
16402095f2dSLang Hames SectionRange R(Sec);
16502095f2dSLang Hames if (!R.empty()) {
16602095f2dSLang Hames auto &FB = *R.getFirstBlock();
16702095f2dSLang Hames if (FB.getAlignmentOffset() != 0) {
16802095f2dSLang Hames auto Padding = G.allocateBuffer(FB.getAlignmentOffset());
16902095f2dSLang Hames memset(Padding.data(), 0, Padding.size());
17002095f2dSLang Hames G.createContentBlock(Sec, Padding,
17102095f2dSLang Hames FB.getAddress() - FB.getAlignmentOffset(),
17202095f2dSLang Hames FB.getAlignment(), 0);
17302095f2dSLang Hames }
17402095f2dSLang Hames }
17502095f2dSLang Hames }
17669be352aSLang Hames }
17769be352aSLang Hames
17869be352aSLang Hames // Create container block.
17969be352aSLang Hames size_t SectionsCmdSize =
18069be352aSLang Hames sizeof(typename MachOTraits::Section) * NumSections;
18169be352aSLang Hames size_t SegmentLCSize =
18269be352aSLang Hames sizeof(typename MachOTraits::SegmentLC) + SectionsCmdSize;
18369be352aSLang Hames size_t ContainerBlockSize =
18469be352aSLang Hames sizeof(typename MachOTraits::Header) + SegmentLCSize;
18569be352aSLang Hames auto ContainerBlockContent = G.allocateBuffer(ContainerBlockSize);
186118e953bSLang Hames MachOContainerBlock = &G.createMutableContentBlock(
187118e953bSLang Hames SDOSec, ContainerBlockContent, orc::ExecutorAddr(), 8, 0);
18869be352aSLang Hames
18969be352aSLang Hames // Copy debug section blocks and symbols.
190118e953bSLang Hames orc::ExecutorAddr NextBlockAddr(MachOContainerBlock->getSize());
19169be352aSLang Hames for (auto &SI : DebugSecInfos) {
19269be352aSLang Hames assert(!llvm::empty(SI.Sec->blocks()) && "Empty debug info section?");
19369be352aSLang Hames
19469be352aSLang Hames // Update addresses in debug section.
19569be352aSLang Hames LLVM_DEBUG({
19669be352aSLang Hames dbgs() << " Appending " << SI.Sec->getName() << " ("
19769be352aSLang Hames << SI.Sec->blocks_size() << " block(s)) at "
19869be352aSLang Hames << formatv("{0:x8}", NextBlockAddr) << "\n";
19969be352aSLang Hames });
20069be352aSLang Hames for (auto *B : SI.Sec->blocks()) {
20169be352aSLang Hames NextBlockAddr = alignToBlock(NextBlockAddr, *B);
20269be352aSLang Hames B->setAddress(NextBlockAddr);
20369be352aSLang Hames NextBlockAddr += B->getSize();
20469be352aSLang Hames }
20569be352aSLang Hames
20669be352aSLang Hames auto &FirstBlock = **SI.Sec->blocks().begin();
20769be352aSLang Hames if (FirstBlock.getAlignmentOffset() != 0)
20869be352aSLang Hames return make_error<StringError>(
20969be352aSLang Hames "First block in " + SI.Sec->getName() +
21069be352aSLang Hames " section has non-zero alignment offset",
21169be352aSLang Hames inconvertibleErrorCode());
21269be352aSLang Hames if (FirstBlock.getAlignment() > std::numeric_limits<uint32_t>::max())
21369be352aSLang Hames return make_error<StringError>("First block in " + SI.Sec->getName() +
21469be352aSLang Hames " has alignment >4Gb",
21569be352aSLang Hames inconvertibleErrorCode());
21669be352aSLang Hames
21769be352aSLang Hames SI.Alignment = FirstBlock.getAlignment();
21869be352aSLang Hames SI.StartAddr = FirstBlock.getAddress();
21969be352aSLang Hames SI.Size = NextBlockAddr - SI.StartAddr;
22069be352aSLang Hames G.mergeSections(SDOSec, *SI.Sec);
22169be352aSLang Hames SI.Sec = nullptr;
22269be352aSLang Hames }
223118e953bSLang Hames size_t DebugSectionsSize =
224118e953bSLang Hames NextBlockAddr - orc::ExecutorAddr(MachOContainerBlock->getSize());
22569be352aSLang Hames
22669be352aSLang Hames // Write MachO header and debug section load commands.
22769be352aSLang Hames MachOStructWriter Writer(MachOContainerBlock->getAlreadyMutableContent());
22869be352aSLang Hames typename MachOTraits::Header Hdr;
22969be352aSLang Hames memset(&Hdr, 0, sizeof(Hdr));
23069be352aSLang Hames Hdr.magic = MachOTraits::Magic;
23169be352aSLang Hames switch (G.getTargetTriple().getArch()) {
23269be352aSLang Hames case Triple::x86_64:
23369be352aSLang Hames Hdr.cputype = MachO::CPU_TYPE_X86_64;
23469be352aSLang Hames Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
23569be352aSLang Hames break;
23669be352aSLang Hames case Triple::aarch64:
23769be352aSLang Hames Hdr.cputype = MachO::CPU_TYPE_ARM64;
23869be352aSLang Hames Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
23969be352aSLang Hames break;
24069be352aSLang Hames default:
24169be352aSLang Hames llvm_unreachable("Unsupported architecture");
24269be352aSLang Hames }
24369be352aSLang Hames Hdr.filetype = MachO::MH_OBJECT;
24469be352aSLang Hames Hdr.ncmds = 1;
24569be352aSLang Hames Hdr.sizeofcmds = SegmentLCSize;
24669be352aSLang Hames Hdr.flags = 0;
24769be352aSLang Hames Writer.write(Hdr);
24869be352aSLang Hames
24969be352aSLang Hames typename MachOTraits::SegmentLC SegLC;
25069be352aSLang Hames memset(&SegLC, 0, sizeof(SegLC));
25169be352aSLang Hames SegLC.cmd = MachOTraits::SegmentCmd;
25269be352aSLang Hames SegLC.cmdsize = SegmentLCSize;
25369be352aSLang Hames SegLC.vmaddr = ContainerBlockSize;
25469be352aSLang Hames SegLC.vmsize = DebugSectionsSize;
25569be352aSLang Hames SegLC.fileoff = ContainerBlockSize;
25669be352aSLang Hames SegLC.filesize = DebugSectionsSize;
25769be352aSLang Hames SegLC.maxprot =
25869be352aSLang Hames MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
25969be352aSLang Hames SegLC.initprot =
26069be352aSLang Hames MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
26169be352aSLang Hames SegLC.nsects = NumSections;
26269be352aSLang Hames SegLC.flags = 0;
26369be352aSLang Hames Writer.write(SegLC);
26469be352aSLang Hames
26569be352aSLang Hames StringSet<> ExistingLongNames;
26669be352aSLang Hames for (auto &SI : DebugSecInfos) {
26769be352aSLang Hames typename MachOTraits::Section Sec;
26869be352aSLang Hames memset(&Sec, 0, sizeof(Sec));
26969be352aSLang Hames memcpy(Sec.sectname, SI.SecName.data(), SI.SecName.size());
27069be352aSLang Hames memcpy(Sec.segname, SI.SegName.data(), SI.SegName.size());
271118e953bSLang Hames Sec.addr = SI.StartAddr.getValue();
27269be352aSLang Hames Sec.size = SI.Size;
273118e953bSLang Hames Sec.offset = SI.StartAddr.getValue();
27469be352aSLang Hames Sec.align = SI.Alignment;
27569be352aSLang Hames Sec.reloff = 0;
27669be352aSLang Hames Sec.nreloc = 0;
27769be352aSLang Hames Sec.flags = MachO::S_ATTR_DEBUG;
27869be352aSLang Hames Writer.write(Sec);
27969be352aSLang Hames }
28069be352aSLang Hames
28169be352aSLang Hames // Set MachOContainerBlock to indicate success to
28269be352aSLang Hames // completeSynthesisAndRegister.
28369be352aSLang Hames NonDebugSectionsStart = Writer.getOffset();
28469be352aSLang Hames return Error::success();
28569be352aSLang Hames }
28669be352aSLang Hames
completeSynthesisAndRegister()28769be352aSLang Hames Error completeSynthesisAndRegister() override {
28869be352aSLang Hames if (!MachOContainerBlock) {
28969be352aSLang Hames LLVM_DEBUG({
29069be352aSLang Hames dbgs() << "Not writing MachO debug object header for " << G.getName()
29169be352aSLang Hames << " since createDebugSection failed\n";
29269be352aSLang Hames });
29369be352aSLang Hames return Error::success();
29469be352aSLang Hames }
29569be352aSLang Hames
29669be352aSLang Hames LLVM_DEBUG({
29769be352aSLang Hames dbgs() << "Writing MachO debug object header for " << G.getName() << "\n";
29869be352aSLang Hames });
29969be352aSLang Hames
30069be352aSLang Hames MachOStructWriter Writer(
30169be352aSLang Hames MachOContainerBlock->getAlreadyMutableContent().drop_front(
30269be352aSLang Hames NonDebugSectionsStart));
30369be352aSLang Hames
30469be352aSLang Hames unsigned LongSectionNameIdx = 0;
30569be352aSLang Hames for (auto *Sec : NonDebugSections) {
30669be352aSLang Hames size_t SepPos = Sec->getName().find(',');
30769be352aSLang Hames StringRef SegName, SecName;
30869be352aSLang Hames std::string CustomSecName;
30969be352aSLang Hames
31069be352aSLang Hames if ((SepPos == StringRef::npos && Sec->getName().size() <= 16)) {
31169be352aSLang Hames // No embedded segment name, short section name.
31269be352aSLang Hames SegName = "__JITLINK_CUSTOM";
31369be352aSLang Hames SecName = Sec->getName();
31469be352aSLang Hames } else if (SepPos < 16 && (Sec->getName().size() - (SepPos + 1) <= 16)) {
31569be352aSLang Hames // Canonical embedded segment and section name.
31669be352aSLang Hames SegName = Sec->getName().substr(0, SepPos);
31769be352aSLang Hames SecName = Sec->getName().substr(SepPos + 1);
31869be352aSLang Hames } else {
31969be352aSLang Hames // Long section name that needs to be truncated.
32069be352aSLang Hames assert(Sec->getName().size() > 16 &&
32169be352aSLang Hames "Short section name should have been handled above");
32269be352aSLang Hames SegName = "__JITLINK_CUSTOM";
32369be352aSLang Hames auto IdxStr = std::to_string(++LongSectionNameIdx);
32469be352aSLang Hames CustomSecName = Sec->getName().substr(0, 15 - IdxStr.size()).str();
32569be352aSLang Hames CustomSecName += ".";
32669be352aSLang Hames CustomSecName += IdxStr;
32769be352aSLang Hames SecName = StringRef(CustomSecName.data(), 16);
32869be352aSLang Hames }
32969be352aSLang Hames
33069be352aSLang Hames SectionRange R(*Sec);
33169be352aSLang Hames if (R.getFirstBlock()->getAlignmentOffset() != 0)
33269be352aSLang Hames return make_error<StringError>(
33369be352aSLang Hames "While building MachO debug object for " + G.getName() +
33469be352aSLang Hames " first block has non-zero alignment offset",
33569be352aSLang Hames inconvertibleErrorCode());
33669be352aSLang Hames
33769be352aSLang Hames typename MachOTraits::Section SecCmd;
33869be352aSLang Hames memset(&SecCmd, 0, sizeof(SecCmd));
33969be352aSLang Hames memcpy(SecCmd.sectname, SecName.data(), SecName.size());
34069be352aSLang Hames memcpy(SecCmd.segname, SegName.data(), SegName.size());
341118e953bSLang Hames SecCmd.addr = R.getStart().getValue();
34269be352aSLang Hames SecCmd.size = R.getSize();
34369be352aSLang Hames SecCmd.offset = 0;
34469be352aSLang Hames SecCmd.align = R.getFirstBlock()->getAlignment();
34569be352aSLang Hames SecCmd.reloff = 0;
34669be352aSLang Hames SecCmd.nreloc = 0;
34769be352aSLang Hames SecCmd.flags = 0;
34869be352aSLang Hames Writer.write(SecCmd);
34969be352aSLang Hames }
35069be352aSLang Hames
35169be352aSLang Hames SectionRange R(MachOContainerBlock->getSection());
352*ec6d6210SPavel Labath G.allocActions().push_back(
353*ec6d6210SPavel Labath {cantFail(shared::WrapperFunctionCall::Create<
354*ec6d6210SPavel Labath shared::SPSArgList<shared::SPSExecutorAddrRange>>(
355089acf25SLang Hames RegisterActionAddr, R.getRange())),
356089acf25SLang Hames {}});
35769be352aSLang Hames return Error::success();
35869be352aSLang Hames }
35969be352aSLang Hames
36069be352aSLang Hames private:
36169be352aSLang Hames Block *MachOContainerBlock = nullptr;
36269be352aSLang Hames SmallVector<Section *, 16> NonDebugSections;
36369be352aSLang Hames size_t NonDebugSectionsStart = 0;
36469be352aSLang Hames };
36569be352aSLang Hames
36669be352aSLang Hames } // end anonymous namespace
36769be352aSLang Hames
36869be352aSLang Hames namespace llvm {
36969be352aSLang Hames namespace orc {
37069be352aSLang Hames
37169be352aSLang Hames Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>>
Create(ExecutionSession & ES,JITDylib & ProcessJD,const Triple & TT)37269be352aSLang Hames GDBJITDebugInfoRegistrationPlugin::Create(ExecutionSession &ES,
37369be352aSLang Hames JITDylib &ProcessJD,
37469be352aSLang Hames const Triple &TT) {
37569be352aSLang Hames auto RegisterActionAddr =
37669be352aSLang Hames TT.isOSBinFormatMachO()
37769be352aSLang Hames ? ES.intern("_llvm_orc_registerJITLoaderGDBAllocAction")
37869be352aSLang Hames : ES.intern("llvm_orc_registerJITLoaderGDBAllocAction");
37969be352aSLang Hames
38069be352aSLang Hames if (auto Addr = ES.lookup({&ProcessJD}, RegisterActionAddr))
38169be352aSLang Hames return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
38269be352aSLang Hames ExecutorAddr(Addr->getAddress()));
38369be352aSLang Hames else
38469be352aSLang Hames return Addr.takeError();
38569be352aSLang Hames }
38669be352aSLang Hames
notifyFailed(MaterializationResponsibility & MR)38769be352aSLang Hames Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
38869be352aSLang Hames MaterializationResponsibility &MR) {
38969be352aSLang Hames return Error::success();
39069be352aSLang Hames }
39169be352aSLang Hames
notifyRemovingResources(ResourceKey K)39269be352aSLang Hames Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
39369be352aSLang Hames ResourceKey K) {
39469be352aSLang Hames return Error::success();
39569be352aSLang Hames }
39669be352aSLang Hames
notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)39769be352aSLang Hames void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
39869be352aSLang Hames ResourceKey DstKey, ResourceKey SrcKey) {}
39969be352aSLang Hames
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & LG,PassConfiguration & PassConfig)40069be352aSLang Hames void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig(
40169be352aSLang Hames MaterializationResponsibility &MR, LinkGraph &LG,
40269be352aSLang Hames PassConfiguration &PassConfig) {
40369be352aSLang Hames
40469be352aSLang Hames if (LG.getTargetTriple().getObjectFormat() == Triple::MachO)
40569be352aSLang Hames modifyPassConfigForMachO(MR, LG, PassConfig);
40669be352aSLang Hames else {
40769be352aSLang Hames LLVM_DEBUG({
40869be352aSLang Hames dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unspported graph "
40969be352aSLang Hames << LG.getName() << "(triple = " << LG.getTargetTriple().str()
41069be352aSLang Hames << "\n";
41169be352aSLang Hames });
41269be352aSLang Hames }
41369be352aSLang Hames }
41469be352aSLang Hames
modifyPassConfigForMachO(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & PassConfig)41569be352aSLang Hames void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
41669be352aSLang Hames MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
41769be352aSLang Hames jitlink::PassConfiguration &PassConfig) {
41869be352aSLang Hames
41969be352aSLang Hames switch (LG.getTargetTriple().getArch()) {
42069be352aSLang Hames case Triple::x86_64:
42169be352aSLang Hames case Triple::aarch64:
42269be352aSLang Hames // Supported, continue.
42369be352aSLang Hames assert(LG.getPointerSize() == 8 && "Graph has incorrect pointer size");
42469be352aSLang Hames assert(LG.getEndianness() == support::little &&
42569be352aSLang Hames "Graph has incorrect endianness");
42669be352aSLang Hames break;
42769be352aSLang Hames default:
42869be352aSLang Hames // Unsupported.
42969be352aSLang Hames LLVM_DEBUG({
43069be352aSLang Hames dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unsupported "
43169be352aSLang Hames << "MachO graph " << LG.getName()
43269be352aSLang Hames << "(triple = " << LG.getTargetTriple().str()
43369be352aSLang Hames << ", pointer size = " << LG.getPointerSize() << ", endianness = "
43469be352aSLang Hames << (LG.getEndianness() == support::big ? "big" : "little")
43569be352aSLang Hames << ")\n";
43669be352aSLang Hames });
43769be352aSLang Hames return;
43869be352aSLang Hames }
43969be352aSLang Hames
44069be352aSLang Hames // Scan for debug sections. If we find one then install passes.
44169be352aSLang Hames bool HasDebugSections = false;
44269be352aSLang Hames for (auto &Sec : LG.sections())
44369be352aSLang Hames if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) {
44469be352aSLang Hames HasDebugSections = true;
44569be352aSLang Hames break;
44669be352aSLang Hames }
44769be352aSLang Hames
44869be352aSLang Hames if (HasDebugSections) {
44969be352aSLang Hames LLVM_DEBUG({
45069be352aSLang Hames dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
45169be352aSLang Hames << " contains debug info. Installing debugger support passes.\n";
45269be352aSLang Hames });
45369be352aSLang Hames
45469be352aSLang Hames auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
45569be352aSLang Hames LG, RegisterActionAddr);
45669be352aSLang Hames PassConfig.PrePrunePasses.push_back(
45769be352aSLang Hames [=](LinkGraph &G) { return MDOS->preserveDebugSections(); });
45869be352aSLang Hames PassConfig.PostPrunePasses.push_back(
45969be352aSLang Hames [=](LinkGraph &G) { return MDOS->startSynthesis(); });
46069be352aSLang Hames PassConfig.PreFixupPasses.push_back(
46169be352aSLang Hames [=](LinkGraph &G) { return MDOS->completeSynthesisAndRegister(); });
46269be352aSLang Hames } else {
46369be352aSLang Hames LLVM_DEBUG({
46469be352aSLang Hames dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
46569be352aSLang Hames << " contains no debug info. Skipping.\n";
46669be352aSLang Hames });
46769be352aSLang Hames }
46869be352aSLang Hames }
46969be352aSLang Hames
47069be352aSLang Hames } // namespace orc
47169be352aSLang Hames } // namespace llvm
472