xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1c0981da4SDimitry Andric //===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
2344a3780SDimitry Andric //
3344a3780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344a3780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5344a3780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344a3780SDimitry Andric //
7344a3780SDimitry Andric //===----------------------------------------------------------------------===//
8c0981da4SDimitry Andric //
9c0981da4SDimitry Andric // FIXME: Update Plugin to poke the debug object into a new JITLink section,
10c0981da4SDimitry Andric //        rather than creating a new allocation.
11c0981da4SDimitry Andric //
12c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
13344a3780SDimitry Andric 
14344a3780SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
15344a3780SDimitry Andric 
16344a3780SDimitry Andric #include "llvm/ADT/ArrayRef.h"
17344a3780SDimitry Andric #include "llvm/ADT/StringMap.h"
18344a3780SDimitry Andric #include "llvm/ADT/StringRef.h"
19344a3780SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
20344a3780SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21344a3780SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22344a3780SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h"
23344a3780SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
24344a3780SDimitry Andric #include "llvm/Object/ObjectFile.h"
25344a3780SDimitry Andric #include "llvm/Support/Errc.h"
26344a3780SDimitry Andric #include "llvm/Support/MSVCErrorWorkarounds.h"
27344a3780SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
28344a3780SDimitry Andric #include "llvm/Support/Process.h"
29344a3780SDimitry Andric #include "llvm/Support/raw_ostream.h"
30344a3780SDimitry Andric 
31344a3780SDimitry Andric #include <set>
32344a3780SDimitry Andric 
33344a3780SDimitry Andric #define DEBUG_TYPE "orc"
34344a3780SDimitry Andric 
35344a3780SDimitry Andric using namespace llvm::jitlink;
36344a3780SDimitry Andric using namespace llvm::object;
37344a3780SDimitry Andric 
38344a3780SDimitry Andric namespace llvm {
39344a3780SDimitry Andric namespace orc {
40344a3780SDimitry Andric 
41344a3780SDimitry Andric class DebugObjectSection {
42344a3780SDimitry Andric public:
43344a3780SDimitry Andric   virtual void setTargetMemoryRange(SectionRange Range) = 0;
dump(raw_ostream & OS,StringRef Name)44344a3780SDimitry Andric   virtual void dump(raw_ostream &OS, StringRef Name) {}
45145449b1SDimitry Andric   virtual ~DebugObjectSection() = default;
46344a3780SDimitry Andric };
47344a3780SDimitry Andric 
48344a3780SDimitry Andric template <typename ELFT>
49344a3780SDimitry Andric class ELFDebugObjectSection : public DebugObjectSection {
50344a3780SDimitry Andric public:
51344a3780SDimitry Andric   // BinaryFormat ELF is not meant as a mutable format. We can only make changes
52344a3780SDimitry Andric   // that don't invalidate the file structure.
ELFDebugObjectSection(const typename ELFT::Shdr * Header)53344a3780SDimitry Andric   ELFDebugObjectSection(const typename ELFT::Shdr *Header)
54344a3780SDimitry Andric       : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
55344a3780SDimitry Andric 
56344a3780SDimitry Andric   void setTargetMemoryRange(SectionRange Range) override;
57344a3780SDimitry Andric   void dump(raw_ostream &OS, StringRef Name) override;
58344a3780SDimitry Andric 
59344a3780SDimitry Andric   Error validateInBounds(StringRef Buffer, const char *Name) const;
60344a3780SDimitry Andric 
61344a3780SDimitry Andric private:
62344a3780SDimitry Andric   typename ELFT::Shdr *Header;
63344a3780SDimitry Andric };
64344a3780SDimitry Andric 
65344a3780SDimitry Andric template <typename ELFT>
setTargetMemoryRange(SectionRange Range)66344a3780SDimitry Andric void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
677fa27ce4SDimitry Andric   // All recorded sections are candidates for load-address patching.
686f8fc217SDimitry Andric   Header->sh_addr =
696f8fc217SDimitry Andric       static_cast<typename ELFT::uint>(Range.getStart().getValue());
70344a3780SDimitry Andric }
71344a3780SDimitry Andric 
72344a3780SDimitry Andric template <typename ELFT>
validateInBounds(StringRef Buffer,const char * Name) const73344a3780SDimitry Andric Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
74344a3780SDimitry Andric                                                     const char *Name) const {
75344a3780SDimitry Andric   const uint8_t *Start = Buffer.bytes_begin();
76344a3780SDimitry Andric   const uint8_t *End = Buffer.bytes_end();
77344a3780SDimitry Andric   const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
78344a3780SDimitry Andric   if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
79344a3780SDimitry Andric     return make_error<StringError>(
80344a3780SDimitry Andric         formatv("{0} section header at {1:x16} not within bounds of the "
81344a3780SDimitry Andric                 "given debug object buffer [{2:x16} - {3:x16}]",
82344a3780SDimitry Andric                 Name, &Header->sh_addr, Start, End),
83344a3780SDimitry Andric         inconvertibleErrorCode());
84344a3780SDimitry Andric   if (Header->sh_offset + Header->sh_size > Buffer.size())
85344a3780SDimitry Andric     return make_error<StringError>(
86344a3780SDimitry Andric         formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
87344a3780SDimitry Andric                 "the given debug object buffer [{3:x16} - {4:x16}]",
88344a3780SDimitry Andric                 Name, Start + Header->sh_offset,
89344a3780SDimitry Andric                 Start + Header->sh_offset + Header->sh_size, Start, End),
90344a3780SDimitry Andric         inconvertibleErrorCode());
91344a3780SDimitry Andric   return Error::success();
92344a3780SDimitry Andric }
93344a3780SDimitry Andric 
94344a3780SDimitry Andric template <typename ELFT>
dump(raw_ostream & OS,StringRef Name)95344a3780SDimitry Andric void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
967fa27ce4SDimitry Andric   if (uint64_t Addr = Header->sh_addr) {
97344a3780SDimitry Andric     OS << formatv("  {0:x16} {1}\n", Addr, Name);
98344a3780SDimitry Andric   } else {
99344a3780SDimitry Andric     OS << formatv("                     {0}\n", Name);
100344a3780SDimitry Andric   }
101344a3780SDimitry Andric }
102344a3780SDimitry Andric 
1037fa27ce4SDimitry Andric enum DebugObjectFlags : int {
104344a3780SDimitry Andric   // Request final target memory load-addresses for all sections.
1057fa27ce4SDimitry Andric   ReportFinalSectionLoadAddresses = 1 << 0,
1067fa27ce4SDimitry Andric 
1077fa27ce4SDimitry Andric   // We found sections with debug information when processing the input object.
1087fa27ce4SDimitry Andric   HasDebugSections = 1 << 1,
109344a3780SDimitry Andric };
110344a3780SDimitry Andric 
111c0981da4SDimitry Andric /// The plugin creates a debug object from when JITLink starts processing the
112c0981da4SDimitry Andric /// corresponding LinkGraph. It provides access to the pass configuration of
113c0981da4SDimitry Andric /// the LinkGraph and calls the finalization function, once the resulting link
114c0981da4SDimitry Andric /// artifact was emitted.
115344a3780SDimitry Andric ///
116344a3780SDimitry Andric class DebugObject {
117344a3780SDimitry Andric public:
DebugObject(JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)118c0981da4SDimitry Andric   DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
119c0981da4SDimitry Andric               ExecutionSession &ES)
1207fa27ce4SDimitry Andric       : MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
121344a3780SDimitry Andric 
hasFlags(DebugObjectFlags F) const1227fa27ce4SDimitry Andric   bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
setFlags(DebugObjectFlags F)1237fa27ce4SDimitry Andric   void setFlags(DebugObjectFlags F) {
1247fa27ce4SDimitry Andric     Flags = static_cast<DebugObjectFlags>(Flags | F);
1257fa27ce4SDimitry Andric   }
clearFlags(DebugObjectFlags F)1267fa27ce4SDimitry Andric   void clearFlags(DebugObjectFlags F) {
1277fa27ce4SDimitry Andric     Flags = static_cast<DebugObjectFlags>(Flags & ~F);
1287fa27ce4SDimitry Andric   }
129344a3780SDimitry Andric 
130c0981da4SDimitry Andric   using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
131c0981da4SDimitry Andric 
132344a3780SDimitry Andric   void finalizeAsync(FinalizeContinuation OnFinalize);
133344a3780SDimitry Andric 
~DebugObject()134344a3780SDimitry Andric   virtual ~DebugObject() {
135c0981da4SDimitry Andric     if (Alloc) {
136c0981da4SDimitry Andric       std::vector<FinalizedAlloc> Allocs;
137c0981da4SDimitry Andric       Allocs.push_back(std::move(Alloc));
138c0981da4SDimitry Andric       if (Error Err = MemMgr.deallocate(std::move(Allocs)))
139344a3780SDimitry Andric         ES.reportError(std::move(Err));
140344a3780SDimitry Andric     }
141c0981da4SDimitry Andric   }
142344a3780SDimitry Andric 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)143344a3780SDimitry Andric   virtual void reportSectionTargetMemoryRange(StringRef Name,
144344a3780SDimitry Andric                                               SectionRange TargetMem) {}
145344a3780SDimitry Andric 
146344a3780SDimitry Andric protected:
147c0981da4SDimitry Andric   using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
148c0981da4SDimitry Andric   using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
149344a3780SDimitry Andric 
150c0981da4SDimitry Andric   virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
151c0981da4SDimitry Andric 
152c0981da4SDimitry Andric   JITLinkMemoryManager &MemMgr;
153c0981da4SDimitry Andric   const JITLinkDylib *JD = nullptr;
154344a3780SDimitry Andric 
155344a3780SDimitry Andric private:
156344a3780SDimitry Andric   ExecutionSession &ES;
1577fa27ce4SDimitry Andric   DebugObjectFlags Flags;
158c0981da4SDimitry Andric   FinalizedAlloc Alloc;
159344a3780SDimitry Andric };
160344a3780SDimitry Andric 
161344a3780SDimitry Andric // Finalize working memory and take ownership of the resulting allocation. Start
162344a3780SDimitry Andric // copying memory over to the target and pass on the result once we're done.
163344a3780SDimitry Andric // Ownership of the allocation remains with us for the rest of our lifetime.
finalizeAsync(FinalizeContinuation OnFinalize)164344a3780SDimitry Andric void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
165c0981da4SDimitry Andric   assert(!Alloc && "Cannot finalize more than once");
166344a3780SDimitry Andric 
167c0981da4SDimitry Andric   if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
168c0981da4SDimitry Andric     auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
1697fa27ce4SDimitry Andric     ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
170c0981da4SDimitry Andric     SimpleSegAlloc->finalize(
171c0981da4SDimitry Andric         [this, DebugObjRange,
172c0981da4SDimitry Andric          OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
173c0981da4SDimitry Andric           if (FA) {
174c0981da4SDimitry Andric             Alloc = std::move(*FA);
175c0981da4SDimitry Andric             OnFinalize(DebugObjRange);
176c0981da4SDimitry Andric           } else
177c0981da4SDimitry Andric             OnFinalize(FA.takeError());
178344a3780SDimitry Andric         });
179c0981da4SDimitry Andric   } else
180c0981da4SDimitry Andric     OnFinalize(SimpleSegAlloc.takeError());
181344a3780SDimitry Andric }
182344a3780SDimitry Andric 
183344a3780SDimitry Andric /// The current implementation of ELFDebugObject replicates the approach used in
184344a3780SDimitry Andric /// RuntimeDyld: It patches executable and data section headers in the given
185344a3780SDimitry Andric /// object buffer with load-addresses of their corresponding sections in target
186344a3780SDimitry Andric /// memory.
187344a3780SDimitry Andric ///
188344a3780SDimitry Andric class ELFDebugObject : public DebugObject {
189344a3780SDimitry Andric public:
190344a3780SDimitry Andric   static Expected<std::unique_ptr<DebugObject>>
191344a3780SDimitry Andric   Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
192344a3780SDimitry Andric 
193344a3780SDimitry Andric   void reportSectionTargetMemoryRange(StringRef Name,
194344a3780SDimitry Andric                                       SectionRange TargetMem) override;
195344a3780SDimitry Andric 
getBuffer() const196344a3780SDimitry Andric   StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
197344a3780SDimitry Andric 
198344a3780SDimitry Andric protected:
199c0981da4SDimitry Andric   Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
200344a3780SDimitry Andric 
201344a3780SDimitry Andric   template <typename ELFT>
202344a3780SDimitry Andric   Error recordSection(StringRef Name,
203344a3780SDimitry Andric                       std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
204344a3780SDimitry Andric   DebugObjectSection *getSection(StringRef Name);
205344a3780SDimitry Andric 
206344a3780SDimitry Andric private:
207344a3780SDimitry Andric   template <typename ELFT>
208344a3780SDimitry Andric   static Expected<std::unique_ptr<ELFDebugObject>>
209c0981da4SDimitry Andric   CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
210c0981da4SDimitry Andric                  const JITLinkDylib *JD, ExecutionSession &ES);
211344a3780SDimitry Andric 
212344a3780SDimitry Andric   static std::unique_ptr<WritableMemoryBuffer>
213344a3780SDimitry Andric   CopyBuffer(MemoryBufferRef Buffer, Error &Err);
214344a3780SDimitry Andric 
ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)215344a3780SDimitry Andric   ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
216c0981da4SDimitry Andric                  JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
217c0981da4SDimitry Andric                  ExecutionSession &ES)
218c0981da4SDimitry Andric       : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
2197fa27ce4SDimitry Andric     setFlags(ReportFinalSectionLoadAddresses);
220344a3780SDimitry Andric   }
221344a3780SDimitry Andric 
222344a3780SDimitry Andric   std::unique_ptr<WritableMemoryBuffer> Buffer;
223344a3780SDimitry Andric   StringMap<std::unique_ptr<DebugObjectSection>> Sections;
224344a3780SDimitry Andric };
225344a3780SDimitry Andric 
226344a3780SDimitry Andric static const std::set<StringRef> DwarfSectionNames = {
227344a3780SDimitry Andric #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
228344a3780SDimitry Andric   ELF_NAME,
229344a3780SDimitry Andric #include "llvm/BinaryFormat/Dwarf.def"
230344a3780SDimitry Andric #undef HANDLE_DWARF_SECTION
231344a3780SDimitry Andric };
232344a3780SDimitry Andric 
isDwarfSection(StringRef SectionName)233344a3780SDimitry Andric static bool isDwarfSection(StringRef SectionName) {
234344a3780SDimitry Andric   return DwarfSectionNames.count(SectionName) == 1;
235344a3780SDimitry Andric }
236344a3780SDimitry Andric 
237344a3780SDimitry Andric std::unique_ptr<WritableMemoryBuffer>
CopyBuffer(MemoryBufferRef Buffer,Error & Err)238344a3780SDimitry Andric ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
239344a3780SDimitry Andric   ErrorAsOutParameter _(&Err);
240344a3780SDimitry Andric   size_t Size = Buffer.getBufferSize();
241344a3780SDimitry Andric   StringRef Name = Buffer.getBufferIdentifier();
242344a3780SDimitry Andric   if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
243344a3780SDimitry Andric     memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
244344a3780SDimitry Andric     return Copy;
245344a3780SDimitry Andric   }
246344a3780SDimitry Andric 
247344a3780SDimitry Andric   Err = errorCodeToError(make_error_code(errc::not_enough_memory));
248344a3780SDimitry Andric   return nullptr;
249344a3780SDimitry Andric }
250344a3780SDimitry Andric 
251344a3780SDimitry Andric template <typename ELFT>
252344a3780SDimitry Andric Expected<std::unique_ptr<ELFDebugObject>>
CreateArchType(MemoryBufferRef Buffer,JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)253c0981da4SDimitry Andric ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
254c0981da4SDimitry Andric                                JITLinkMemoryManager &MemMgr,
255c0981da4SDimitry Andric                                const JITLinkDylib *JD, ExecutionSession &ES) {
256344a3780SDimitry Andric   using SectionHeader = typename ELFT::Shdr;
257344a3780SDimitry Andric 
258344a3780SDimitry Andric   Error Err = Error::success();
259344a3780SDimitry Andric   std::unique_ptr<ELFDebugObject> DebugObj(
260c0981da4SDimitry Andric       new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
261344a3780SDimitry Andric   if (Err)
262344a3780SDimitry Andric     return std::move(Err);
263344a3780SDimitry Andric 
264344a3780SDimitry Andric   Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
265344a3780SDimitry Andric   if (!ObjRef)
266344a3780SDimitry Andric     return ObjRef.takeError();
267344a3780SDimitry Andric 
268344a3780SDimitry Andric   Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
269344a3780SDimitry Andric   if (!Sections)
270344a3780SDimitry Andric     return Sections.takeError();
271344a3780SDimitry Andric 
272344a3780SDimitry Andric   for (const SectionHeader &Header : *Sections) {
273344a3780SDimitry Andric     Expected<StringRef> Name = ObjRef->getSectionName(Header);
274344a3780SDimitry Andric     if (!Name)
275344a3780SDimitry Andric       return Name.takeError();
276344a3780SDimitry Andric     if (Name->empty())
277344a3780SDimitry Andric       continue;
2787fa27ce4SDimitry Andric     if (isDwarfSection(*Name))
2797fa27ce4SDimitry Andric       DebugObj->setFlags(HasDebugSections);
280344a3780SDimitry Andric 
2817fa27ce4SDimitry Andric     // Only record text and data sections (i.e. no bss, comments, rel, etc.)
2827fa27ce4SDimitry Andric     if (Header.sh_type != ELF::SHT_PROGBITS &&
2837fa27ce4SDimitry Andric         Header.sh_type != ELF::SHT_X86_64_UNWIND)
2847fa27ce4SDimitry Andric       continue;
285e3b55780SDimitry Andric     if (!(Header.sh_flags & ELF::SHF_ALLOC))
286e3b55780SDimitry Andric       continue;
287e3b55780SDimitry Andric 
288344a3780SDimitry Andric     auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
289344a3780SDimitry Andric     if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
290344a3780SDimitry Andric       return std::move(Err);
291344a3780SDimitry Andric   }
292344a3780SDimitry Andric 
293344a3780SDimitry Andric   return std::move(DebugObj);
294344a3780SDimitry Andric }
295344a3780SDimitry Andric 
296344a3780SDimitry Andric Expected<std::unique_ptr<DebugObject>>
Create(MemoryBufferRef Buffer,JITLinkContext & Ctx,ExecutionSession & ES)297344a3780SDimitry Andric ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
298344a3780SDimitry Andric                        ExecutionSession &ES) {
299344a3780SDimitry Andric   unsigned char Class, Endian;
300344a3780SDimitry Andric   std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
301344a3780SDimitry Andric 
302344a3780SDimitry Andric   if (Class == ELF::ELFCLASS32) {
303344a3780SDimitry Andric     if (Endian == ELF::ELFDATA2LSB)
304c0981da4SDimitry Andric       return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
305c0981da4SDimitry Andric                                      Ctx.getJITLinkDylib(), ES);
306344a3780SDimitry Andric     if (Endian == ELF::ELFDATA2MSB)
307c0981da4SDimitry Andric       return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
308c0981da4SDimitry Andric                                      Ctx.getJITLinkDylib(), ES);
309344a3780SDimitry Andric     return nullptr;
310344a3780SDimitry Andric   }
311344a3780SDimitry Andric   if (Class == ELF::ELFCLASS64) {
312344a3780SDimitry Andric     if (Endian == ELF::ELFDATA2LSB)
313c0981da4SDimitry Andric       return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
314c0981da4SDimitry Andric                                      Ctx.getJITLinkDylib(), ES);
315344a3780SDimitry Andric     if (Endian == ELF::ELFDATA2MSB)
316c0981da4SDimitry Andric       return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
317c0981da4SDimitry Andric                                      Ctx.getJITLinkDylib(), ES);
318344a3780SDimitry Andric     return nullptr;
319344a3780SDimitry Andric   }
320344a3780SDimitry Andric   return nullptr;
321344a3780SDimitry Andric }
322344a3780SDimitry Andric 
finalizeWorkingMemory()323c0981da4SDimitry Andric Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
324344a3780SDimitry Andric   LLVM_DEBUG({
325344a3780SDimitry Andric     dbgs() << "Section load-addresses in debug object for \""
326344a3780SDimitry Andric            << Buffer->getBufferIdentifier() << "\":\n";
327344a3780SDimitry Andric     for (const auto &KV : Sections)
328344a3780SDimitry Andric       KV.second->dump(dbgs(), KV.first());
329344a3780SDimitry Andric   });
330344a3780SDimitry Andric 
331344a3780SDimitry Andric   // TODO: This works, but what actual alignment requirements do we have?
332c0981da4SDimitry Andric   unsigned PageSize = sys::Process::getPageSizeEstimate();
333344a3780SDimitry Andric   size_t Size = Buffer->getBufferSize();
334344a3780SDimitry Andric 
335344a3780SDimitry Andric   // Allocate working memory for debug object in read-only segment.
336c0981da4SDimitry Andric   auto Alloc = SimpleSegmentAlloc::Create(
337c0981da4SDimitry Andric       MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}});
338c0981da4SDimitry Andric   if (!Alloc)
339c0981da4SDimitry Andric     return Alloc;
340344a3780SDimitry Andric 
341344a3780SDimitry Andric   // Initialize working memory with a copy of our object buffer.
342c0981da4SDimitry Andric   auto SegInfo = Alloc->getSegInfo(MemProt::Read);
343c0981da4SDimitry Andric   memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
344344a3780SDimitry Andric   Buffer.reset();
345344a3780SDimitry Andric 
346c0981da4SDimitry Andric   return Alloc;
347344a3780SDimitry Andric }
348344a3780SDimitry Andric 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)349344a3780SDimitry Andric void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
350344a3780SDimitry Andric                                                     SectionRange TargetMem) {
351344a3780SDimitry Andric   if (auto *DebugObjSection = getSection(Name))
352344a3780SDimitry Andric     DebugObjSection->setTargetMemoryRange(TargetMem);
353344a3780SDimitry Andric }
354344a3780SDimitry Andric 
355344a3780SDimitry Andric template <typename ELFT>
recordSection(StringRef Name,std::unique_ptr<ELFDebugObjectSection<ELFT>> Section)356344a3780SDimitry Andric Error ELFDebugObject::recordSection(
357344a3780SDimitry Andric     StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
358344a3780SDimitry Andric   if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
359344a3780SDimitry Andric     return Err;
3607fa27ce4SDimitry Andric   bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
3617fa27ce4SDimitry Andric   if (!Inserted)
3627fa27ce4SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
3637fa27ce4SDimitry Andric                       << "' in object " << Buffer->getBufferIdentifier()
3647fa27ce4SDimitry Andric                       << " (duplicate name)\n");
365344a3780SDimitry Andric   return Error::success();
366344a3780SDimitry Andric }
367344a3780SDimitry Andric 
getSection(StringRef Name)368344a3780SDimitry Andric DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
369344a3780SDimitry Andric   auto It = Sections.find(Name);
370344a3780SDimitry Andric   return It == Sections.end() ? nullptr : It->second.get();
371344a3780SDimitry Andric }
372344a3780SDimitry Andric 
373344a3780SDimitry Andric /// Creates a debug object based on the input object file from
374344a3780SDimitry Andric /// ObjectLinkingLayerJITLinkContext.
375344a3780SDimitry Andric ///
376344a3780SDimitry Andric static Expected<std::unique_ptr<DebugObject>>
createDebugObjectFromBuffer(ExecutionSession & ES,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)377344a3780SDimitry Andric createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
378344a3780SDimitry Andric                             JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
379344a3780SDimitry Andric   switch (G.getTargetTriple().getObjectFormat()) {
380344a3780SDimitry Andric   case Triple::ELF:
381344a3780SDimitry Andric     return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
382344a3780SDimitry Andric 
383344a3780SDimitry Andric   default:
384344a3780SDimitry Andric     // TODO: Once we add support for other formats, we might want to split this
385344a3780SDimitry Andric     // into multiple files.
386344a3780SDimitry Andric     return nullptr;
387344a3780SDimitry Andric   }
388344a3780SDimitry Andric }
389344a3780SDimitry Andric 
DebugObjectManagerPlugin(ExecutionSession & ES,std::unique_ptr<DebugObjectRegistrar> Target,bool RequireDebugSections,bool AutoRegisterCode)390344a3780SDimitry Andric DebugObjectManagerPlugin::DebugObjectManagerPlugin(
3917fa27ce4SDimitry Andric     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
3927fa27ce4SDimitry Andric     bool RequireDebugSections, bool AutoRegisterCode)
3937fa27ce4SDimitry Andric     : ES(ES), Target(std::move(Target)),
3947fa27ce4SDimitry Andric       RequireDebugSections(RequireDebugSections),
3957fa27ce4SDimitry Andric       AutoRegisterCode(AutoRegisterCode) {}
3967fa27ce4SDimitry Andric 
DebugObjectManagerPlugin(ExecutionSession & ES,std::unique_ptr<DebugObjectRegistrar> Target)3977fa27ce4SDimitry Andric DebugObjectManagerPlugin::DebugObjectManagerPlugin(
398344a3780SDimitry Andric     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
3997fa27ce4SDimitry Andric     : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
400344a3780SDimitry Andric 
401344a3780SDimitry Andric DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
402344a3780SDimitry Andric 
notifyMaterializing(MaterializationResponsibility & MR,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)403344a3780SDimitry Andric void DebugObjectManagerPlugin::notifyMaterializing(
404344a3780SDimitry Andric     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
405344a3780SDimitry Andric     MemoryBufferRef ObjBuffer) {
406344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(PendingObjsLock);
407344a3780SDimitry Andric   assert(PendingObjs.count(&MR) == 0 &&
408344a3780SDimitry Andric          "Cannot have more than one pending debug object per "
409344a3780SDimitry Andric          "MaterializationResponsibility");
410344a3780SDimitry Andric 
411344a3780SDimitry Andric   if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
412344a3780SDimitry Andric     // Not all link artifacts allow debugging.
4137fa27ce4SDimitry Andric     if (*DebugObj == nullptr)
4147fa27ce4SDimitry Andric       return;
4157fa27ce4SDimitry Andric     if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
4167fa27ce4SDimitry Andric       LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
4177fa27ce4SDimitry Andric                         << G.getName() << "': no debug info\n");
4187fa27ce4SDimitry Andric       return;
4197fa27ce4SDimitry Andric     }
420344a3780SDimitry Andric     PendingObjs[&MR] = std::move(*DebugObj);
421344a3780SDimitry Andric   } else {
422344a3780SDimitry Andric     ES.reportError(DebugObj.takeError());
423344a3780SDimitry Andric   }
424344a3780SDimitry Andric }
425344a3780SDimitry Andric 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)426344a3780SDimitry Andric void DebugObjectManagerPlugin::modifyPassConfig(
427344a3780SDimitry Andric     MaterializationResponsibility &MR, LinkGraph &G,
428344a3780SDimitry Andric     PassConfiguration &PassConfig) {
429344a3780SDimitry Andric   // Not all link artifacts have associated debug objects.
430344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(PendingObjsLock);
431344a3780SDimitry Andric   auto It = PendingObjs.find(&MR);
432344a3780SDimitry Andric   if (It == PendingObjs.end())
433344a3780SDimitry Andric     return;
434344a3780SDimitry Andric 
435344a3780SDimitry Andric   DebugObject &DebugObj = *It->second;
4367fa27ce4SDimitry Andric   if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
437344a3780SDimitry Andric     PassConfig.PostAllocationPasses.push_back(
438344a3780SDimitry Andric         [&DebugObj](LinkGraph &Graph) -> Error {
439344a3780SDimitry Andric           for (const Section &GraphSection : Graph.sections())
440344a3780SDimitry Andric             DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
441344a3780SDimitry Andric                                                     SectionRange(GraphSection));
442344a3780SDimitry Andric           return Error::success();
443344a3780SDimitry Andric         });
444344a3780SDimitry Andric   }
445344a3780SDimitry Andric }
446344a3780SDimitry Andric 
notifyEmitted(MaterializationResponsibility & MR)447344a3780SDimitry Andric Error DebugObjectManagerPlugin::notifyEmitted(
448344a3780SDimitry Andric     MaterializationResponsibility &MR) {
449344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(PendingObjsLock);
450344a3780SDimitry Andric   auto It = PendingObjs.find(&MR);
451344a3780SDimitry Andric   if (It == PendingObjs.end())
452344a3780SDimitry Andric     return Error::success();
453344a3780SDimitry Andric 
454344a3780SDimitry Andric   // During finalization the debug object is registered with the target.
455344a3780SDimitry Andric   // Materialization must wait for this process to finish. Otherwise we might
456344a3780SDimitry Andric   // start running code before the debugger processed the corresponding debug
457344a3780SDimitry Andric   // info.
458344a3780SDimitry Andric   std::promise<MSVCPError> FinalizePromise;
459344a3780SDimitry Andric   std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
460344a3780SDimitry Andric 
461344a3780SDimitry Andric   It->second->finalizeAsync(
462c0981da4SDimitry Andric       [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
463344a3780SDimitry Andric         // Any failure here will fail materialization.
464344a3780SDimitry Andric         if (!TargetMem) {
465344a3780SDimitry Andric           FinalizePromise.set_value(TargetMem.takeError());
466344a3780SDimitry Andric           return;
467344a3780SDimitry Andric         }
4687fa27ce4SDimitry Andric         if (Error Err =
4697fa27ce4SDimitry Andric                 Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
470344a3780SDimitry Andric           FinalizePromise.set_value(std::move(Err));
471344a3780SDimitry Andric           return;
472344a3780SDimitry Andric         }
473344a3780SDimitry Andric 
474344a3780SDimitry Andric         // Once our tracking info is updated, notifyEmitted() can return and
475344a3780SDimitry Andric         // finish materialization.
476344a3780SDimitry Andric         FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
477344a3780SDimitry Andric           assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
478344a3780SDimitry Andric           std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
479344a3780SDimitry Andric           RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
480344a3780SDimitry Andric           PendingObjs.erase(&MR);
481344a3780SDimitry Andric         }));
482344a3780SDimitry Andric       });
483344a3780SDimitry Andric 
484344a3780SDimitry Andric   return FinalizeErr.get();
485344a3780SDimitry Andric }
486344a3780SDimitry Andric 
notifyFailed(MaterializationResponsibility & MR)487344a3780SDimitry Andric Error DebugObjectManagerPlugin::notifyFailed(
488344a3780SDimitry Andric     MaterializationResponsibility &MR) {
489344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(PendingObjsLock);
490344a3780SDimitry Andric   PendingObjs.erase(&MR);
491344a3780SDimitry Andric   return Error::success();
492344a3780SDimitry Andric }
493344a3780SDimitry Andric 
notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)494e3b55780SDimitry Andric void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
495e3b55780SDimitry Andric                                                            ResourceKey DstKey,
496344a3780SDimitry Andric                                                            ResourceKey SrcKey) {
497344a3780SDimitry Andric   // Debug objects are stored by ResourceKey only after registration.
498344a3780SDimitry Andric   // Thus, pending objects don't need to be updated here.
499344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
500344a3780SDimitry Andric   auto SrcIt = RegisteredObjs.find(SrcKey);
501344a3780SDimitry Andric   if (SrcIt != RegisteredObjs.end()) {
502344a3780SDimitry Andric     // Resources from distinct MaterializationResponsibilitys can get merged
503344a3780SDimitry Andric     // after emission, so we can have multiple debug objects per resource key.
504344a3780SDimitry Andric     for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
505344a3780SDimitry Andric       RegisteredObjs[DstKey].push_back(std::move(DebugObj));
506344a3780SDimitry Andric     RegisteredObjs.erase(SrcIt);
507344a3780SDimitry Andric   }
508344a3780SDimitry Andric }
509344a3780SDimitry Andric 
notifyRemovingResources(JITDylib & JD,ResourceKey Key)510e3b55780SDimitry Andric Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
511e3b55780SDimitry Andric                                                         ResourceKey Key) {
512344a3780SDimitry Andric   // Removing the resource for a pending object fails materialization, so they
513344a3780SDimitry Andric   // get cleaned up in the notifyFailed() handler.
514344a3780SDimitry Andric   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
515344a3780SDimitry Andric   RegisteredObjs.erase(Key);
516344a3780SDimitry Andric 
517344a3780SDimitry Andric   // TODO: Implement unregister notifications.
518344a3780SDimitry Andric   return Error::success();
519344a3780SDimitry Andric }
520344a3780SDimitry Andric 
521344a3780SDimitry Andric } // namespace orc
522344a3780SDimitry Andric } // namespace llvm
523