xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1b1c73532SDimitry Andric //===------- DebuggerSupportPlugin.cpp - Utils for debugger support -------===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric //
9b1c73532SDimitry Andric //
10b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
11b1c73532SDimitry Andric 
12b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
13b1c73532SDimitry Andric #include "llvm/ExecutionEngine/Orc/MachOBuilder.h"
14b1c73532SDimitry Andric 
15b1c73532SDimitry Andric #include "llvm/ADT/SmallSet.h"
16b1c73532SDimitry Andric #include "llvm/ADT/SmallVector.h"
17b1c73532SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
18b1c73532SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h"
19b1c73532SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
20b1c73532SDimitry Andric 
21b1c73532SDimitry Andric #include <chrono>
22b1c73532SDimitry Andric 
23b1c73532SDimitry Andric #define DEBUG_TYPE "orc"
24b1c73532SDimitry Andric 
25b1c73532SDimitry Andric using namespace llvm;
26b1c73532SDimitry Andric using namespace llvm::jitlink;
27b1c73532SDimitry Andric using namespace llvm::orc;
28b1c73532SDimitry Andric 
29b1c73532SDimitry Andric static const char *SynthDebugSectionName = "__jitlink_synth_debug_object";
30b1c73532SDimitry Andric 
31b1c73532SDimitry Andric namespace {
32b1c73532SDimitry Andric 
33b1c73532SDimitry Andric class MachODebugObjectSynthesizerBase
34b1c73532SDimitry Andric     : public GDBJITDebugInfoRegistrationPlugin::DebugSectionSynthesizer {
35b1c73532SDimitry Andric public:
isDebugSection(Section & Sec)36b1c73532SDimitry Andric   static bool isDebugSection(Section &Sec) {
37312c0ed1SDimitry Andric     return Sec.getName().starts_with("__DWARF,");
38b1c73532SDimitry Andric   }
39b1c73532SDimitry Andric 
MachODebugObjectSynthesizerBase(LinkGraph & G,ExecutorAddr RegisterActionAddr)40b1c73532SDimitry Andric   MachODebugObjectSynthesizerBase(LinkGraph &G, ExecutorAddr RegisterActionAddr)
41b1c73532SDimitry Andric       : G(G), RegisterActionAddr(RegisterActionAddr) {}
42b1c73532SDimitry Andric   virtual ~MachODebugObjectSynthesizerBase() = default;
43b1c73532SDimitry Andric 
preserveDebugSections()44b1c73532SDimitry Andric   Error preserveDebugSections() {
45b1c73532SDimitry Andric     if (G.findSectionByName(SynthDebugSectionName)) {
46b1c73532SDimitry Andric       LLVM_DEBUG({
47b1c73532SDimitry Andric         dbgs() << "MachODebugObjectSynthesizer skipping graph " << G.getName()
48b1c73532SDimitry Andric                << " which contains an unexpected existing "
49b1c73532SDimitry Andric                << SynthDebugSectionName << " section.\n";
50b1c73532SDimitry Andric       });
51b1c73532SDimitry Andric       return Error::success();
52b1c73532SDimitry Andric     }
53b1c73532SDimitry Andric 
54b1c73532SDimitry Andric     LLVM_DEBUG({
55b1c73532SDimitry Andric       dbgs() << "MachODebugObjectSynthesizer visiting graph " << G.getName()
56b1c73532SDimitry Andric              << "\n";
57b1c73532SDimitry Andric     });
58b1c73532SDimitry Andric     for (auto &Sec : G.sections()) {
59b1c73532SDimitry Andric       if (!isDebugSection(Sec))
60b1c73532SDimitry Andric         continue;
61b1c73532SDimitry Andric       // Preserve blocks in this debug section by marking one existing symbol
62b1c73532SDimitry Andric       // live for each block, and introducing a new live, anonymous symbol for
63b1c73532SDimitry Andric       // each currently unreferenced block.
64b1c73532SDimitry Andric       LLVM_DEBUG({
65b1c73532SDimitry Andric         dbgs() << "  Preserving debug section " << Sec.getName() << "\n";
66b1c73532SDimitry Andric       });
67b1c73532SDimitry Andric       SmallSet<Block *, 8> PreservedBlocks;
68b1c73532SDimitry Andric       for (auto *Sym : Sec.symbols()) {
69b1c73532SDimitry Andric         bool NewPreservedBlock =
70b1c73532SDimitry Andric             PreservedBlocks.insert(&Sym->getBlock()).second;
71b1c73532SDimitry Andric         if (NewPreservedBlock)
72b1c73532SDimitry Andric           Sym->setLive(true);
73b1c73532SDimitry Andric       }
74b1c73532SDimitry Andric       for (auto *B : Sec.blocks())
75b1c73532SDimitry Andric         if (!PreservedBlocks.count(B))
76b1c73532SDimitry Andric           G.addAnonymousSymbol(*B, 0, 0, false, true);
77b1c73532SDimitry Andric     }
78b1c73532SDimitry Andric 
79b1c73532SDimitry Andric     return Error::success();
80b1c73532SDimitry Andric   }
81b1c73532SDimitry Andric 
82b1c73532SDimitry Andric protected:
83b1c73532SDimitry Andric   LinkGraph &G;
84b1c73532SDimitry Andric   ExecutorAddr RegisterActionAddr;
85b1c73532SDimitry Andric };
86b1c73532SDimitry Andric 
87b1c73532SDimitry Andric template <typename MachOTraits>
88b1c73532SDimitry Andric class MachODebugObjectSynthesizer : public MachODebugObjectSynthesizerBase {
89b1c73532SDimitry Andric public:
MachODebugObjectSynthesizer(ExecutionSession & ES,LinkGraph & G,ExecutorAddr RegisterActionAddr)90b1c73532SDimitry Andric   MachODebugObjectSynthesizer(ExecutionSession &ES, LinkGraph &G,
91b1c73532SDimitry Andric                               ExecutorAddr RegisterActionAddr)
92b1c73532SDimitry Andric       : MachODebugObjectSynthesizerBase(G, RegisterActionAddr),
93b1c73532SDimitry Andric         Builder(ES.getPageSize()) {}
94b1c73532SDimitry Andric 
95b1c73532SDimitry Andric   using MachODebugObjectSynthesizerBase::MachODebugObjectSynthesizerBase;
96b1c73532SDimitry Andric 
startSynthesis()97b1c73532SDimitry Andric   Error startSynthesis() override {
98b1c73532SDimitry Andric     LLVM_DEBUG({
99b1c73532SDimitry Andric       dbgs() << "Creating " << SynthDebugSectionName << " for " << G.getName()
100b1c73532SDimitry Andric              << "\n";
101b1c73532SDimitry Andric     });
102b1c73532SDimitry Andric 
103b1c73532SDimitry Andric     for (auto &Sec : G.sections()) {
104b1c73532SDimitry Andric       if (Sec.blocks().empty())
105b1c73532SDimitry Andric         continue;
106b1c73532SDimitry Andric 
107b1c73532SDimitry Andric       // Skip sections whose name's don't fit the MachO standard.
108b1c73532SDimitry Andric       if (Sec.getName().empty() || Sec.getName().size() > 33 ||
109b1c73532SDimitry Andric           Sec.getName().find(',') > 16)
110b1c73532SDimitry Andric         continue;
111b1c73532SDimitry Andric 
112b1c73532SDimitry Andric       if (isDebugSection(Sec))
113b1c73532SDimitry Andric         DebugSections.push_back({&Sec, nullptr});
114b1c73532SDimitry Andric       else if (Sec.getMemLifetime() != MemLifetime::NoAlloc)
115b1c73532SDimitry Andric         NonDebugSections.push_back({&Sec, nullptr});
116b1c73532SDimitry Andric     }
117b1c73532SDimitry Andric 
118b1c73532SDimitry Andric     // Bail out early if no debug sections.
119b1c73532SDimitry Andric     if (DebugSections.empty())
120b1c73532SDimitry Andric       return Error::success();
121b1c73532SDimitry Andric 
122b1c73532SDimitry Andric     // Write MachO header and debug section load commands.
123b1c73532SDimitry Andric     Builder.Header.filetype = MachO::MH_OBJECT;
124b1c73532SDimitry Andric     switch (G.getTargetTriple().getArch()) {
125b1c73532SDimitry Andric     case Triple::x86_64:
126b1c73532SDimitry Andric       Builder.Header.cputype = MachO::CPU_TYPE_X86_64;
127b1c73532SDimitry Andric       Builder.Header.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL;
128b1c73532SDimitry Andric       break;
129b1c73532SDimitry Andric     case Triple::aarch64:
130b1c73532SDimitry Andric       Builder.Header.cputype = MachO::CPU_TYPE_ARM64;
131b1c73532SDimitry Andric       Builder.Header.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL;
132b1c73532SDimitry Andric       break;
133b1c73532SDimitry Andric     default:
134b1c73532SDimitry Andric       llvm_unreachable("Unsupported architecture");
135b1c73532SDimitry Andric     }
136b1c73532SDimitry Andric 
137b1c73532SDimitry Andric     Seg = &Builder.addSegment("");
138b1c73532SDimitry Andric 
139b1c73532SDimitry Andric     StringMap<std::unique_ptr<MemoryBuffer>> DebugSectionMap;
140b1c73532SDimitry Andric     StringRef DebugLineSectionData;
141b1c73532SDimitry Andric     for (auto &DSec : DebugSections) {
142b1c73532SDimitry Andric       auto [SegName, SecName] = DSec.GraphSec->getName().split(',');
143b1c73532SDimitry Andric       DSec.BuilderSec = &Seg->addSection(SecName, SegName);
144b1c73532SDimitry Andric 
145b1c73532SDimitry Andric       SectionRange SR(*DSec.GraphSec);
146b1c73532SDimitry Andric       DSec.BuilderSec->Content.Size = SR.getSize();
147b1c73532SDimitry Andric       if (!SR.empty()) {
148b1c73532SDimitry Andric         DSec.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
149b1c73532SDimitry Andric         StringRef SectionData(SR.getFirstBlock()->getContent().data(),
150b1c73532SDimitry Andric                               SR.getFirstBlock()->getSize());
151b1c73532SDimitry Andric         DebugSectionMap[SecName] =
152b1c73532SDimitry Andric             MemoryBuffer::getMemBuffer(SectionData, G.getName(), false);
153b1c73532SDimitry Andric         if (SecName == "__debug_line")
154b1c73532SDimitry Andric           DebugLineSectionData = SectionData;
155b1c73532SDimitry Andric       }
156b1c73532SDimitry Andric     }
157b1c73532SDimitry Andric 
158b1c73532SDimitry Andric     std::optional<StringRef> FileName;
159b1c73532SDimitry Andric     if (!DebugLineSectionData.empty()) {
160b1c73532SDimitry Andric       assert((G.getEndianness() == llvm::endianness::big ||
161b1c73532SDimitry Andric               G.getEndianness() == llvm::endianness::little) &&
162b1c73532SDimitry Andric              "G.getEndianness() must be either big or little");
163b1c73532SDimitry Andric       auto DWARFCtx =
164b1c73532SDimitry Andric           DWARFContext::create(DebugSectionMap, G.getPointerSize(),
165b1c73532SDimitry Andric                                G.getEndianness() == llvm::endianness::little);
166b1c73532SDimitry Andric       DWARFDataExtractor DebugLineData(
167b1c73532SDimitry Andric           DebugLineSectionData, G.getEndianness() == llvm::endianness::little,
168b1c73532SDimitry Andric           G.getPointerSize());
169b1c73532SDimitry Andric       uint64_t Offset = 0;
170b1c73532SDimitry Andric       DWARFDebugLine::LineTable LineTable;
171b1c73532SDimitry Andric 
172b1c73532SDimitry Andric       // Try to parse line data. Consume error on failure.
173b1c73532SDimitry Andric       if (auto Err = LineTable.parse(DebugLineData, &Offset, *DWARFCtx, nullptr,
174b1c73532SDimitry Andric                                      consumeError)) {
175b1c73532SDimitry Andric         handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
176b1c73532SDimitry Andric           LLVM_DEBUG({
177b1c73532SDimitry Andric             dbgs() << "Cannot parse line table for \"" << G.getName() << "\": ";
178b1c73532SDimitry Andric             EIB.log(dbgs());
179b1c73532SDimitry Andric             dbgs() << "\n";
180b1c73532SDimitry Andric           });
181b1c73532SDimitry Andric         });
182b1c73532SDimitry Andric       } else {
183b1c73532SDimitry Andric         if (!LineTable.Prologue.FileNames.empty())
184b1c73532SDimitry Andric           FileName = *dwarf::toString(LineTable.Prologue.FileNames[0].Name);
185b1c73532SDimitry Andric       }
186b1c73532SDimitry Andric     }
187b1c73532SDimitry Andric 
188b1c73532SDimitry Andric     // If no line table (or unable to use) then use graph name.
189b1c73532SDimitry Andric     // FIXME: There are probably other debug sections we should look in first.
190b1c73532SDimitry Andric     if (!FileName)
191b1c73532SDimitry Andric       FileName = StringRef(G.getName());
192b1c73532SDimitry Andric 
193b1c73532SDimitry Andric     Builder.addSymbol("", MachO::N_SO, 0, 0, 0);
194b1c73532SDimitry Andric     Builder.addSymbol(*FileName, MachO::N_SO, 0, 0, 0);
195b1c73532SDimitry Andric     auto TimeStamp = std::chrono::duration_cast<std::chrono::seconds>(
196b1c73532SDimitry Andric                          std::chrono::system_clock::now().time_since_epoch())
197b1c73532SDimitry Andric                          .count();
198b1c73532SDimitry Andric     Builder.addSymbol("", MachO::N_OSO, 3, 1, TimeStamp);
199b1c73532SDimitry Andric 
200b1c73532SDimitry Andric     for (auto &NDSP : NonDebugSections) {
201b1c73532SDimitry Andric       auto [SegName, SecName] = NDSP.GraphSec->getName().split(',');
202b1c73532SDimitry Andric       NDSP.BuilderSec = &Seg->addSection(SecName, SegName);
203b1c73532SDimitry Andric       SectionRange SR(*NDSP.GraphSec);
204b1c73532SDimitry Andric       if (!SR.empty())
205b1c73532SDimitry Andric         NDSP.BuilderSec->align = Log2_64(SR.getFirstBlock()->getAlignment());
206b1c73532SDimitry Andric 
207b1c73532SDimitry Andric       // Add stabs.
208b1c73532SDimitry Andric       for (auto *Sym : NDSP.GraphSec->symbols()) {
209b1c73532SDimitry Andric         // Skip anonymous symbols.
210b1c73532SDimitry Andric         if (!Sym->hasName())
211b1c73532SDimitry Andric           continue;
212b1c73532SDimitry Andric 
213b1c73532SDimitry Andric         uint8_t SymType = Sym->isCallable() ? MachO::N_FUN : MachO::N_GSYM;
214b1c73532SDimitry Andric 
215b1c73532SDimitry Andric         Builder.addSymbol("", MachO::N_BNSYM, 1, 0, 0);
216b1c73532SDimitry Andric         StabSymbols.push_back(
217b1c73532SDimitry Andric             {*Sym, Builder.addSymbol(Sym->getName(), SymType, 1, 0, 0),
218b1c73532SDimitry Andric              Builder.addSymbol(Sym->getName(), SymType, 0, 0, 0)});
219b1c73532SDimitry Andric         Builder.addSymbol("", MachO::N_ENSYM, 1, 0, 0);
220b1c73532SDimitry Andric       }
221b1c73532SDimitry Andric     }
222b1c73532SDimitry Andric 
223b1c73532SDimitry Andric     Builder.addSymbol("", MachO::N_SO, 1, 0, 0);
224b1c73532SDimitry Andric 
225b1c73532SDimitry Andric     // Lay out the debug object, create a section and block for it.
226b1c73532SDimitry Andric     size_t DebugObjectSize = Builder.layout();
227b1c73532SDimitry Andric 
228b1c73532SDimitry Andric     auto &SDOSec = G.createSection(SynthDebugSectionName, MemProt::Read);
229b1c73532SDimitry Andric     MachOContainerBlock = &G.createMutableContentBlock(
230b1c73532SDimitry Andric         SDOSec, G.allocateBuffer(DebugObjectSize), orc::ExecutorAddr(), 8, 0);
231b1c73532SDimitry Andric 
232b1c73532SDimitry Andric     return Error::success();
233b1c73532SDimitry Andric   }
234b1c73532SDimitry Andric 
completeSynthesisAndRegister()235b1c73532SDimitry Andric   Error completeSynthesisAndRegister() override {
236b1c73532SDimitry Andric     if (!MachOContainerBlock) {
237b1c73532SDimitry Andric       LLVM_DEBUG({
238b1c73532SDimitry Andric         dbgs() << "Not writing MachO debug object header for " << G.getName()
239b1c73532SDimitry Andric                << " since createDebugSection failed\n";
240b1c73532SDimitry Andric       });
241b1c73532SDimitry Andric 
242b1c73532SDimitry Andric       return Error::success();
243b1c73532SDimitry Andric     }
244b1c73532SDimitry Andric     ExecutorAddr MaxAddr;
245b1c73532SDimitry Andric     for (auto &NDSec : NonDebugSections) {
246b1c73532SDimitry Andric       SectionRange SR(*NDSec.GraphSec);
247b1c73532SDimitry Andric       NDSec.BuilderSec->addr = SR.getStart().getValue();
248b1c73532SDimitry Andric       NDSec.BuilderSec->size = SR.getSize();
249b1c73532SDimitry Andric       NDSec.BuilderSec->offset = SR.getStart().getValue();
250b1c73532SDimitry Andric       if (SR.getEnd() > MaxAddr)
251b1c73532SDimitry Andric         MaxAddr = SR.getEnd();
252b1c73532SDimitry Andric     }
253b1c73532SDimitry Andric 
254b1c73532SDimitry Andric     for (auto &DSec : DebugSections) {
255b1c73532SDimitry Andric       if (DSec.GraphSec->blocks_size() != 1)
256b1c73532SDimitry Andric         return make_error<StringError>(
257b1c73532SDimitry Andric             "Unexpected number of blocks in debug info section",
258b1c73532SDimitry Andric             inconvertibleErrorCode());
259b1c73532SDimitry Andric 
260b1c73532SDimitry Andric       if (ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size > MaxAddr)
261b1c73532SDimitry Andric         MaxAddr = ExecutorAddr(DSec.BuilderSec->addr) + DSec.BuilderSec->size;
262b1c73532SDimitry Andric 
263b1c73532SDimitry Andric       auto &B = **DSec.GraphSec->blocks().begin();
264b1c73532SDimitry Andric       DSec.BuilderSec->Content.Data = B.getContent().data();
265b1c73532SDimitry Andric       DSec.BuilderSec->Content.Size = B.getContent().size();
266b1c73532SDimitry Andric       DSec.BuilderSec->flags |= MachO::S_ATTR_DEBUG;
267b1c73532SDimitry Andric     }
268b1c73532SDimitry Andric 
269b1c73532SDimitry Andric     LLVM_DEBUG({
270b1c73532SDimitry Andric       dbgs() << "Writing MachO debug object header for " << G.getName() << "\n";
271b1c73532SDimitry Andric     });
272b1c73532SDimitry Andric 
273b1c73532SDimitry Andric     // Update stab symbol addresses.
274b1c73532SDimitry Andric     for (auto &SS : StabSymbols) {
275b1c73532SDimitry Andric       SS.StartStab.nlist().n_value = SS.Sym.getAddress().getValue();
276b1c73532SDimitry Andric       SS.EndStab.nlist().n_value = SS.Sym.getSize();
277b1c73532SDimitry Andric     }
278b1c73532SDimitry Andric 
279b1c73532SDimitry Andric     Builder.write(MachOContainerBlock->getAlreadyMutableContent());
280b1c73532SDimitry Andric 
281b1c73532SDimitry Andric     static constexpr bool AutoRegisterCode = true;
282b1c73532SDimitry Andric     SectionRange R(MachOContainerBlock->getSection());
283b1c73532SDimitry Andric     G.allocActions().push_back(
284b1c73532SDimitry Andric         {cantFail(shared::WrapperFunctionCall::Create<
285b1c73532SDimitry Andric                   shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
286b1c73532SDimitry Andric              RegisterActionAddr, R.getRange(), AutoRegisterCode)),
287b1c73532SDimitry Andric          {}});
288b1c73532SDimitry Andric 
289b1c73532SDimitry Andric     return Error::success();
290b1c73532SDimitry Andric   }
291b1c73532SDimitry Andric 
292b1c73532SDimitry Andric private:
293b1c73532SDimitry Andric   struct SectionPair {
294b1c73532SDimitry Andric     Section *GraphSec = nullptr;
295b1c73532SDimitry Andric     typename MachOBuilder<MachOTraits>::Section *BuilderSec = nullptr;
296b1c73532SDimitry Andric   };
297b1c73532SDimitry Andric 
298b1c73532SDimitry Andric   struct StabSymbolsEntry {
299b1c73532SDimitry Andric     using RelocTarget = typename MachOBuilder<MachOTraits>::RelocTarget;
300b1c73532SDimitry Andric 
StabSymbolsEntry__anon35c4419d0111::MachODebugObjectSynthesizer::StabSymbolsEntry301b1c73532SDimitry Andric     StabSymbolsEntry(Symbol &Sym, RelocTarget StartStab, RelocTarget EndStab)
302b1c73532SDimitry Andric         : Sym(Sym), StartStab(StartStab), EndStab(EndStab) {}
303b1c73532SDimitry Andric 
304b1c73532SDimitry Andric     Symbol &Sym;
305b1c73532SDimitry Andric     RelocTarget StartStab, EndStab;
306b1c73532SDimitry Andric   };
307b1c73532SDimitry Andric 
308b1c73532SDimitry Andric   using BuilderType = MachOBuilder<MachOTraits>;
309b1c73532SDimitry Andric 
310b1c73532SDimitry Andric   Block *MachOContainerBlock = nullptr;
311b1c73532SDimitry Andric   MachOBuilder<MachOTraits> Builder;
312b1c73532SDimitry Andric   typename MachOBuilder<MachOTraits>::Segment *Seg = nullptr;
313b1c73532SDimitry Andric   std::vector<StabSymbolsEntry> StabSymbols;
314b1c73532SDimitry Andric   SmallVector<SectionPair, 16> DebugSections;
315b1c73532SDimitry Andric   SmallVector<SectionPair, 16> NonDebugSections;
316b1c73532SDimitry Andric };
317b1c73532SDimitry Andric 
318b1c73532SDimitry Andric } // end anonymous namespace
319b1c73532SDimitry Andric 
320b1c73532SDimitry Andric namespace llvm {
321b1c73532SDimitry Andric namespace orc {
322b1c73532SDimitry Andric 
323b1c73532SDimitry Andric Expected<std::unique_ptr<GDBJITDebugInfoRegistrationPlugin>>
Create(ExecutionSession & ES,JITDylib & ProcessJD,const Triple & TT)324b1c73532SDimitry Andric GDBJITDebugInfoRegistrationPlugin::Create(ExecutionSession &ES,
325b1c73532SDimitry Andric                                           JITDylib &ProcessJD,
326b1c73532SDimitry Andric                                           const Triple &TT) {
327b1c73532SDimitry Andric   auto RegisterActionAddr =
328b1c73532SDimitry Andric       TT.isOSBinFormatMachO()
329b1c73532SDimitry Andric           ? ES.intern("_llvm_orc_registerJITLoaderGDBAllocAction")
330b1c73532SDimitry Andric           : ES.intern("llvm_orc_registerJITLoaderGDBAllocAction");
331b1c73532SDimitry Andric 
332b1c73532SDimitry Andric   if (auto RegisterSym = ES.lookup({&ProcessJD}, RegisterActionAddr))
333b1c73532SDimitry Andric     return std::make_unique<GDBJITDebugInfoRegistrationPlugin>(
334b1c73532SDimitry Andric         RegisterSym->getAddress());
335b1c73532SDimitry Andric   else
336b1c73532SDimitry Andric     return RegisterSym.takeError();
337b1c73532SDimitry Andric }
338b1c73532SDimitry Andric 
notifyFailed(MaterializationResponsibility & MR)339b1c73532SDimitry Andric Error GDBJITDebugInfoRegistrationPlugin::notifyFailed(
340b1c73532SDimitry Andric     MaterializationResponsibility &MR) {
341b1c73532SDimitry Andric   return Error::success();
342b1c73532SDimitry Andric }
343b1c73532SDimitry Andric 
notifyRemovingResources(JITDylib & JD,ResourceKey K)344b1c73532SDimitry Andric Error GDBJITDebugInfoRegistrationPlugin::notifyRemovingResources(
345b1c73532SDimitry Andric     JITDylib &JD, ResourceKey K) {
346b1c73532SDimitry Andric   return Error::success();
347b1c73532SDimitry Andric }
348b1c73532SDimitry Andric 
notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)349b1c73532SDimitry Andric void GDBJITDebugInfoRegistrationPlugin::notifyTransferringResources(
350b1c73532SDimitry Andric     JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {}
351b1c73532SDimitry Andric 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & LG,PassConfiguration & PassConfig)352b1c73532SDimitry Andric void GDBJITDebugInfoRegistrationPlugin::modifyPassConfig(
353b1c73532SDimitry Andric     MaterializationResponsibility &MR, LinkGraph &LG,
354b1c73532SDimitry Andric     PassConfiguration &PassConfig) {
355b1c73532SDimitry Andric 
356b1c73532SDimitry Andric   if (LG.getTargetTriple().getObjectFormat() == Triple::MachO)
357b1c73532SDimitry Andric     modifyPassConfigForMachO(MR, LG, PassConfig);
358b1c73532SDimitry Andric   else {
359b1c73532SDimitry Andric     LLVM_DEBUG({
360b1c73532SDimitry Andric       dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unspported graph "
361b1c73532SDimitry Andric              << LG.getName() << "(triple = " << LG.getTargetTriple().str()
362b1c73532SDimitry Andric              << "\n";
363b1c73532SDimitry Andric     });
364b1c73532SDimitry Andric   }
365b1c73532SDimitry Andric }
366b1c73532SDimitry Andric 
modifyPassConfigForMachO(MaterializationResponsibility & MR,jitlink::LinkGraph & LG,jitlink::PassConfiguration & PassConfig)367b1c73532SDimitry Andric void GDBJITDebugInfoRegistrationPlugin::modifyPassConfigForMachO(
368b1c73532SDimitry Andric     MaterializationResponsibility &MR, jitlink::LinkGraph &LG,
369b1c73532SDimitry Andric     jitlink::PassConfiguration &PassConfig) {
370b1c73532SDimitry Andric 
371b1c73532SDimitry Andric   switch (LG.getTargetTriple().getArch()) {
372b1c73532SDimitry Andric   case Triple::x86_64:
373b1c73532SDimitry Andric   case Triple::aarch64:
374b1c73532SDimitry Andric     // Supported, continue.
375b1c73532SDimitry Andric     assert(LG.getPointerSize() == 8 && "Graph has incorrect pointer size");
376b1c73532SDimitry Andric     assert(LG.getEndianness() == llvm::endianness::little &&
377b1c73532SDimitry Andric            "Graph has incorrect endianness");
378b1c73532SDimitry Andric     break;
379b1c73532SDimitry Andric   default:
380b1c73532SDimitry Andric     // Unsupported.
381b1c73532SDimitry Andric     LLVM_DEBUG({
382b1c73532SDimitry Andric       dbgs() << "GDBJITDebugInfoRegistrationPlugin skipping unsupported "
383b1c73532SDimitry Andric              << "MachO graph " << LG.getName()
384b1c73532SDimitry Andric              << "(triple = " << LG.getTargetTriple().str()
385b1c73532SDimitry Andric              << ", pointer size = " << LG.getPointerSize() << ", endianness = "
386b1c73532SDimitry Andric              << (LG.getEndianness() == llvm::endianness::big ? "big" : "little")
387b1c73532SDimitry Andric              << ")\n";
388b1c73532SDimitry Andric     });
389b1c73532SDimitry Andric     return;
390b1c73532SDimitry Andric   }
391b1c73532SDimitry Andric 
392b1c73532SDimitry Andric   // Scan for debug sections. If we find one then install passes.
393b1c73532SDimitry Andric   bool HasDebugSections = false;
394b1c73532SDimitry Andric   for (auto &Sec : LG.sections())
395b1c73532SDimitry Andric     if (MachODebugObjectSynthesizerBase::isDebugSection(Sec)) {
396b1c73532SDimitry Andric       HasDebugSections = true;
397b1c73532SDimitry Andric       break;
398b1c73532SDimitry Andric     }
399b1c73532SDimitry Andric 
400b1c73532SDimitry Andric   if (HasDebugSections) {
401b1c73532SDimitry Andric     LLVM_DEBUG({
402b1c73532SDimitry Andric       dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
403b1c73532SDimitry Andric              << " contains debug info. Installing debugger support passes.\n";
404b1c73532SDimitry Andric     });
405b1c73532SDimitry Andric 
406b1c73532SDimitry Andric     auto MDOS = std::make_shared<MachODebugObjectSynthesizer<MachO64LE>>(
407b1c73532SDimitry Andric         MR.getTargetJITDylib().getExecutionSession(), LG, RegisterActionAddr);
408b1c73532SDimitry Andric     PassConfig.PrePrunePasses.push_back(
409b1c73532SDimitry Andric         [=](LinkGraph &G) { return MDOS->preserveDebugSections(); });
410b1c73532SDimitry Andric     PassConfig.PostPrunePasses.push_back(
411b1c73532SDimitry Andric         [=](LinkGraph &G) { return MDOS->startSynthesis(); });
412b1c73532SDimitry Andric     PassConfig.PostFixupPasses.push_back(
413b1c73532SDimitry Andric         [=](LinkGraph &G) { return MDOS->completeSynthesisAndRegister(); });
414b1c73532SDimitry Andric   } else {
415b1c73532SDimitry Andric     LLVM_DEBUG({
416b1c73532SDimitry Andric       dbgs() << "GDBJITDebugInfoRegistrationPlugin: Graph " << LG.getName()
417b1c73532SDimitry Andric              << " contains no debug info. Skipping.\n";
418b1c73532SDimitry Andric     });
419b1c73532SDimitry Andric   }
420b1c73532SDimitry Andric }
421b1c73532SDimitry Andric 
422b1c73532SDimitry Andric } // namespace orc
423b1c73532SDimitry Andric } // namespace llvm
424