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