1*da58b97aSjoerg //===---- DebugObjectManagerPlugin.h - JITLink debug objects ---*- C++ -*-===//
2*da58b97aSjoerg //
3*da58b97aSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*da58b97aSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*da58b97aSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*da58b97aSjoerg //
7*da58b97aSjoerg //===----------------------------------------------------------------------===//
8*da58b97aSjoerg 
9*da58b97aSjoerg #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
10*da58b97aSjoerg 
11*da58b97aSjoerg #include "llvm/ADT/ArrayRef.h"
12*da58b97aSjoerg #include "llvm/ADT/StringMap.h"
13*da58b97aSjoerg #include "llvm/ADT/StringRef.h"
14*da58b97aSjoerg #include "llvm/BinaryFormat/ELF.h"
15*da58b97aSjoerg #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
16*da58b97aSjoerg #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
17*da58b97aSjoerg #include "llvm/ExecutionEngine/JITSymbol.h"
18*da58b97aSjoerg #include "llvm/Object/ELFObjectFile.h"
19*da58b97aSjoerg #include "llvm/Object/ObjectFile.h"
20*da58b97aSjoerg #include "llvm/Support/Errc.h"
21*da58b97aSjoerg #include "llvm/Support/MSVCErrorWorkarounds.h"
22*da58b97aSjoerg #include "llvm/Support/MemoryBuffer.h"
23*da58b97aSjoerg #include "llvm/Support/Process.h"
24*da58b97aSjoerg #include "llvm/Support/raw_ostream.h"
25*da58b97aSjoerg 
26*da58b97aSjoerg #include <set>
27*da58b97aSjoerg 
28*da58b97aSjoerg #define DEBUG_TYPE "orc"
29*da58b97aSjoerg 
30*da58b97aSjoerg using namespace llvm::jitlink;
31*da58b97aSjoerg using namespace llvm::object;
32*da58b97aSjoerg 
33*da58b97aSjoerg namespace llvm {
34*da58b97aSjoerg namespace orc {
35*da58b97aSjoerg 
36*da58b97aSjoerg class DebugObjectSection {
37*da58b97aSjoerg public:
38*da58b97aSjoerg   virtual void setTargetMemoryRange(SectionRange Range) = 0;
dump(raw_ostream & OS,StringRef Name)39*da58b97aSjoerg   virtual void dump(raw_ostream &OS, StringRef Name) {}
~DebugObjectSection()40*da58b97aSjoerg   virtual ~DebugObjectSection() {}
41*da58b97aSjoerg };
42*da58b97aSjoerg 
43*da58b97aSjoerg template <typename ELFT>
44*da58b97aSjoerg class ELFDebugObjectSection : public DebugObjectSection {
45*da58b97aSjoerg public:
46*da58b97aSjoerg   // BinaryFormat ELF is not meant as a mutable format. We can only make changes
47*da58b97aSjoerg   // that don't invalidate the file structure.
ELFDebugObjectSection(const typename ELFT::Shdr * Header)48*da58b97aSjoerg   ELFDebugObjectSection(const typename ELFT::Shdr *Header)
49*da58b97aSjoerg       : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
50*da58b97aSjoerg 
51*da58b97aSjoerg   void setTargetMemoryRange(SectionRange Range) override;
52*da58b97aSjoerg   void dump(raw_ostream &OS, StringRef Name) override;
53*da58b97aSjoerg 
54*da58b97aSjoerg   Error validateInBounds(StringRef Buffer, const char *Name) const;
55*da58b97aSjoerg 
56*da58b97aSjoerg private:
57*da58b97aSjoerg   typename ELFT::Shdr *Header;
58*da58b97aSjoerg 
59*da58b97aSjoerg   bool isTextOrDataSection() const;
60*da58b97aSjoerg };
61*da58b97aSjoerg 
62*da58b97aSjoerg template <typename ELFT>
setTargetMemoryRange(SectionRange Range)63*da58b97aSjoerg void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
64*da58b97aSjoerg   // Only patch load-addresses for executable and data sections.
65*da58b97aSjoerg   if (isTextOrDataSection()) {
66*da58b97aSjoerg     Header->sh_addr = static_cast<typename ELFT::uint>(Range.getStart());
67*da58b97aSjoerg   }
68*da58b97aSjoerg }
69*da58b97aSjoerg 
70*da58b97aSjoerg template <typename ELFT>
isTextOrDataSection() const71*da58b97aSjoerg bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
72*da58b97aSjoerg   switch (Header->sh_type) {
73*da58b97aSjoerg   case ELF::SHT_PROGBITS:
74*da58b97aSjoerg   case ELF::SHT_X86_64_UNWIND:
75*da58b97aSjoerg     return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
76*da58b97aSjoerg   }
77*da58b97aSjoerg   return false;
78*da58b97aSjoerg }
79*da58b97aSjoerg 
80*da58b97aSjoerg template <typename ELFT>
validateInBounds(StringRef Buffer,const char * Name) const81*da58b97aSjoerg Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
82*da58b97aSjoerg                                                     const char *Name) const {
83*da58b97aSjoerg   const uint8_t *Start = Buffer.bytes_begin();
84*da58b97aSjoerg   const uint8_t *End = Buffer.bytes_end();
85*da58b97aSjoerg   const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
86*da58b97aSjoerg   if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
87*da58b97aSjoerg     return make_error<StringError>(
88*da58b97aSjoerg         formatv("{0} section header at {1:x16} not within bounds of the "
89*da58b97aSjoerg                 "given debug object buffer [{2:x16} - {3:x16}]",
90*da58b97aSjoerg                 Name, &Header->sh_addr, Start, End),
91*da58b97aSjoerg         inconvertibleErrorCode());
92*da58b97aSjoerg   if (Header->sh_offset + Header->sh_size > Buffer.size())
93*da58b97aSjoerg     return make_error<StringError>(
94*da58b97aSjoerg         formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
95*da58b97aSjoerg                 "the given debug object buffer [{3:x16} - {4:x16}]",
96*da58b97aSjoerg                 Name, Start + Header->sh_offset,
97*da58b97aSjoerg                 Start + Header->sh_offset + Header->sh_size, Start, End),
98*da58b97aSjoerg         inconvertibleErrorCode());
99*da58b97aSjoerg   return Error::success();
100*da58b97aSjoerg }
101*da58b97aSjoerg 
102*da58b97aSjoerg template <typename ELFT>
dump(raw_ostream & OS,StringRef Name)103*da58b97aSjoerg void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
104*da58b97aSjoerg   if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
105*da58b97aSjoerg     OS << formatv("  {0:x16} {1}\n", Addr, Name);
106*da58b97aSjoerg   } else {
107*da58b97aSjoerg     OS << formatv("                     {0}\n", Name);
108*da58b97aSjoerg   }
109*da58b97aSjoerg }
110*da58b97aSjoerg 
111*da58b97aSjoerg static constexpr sys::Memory::ProtectionFlags ReadOnly =
112*da58b97aSjoerg     static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ);
113*da58b97aSjoerg 
114*da58b97aSjoerg enum class Requirement {
115*da58b97aSjoerg   // Request final target memory load-addresses for all sections.
116*da58b97aSjoerg   ReportFinalSectionLoadAddresses,
117*da58b97aSjoerg };
118*da58b97aSjoerg 
119*da58b97aSjoerg /// The plugin creates a debug object from JITLinkContext when JITLink starts
120*da58b97aSjoerg /// processing the corresponding LinkGraph. It provides access to the pass
121*da58b97aSjoerg /// configuration of the LinkGraph and calls the finalization function, once
122*da58b97aSjoerg /// the resulting link artifact was emitted.
123*da58b97aSjoerg ///
124*da58b97aSjoerg class DebugObject {
125*da58b97aSjoerg public:
DebugObject(JITLinkContext & Ctx,ExecutionSession & ES)126*da58b97aSjoerg   DebugObject(JITLinkContext &Ctx, ExecutionSession &ES) : Ctx(Ctx), ES(ES) {}
127*da58b97aSjoerg 
set(Requirement Req)128*da58b97aSjoerg   void set(Requirement Req) { Reqs.insert(Req); }
has(Requirement Req) const129*da58b97aSjoerg   bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
130*da58b97aSjoerg 
131*da58b97aSjoerg   using FinalizeContinuation = std::function<void(Expected<sys::MemoryBlock>)>;
132*da58b97aSjoerg   void finalizeAsync(FinalizeContinuation OnFinalize);
133*da58b97aSjoerg 
~DebugObject()134*da58b97aSjoerg   virtual ~DebugObject() {
135*da58b97aSjoerg     if (Alloc)
136*da58b97aSjoerg       if (Error Err = Alloc->deallocate())
137*da58b97aSjoerg         ES.reportError(std::move(Err));
138*da58b97aSjoerg   }
139*da58b97aSjoerg 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)140*da58b97aSjoerg   virtual void reportSectionTargetMemoryRange(StringRef Name,
141*da58b97aSjoerg                                               SectionRange TargetMem) {}
142*da58b97aSjoerg 
143*da58b97aSjoerg protected:
144*da58b97aSjoerg   using Allocation = JITLinkMemoryManager::Allocation;
145*da58b97aSjoerg 
146*da58b97aSjoerg   virtual Expected<std::unique_ptr<Allocation>>
147*da58b97aSjoerg   finalizeWorkingMemory(JITLinkContext &Ctx) = 0;
148*da58b97aSjoerg 
149*da58b97aSjoerg private:
150*da58b97aSjoerg   JITLinkContext &Ctx;
151*da58b97aSjoerg   ExecutionSession &ES;
152*da58b97aSjoerg   std::set<Requirement> Reqs;
153*da58b97aSjoerg   std::unique_ptr<Allocation> Alloc{nullptr};
154*da58b97aSjoerg };
155*da58b97aSjoerg 
156*da58b97aSjoerg // Finalize working memory and take ownership of the resulting allocation. Start
157*da58b97aSjoerg // copying memory over to the target and pass on the result once we're done.
158*da58b97aSjoerg // Ownership of the allocation remains with us for the rest of our lifetime.
finalizeAsync(FinalizeContinuation OnFinalize)159*da58b97aSjoerg void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
160*da58b97aSjoerg   assert(Alloc == nullptr && "Cannot finalize more than once");
161*da58b97aSjoerg 
162*da58b97aSjoerg   auto AllocOrErr = finalizeWorkingMemory(Ctx);
163*da58b97aSjoerg   if (!AllocOrErr)
164*da58b97aSjoerg     OnFinalize(AllocOrErr.takeError());
165*da58b97aSjoerg   Alloc = std::move(*AllocOrErr);
166*da58b97aSjoerg 
167*da58b97aSjoerg   Alloc->finalizeAsync([this, OnFinalize](Error Err) {
168*da58b97aSjoerg     if (Err)
169*da58b97aSjoerg       OnFinalize(std::move(Err));
170*da58b97aSjoerg     else
171*da58b97aSjoerg       OnFinalize(sys::MemoryBlock(
172*da58b97aSjoerg           jitTargetAddressToPointer<void *>(Alloc->getTargetMemory(ReadOnly)),
173*da58b97aSjoerg           Alloc->getWorkingMemory(ReadOnly).size()));
174*da58b97aSjoerg   });
175*da58b97aSjoerg }
176*da58b97aSjoerg 
177*da58b97aSjoerg /// The current implementation of ELFDebugObject replicates the approach used in
178*da58b97aSjoerg /// RuntimeDyld: It patches executable and data section headers in the given
179*da58b97aSjoerg /// object buffer with load-addresses of their corresponding sections in target
180*da58b97aSjoerg /// memory.
181*da58b97aSjoerg ///
182*da58b97aSjoerg class ELFDebugObject : public DebugObject {
183*da58b97aSjoerg public:
184*da58b97aSjoerg   static Expected<std::unique_ptr<DebugObject>>
185*da58b97aSjoerg   Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
186*da58b97aSjoerg 
187*da58b97aSjoerg   void reportSectionTargetMemoryRange(StringRef Name,
188*da58b97aSjoerg                                       SectionRange TargetMem) override;
189*da58b97aSjoerg 
getBuffer() const190*da58b97aSjoerg   StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
191*da58b97aSjoerg 
192*da58b97aSjoerg protected:
193*da58b97aSjoerg   Expected<std::unique_ptr<Allocation>>
194*da58b97aSjoerg   finalizeWorkingMemory(JITLinkContext &Ctx) override;
195*da58b97aSjoerg 
196*da58b97aSjoerg   template <typename ELFT>
197*da58b97aSjoerg   Error recordSection(StringRef Name,
198*da58b97aSjoerg                       std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
199*da58b97aSjoerg   DebugObjectSection *getSection(StringRef Name);
200*da58b97aSjoerg 
201*da58b97aSjoerg private:
202*da58b97aSjoerg   template <typename ELFT>
203*da58b97aSjoerg   static Expected<std::unique_ptr<ELFDebugObject>>
204*da58b97aSjoerg   CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx,
205*da58b97aSjoerg                  ExecutionSession &ES);
206*da58b97aSjoerg 
207*da58b97aSjoerg   static std::unique_ptr<WritableMemoryBuffer>
208*da58b97aSjoerg   CopyBuffer(MemoryBufferRef Buffer, Error &Err);
209*da58b97aSjoerg 
ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,JITLinkContext & Ctx,ExecutionSession & ES)210*da58b97aSjoerg   ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
211*da58b97aSjoerg                  JITLinkContext &Ctx, ExecutionSession &ES)
212*da58b97aSjoerg       : DebugObject(Ctx, ES), Buffer(std::move(Buffer)) {
213*da58b97aSjoerg     set(Requirement::ReportFinalSectionLoadAddresses);
214*da58b97aSjoerg   }
215*da58b97aSjoerg 
216*da58b97aSjoerg   std::unique_ptr<WritableMemoryBuffer> Buffer;
217*da58b97aSjoerg   StringMap<std::unique_ptr<DebugObjectSection>> Sections;
218*da58b97aSjoerg };
219*da58b97aSjoerg 
220*da58b97aSjoerg static const std::set<StringRef> DwarfSectionNames = {
221*da58b97aSjoerg #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
222*da58b97aSjoerg   ELF_NAME,
223*da58b97aSjoerg #include "llvm/BinaryFormat/Dwarf.def"
224*da58b97aSjoerg #undef HANDLE_DWARF_SECTION
225*da58b97aSjoerg };
226*da58b97aSjoerg 
isDwarfSection(StringRef SectionName)227*da58b97aSjoerg static bool isDwarfSection(StringRef SectionName) {
228*da58b97aSjoerg   return DwarfSectionNames.count(SectionName) == 1;
229*da58b97aSjoerg }
230*da58b97aSjoerg 
231*da58b97aSjoerg std::unique_ptr<WritableMemoryBuffer>
CopyBuffer(MemoryBufferRef Buffer,Error & Err)232*da58b97aSjoerg ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
233*da58b97aSjoerg   ErrorAsOutParameter _(&Err);
234*da58b97aSjoerg   size_t Size = Buffer.getBufferSize();
235*da58b97aSjoerg   StringRef Name = Buffer.getBufferIdentifier();
236*da58b97aSjoerg   if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
237*da58b97aSjoerg     memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
238*da58b97aSjoerg     return Copy;
239*da58b97aSjoerg   }
240*da58b97aSjoerg 
241*da58b97aSjoerg   Err = errorCodeToError(make_error_code(errc::not_enough_memory));
242*da58b97aSjoerg   return nullptr;
243*da58b97aSjoerg }
244*da58b97aSjoerg 
245*da58b97aSjoerg template <typename ELFT>
246*da58b97aSjoerg Expected<std::unique_ptr<ELFDebugObject>>
CreateArchType(MemoryBufferRef Buffer,JITLinkContext & Ctx,ExecutionSession & ES)247*da58b97aSjoerg ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx,
248*da58b97aSjoerg                                ExecutionSession &ES) {
249*da58b97aSjoerg   using SectionHeader = typename ELFT::Shdr;
250*da58b97aSjoerg 
251*da58b97aSjoerg   Error Err = Error::success();
252*da58b97aSjoerg   std::unique_ptr<ELFDebugObject> DebugObj(
253*da58b97aSjoerg       new ELFDebugObject(CopyBuffer(Buffer, Err), Ctx, ES));
254*da58b97aSjoerg   if (Err)
255*da58b97aSjoerg     return std::move(Err);
256*da58b97aSjoerg 
257*da58b97aSjoerg   Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
258*da58b97aSjoerg   if (!ObjRef)
259*da58b97aSjoerg     return ObjRef.takeError();
260*da58b97aSjoerg 
261*da58b97aSjoerg   // TODO: Add support for other architectures.
262*da58b97aSjoerg   uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
263*da58b97aSjoerg   if (TargetMachineArch != ELF::EM_X86_64)
264*da58b97aSjoerg     return nullptr;
265*da58b97aSjoerg 
266*da58b97aSjoerg   Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
267*da58b97aSjoerg   if (!Sections)
268*da58b97aSjoerg     return Sections.takeError();
269*da58b97aSjoerg 
270*da58b97aSjoerg   bool HasDwarfSection = false;
271*da58b97aSjoerg   for (const SectionHeader &Header : *Sections) {
272*da58b97aSjoerg     Expected<StringRef> Name = ObjRef->getSectionName(Header);
273*da58b97aSjoerg     if (!Name)
274*da58b97aSjoerg       return Name.takeError();
275*da58b97aSjoerg     if (Name->empty())
276*da58b97aSjoerg       continue;
277*da58b97aSjoerg     HasDwarfSection |= isDwarfSection(*Name);
278*da58b97aSjoerg 
279*da58b97aSjoerg     auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
280*da58b97aSjoerg     if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
281*da58b97aSjoerg       return std::move(Err);
282*da58b97aSjoerg   }
283*da58b97aSjoerg 
284*da58b97aSjoerg   if (!HasDwarfSection) {
285*da58b97aSjoerg     LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
286*da58b97aSjoerg                       << DebugObj->Buffer->getBufferIdentifier()
287*da58b97aSjoerg                       << "\": input object contains no debug info\n");
288*da58b97aSjoerg     return nullptr;
289*da58b97aSjoerg   }
290*da58b97aSjoerg 
291*da58b97aSjoerg   return std::move(DebugObj);
292*da58b97aSjoerg }
293*da58b97aSjoerg 
294*da58b97aSjoerg Expected<std::unique_ptr<DebugObject>>
Create(MemoryBufferRef Buffer,JITLinkContext & Ctx,ExecutionSession & ES)295*da58b97aSjoerg ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
296*da58b97aSjoerg                        ExecutionSession &ES) {
297*da58b97aSjoerg   unsigned char Class, Endian;
298*da58b97aSjoerg   std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
299*da58b97aSjoerg 
300*da58b97aSjoerg   if (Class == ELF::ELFCLASS32) {
301*da58b97aSjoerg     if (Endian == ELF::ELFDATA2LSB)
302*da58b97aSjoerg       return CreateArchType<ELF32LE>(Buffer, Ctx, ES);
303*da58b97aSjoerg     if (Endian == ELF::ELFDATA2MSB)
304*da58b97aSjoerg       return CreateArchType<ELF32BE>(Buffer, Ctx, ES);
305*da58b97aSjoerg     return nullptr;
306*da58b97aSjoerg   }
307*da58b97aSjoerg   if (Class == ELF::ELFCLASS64) {
308*da58b97aSjoerg     if (Endian == ELF::ELFDATA2LSB)
309*da58b97aSjoerg       return CreateArchType<ELF64LE>(Buffer, Ctx, ES);
310*da58b97aSjoerg     if (Endian == ELF::ELFDATA2MSB)
311*da58b97aSjoerg       return CreateArchType<ELF64BE>(Buffer, Ctx, ES);
312*da58b97aSjoerg     return nullptr;
313*da58b97aSjoerg   }
314*da58b97aSjoerg   return nullptr;
315*da58b97aSjoerg }
316*da58b97aSjoerg 
317*da58b97aSjoerg Expected<std::unique_ptr<DebugObject::Allocation>>
finalizeWorkingMemory(JITLinkContext & Ctx)318*da58b97aSjoerg ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) {
319*da58b97aSjoerg   LLVM_DEBUG({
320*da58b97aSjoerg     dbgs() << "Section load-addresses in debug object for \""
321*da58b97aSjoerg            << Buffer->getBufferIdentifier() << "\":\n";
322*da58b97aSjoerg     for (const auto &KV : Sections)
323*da58b97aSjoerg       KV.second->dump(dbgs(), KV.first());
324*da58b97aSjoerg   });
325*da58b97aSjoerg 
326*da58b97aSjoerg   // TODO: This works, but what actual alignment requirements do we have?
327*da58b97aSjoerg   unsigned Alignment = sys::Process::getPageSizeEstimate();
328*da58b97aSjoerg   JITLinkMemoryManager &MemMgr = Ctx.getMemoryManager();
329*da58b97aSjoerg   const JITLinkDylib *JD = Ctx.getJITLinkDylib();
330*da58b97aSjoerg   size_t Size = Buffer->getBufferSize();
331*da58b97aSjoerg 
332*da58b97aSjoerg   // Allocate working memory for debug object in read-only segment.
333*da58b97aSjoerg   JITLinkMemoryManager::SegmentsRequestMap SingleReadOnlySegment;
334*da58b97aSjoerg   SingleReadOnlySegment[ReadOnly] =
335*da58b97aSjoerg       JITLinkMemoryManager::SegmentRequest(Alignment, Size, 0);
336*da58b97aSjoerg 
337*da58b97aSjoerg   auto AllocOrErr = MemMgr.allocate(JD, SingleReadOnlySegment);
338*da58b97aSjoerg   if (!AllocOrErr)
339*da58b97aSjoerg     return AllocOrErr.takeError();
340*da58b97aSjoerg 
341*da58b97aSjoerg   // Initialize working memory with a copy of our object buffer.
342*da58b97aSjoerg   // TODO: Use our buffer as working memory directly.
343*da58b97aSjoerg   std::unique_ptr<Allocation> Alloc = std::move(*AllocOrErr);
344*da58b97aSjoerg   MutableArrayRef<char> WorkingMem = Alloc->getWorkingMemory(ReadOnly);
345*da58b97aSjoerg   memcpy(WorkingMem.data(), Buffer->getBufferStart(), Size);
346*da58b97aSjoerg   Buffer.reset();
347*da58b97aSjoerg 
348*da58b97aSjoerg   return std::move(Alloc);
349*da58b97aSjoerg }
350*da58b97aSjoerg 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)351*da58b97aSjoerg void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
352*da58b97aSjoerg                                                     SectionRange TargetMem) {
353*da58b97aSjoerg   if (auto *DebugObjSection = getSection(Name))
354*da58b97aSjoerg     DebugObjSection->setTargetMemoryRange(TargetMem);
355*da58b97aSjoerg }
356*da58b97aSjoerg 
357*da58b97aSjoerg template <typename ELFT>
recordSection(StringRef Name,std::unique_ptr<ELFDebugObjectSection<ELFT>> Section)358*da58b97aSjoerg Error ELFDebugObject::recordSection(
359*da58b97aSjoerg     StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
360*da58b97aSjoerg   if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
361*da58b97aSjoerg     return Err;
362*da58b97aSjoerg   auto ItInserted = Sections.try_emplace(Name, std::move(Section));
363*da58b97aSjoerg   if (!ItInserted.second)
364*da58b97aSjoerg     return make_error<StringError>("Duplicate section",
365*da58b97aSjoerg                                    inconvertibleErrorCode());
366*da58b97aSjoerg   return Error::success();
367*da58b97aSjoerg }
368*da58b97aSjoerg 
getSection(StringRef Name)369*da58b97aSjoerg DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
370*da58b97aSjoerg   auto It = Sections.find(Name);
371*da58b97aSjoerg   return It == Sections.end() ? nullptr : It->second.get();
372*da58b97aSjoerg }
373*da58b97aSjoerg 
374*da58b97aSjoerg /// Creates a debug object based on the input object file from
375*da58b97aSjoerg /// ObjectLinkingLayerJITLinkContext.
376*da58b97aSjoerg ///
377*da58b97aSjoerg static Expected<std::unique_ptr<DebugObject>>
createDebugObjectFromBuffer(ExecutionSession & ES,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)378*da58b97aSjoerg createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
379*da58b97aSjoerg                             JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
380*da58b97aSjoerg   switch (G.getTargetTriple().getObjectFormat()) {
381*da58b97aSjoerg   case Triple::ELF:
382*da58b97aSjoerg     return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
383*da58b97aSjoerg 
384*da58b97aSjoerg   default:
385*da58b97aSjoerg     // TODO: Once we add support for other formats, we might want to split this
386*da58b97aSjoerg     // into multiple files.
387*da58b97aSjoerg     return nullptr;
388*da58b97aSjoerg   }
389*da58b97aSjoerg }
390*da58b97aSjoerg 
DebugObjectManagerPlugin(ExecutionSession & ES,std::unique_ptr<DebugObjectRegistrar> Target)391*da58b97aSjoerg DebugObjectManagerPlugin::DebugObjectManagerPlugin(
392*da58b97aSjoerg     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
393*da58b97aSjoerg     : ES(ES), Target(std::move(Target)) {}
394*da58b97aSjoerg 
395*da58b97aSjoerg DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
396*da58b97aSjoerg 
notifyMaterializing(MaterializationResponsibility & MR,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)397*da58b97aSjoerg void DebugObjectManagerPlugin::notifyMaterializing(
398*da58b97aSjoerg     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
399*da58b97aSjoerg     MemoryBufferRef ObjBuffer) {
400*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(PendingObjsLock);
401*da58b97aSjoerg   assert(PendingObjs.count(&MR) == 0 &&
402*da58b97aSjoerg          "Cannot have more than one pending debug object per "
403*da58b97aSjoerg          "MaterializationResponsibility");
404*da58b97aSjoerg 
405*da58b97aSjoerg   if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
406*da58b97aSjoerg     // Not all link artifacts allow debugging.
407*da58b97aSjoerg     if (*DebugObj != nullptr)
408*da58b97aSjoerg       PendingObjs[&MR] = std::move(*DebugObj);
409*da58b97aSjoerg   } else {
410*da58b97aSjoerg     ES.reportError(DebugObj.takeError());
411*da58b97aSjoerg   }
412*da58b97aSjoerg }
413*da58b97aSjoerg 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)414*da58b97aSjoerg void DebugObjectManagerPlugin::modifyPassConfig(
415*da58b97aSjoerg     MaterializationResponsibility &MR, LinkGraph &G,
416*da58b97aSjoerg     PassConfiguration &PassConfig) {
417*da58b97aSjoerg   // Not all link artifacts have associated debug objects.
418*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(PendingObjsLock);
419*da58b97aSjoerg   auto It = PendingObjs.find(&MR);
420*da58b97aSjoerg   if (It == PendingObjs.end())
421*da58b97aSjoerg     return;
422*da58b97aSjoerg 
423*da58b97aSjoerg   DebugObject &DebugObj = *It->second;
424*da58b97aSjoerg   if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
425*da58b97aSjoerg     PassConfig.PostAllocationPasses.push_back(
426*da58b97aSjoerg         [&DebugObj](LinkGraph &Graph) -> Error {
427*da58b97aSjoerg           for (const Section &GraphSection : Graph.sections())
428*da58b97aSjoerg             DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
429*da58b97aSjoerg                                                     SectionRange(GraphSection));
430*da58b97aSjoerg           return Error::success();
431*da58b97aSjoerg         });
432*da58b97aSjoerg   }
433*da58b97aSjoerg }
434*da58b97aSjoerg 
notifyEmitted(MaterializationResponsibility & MR)435*da58b97aSjoerg Error DebugObjectManagerPlugin::notifyEmitted(
436*da58b97aSjoerg     MaterializationResponsibility &MR) {
437*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(PendingObjsLock);
438*da58b97aSjoerg   auto It = PendingObjs.find(&MR);
439*da58b97aSjoerg   if (It == PendingObjs.end())
440*da58b97aSjoerg     return Error::success();
441*da58b97aSjoerg 
442*da58b97aSjoerg   // During finalization the debug object is registered with the target.
443*da58b97aSjoerg   // Materialization must wait for this process to finish. Otherwise we might
444*da58b97aSjoerg   // start running code before the debugger processed the corresponding debug
445*da58b97aSjoerg   // info.
446*da58b97aSjoerg   std::promise<MSVCPError> FinalizePromise;
447*da58b97aSjoerg   std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
448*da58b97aSjoerg 
449*da58b97aSjoerg   It->second->finalizeAsync(
450*da58b97aSjoerg       [this, &FinalizePromise, &MR](Expected<sys::MemoryBlock> TargetMem) {
451*da58b97aSjoerg         // Any failure here will fail materialization.
452*da58b97aSjoerg         if (!TargetMem) {
453*da58b97aSjoerg           FinalizePromise.set_value(TargetMem.takeError());
454*da58b97aSjoerg           return;
455*da58b97aSjoerg         }
456*da58b97aSjoerg         if (Error Err = Target->registerDebugObject(*TargetMem)) {
457*da58b97aSjoerg           FinalizePromise.set_value(std::move(Err));
458*da58b97aSjoerg           return;
459*da58b97aSjoerg         }
460*da58b97aSjoerg 
461*da58b97aSjoerg         // Once our tracking info is updated, notifyEmitted() can return and
462*da58b97aSjoerg         // finish materialization.
463*da58b97aSjoerg         FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
464*da58b97aSjoerg           assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
465*da58b97aSjoerg           std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
466*da58b97aSjoerg           RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
467*da58b97aSjoerg           PendingObjs.erase(&MR);
468*da58b97aSjoerg         }));
469*da58b97aSjoerg       });
470*da58b97aSjoerg 
471*da58b97aSjoerg   return FinalizeErr.get();
472*da58b97aSjoerg }
473*da58b97aSjoerg 
notifyFailed(MaterializationResponsibility & MR)474*da58b97aSjoerg Error DebugObjectManagerPlugin::notifyFailed(
475*da58b97aSjoerg     MaterializationResponsibility &MR) {
476*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(PendingObjsLock);
477*da58b97aSjoerg   PendingObjs.erase(&MR);
478*da58b97aSjoerg   return Error::success();
479*da58b97aSjoerg }
480*da58b97aSjoerg 
notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)481*da58b97aSjoerg void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
482*da58b97aSjoerg                                                            ResourceKey SrcKey) {
483*da58b97aSjoerg   // Debug objects are stored by ResourceKey only after registration.
484*da58b97aSjoerg   // Thus, pending objects don't need to be updated here.
485*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
486*da58b97aSjoerg   auto SrcIt = RegisteredObjs.find(SrcKey);
487*da58b97aSjoerg   if (SrcIt != RegisteredObjs.end()) {
488*da58b97aSjoerg     // Resources from distinct MaterializationResponsibilitys can get merged
489*da58b97aSjoerg     // after emission, so we can have multiple debug objects per resource key.
490*da58b97aSjoerg     for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
491*da58b97aSjoerg       RegisteredObjs[DstKey].push_back(std::move(DebugObj));
492*da58b97aSjoerg     RegisteredObjs.erase(SrcIt);
493*da58b97aSjoerg   }
494*da58b97aSjoerg }
495*da58b97aSjoerg 
notifyRemovingResources(ResourceKey Key)496*da58b97aSjoerg Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
497*da58b97aSjoerg   // Removing the resource for a pending object fails materialization, so they
498*da58b97aSjoerg   // get cleaned up in the notifyFailed() handler.
499*da58b97aSjoerg   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
500*da58b97aSjoerg   RegisteredObjs.erase(Key);
501*da58b97aSjoerg 
502*da58b97aSjoerg   // TODO: Implement unregister notifications.
503*da58b97aSjoerg   return Error::success();
504*da58b97aSjoerg }
505*da58b97aSjoerg 
506*da58b97aSjoerg } // namespace orc
507*da58b97aSjoerg } // namespace llvm
508