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