xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
1962a2479SLang Hames //===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
2ef238923SStefan Gränitz //
3ef238923SStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ef238923SStefan Gränitz // See https://llvm.org/LICENSE.txt for license information.
5ef238923SStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef238923SStefan Gränitz //
7ef238923SStefan Gränitz //===----------------------------------------------------------------------===//
8962a2479SLang Hames //
9962a2479SLang Hames // FIXME: Update Plugin to poke the debug object into a new JITLink section,
10962a2479SLang Hames //        rather than creating a new allocation.
11962a2479SLang Hames //
12962a2479SLang Hames //===----------------------------------------------------------------------===//
13ef238923SStefan Gränitz 
14ef238923SStefan Gränitz #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
15ef238923SStefan Gränitz 
16ef238923SStefan Gränitz #include "llvm/ADT/ArrayRef.h"
17ef238923SStefan Gränitz #include "llvm/ADT/StringMap.h"
18ef238923SStefan Gränitz #include "llvm/ADT/StringRef.h"
19ef238923SStefan Gränitz #include "llvm/BinaryFormat/ELF.h"
20ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22ef238923SStefan Gränitz #include "llvm/Object/ELFObjectFile.h"
23ef238923SStefan Gränitz #include "llvm/Support/Errc.h"
24ff52121bSStefan Gränitz #include "llvm/Support/MSVCErrorWorkarounds.h"
25ef238923SStefan Gränitz #include "llvm/Support/MemoryBuffer.h"
26ef238923SStefan Gränitz #include "llvm/Support/Process.h"
27ef238923SStefan Gränitz #include "llvm/Support/raw_ostream.h"
28ef238923SStefan Gränitz 
29ef238923SStefan Gränitz #include <set>
30ef238923SStefan Gränitz 
31ef238923SStefan Gränitz #define DEBUG_TYPE "orc"
32ef238923SStefan Gränitz 
33ef238923SStefan Gränitz using namespace llvm::jitlink;
34ef238923SStefan Gränitz using namespace llvm::object;
35ef238923SStefan Gränitz 
36ef238923SStefan Gränitz namespace llvm {
37ef238923SStefan Gränitz namespace orc {
38ef238923SStefan Gränitz 
39ef238923SStefan Gränitz class DebugObjectSection {
40ef238923SStefan Gränitz public:
41ef238923SStefan Gränitz   virtual void setTargetMemoryRange(SectionRange Range) = 0;
42ef238923SStefan Gränitz   virtual void dump(raw_ostream &OS, StringRef Name) {}
433a3cb929SKazu Hirata   virtual ~DebugObjectSection() = default;
44ef238923SStefan Gränitz };
45ef238923SStefan Gränitz 
46ef238923SStefan Gränitz template <typename ELFT>
47ef238923SStefan Gränitz class ELFDebugObjectSection : public DebugObjectSection {
48ef238923SStefan Gränitz public:
49ef238923SStefan Gränitz   // BinaryFormat ELF is not meant as a mutable format. We can only make changes
50ef238923SStefan Gränitz   // that don't invalidate the file structure.
51ef238923SStefan Gränitz   ELFDebugObjectSection(const typename ELFT::Shdr *Header)
52ef238923SStefan Gränitz       : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
53ef238923SStefan Gränitz 
54ef238923SStefan Gränitz   void setTargetMemoryRange(SectionRange Range) override;
55ef238923SStefan Gränitz   void dump(raw_ostream &OS, StringRef Name) override;
56ef238923SStefan Gränitz 
57265bc5afSStefan Gränitz   Error validateInBounds(StringRef Buffer, const char *Name) const;
58265bc5afSStefan Gränitz 
59ef238923SStefan Gränitz private:
60ef238923SStefan Gränitz   typename ELFT::Shdr *Header;
61ef238923SStefan Gränitz };
62ef238923SStefan Gränitz 
63ef238923SStefan Gränitz template <typename ELFT>
64ef238923SStefan Gränitz void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
6588d8f127SStefan Gränitz   // All recorded sections are candidates for load-address patching.
66118e953bSLang Hames   Header->sh_addr =
67118e953bSLang Hames       static_cast<typename ELFT::uint>(Range.getStart().getValue());
68ef238923SStefan Gränitz }
69ef238923SStefan Gränitz 
70ef238923SStefan Gränitz template <typename ELFT>
71265bc5afSStefan Gränitz Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
72265bc5afSStefan Gränitz                                                     const char *Name) const {
73265bc5afSStefan Gränitz   const uint8_t *Start = Buffer.bytes_begin();
74265bc5afSStefan Gränitz   const uint8_t *End = Buffer.bytes_end();
75265bc5afSStefan Gränitz   const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
76265bc5afSStefan Gränitz   if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
77265bc5afSStefan Gränitz     return make_error<StringError>(
78265bc5afSStefan Gränitz         formatv("{0} section header at {1:x16} not within bounds of the "
79265bc5afSStefan Gränitz                 "given debug object buffer [{2:x16} - {3:x16}]",
80265bc5afSStefan Gränitz                 Name, &Header->sh_addr, Start, End),
81265bc5afSStefan Gränitz         inconvertibleErrorCode());
82265bc5afSStefan Gränitz   if (Header->sh_offset + Header->sh_size > Buffer.size())
83265bc5afSStefan Gränitz     return make_error<StringError>(
84265bc5afSStefan Gränitz         formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
85265bc5afSStefan Gränitz                 "the given debug object buffer [{3:x16} - {4:x16}]",
86265bc5afSStefan Gränitz                 Name, Start + Header->sh_offset,
87265bc5afSStefan Gränitz                 Start + Header->sh_offset + Header->sh_size, Start, End),
88265bc5afSStefan Gränitz         inconvertibleErrorCode());
89265bc5afSStefan Gränitz   return Error::success();
90265bc5afSStefan Gränitz }
91265bc5afSStefan Gränitz 
92265bc5afSStefan Gränitz template <typename ELFT>
93265bc5afSStefan Gränitz void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
94cc26222eSStefan Gränitz   if (uint64_t Addr = Header->sh_addr) {
95cc26222eSStefan Gränitz     OS << formatv("  {0:x16} {1}\n", Addr, Name);
96265bc5afSStefan Gränitz   } else {
97265bc5afSStefan Gränitz     OS << formatv("                     {0}\n", Name);
98265bc5afSStefan Gränitz   }
99265bc5afSStefan Gränitz }
100265bc5afSStefan Gränitz 
101811832a9SStefan Gränitz enum DebugObjectFlags : int {
102ef238923SStefan Gränitz   // Request final target memory load-addresses for all sections.
103811832a9SStefan Gränitz   ReportFinalSectionLoadAddresses = 1 << 0,
104360a0530SStefan Gränitz 
105360a0530SStefan Gränitz   // We found sections with debug information when processing the input object.
106360a0530SStefan Gränitz   HasDebugSections = 1 << 1,
107ef238923SStefan Gränitz };
108ef238923SStefan Gränitz 
109962a2479SLang Hames /// The plugin creates a debug object from when JITLink starts processing the
110962a2479SLang Hames /// corresponding LinkGraph. It provides access to the pass configuration of
111962a2479SLang Hames /// the LinkGraph and calls the finalization function, once the resulting link
112962a2479SLang Hames /// artifact was emitted.
113ef238923SStefan Gränitz ///
114ef238923SStefan Gränitz class DebugObject {
115ef238923SStefan Gränitz public:
116962a2479SLang Hames   DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
117962a2479SLang Hames               ExecutionSession &ES)
118360a0530SStefan Gränitz       : MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
119ef238923SStefan Gränitz 
120811832a9SStefan Gränitz   bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
121811832a9SStefan Gränitz   void setFlags(DebugObjectFlags F) {
122811832a9SStefan Gränitz     Flags = static_cast<DebugObjectFlags>(Flags | F);
123811832a9SStefan Gränitz   }
124811832a9SStefan Gränitz   void clearFlags(DebugObjectFlags F) {
125811832a9SStefan Gränitz     Flags = static_cast<DebugObjectFlags>(Flags & ~F);
126811832a9SStefan Gränitz   }
127ef238923SStefan Gränitz 
128962a2479SLang Hames   using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
129962a2479SLang Hames 
130ef238923SStefan Gränitz   void finalizeAsync(FinalizeContinuation OnFinalize);
131ef238923SStefan Gränitz 
132b26c953fSStefan Gränitz   virtual ~DebugObject() {
133962a2479SLang Hames     if (Alloc) {
134962a2479SLang Hames       std::vector<FinalizedAlloc> Allocs;
135962a2479SLang Hames       Allocs.push_back(std::move(Alloc));
136962a2479SLang Hames       if (Error Err = MemMgr.deallocate(std::move(Allocs)))
137b26c953fSStefan Gränitz         ES.reportError(std::move(Err));
138ee5e7a3aSStefan Gränitz     }
139962a2479SLang Hames   }
140ee5e7a3aSStefan Gränitz 
141ef238923SStefan Gränitz   virtual void reportSectionTargetMemoryRange(StringRef Name,
142ef238923SStefan Gränitz                                               SectionRange TargetMem) {}
143ef238923SStefan Gränitz 
144ef238923SStefan Gränitz protected:
145962a2479SLang Hames   using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
146962a2479SLang Hames   using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
147ef238923SStefan Gränitz 
148962a2479SLang Hames   virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
149962a2479SLang Hames 
150962a2479SLang Hames   JITLinkMemoryManager &MemMgr;
151962a2479SLang Hames   const JITLinkDylib *JD = nullptr;
1522ccf7ed2SJared Wyles   ExecutionSession &ES;
153ef238923SStefan Gränitz 
154ef238923SStefan Gränitz private:
155811832a9SStefan Gränitz   DebugObjectFlags Flags;
156962a2479SLang Hames   FinalizedAlloc Alloc;
157ef238923SStefan Gränitz };
158ef238923SStefan Gränitz 
159ef238923SStefan Gränitz // Finalize working memory and take ownership of the resulting allocation. Start
160ef238923SStefan Gränitz // copying memory over to the target and pass on the result once we're done.
161ef238923SStefan Gränitz // Ownership of the allocation remains with us for the rest of our lifetime.
162ef238923SStefan Gränitz void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
163962a2479SLang Hames   assert(!Alloc && "Cannot finalize more than once");
164ef238923SStefan Gränitz 
165962a2479SLang Hames   if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
166962a2479SLang Hames     auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
1675baaf0c2SLang Hames     ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
168962a2479SLang Hames     SimpleSegAlloc->finalize(
169962a2479SLang Hames         [this, DebugObjRange,
170962a2479SLang Hames          OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
171962a2479SLang Hames           if (FA) {
172962a2479SLang Hames             Alloc = std::move(*FA);
173962a2479SLang Hames             OnFinalize(DebugObjRange);
174962a2479SLang Hames           } else
175962a2479SLang Hames             OnFinalize(FA.takeError());
176ef238923SStefan Gränitz         });
177962a2479SLang Hames   } else
178962a2479SLang Hames     OnFinalize(SimpleSegAlloc.takeError());
179ef238923SStefan Gränitz }
180ef238923SStefan Gränitz 
181ef238923SStefan Gränitz /// The current implementation of ELFDebugObject replicates the approach used in
182ef238923SStefan Gränitz /// RuntimeDyld: It patches executable and data section headers in the given
183ef238923SStefan Gränitz /// object buffer with load-addresses of their corresponding sections in target
184ef238923SStefan Gränitz /// memory.
185ef238923SStefan Gränitz ///
186ef238923SStefan Gränitz class ELFDebugObject : public DebugObject {
187ef238923SStefan Gränitz public:
188b26c953fSStefan Gränitz   static Expected<std::unique_ptr<DebugObject>>
189b26c953fSStefan Gränitz   Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
190ef238923SStefan Gränitz 
191ef238923SStefan Gränitz   void reportSectionTargetMemoryRange(StringRef Name,
192ef238923SStefan Gränitz                                       SectionRange TargetMem) override;
193ef238923SStefan Gränitz 
1947d18cd93SStefan Gränitz   StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
1957d18cd93SStefan Gränitz 
196ef238923SStefan Gränitz protected:
197962a2479SLang Hames   Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
198ef238923SStefan Gränitz 
199265bc5afSStefan Gränitz   template <typename ELFT>
200ef238923SStefan Gränitz   Error recordSection(StringRef Name,
201265bc5afSStefan Gränitz                       std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
202ef238923SStefan Gränitz   DebugObjectSection *getSection(StringRef Name);
203ef238923SStefan Gränitz 
204ef238923SStefan Gränitz private:
205ef238923SStefan Gränitz   template <typename ELFT>
206ef238923SStefan Gränitz   static Expected<std::unique_ptr<ELFDebugObject>>
207962a2479SLang Hames   CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
208962a2479SLang Hames                  const JITLinkDylib *JD, ExecutionSession &ES);
209ef238923SStefan Gränitz 
2107d18cd93SStefan Gränitz   static std::unique_ptr<WritableMemoryBuffer>
2117d18cd93SStefan Gränitz   CopyBuffer(MemoryBufferRef Buffer, Error &Err);
212ef238923SStefan Gränitz 
213ef238923SStefan Gränitz   ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
214962a2479SLang Hames                  JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
215962a2479SLang Hames                  ExecutionSession &ES)
216962a2479SLang Hames       : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
217811832a9SStefan Gränitz     setFlags(ReportFinalSectionLoadAddresses);
218ef238923SStefan Gränitz   }
219ef238923SStefan Gränitz 
220ef238923SStefan Gränitz   std::unique_ptr<WritableMemoryBuffer> Buffer;
221ef238923SStefan Gränitz   StringMap<std::unique_ptr<DebugObjectSection>> Sections;
222ef238923SStefan Gränitz };
223ef238923SStefan Gränitz 
224ef238923SStefan Gränitz static const std::set<StringRef> DwarfSectionNames = {
225ef238923SStefan Gränitz #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
226ef238923SStefan Gränitz   ELF_NAME,
227ef238923SStefan Gränitz #include "llvm/BinaryFormat/Dwarf.def"
228ef238923SStefan Gränitz #undef HANDLE_DWARF_SECTION
229ef238923SStefan Gränitz };
230ef238923SStefan Gränitz 
231ef238923SStefan Gränitz static bool isDwarfSection(StringRef SectionName) {
232ef238923SStefan Gränitz   return DwarfSectionNames.count(SectionName) == 1;
233ef238923SStefan Gränitz }
234ef238923SStefan Gränitz 
2357d18cd93SStefan Gränitz std::unique_ptr<WritableMemoryBuffer>
2367d18cd93SStefan Gränitz ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
237d02c1676SLang Hames   ErrorAsOutParameter _(Err);
238ef238923SStefan Gränitz   size_t Size = Buffer.getBufferSize();
239ef238923SStefan Gränitz   StringRef Name = Buffer.getBufferIdentifier();
2407d18cd93SStefan Gränitz   if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
241ef238923SStefan Gränitz     memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
2427d18cd93SStefan Gränitz     return Copy;
2437d18cd93SStefan Gränitz   }
2447d18cd93SStefan Gränitz 
2457d18cd93SStefan Gränitz   Err = errorCodeToError(make_error_code(errc::not_enough_memory));
2467d18cd93SStefan Gränitz   return nullptr;
247ef238923SStefan Gränitz }
248ef238923SStefan Gränitz 
249ef238923SStefan Gränitz template <typename ELFT>
250ef238923SStefan Gränitz Expected<std::unique_ptr<ELFDebugObject>>
251962a2479SLang Hames ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
252962a2479SLang Hames                                JITLinkMemoryManager &MemMgr,
253962a2479SLang Hames                                const JITLinkDylib *JD, ExecutionSession &ES) {
254ef238923SStefan Gränitz   using SectionHeader = typename ELFT::Shdr;
255ef238923SStefan Gränitz 
2567d18cd93SStefan Gränitz   Error Err = Error::success();
2577d18cd93SStefan Gränitz   std::unique_ptr<ELFDebugObject> DebugObj(
258962a2479SLang Hames       new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
2597d18cd93SStefan Gränitz   if (Err)
2607d18cd93SStefan Gränitz     return std::move(Err);
2617d18cd93SStefan Gränitz 
2627d18cd93SStefan Gränitz   Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
263ef238923SStefan Gränitz   if (!ObjRef)
264ef238923SStefan Gränitz     return ObjRef.takeError();
265ef238923SStefan Gränitz 
266ef238923SStefan Gränitz   Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
267ef238923SStefan Gränitz   if (!Sections)
268ef238923SStefan Gränitz     return Sections.takeError();
269ef238923SStefan Gränitz 
270ef238923SStefan Gränitz   for (const SectionHeader &Header : *Sections) {
271ef238923SStefan Gränitz     Expected<StringRef> Name = ObjRef->getSectionName(Header);
272ef238923SStefan Gränitz     if (!Name)
273ef238923SStefan Gränitz       return Name.takeError();
274ef238923SStefan Gränitz     if (Name->empty())
275ef238923SStefan Gränitz       continue;
276360a0530SStefan Gränitz     if (isDwarfSection(*Name))
277360a0530SStefan Gränitz       DebugObj->setFlags(HasDebugSections);
278ef238923SStefan Gränitz 
27988d8f127SStefan Gränitz     // Only record text and data sections (i.e. no bss, comments, rel, etc.)
28088d8f127SStefan Gränitz     if (Header.sh_type != ELF::SHT_PROGBITS &&
28188d8f127SStefan Gränitz         Header.sh_type != ELF::SHT_X86_64_UNWIND)
28288d8f127SStefan Gränitz       continue;
283b26f45e5SLang Hames     if (!(Header.sh_flags & ELF::SHF_ALLOC))
284b26f45e5SLang Hames       continue;
285b26f45e5SLang Hames 
286ef238923SStefan Gränitz     auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
287ef238923SStefan Gränitz     if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
288ef238923SStefan Gränitz       return std::move(Err);
289ef238923SStefan Gränitz   }
290ef238923SStefan Gränitz 
291ef238923SStefan Gränitz   return std::move(DebugObj);
292ef238923SStefan Gränitz }
293ef238923SStefan Gränitz 
294ef238923SStefan Gränitz Expected<std::unique_ptr<DebugObject>>
295b26c953fSStefan Gränitz ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
296b26c953fSStefan Gränitz                        ExecutionSession &ES) {
297ef238923SStefan Gränitz   unsigned char Class, Endian;
298ef238923SStefan Gränitz   std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
299ef238923SStefan Gränitz 
300ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS32) {
301ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
302962a2479SLang Hames       return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
303962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
304ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
305962a2479SLang Hames       return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
306962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
307ef238923SStefan Gränitz     return nullptr;
308ef238923SStefan Gränitz   }
309ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS64) {
310ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
311962a2479SLang Hames       return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
312962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
313ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
314962a2479SLang Hames       return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
315962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
316ef238923SStefan Gränitz     return nullptr;
317ef238923SStefan Gränitz   }
318ef238923SStefan Gränitz   return nullptr;
319ef238923SStefan Gränitz }
320ef238923SStefan Gränitz 
321962a2479SLang Hames Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
322ef238923SStefan Gränitz   LLVM_DEBUG({
323ef238923SStefan Gränitz     dbgs() << "Section load-addresses in debug object for \""
324ef238923SStefan Gränitz            << Buffer->getBufferIdentifier() << "\":\n";
325ef238923SStefan Gränitz     for (const auto &KV : Sections)
326ef238923SStefan Gränitz       KV.second->dump(dbgs(), KV.first());
327ef238923SStefan Gränitz   });
328ef238923SStefan Gränitz 
329ef238923SStefan Gränitz   // TODO: This works, but what actual alignment requirements do we have?
330962a2479SLang Hames   unsigned PageSize = sys::Process::getPageSizeEstimate();
331ef238923SStefan Gränitz   size_t Size = Buffer->getBufferSize();
332ef238923SStefan Gränitz 
333ef238923SStefan Gränitz   // Allocate working memory for debug object in read-only segment.
334*4eaff6c5SLang Hames   auto Alloc = SimpleSegmentAlloc::Create(
335*4eaff6c5SLang Hames       MemMgr, ES.getSymbolStringPool(), ES.getTargetTriple(), JD,
3362ccf7ed2SJared Wyles       {{MemProt::Read, {Size, Align(PageSize)}}});
337962a2479SLang Hames   if (!Alloc)
338962a2479SLang Hames     return Alloc;
339ef238923SStefan Gränitz 
340ef238923SStefan Gränitz   // Initialize working memory with a copy of our object buffer.
341962a2479SLang Hames   auto SegInfo = Alloc->getSegInfo(MemProt::Read);
342962a2479SLang Hames   memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
343ef238923SStefan Gränitz   Buffer.reset();
344ef238923SStefan Gränitz 
345962a2479SLang Hames   return Alloc;
346ef238923SStefan Gränitz }
347ef238923SStefan Gränitz 
348ef238923SStefan Gränitz void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
349ef238923SStefan Gränitz                                                     SectionRange TargetMem) {
350ef238923SStefan Gränitz   if (auto *DebugObjSection = getSection(Name))
351ef238923SStefan Gränitz     DebugObjSection->setTargetMemoryRange(TargetMem);
352ef238923SStefan Gränitz }
353ef238923SStefan Gränitz 
354265bc5afSStefan Gränitz template <typename ELFT>
355ef238923SStefan Gränitz Error ELFDebugObject::recordSection(
356265bc5afSStefan Gränitz     StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
357265bc5afSStefan Gränitz   if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
358265bc5afSStefan Gränitz     return Err;
3590a927bdcSStefan Gränitz   bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
3600a927bdcSStefan Gränitz   if (!Inserted)
361bd20a344SBenjamin Kramer     LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
3620a927bdcSStefan Gränitz                       << "' in object " << Buffer->getBufferIdentifier()
363bd20a344SBenjamin Kramer                       << " (duplicate name)\n");
364ef238923SStefan Gränitz   return Error::success();
365ef238923SStefan Gränitz }
366ef238923SStefan Gränitz 
367ef238923SStefan Gränitz DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
368ef238923SStefan Gränitz   auto It = Sections.find(Name);
369ef238923SStefan Gränitz   return It == Sections.end() ? nullptr : It->second.get();
370ef238923SStefan Gränitz }
371ef238923SStefan Gränitz 
372ef238923SStefan Gränitz /// Creates a debug object based on the input object file from
373ef238923SStefan Gränitz /// ObjectLinkingLayerJITLinkContext.
374ef238923SStefan Gränitz ///
375ef238923SStefan Gränitz static Expected<std::unique_ptr<DebugObject>>
376b26c953fSStefan Gränitz createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
377b26c953fSStefan Gränitz                             JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
378ef238923SStefan Gränitz   switch (G.getTargetTriple().getObjectFormat()) {
379ef238923SStefan Gränitz   case Triple::ELF:
380b26c953fSStefan Gränitz     return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
381ef238923SStefan Gränitz 
382ef238923SStefan Gränitz   default:
383ef238923SStefan Gränitz     // TODO: Once we add support for other formats, we might want to split this
384ef238923SStefan Gränitz     // into multiple files.
385ef238923SStefan Gränitz     return nullptr;
386ef238923SStefan Gränitz   }
387ef238923SStefan Gränitz }
388ef238923SStefan Gränitz 
389ef238923SStefan Gränitz DebugObjectManagerPlugin::DebugObjectManagerPlugin(
390360a0530SStefan Gränitz     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
3914c7f53b9SStefan Gränitz     bool RequireDebugSections, bool AutoRegisterCode)
392360a0530SStefan Gränitz     : ES(ES), Target(std::move(Target)),
3934c7f53b9SStefan Gränitz       RequireDebugSections(RequireDebugSections),
3944c7f53b9SStefan Gränitz       AutoRegisterCode(AutoRegisterCode) {}
395360a0530SStefan Gränitz 
396360a0530SStefan Gränitz DebugObjectManagerPlugin::DebugObjectManagerPlugin(
397ef238923SStefan Gränitz     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
3984c7f53b9SStefan Gränitz     : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
399ef238923SStefan Gränitz 
400b26c953fSStefan Gränitz DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
401ef238923SStefan Gränitz 
402ef238923SStefan Gränitz void DebugObjectManagerPlugin::notifyMaterializing(
403ef238923SStefan Gränitz     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
404ef238923SStefan Gränitz     MemoryBufferRef ObjBuffer) {
405c154cddaSStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
406c154cddaSStefan Gränitz   assert(PendingObjs.count(&MR) == 0 &&
407ef238923SStefan Gränitz          "Cannot have more than one pending debug object per "
408ef238923SStefan Gränitz          "MaterializationResponsibility");
409ef238923SStefan Gränitz 
410b26c953fSStefan Gränitz   if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
411ef238923SStefan Gränitz     // Not all link artifacts allow debugging.
412360a0530SStefan Gränitz     if (*DebugObj == nullptr)
413360a0530SStefan Gränitz       return;
414360a0530SStefan Gränitz     if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
415360a0530SStefan Gränitz       LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
416360a0530SStefan Gränitz                         << G.getName() << "': no debug info\n");
417360a0530SStefan Gränitz       return;
418360a0530SStefan Gränitz     }
419c154cddaSStefan Gränitz     PendingObjs[&MR] = std::move(*DebugObj);
420ef238923SStefan Gränitz   } else {
421ef238923SStefan Gränitz     ES.reportError(DebugObj.takeError());
422ef238923SStefan Gränitz   }
423ef238923SStefan Gränitz }
424ef238923SStefan Gränitz 
425ef238923SStefan Gränitz void DebugObjectManagerPlugin::modifyPassConfig(
4264e30b20bSLang Hames     MaterializationResponsibility &MR, LinkGraph &G,
427ef238923SStefan Gränitz     PassConfiguration &PassConfig) {
428ef238923SStefan Gränitz   // Not all link artifacts have associated debug objects.
429ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
430c154cddaSStefan Gränitz   auto It = PendingObjs.find(&MR);
431ef238923SStefan Gränitz   if (It == PendingObjs.end())
432ef238923SStefan Gränitz     return;
433ef238923SStefan Gränitz 
434ef238923SStefan Gränitz   DebugObject &DebugObj = *It->second;
435811832a9SStefan Gränitz   if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
436ef238923SStefan Gränitz     PassConfig.PostAllocationPasses.push_back(
437ef238923SStefan Gränitz         [&DebugObj](LinkGraph &Graph) -> Error {
438ef238923SStefan Gränitz           for (const Section &GraphSection : Graph.sections())
439ef238923SStefan Gränitz             DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
440ef238923SStefan Gränitz                                                     SectionRange(GraphSection));
441ef238923SStefan Gränitz           return Error::success();
442ef238923SStefan Gränitz         });
443ef238923SStefan Gränitz   }
444ef238923SStefan Gränitz }
445ef238923SStefan Gränitz 
446ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyEmitted(
447ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
448ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
449c154cddaSStefan Gränitz   auto It = PendingObjs.find(&MR);
450ef238923SStefan Gränitz   if (It == PendingObjs.end())
451ef238923SStefan Gränitz     return Error::success();
452ef238923SStefan Gränitz 
453ff52121bSStefan Gränitz   // During finalization the debug object is registered with the target.
454ff52121bSStefan Gränitz   // Materialization must wait for this process to finish. Otherwise we might
455ff52121bSStefan Gränitz   // start running code before the debugger processed the corresponding debug
456ff52121bSStefan Gränitz   // info.
457ff52121bSStefan Gränitz   std::promise<MSVCPError> FinalizePromise;
458ff52121bSStefan Gränitz   std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
459ff52121bSStefan Gränitz 
460cbcc1c9fSStefan Gränitz   It->second->finalizeAsync(
461962a2479SLang Hames       [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
462cbcc1c9fSStefan Gränitz         // Any failure here will fail materialization.
463ef238923SStefan Gränitz         if (!TargetMem) {
464ff52121bSStefan Gränitz           FinalizePromise.set_value(TargetMem.takeError());
465ef238923SStefan Gränitz           return;
466ef238923SStefan Gränitz         }
4674c7f53b9SStefan Gränitz         if (Error Err =
4684c7f53b9SStefan Gränitz                 Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
469ff52121bSStefan Gränitz           FinalizePromise.set_value(std::move(Err));
470ef238923SStefan Gränitz           return;
471ef238923SStefan Gränitz         }
472ef238923SStefan Gränitz 
473cbcc1c9fSStefan Gränitz         // Once our tracking info is updated, notifyEmitted() can return and
474cbcc1c9fSStefan Gränitz         // finish materialization.
475cbcc1c9fSStefan Gränitz         FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
476cbcc1c9fSStefan Gränitz           assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
477ef238923SStefan Gränitz           std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
478cbcc1c9fSStefan Gränitz           RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
479cbcc1c9fSStefan Gränitz           PendingObjs.erase(&MR);
480cbcc1c9fSStefan Gränitz         }));
481ef238923SStefan Gränitz       });
482ef238923SStefan Gränitz 
483ff52121bSStefan Gränitz   return FinalizeErr.get();
484ef238923SStefan Gränitz }
485ef238923SStefan Gränitz 
486ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyFailed(
487ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
488ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
489c154cddaSStefan Gränitz   PendingObjs.erase(&MR);
490ef238923SStefan Gränitz   return Error::success();
491ef238923SStefan Gränitz }
492ef238923SStefan Gränitz 
493bf6d7ca9SLang Hames void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
494bf6d7ca9SLang Hames                                                            ResourceKey DstKey,
495ef238923SStefan Gränitz                                                            ResourceKey SrcKey) {
496c154cddaSStefan Gränitz   // Debug objects are stored by ResourceKey only after registration.
497c154cddaSStefan Gränitz   // Thus, pending objects don't need to be updated here.
498ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
499ef238923SStefan Gränitz   auto SrcIt = RegisteredObjs.find(SrcKey);
500ef238923SStefan Gränitz   if (SrcIt != RegisteredObjs.end()) {
501ef238923SStefan Gränitz     // Resources from distinct MaterializationResponsibilitys can get merged
502ef238923SStefan Gränitz     // after emission, so we can have multiple debug objects per resource key.
503ef238923SStefan Gränitz     for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
504ef238923SStefan Gränitz       RegisteredObjs[DstKey].push_back(std::move(DebugObj));
505ef238923SStefan Gränitz     RegisteredObjs.erase(SrcIt);
506ef238923SStefan Gränitz   }
507ef238923SStefan Gränitz }
508ef238923SStefan Gränitz 
509bf6d7ca9SLang Hames Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
510bf6d7ca9SLang Hames                                                         ResourceKey Key) {
511c154cddaSStefan Gränitz   // Removing the resource for a pending object fails materialization, so they
512c154cddaSStefan Gränitz   // get cleaned up in the notifyFailed() handler.
513ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
514c154cddaSStefan Gränitz   RegisteredObjs.erase(Key);
515ef238923SStefan Gränitz 
516c154cddaSStefan Gränitz   // TODO: Implement unregister notifications.
517ef238923SStefan Gränitz   return Error::success();
518ef238923SStefan Gränitz }
519ef238923SStefan Gränitz 
520ef238923SStefan Gränitz } // namespace orc
521ef238923SStefan Gränitz } // namespace llvm
522