1ef238923SStefan Gränitz //===---- DebugObjectManagerPlugin.h - JITLink debug objects ---*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
8ef238923SStefan Gränitz 
9ef238923SStefan Gränitz #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
10ef238923SStefan Gränitz 
11ef238923SStefan Gränitz #include "llvm/ADT/ArrayRef.h"
12ef238923SStefan Gränitz #include "llvm/ADT/StringMap.h"
13ef238923SStefan Gränitz #include "llvm/ADT/StringRef.h"
14ef238923SStefan Gränitz #include "llvm/BinaryFormat/ELF.h"
15ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
16ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
17ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITSymbol.h"
18ef238923SStefan Gränitz #include "llvm/Object/ELFObjectFile.h"
19ef238923SStefan Gränitz #include "llvm/Object/ObjectFile.h"
20ef238923SStefan Gränitz #include "llvm/Support/Errc.h"
21ff52121bSStefan Gränitz #include "llvm/Support/MSVCErrorWorkarounds.h"
22ef238923SStefan Gränitz #include "llvm/Support/MemoryBuffer.h"
23ef238923SStefan Gränitz #include "llvm/Support/Process.h"
24ef238923SStefan Gränitz #include "llvm/Support/raw_ostream.h"
25ef238923SStefan Gränitz 
26ef238923SStefan Gränitz #include <set>
27ef238923SStefan Gränitz 
28ef238923SStefan Gränitz #define DEBUG_TYPE "orc"
29ef238923SStefan Gränitz 
30ef238923SStefan Gränitz using namespace llvm::jitlink;
31ef238923SStefan Gränitz using namespace llvm::object;
32ef238923SStefan Gränitz 
33ef238923SStefan Gränitz namespace llvm {
34ef238923SStefan Gränitz namespace orc {
35ef238923SStefan Gränitz 
36ef238923SStefan Gränitz class DebugObjectSection {
37ef238923SStefan Gränitz public:
38ef238923SStefan Gränitz   virtual void setTargetMemoryRange(SectionRange Range) = 0;
39ef238923SStefan Gränitz   virtual void dump(raw_ostream &OS, StringRef Name) {}
40ef238923SStefan Gränitz   virtual ~DebugObjectSection() {}
41ef238923SStefan Gränitz };
42ef238923SStefan Gränitz 
43ef238923SStefan Gränitz template <typename ELFT>
44ef238923SStefan Gränitz class ELFDebugObjectSection : public DebugObjectSection {
45ef238923SStefan Gränitz public:
46ef238923SStefan Gränitz   // BinaryFormat ELF is not meant as a mutable format. We can only make changes
47ef238923SStefan Gränitz   // that don't invalidate the file structure.
48ef238923SStefan Gränitz   ELFDebugObjectSection(const typename ELFT::Shdr *Header)
49ef238923SStefan Gränitz       : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
50ef238923SStefan Gränitz 
51ef238923SStefan Gränitz   void setTargetMemoryRange(SectionRange Range) override;
52ef238923SStefan Gränitz   void dump(raw_ostream &OS, StringRef Name) override;
53ef238923SStefan Gränitz 
54265bc5afSStefan Gränitz   Error validateInBounds(StringRef Buffer, const char *Name) const;
55265bc5afSStefan Gränitz 
56ef238923SStefan Gränitz private:
57ef238923SStefan Gränitz   typename ELFT::Shdr *Header;
58ef238923SStefan Gränitz 
59ef238923SStefan Gränitz   bool isTextOrDataSection() const;
60ef238923SStefan Gränitz };
61ef238923SStefan Gränitz 
62ef238923SStefan Gränitz template <typename ELFT>
63ef238923SStefan Gränitz void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
64ef238923SStefan Gränitz   // Only patch load-addresses for executable and data sections.
65ef238923SStefan Gränitz   if (isTextOrDataSection()) {
66ef238923SStefan Gränitz     Header->sh_addr = static_cast<typename ELFT::uint>(Range.getStart());
67ef238923SStefan Gränitz   }
68ef238923SStefan Gränitz }
69ef238923SStefan Gränitz 
70ef238923SStefan Gränitz template <typename ELFT>
71ef238923SStefan Gränitz bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
72ef238923SStefan Gränitz   switch (Header->sh_type) {
73ef238923SStefan Gränitz   case ELF::SHT_PROGBITS:
74ef238923SStefan Gränitz   case ELF::SHT_X86_64_UNWIND:
75ef238923SStefan Gränitz     return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
76ef238923SStefan Gränitz   }
77ef238923SStefan Gränitz   return false;
78ef238923SStefan Gränitz }
79ef238923SStefan Gränitz 
80265bc5afSStefan Gränitz template <typename ELFT>
81265bc5afSStefan Gränitz Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
82265bc5afSStefan Gränitz                                                     const char *Name) const {
83265bc5afSStefan Gränitz   const uint8_t *Start = Buffer.bytes_begin();
84265bc5afSStefan Gränitz   const uint8_t *End = Buffer.bytes_end();
85265bc5afSStefan Gränitz   const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
86265bc5afSStefan Gränitz   if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
87265bc5afSStefan Gränitz     return make_error<StringError>(
88265bc5afSStefan Gränitz         formatv("{0} section header at {1:x16} not within bounds of the "
89265bc5afSStefan Gränitz                 "given debug object buffer [{2:x16} - {3:x16}]",
90265bc5afSStefan Gränitz                 Name, &Header->sh_addr, Start, End),
91265bc5afSStefan Gränitz         inconvertibleErrorCode());
92265bc5afSStefan Gränitz   if (Header->sh_offset + Header->sh_size > Buffer.size())
93265bc5afSStefan Gränitz     return make_error<StringError>(
94265bc5afSStefan Gränitz         formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
95265bc5afSStefan Gränitz                 "the given debug object buffer [{3:x16} - {4:x16}]",
96265bc5afSStefan Gränitz                 Name, Start + Header->sh_offset,
97265bc5afSStefan Gränitz                 Start + Header->sh_offset + Header->sh_size, Start, End),
98265bc5afSStefan Gränitz         inconvertibleErrorCode());
99265bc5afSStefan Gränitz   return Error::success();
100265bc5afSStefan Gränitz }
101265bc5afSStefan Gränitz 
102265bc5afSStefan Gränitz template <typename ELFT>
103265bc5afSStefan Gränitz void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
104265bc5afSStefan Gränitz   if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
105265bc5afSStefan Gränitz     OS << formatv("  {0:x16} {1}\n", Addr, Name);
106265bc5afSStefan Gränitz   } else {
107265bc5afSStefan Gränitz     OS << formatv("                     {0}\n", Name);
108265bc5afSStefan Gränitz   }
109265bc5afSStefan Gränitz }
110265bc5afSStefan Gränitz 
111ef238923SStefan Gränitz static constexpr sys::Memory::ProtectionFlags ReadOnly =
112ef238923SStefan Gränitz     static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ);
113ef238923SStefan Gränitz 
114ef238923SStefan Gränitz enum class Requirement {
115ef238923SStefan Gränitz   // Request final target memory load-addresses for all sections.
116ef238923SStefan Gränitz   ReportFinalSectionLoadAddresses,
117ef238923SStefan Gränitz };
118ef238923SStefan Gränitz 
119ef238923SStefan Gränitz /// The plugin creates a debug object from JITLinkContext when JITLink starts
120ef238923SStefan Gränitz /// processing the corresponding LinkGraph. It provides access to the pass
121ef238923SStefan Gränitz /// configuration of the LinkGraph and calls the finalization function, once
122ef238923SStefan Gränitz /// the resulting link artifact was emitted.
123ef238923SStefan Gränitz ///
124ef238923SStefan Gränitz class DebugObject {
125ef238923SStefan Gränitz public:
126ef238923SStefan Gränitz   DebugObject(JITLinkContext &Ctx) : Ctx(Ctx) {}
127ee5e7a3aSStefan Gränitz   virtual ~DebugObject() = default;
128ef238923SStefan Gränitz 
129ef238923SStefan Gränitz   void set(Requirement Req) { Reqs.insert(Req); }
130ef238923SStefan Gränitz   bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
131ef238923SStefan Gränitz 
132ef238923SStefan Gränitz   using FinalizeContinuation = std::function<void(Expected<sys::MemoryBlock>)>;
133ef238923SStefan Gränitz   void finalizeAsync(FinalizeContinuation OnFinalize);
134ef238923SStefan Gränitz 
135ee5e7a3aSStefan Gränitz   Error deallocate() {
136ee5e7a3aSStefan Gränitz     if (Alloc)
137ee5e7a3aSStefan Gränitz       return Alloc->deallocate();
138ee5e7a3aSStefan Gränitz     return Error::success();
139ee5e7a3aSStefan Gränitz   }
140ee5e7a3aSStefan Gränitz 
141ef238923SStefan Gränitz   virtual void reportSectionTargetMemoryRange(StringRef Name,
142ef238923SStefan Gränitz                                               SectionRange TargetMem) {}
143ef238923SStefan Gränitz 
144ef238923SStefan Gränitz protected:
145ef238923SStefan Gränitz   using Allocation = JITLinkMemoryManager::Allocation;
146ef238923SStefan Gränitz 
147ef238923SStefan Gränitz   virtual Expected<std::unique_ptr<Allocation>>
148ef238923SStefan Gränitz   finalizeWorkingMemory(JITLinkContext &Ctx) = 0;
149ef238923SStefan Gränitz 
150ef238923SStefan Gränitz private:
151ef238923SStefan Gränitz   JITLinkContext &Ctx;
152ef238923SStefan Gränitz   std::set<Requirement> Reqs;
153ef238923SStefan Gränitz   std::unique_ptr<Allocation> Alloc{nullptr};
154ef238923SStefan Gränitz };
155ef238923SStefan Gränitz 
156ef238923SStefan Gränitz // Finalize working memory and take ownership of the resulting allocation. Start
157ef238923SStefan Gränitz // copying memory over to the target and pass on the result once we're done.
158ef238923SStefan Gränitz // Ownership of the allocation remains with us for the rest of our lifetime.
159ef238923SStefan Gränitz void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
160ef238923SStefan Gränitz   assert(Alloc == nullptr && "Cannot finalize more than once");
161ef238923SStefan Gränitz 
162ef238923SStefan Gränitz   auto AllocOrErr = finalizeWorkingMemory(Ctx);
163ef238923SStefan Gränitz   if (!AllocOrErr)
164ef238923SStefan Gränitz     OnFinalize(AllocOrErr.takeError());
165ef238923SStefan Gränitz   Alloc = std::move(*AllocOrErr);
166ef238923SStefan Gränitz 
167ef238923SStefan Gränitz   Alloc->finalizeAsync([this, OnFinalize](Error Err) {
168ef238923SStefan Gränitz     if (Err)
169ef238923SStefan Gränitz       OnFinalize(std::move(Err));
170ef238923SStefan Gränitz     else
171ef238923SStefan Gränitz       OnFinalize(sys::MemoryBlock(
172ef238923SStefan Gränitz           jitTargetAddressToPointer<void *>(Alloc->getTargetMemory(ReadOnly)),
173ef238923SStefan Gränitz           Alloc->getWorkingMemory(ReadOnly).size()));
174ef238923SStefan Gränitz   });
175ef238923SStefan Gränitz }
176ef238923SStefan Gränitz 
177ef238923SStefan Gränitz /// The current implementation of ELFDebugObject replicates the approach used in
178ef238923SStefan Gränitz /// RuntimeDyld: It patches executable and data section headers in the given
179ef238923SStefan Gränitz /// object buffer with load-addresses of their corresponding sections in target
180ef238923SStefan Gränitz /// memory.
181ef238923SStefan Gränitz ///
182ef238923SStefan Gränitz class ELFDebugObject : public DebugObject {
183ef238923SStefan Gränitz public:
184ef238923SStefan Gränitz   static Expected<std::unique_ptr<DebugObject>> Create(MemoryBufferRef Buffer,
185ef238923SStefan Gränitz                                                        JITLinkContext &Ctx);
186ef238923SStefan Gränitz 
187ef238923SStefan Gränitz   void reportSectionTargetMemoryRange(StringRef Name,
188ef238923SStefan Gränitz                                       SectionRange TargetMem) override;
189ef238923SStefan Gränitz 
1907d18cd93SStefan Gränitz   StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
1917d18cd93SStefan Gränitz 
192ef238923SStefan Gränitz protected:
193ef238923SStefan Gränitz   Expected<std::unique_ptr<Allocation>>
194ef238923SStefan Gränitz   finalizeWorkingMemory(JITLinkContext &Ctx) override;
195ef238923SStefan Gränitz 
196265bc5afSStefan Gränitz   template <typename ELFT>
197ef238923SStefan Gränitz   Error recordSection(StringRef Name,
198265bc5afSStefan Gränitz                       std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
199ef238923SStefan Gränitz   DebugObjectSection *getSection(StringRef Name);
200ef238923SStefan Gränitz 
201ef238923SStefan Gränitz private:
202ef238923SStefan Gränitz   template <typename ELFT>
203ef238923SStefan Gränitz   static Expected<std::unique_ptr<ELFDebugObject>>
204ef238923SStefan Gränitz   CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx);
205ef238923SStefan Gränitz 
2067d18cd93SStefan Gränitz   static std::unique_ptr<WritableMemoryBuffer>
2077d18cd93SStefan Gränitz   CopyBuffer(MemoryBufferRef Buffer, Error &Err);
208ef238923SStefan Gränitz 
209ef238923SStefan Gränitz   ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
210ef238923SStefan Gränitz                  JITLinkContext &Ctx)
211ef238923SStefan Gränitz       : DebugObject(Ctx), Buffer(std::move(Buffer)) {
212ef238923SStefan Gränitz     set(Requirement::ReportFinalSectionLoadAddresses);
213ef238923SStefan Gränitz   }
214ef238923SStefan Gränitz 
215ef238923SStefan Gränitz   std::unique_ptr<WritableMemoryBuffer> Buffer;
216ef238923SStefan Gränitz   StringMap<std::unique_ptr<DebugObjectSection>> Sections;
217ef238923SStefan Gränitz };
218ef238923SStefan Gränitz 
219ef238923SStefan Gränitz static const std::set<StringRef> DwarfSectionNames = {
220ef238923SStefan Gränitz #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
221ef238923SStefan Gränitz   ELF_NAME,
222ef238923SStefan Gränitz #include "llvm/BinaryFormat/Dwarf.def"
223ef238923SStefan Gränitz #undef HANDLE_DWARF_SECTION
224ef238923SStefan Gränitz };
225ef238923SStefan Gränitz 
226ef238923SStefan Gränitz static bool isDwarfSection(StringRef SectionName) {
227ef238923SStefan Gränitz   return DwarfSectionNames.count(SectionName) == 1;
228ef238923SStefan Gränitz }
229ef238923SStefan Gränitz 
2307d18cd93SStefan Gränitz std::unique_ptr<WritableMemoryBuffer>
2317d18cd93SStefan Gränitz ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
2327d18cd93SStefan Gränitz   ErrorAsOutParameter _(&Err);
233ef238923SStefan Gränitz   size_t Size = Buffer.getBufferSize();
234ef238923SStefan Gränitz   StringRef Name = Buffer.getBufferIdentifier();
2357d18cd93SStefan Gränitz   if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
236ef238923SStefan Gränitz     memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
2377d18cd93SStefan Gränitz     return Copy;
2387d18cd93SStefan Gränitz   }
2397d18cd93SStefan Gränitz 
2407d18cd93SStefan Gränitz   Err = errorCodeToError(make_error_code(errc::not_enough_memory));
2417d18cd93SStefan Gränitz   return nullptr;
242ef238923SStefan Gränitz }
243ef238923SStefan Gränitz 
244ef238923SStefan Gränitz template <typename ELFT>
245ef238923SStefan Gränitz Expected<std::unique_ptr<ELFDebugObject>>
246ef238923SStefan Gränitz ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx) {
247ef238923SStefan Gränitz   using SectionHeader = typename ELFT::Shdr;
248ef238923SStefan Gränitz 
2497d18cd93SStefan Gränitz   Error Err = Error::success();
2507d18cd93SStefan Gränitz   std::unique_ptr<ELFDebugObject> DebugObj(
2517d18cd93SStefan Gränitz       new ELFDebugObject(CopyBuffer(Buffer, Err), Ctx));
2527d18cd93SStefan Gränitz   if (Err)
2537d18cd93SStefan Gränitz     return std::move(Err);
2547d18cd93SStefan Gränitz 
2557d18cd93SStefan Gränitz   Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
256ef238923SStefan Gränitz   if (!ObjRef)
257ef238923SStefan Gränitz     return ObjRef.takeError();
258ef238923SStefan Gränitz 
259ef238923SStefan Gränitz   // TODO: Add support for other architectures.
260ef238923SStefan Gränitz   uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
261ef238923SStefan Gränitz   if (TargetMachineArch != ELF::EM_X86_64)
262ef238923SStefan Gränitz     return nullptr;
263ef238923SStefan Gränitz 
264ef238923SStefan Gränitz   Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
265ef238923SStefan Gränitz   if (!Sections)
266ef238923SStefan Gränitz     return Sections.takeError();
267ef238923SStefan Gränitz 
268ef238923SStefan Gränitz   bool HasDwarfSection = false;
269ef238923SStefan Gränitz   for (const SectionHeader &Header : *Sections) {
270ef238923SStefan Gränitz     Expected<StringRef> Name = ObjRef->getSectionName(Header);
271ef238923SStefan Gränitz     if (!Name)
272ef238923SStefan Gränitz       return Name.takeError();
273ef238923SStefan Gränitz     if (Name->empty())
274ef238923SStefan Gränitz       continue;
275ef238923SStefan Gränitz     HasDwarfSection |= isDwarfSection(*Name);
276ef238923SStefan Gränitz 
277ef238923SStefan Gränitz     auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
278ef238923SStefan Gränitz     if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
279ef238923SStefan Gränitz       return std::move(Err);
280ef238923SStefan Gränitz   }
281ef238923SStefan Gränitz 
282ef238923SStefan Gränitz   if (!HasDwarfSection) {
283ef238923SStefan Gränitz     LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
284ef238923SStefan Gränitz                       << DebugObj->Buffer->getBufferIdentifier()
285ef238923SStefan Gränitz                       << "\": input object contains no debug info\n");
286ef238923SStefan Gränitz     return nullptr;
287ef238923SStefan Gränitz   }
288ef238923SStefan Gränitz 
289ef238923SStefan Gränitz   return std::move(DebugObj);
290ef238923SStefan Gränitz }
291ef238923SStefan Gränitz 
292ef238923SStefan Gränitz Expected<std::unique_ptr<DebugObject>>
293ef238923SStefan Gränitz ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx) {
294ef238923SStefan Gränitz   unsigned char Class, Endian;
295ef238923SStefan Gränitz   std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
296ef238923SStefan Gränitz 
297ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS32) {
298ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
299ef238923SStefan Gränitz       return CreateArchType<ELF32LE>(Buffer, Ctx);
300ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
301ef238923SStefan Gränitz       return CreateArchType<ELF32BE>(Buffer, Ctx);
302ef238923SStefan Gränitz     return nullptr;
303ef238923SStefan Gränitz   }
304ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS64) {
305ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
306ef238923SStefan Gränitz       return CreateArchType<ELF64LE>(Buffer, Ctx);
307ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
308ef238923SStefan Gränitz       return CreateArchType<ELF64BE>(Buffer, Ctx);
309ef238923SStefan Gränitz     return nullptr;
310ef238923SStefan Gränitz   }
311ef238923SStefan Gränitz   return nullptr;
312ef238923SStefan Gränitz }
313ef238923SStefan Gränitz 
314ef238923SStefan Gränitz Expected<std::unique_ptr<DebugObject::Allocation>>
315ef238923SStefan Gränitz ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) {
316ef238923SStefan Gränitz   LLVM_DEBUG({
317ef238923SStefan Gränitz     dbgs() << "Section load-addresses in debug object for \""
318ef238923SStefan Gränitz            << Buffer->getBufferIdentifier() << "\":\n";
319ef238923SStefan Gränitz     for (const auto &KV : Sections)
320ef238923SStefan Gränitz       KV.second->dump(dbgs(), KV.first());
321ef238923SStefan Gränitz   });
322ef238923SStefan Gränitz 
323ef238923SStefan Gränitz   // TODO: This works, but what actual alignment requirements do we have?
324ef238923SStefan Gränitz   unsigned Alignment = sys::Process::getPageSizeEstimate();
325ef238923SStefan Gränitz   JITLinkMemoryManager &MemMgr = Ctx.getMemoryManager();
326ef238923SStefan Gränitz   const JITLinkDylib *JD = Ctx.getJITLinkDylib();
327ef238923SStefan Gränitz   size_t Size = Buffer->getBufferSize();
328ef238923SStefan Gränitz 
329ef238923SStefan Gränitz   // Allocate working memory for debug object in read-only segment.
330a747e35cSStefan Gränitz   JITLinkMemoryManager::SegmentsRequestMap SingleReadOnlySegment;
331a747e35cSStefan Gränitz   SingleReadOnlySegment[ReadOnly] =
332a747e35cSStefan Gränitz       JITLinkMemoryManager::SegmentRequest(Alignment, Size, 0);
333a747e35cSStefan Gränitz 
334a747e35cSStefan Gränitz   auto AllocOrErr = MemMgr.allocate(JD, SingleReadOnlySegment);
335ef238923SStefan Gränitz   if (!AllocOrErr)
336ef238923SStefan Gränitz     return AllocOrErr.takeError();
337ef238923SStefan Gränitz 
338ef238923SStefan Gränitz   // Initialize working memory with a copy of our object buffer.
339ef238923SStefan Gränitz   // TODO: Use our buffer as working memory directly.
340ef238923SStefan Gränitz   std::unique_ptr<Allocation> Alloc = std::move(*AllocOrErr);
341ef238923SStefan Gränitz   MutableArrayRef<char> WorkingMem = Alloc->getWorkingMemory(ReadOnly);
342ef238923SStefan Gränitz   memcpy(WorkingMem.data(), Buffer->getBufferStart(), Size);
343ef238923SStefan Gränitz   Buffer.reset();
344ef238923SStefan Gränitz 
345ef238923SStefan Gränitz   return std::move(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;
359ef238923SStefan Gränitz   auto ItInserted = Sections.try_emplace(Name, std::move(Section));
360ef238923SStefan Gränitz   if (!ItInserted.second)
361ef238923SStefan Gränitz     return make_error<StringError>("Duplicate section",
362ef238923SStefan Gränitz                                    inconvertibleErrorCode());
363ef238923SStefan Gränitz   return Error::success();
364ef238923SStefan Gränitz }
365ef238923SStefan Gränitz 
366ef238923SStefan Gränitz DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
367ef238923SStefan Gränitz   auto It = Sections.find(Name);
368ef238923SStefan Gränitz   return It == Sections.end() ? nullptr : It->second.get();
369ef238923SStefan Gränitz }
370ef238923SStefan Gränitz 
371ef238923SStefan Gränitz static ResourceKey getResourceKey(MaterializationResponsibility &MR) {
372ef238923SStefan Gränitz   ResourceKey Key;
373ef238923SStefan Gränitz   if (auto Err = MR.withResourceKeyDo([&](ResourceKey K) { Key = K; })) {
374ef238923SStefan Gränitz     MR.getExecutionSession().reportError(std::move(Err));
375ef238923SStefan Gränitz     return ResourceKey{};
376ef238923SStefan Gränitz   }
377ef238923SStefan Gränitz   assert(Key && "Invalid key");
378ef238923SStefan Gränitz   return Key;
379ef238923SStefan Gränitz }
380ef238923SStefan Gränitz 
381ef238923SStefan Gränitz /// Creates a debug object based on the input object file from
382ef238923SStefan Gränitz /// ObjectLinkingLayerJITLinkContext.
383ef238923SStefan Gränitz ///
384ef238923SStefan Gränitz static Expected<std::unique_ptr<DebugObject>>
385ef238923SStefan Gränitz createDebugObjectFromBuffer(LinkGraph &G, JITLinkContext &Ctx,
386ef238923SStefan Gränitz                             MemoryBufferRef ObjBuffer) {
387ef238923SStefan Gränitz   switch (G.getTargetTriple().getObjectFormat()) {
388ef238923SStefan Gränitz   case Triple::ELF:
389ef238923SStefan Gränitz     return ELFDebugObject::Create(ObjBuffer, Ctx);
390ef238923SStefan Gränitz 
391ef238923SStefan Gränitz   default:
392ef238923SStefan Gränitz     // TODO: Once we add support for other formats, we might want to split this
393ef238923SStefan Gränitz     // into multiple files.
394ef238923SStefan Gränitz     return nullptr;
395ef238923SStefan Gränitz   }
396ef238923SStefan Gränitz }
397ef238923SStefan Gränitz 
398ef238923SStefan Gränitz DebugObjectManagerPlugin::DebugObjectManagerPlugin(
399ef238923SStefan Gränitz     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
400ef238923SStefan Gränitz     : ES(ES), Target(std::move(Target)) {}
401ef238923SStefan Gränitz 
402ee5e7a3aSStefan Gränitz DebugObjectManagerPlugin::~DebugObjectManagerPlugin() {
403ee5e7a3aSStefan Gränitz   for (auto &KV : PendingObjs) {
404ee5e7a3aSStefan Gränitz     std::unique_ptr<DebugObject> &DebugObj = KV.second;
405ee5e7a3aSStefan Gränitz     if (Error Err = DebugObj->deallocate())
406ee5e7a3aSStefan Gränitz       ES.reportError(std::move(Err));
407ee5e7a3aSStefan Gränitz   }
408ee5e7a3aSStefan Gränitz   for (auto &KV : RegisteredObjs) {
409ee5e7a3aSStefan Gränitz     for (std::unique_ptr<DebugObject> &DebugObj : KV.second)
410ee5e7a3aSStefan Gränitz       if (Error Err = DebugObj->deallocate())
411ee5e7a3aSStefan Gränitz         ES.reportError(std::move(Err));
412ee5e7a3aSStefan Gränitz   }
413ee5e7a3aSStefan Gränitz }
414ef238923SStefan Gränitz 
415ef238923SStefan Gränitz void DebugObjectManagerPlugin::notifyMaterializing(
416ef238923SStefan Gränitz     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
417ef238923SStefan Gränitz     MemoryBufferRef ObjBuffer) {
418ef238923SStefan Gränitz   assert(PendingObjs.count(getResourceKey(MR)) == 0 &&
419ef238923SStefan Gränitz          "Cannot have more than one pending debug object per "
420ef238923SStefan Gränitz          "MaterializationResponsibility");
421ef238923SStefan Gränitz 
422ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
423ef238923SStefan Gränitz   if (auto DebugObj = createDebugObjectFromBuffer(G, Ctx, ObjBuffer)) {
424ef238923SStefan Gränitz     // Not all link artifacts allow debugging.
425ef238923SStefan Gränitz     if (*DebugObj != nullptr) {
426ef238923SStefan Gränitz       ResourceKey Key = getResourceKey(MR);
427ef238923SStefan Gränitz       PendingObjs[Key] = std::move(*DebugObj);
428ef238923SStefan Gränitz     }
429ef238923SStefan Gränitz   } else {
430ef238923SStefan Gränitz     ES.reportError(DebugObj.takeError());
431ef238923SStefan Gränitz   }
432ef238923SStefan Gränitz }
433ef238923SStefan Gränitz 
434ef238923SStefan Gränitz void DebugObjectManagerPlugin::modifyPassConfig(
435*4e30b20bSLang Hames     MaterializationResponsibility &MR, LinkGraph &G,
436ef238923SStefan Gränitz     PassConfiguration &PassConfig) {
437ef238923SStefan Gränitz   // Not all link artifacts have associated debug objects.
438ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
439ef238923SStefan Gränitz   auto It = PendingObjs.find(getResourceKey(MR));
440ef238923SStefan Gränitz   if (It == PendingObjs.end())
441ef238923SStefan Gränitz     return;
442ef238923SStefan Gränitz 
443ef238923SStefan Gränitz   DebugObject &DebugObj = *It->second;
444ef238923SStefan Gränitz   if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
445ef238923SStefan Gränitz     PassConfig.PostAllocationPasses.push_back(
446ef238923SStefan Gränitz         [&DebugObj](LinkGraph &Graph) -> Error {
447ef238923SStefan Gränitz           for (const Section &GraphSection : Graph.sections())
448ef238923SStefan Gränitz             DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
449ef238923SStefan Gränitz                                                     SectionRange(GraphSection));
450ef238923SStefan Gränitz           return Error::success();
451ef238923SStefan Gränitz         });
452ef238923SStefan Gränitz   }
453ef238923SStefan Gränitz }
454ef238923SStefan Gränitz 
455ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyEmitted(
456ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
457ef238923SStefan Gränitz   ResourceKey Key = getResourceKey(MR);
458ef238923SStefan Gränitz 
459ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
460ef238923SStefan Gränitz   auto It = PendingObjs.find(Key);
461ef238923SStefan Gränitz   if (It == PendingObjs.end())
462ef238923SStefan Gränitz     return Error::success();
463ef238923SStefan Gränitz 
464ef238923SStefan Gränitz   DebugObject *UnownedDebugObj = It->second.release();
465ef238923SStefan Gränitz   PendingObjs.erase(It);
466ef238923SStefan Gränitz 
467ff52121bSStefan Gränitz   // During finalization the debug object is registered with the target.
468ff52121bSStefan Gränitz   // Materialization must wait for this process to finish. Otherwise we might
469ff52121bSStefan Gränitz   // start running code before the debugger processed the corresponding debug
470ff52121bSStefan Gränitz   // info.
471ff52121bSStefan Gränitz   std::promise<MSVCPError> FinalizePromise;
472ff52121bSStefan Gränitz   std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
473ff52121bSStefan Gränitz 
474ef238923SStefan Gränitz   // FIXME: We released ownership of the DebugObject, so we can easily capture
475ef238923SStefan Gränitz   // the raw pointer in the continuation function, which re-owns it immediately.
476ef238923SStefan Gränitz   if (UnownedDebugObj)
477ef238923SStefan Gränitz     UnownedDebugObj->finalizeAsync(
478ff52121bSStefan Gränitz         [this, Key, UnownedDebugObj,
479ff52121bSStefan Gränitz          &FinalizePromise](Expected<sys::MemoryBlock> TargetMem) {
480ef238923SStefan Gränitz           std::unique_ptr<DebugObject> ReownedDebugObj(UnownedDebugObj);
481ef238923SStefan Gränitz           if (!TargetMem) {
482ff52121bSStefan Gränitz             FinalizePromise.set_value(TargetMem.takeError());
483ef238923SStefan Gränitz             return;
484ef238923SStefan Gränitz           }
485ef238923SStefan Gränitz           if (Error Err = Target->registerDebugObject(*TargetMem)) {
486ff52121bSStefan Gränitz             FinalizePromise.set_value(std::move(Err));
487ef238923SStefan Gränitz             return;
488ef238923SStefan Gränitz           }
489ef238923SStefan Gränitz 
490ff52121bSStefan Gränitz           // Registration successful, notifyEmitted() can return now and
491ff52121bSStefan Gränitz           // materialization can finish.
492ff52121bSStefan Gränitz           FinalizePromise.set_value(Error::success());
493ff52121bSStefan Gränitz 
494ef238923SStefan Gränitz           std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
495ef238923SStefan Gränitz           RegisteredObjs[Key].push_back(std::move(ReownedDebugObj));
496ef238923SStefan Gränitz         });
497ef238923SStefan Gränitz 
498ff52121bSStefan Gränitz   return FinalizeErr.get();
499ef238923SStefan Gränitz }
500ef238923SStefan Gränitz 
501ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyFailed(
502ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
503ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
504ef238923SStefan Gränitz   PendingObjs.erase(getResourceKey(MR));
505ef238923SStefan Gränitz   return Error::success();
506ef238923SStefan Gränitz }
507ef238923SStefan Gränitz 
508ef238923SStefan Gränitz void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
509ef238923SStefan Gränitz                                                            ResourceKey SrcKey) {
510ef238923SStefan Gränitz   {
511ef238923SStefan Gränitz     std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
512ef238923SStefan Gränitz     auto SrcIt = RegisteredObjs.find(SrcKey);
513ef238923SStefan Gränitz     if (SrcIt != RegisteredObjs.end()) {
514ef238923SStefan Gränitz       // Resources from distinct MaterializationResponsibilitys can get merged
515ef238923SStefan Gränitz       // after emission, so we can have multiple debug objects per resource key.
516ef238923SStefan Gränitz       for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
517ef238923SStefan Gränitz         RegisteredObjs[DstKey].push_back(std::move(DebugObj));
518ef238923SStefan Gränitz       RegisteredObjs.erase(SrcIt);
519ef238923SStefan Gränitz     }
520ef238923SStefan Gränitz   }
521ef238923SStefan Gränitz   {
522ef238923SStefan Gränitz     std::lock_guard<std::mutex> Lock(PendingObjsLock);
523ef238923SStefan Gränitz     auto SrcIt = PendingObjs.find(SrcKey);
524ef238923SStefan Gränitz     if (SrcIt != PendingObjs.end()) {
525ef238923SStefan Gränitz       assert(PendingObjs.count(DstKey) == 0 &&
526ef238923SStefan Gränitz              "Cannot have more than one pending debug object per "
527ef238923SStefan Gränitz              "MaterializationResponsibility");
528ef238923SStefan Gränitz       PendingObjs[DstKey] = std::move(SrcIt->second);
529ef238923SStefan Gränitz       PendingObjs.erase(SrcIt);
530ef238923SStefan Gränitz     }
531ef238923SStefan Gränitz   }
532ef238923SStefan Gränitz }
533ef238923SStefan Gränitz 
534ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey K) {
535ef238923SStefan Gränitz   {
536ef238923SStefan Gränitz     std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
537ef238923SStefan Gränitz     RegisteredObjs.erase(K);
538ef238923SStefan Gränitz     // TODO: Implement unregister notifications.
539ef238923SStefan Gränitz   }
540ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
541ef238923SStefan Gränitz   PendingObjs.erase(K);
542ef238923SStefan Gränitz 
543ef238923SStefan Gränitz   return Error::success();
544ef238923SStefan Gränitz }
545ef238923SStefan Gränitz 
546ef238923SStefan Gränitz } // namespace orc
547ef238923SStefan Gränitz } // namespace llvm
548