1962a2479SLang Hames //===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===//
2ef238923SStefan Gränitz //
3ef238923SStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ef238923SStefan Gränitz // See https://llvm.org/LICENSE.txt for license information.
5ef238923SStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef238923SStefan Gränitz //
7ef238923SStefan Gränitz //===----------------------------------------------------------------------===//
8962a2479SLang Hames //
9962a2479SLang Hames // FIXME: Update Plugin to poke the debug object into a new JITLink section,
10962a2479SLang Hames //        rather than creating a new allocation.
11962a2479SLang Hames //
12962a2479SLang Hames //===----------------------------------------------------------------------===//
13ef238923SStefan Gränitz 
14ef238923SStefan Gränitz #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
15ef238923SStefan Gränitz 
16ef238923SStefan Gränitz #include "llvm/ADT/ArrayRef.h"
17ef238923SStefan Gränitz #include "llvm/ADT/StringMap.h"
18ef238923SStefan Gränitz #include "llvm/ADT/StringRef.h"
19ef238923SStefan Gränitz #include "llvm/BinaryFormat/ELF.h"
20ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
22ef238923SStefan Gränitz #include "llvm/ExecutionEngine/JITSymbol.h"
23ef238923SStefan Gränitz #include "llvm/Object/ELFObjectFile.h"
24ef238923SStefan Gränitz #include "llvm/Object/ObjectFile.h"
25ef238923SStefan Gränitz #include "llvm/Support/Errc.h"
26ff52121bSStefan Gränitz #include "llvm/Support/MSVCErrorWorkarounds.h"
27ef238923SStefan Gränitz #include "llvm/Support/MemoryBuffer.h"
28ef238923SStefan Gränitz #include "llvm/Support/Process.h"
29ef238923SStefan Gränitz #include "llvm/Support/raw_ostream.h"
30ef238923SStefan Gränitz 
31ef238923SStefan Gränitz #include <set>
32ef238923SStefan Gränitz 
33ef238923SStefan Gränitz #define DEBUG_TYPE "orc"
34ef238923SStefan Gränitz 
35ef238923SStefan Gränitz using namespace llvm::jitlink;
36ef238923SStefan Gränitz using namespace llvm::object;
37ef238923SStefan Gränitz 
38ef238923SStefan Gränitz namespace llvm {
39ef238923SStefan Gränitz namespace orc {
40ef238923SStefan Gränitz 
41ef238923SStefan Gränitz class DebugObjectSection {
42ef238923SStefan Gränitz public:
43ef238923SStefan Gränitz   virtual void setTargetMemoryRange(SectionRange Range) = 0;
dump(raw_ostream & OS,StringRef Name)44ef238923SStefan Gränitz   virtual void dump(raw_ostream &OS, StringRef Name) {}
45*3a3cb929SKazu Hirata   virtual ~DebugObjectSection() = default;
46ef238923SStefan Gränitz };
47ef238923SStefan Gränitz 
48ef238923SStefan Gränitz template <typename ELFT>
49ef238923SStefan Gränitz class ELFDebugObjectSection : public DebugObjectSection {
50ef238923SStefan Gränitz public:
51ef238923SStefan Gränitz   // BinaryFormat ELF is not meant as a mutable format. We can only make changes
52ef238923SStefan Gränitz   // that don't invalidate the file structure.
ELFDebugObjectSection(const typename ELFT::Shdr * Header)53ef238923SStefan Gränitz   ELFDebugObjectSection(const typename ELFT::Shdr *Header)
54ef238923SStefan Gränitz       : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
55ef238923SStefan Gränitz 
56ef238923SStefan Gränitz   void setTargetMemoryRange(SectionRange Range) override;
57ef238923SStefan Gränitz   void dump(raw_ostream &OS, StringRef Name) override;
58ef238923SStefan Gränitz 
59265bc5afSStefan Gränitz   Error validateInBounds(StringRef Buffer, const char *Name) const;
60265bc5afSStefan Gränitz 
61ef238923SStefan Gränitz private:
62ef238923SStefan Gränitz   typename ELFT::Shdr *Header;
63ef238923SStefan Gränitz 
64ef238923SStefan Gränitz   bool isTextOrDataSection() const;
65ef238923SStefan Gränitz };
66ef238923SStefan Gränitz 
67ef238923SStefan Gränitz template <typename ELFT>
setTargetMemoryRange(SectionRange Range)68ef238923SStefan Gränitz void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
69ef238923SStefan Gränitz   // Only patch load-addresses for executable and data sections.
70118e953bSLang Hames   if (isTextOrDataSection())
71118e953bSLang Hames     Header->sh_addr =
72118e953bSLang Hames         static_cast<typename ELFT::uint>(Range.getStart().getValue());
73ef238923SStefan Gränitz }
74ef238923SStefan Gränitz 
75ef238923SStefan Gränitz template <typename ELFT>
isTextOrDataSection() const76ef238923SStefan Gränitz bool ELFDebugObjectSection<ELFT>::isTextOrDataSection() const {
77ef238923SStefan Gränitz   switch (Header->sh_type) {
78ef238923SStefan Gränitz   case ELF::SHT_PROGBITS:
79ef238923SStefan Gränitz   case ELF::SHT_X86_64_UNWIND:
80ef238923SStefan Gränitz     return Header->sh_flags & (ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
81ef238923SStefan Gränitz   }
82ef238923SStefan Gränitz   return false;
83ef238923SStefan Gränitz }
84ef238923SStefan Gränitz 
85265bc5afSStefan Gränitz template <typename ELFT>
validateInBounds(StringRef Buffer,const char * Name) const86265bc5afSStefan Gränitz Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
87265bc5afSStefan Gränitz                                                     const char *Name) const {
88265bc5afSStefan Gränitz   const uint8_t *Start = Buffer.bytes_begin();
89265bc5afSStefan Gränitz   const uint8_t *End = Buffer.bytes_end();
90265bc5afSStefan Gränitz   const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
91265bc5afSStefan Gränitz   if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
92265bc5afSStefan Gränitz     return make_error<StringError>(
93265bc5afSStefan Gränitz         formatv("{0} section header at {1:x16} not within bounds of the "
94265bc5afSStefan Gränitz                 "given debug object buffer [{2:x16} - {3:x16}]",
95265bc5afSStefan Gränitz                 Name, &Header->sh_addr, Start, End),
96265bc5afSStefan Gränitz         inconvertibleErrorCode());
97265bc5afSStefan Gränitz   if (Header->sh_offset + Header->sh_size > Buffer.size())
98265bc5afSStefan Gränitz     return make_error<StringError>(
99265bc5afSStefan Gränitz         formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
100265bc5afSStefan Gränitz                 "the given debug object buffer [{3:x16} - {4:x16}]",
101265bc5afSStefan Gränitz                 Name, Start + Header->sh_offset,
102265bc5afSStefan Gränitz                 Start + Header->sh_offset + Header->sh_size, Start, End),
103265bc5afSStefan Gränitz         inconvertibleErrorCode());
104265bc5afSStefan Gränitz   return Error::success();
105265bc5afSStefan Gränitz }
106265bc5afSStefan Gränitz 
107265bc5afSStefan Gränitz template <typename ELFT>
dump(raw_ostream & OS,StringRef Name)108265bc5afSStefan Gränitz void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
109265bc5afSStefan Gränitz   if (auto Addr = static_cast<JITTargetAddress>(Header->sh_addr)) {
110265bc5afSStefan Gränitz     OS << formatv("  {0:x16} {1}\n", Addr, Name);
111265bc5afSStefan Gränitz   } else {
112265bc5afSStefan Gränitz     OS << formatv("                     {0}\n", Name);
113265bc5afSStefan Gränitz   }
114265bc5afSStefan Gränitz }
115265bc5afSStefan Gränitz 
116ef238923SStefan Gränitz enum class Requirement {
117ef238923SStefan Gränitz   // Request final target memory load-addresses for all sections.
118ef238923SStefan Gränitz   ReportFinalSectionLoadAddresses,
119ef238923SStefan Gränitz };
120ef238923SStefan Gränitz 
121962a2479SLang Hames /// The plugin creates a debug object from when JITLink starts processing the
122962a2479SLang Hames /// corresponding LinkGraph. It provides access to the pass configuration of
123962a2479SLang Hames /// the LinkGraph and calls the finalization function, once the resulting link
124962a2479SLang Hames /// artifact was emitted.
125ef238923SStefan Gränitz ///
126ef238923SStefan Gränitz class DebugObject {
127ef238923SStefan Gränitz public:
DebugObject(JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)128962a2479SLang Hames   DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
129962a2479SLang Hames               ExecutionSession &ES)
130962a2479SLang Hames       : MemMgr(MemMgr), JD(JD), ES(ES) {}
131ef238923SStefan Gränitz 
set(Requirement Req)132ef238923SStefan Gränitz   void set(Requirement Req) { Reqs.insert(Req); }
has(Requirement Req) const133ef238923SStefan Gränitz   bool has(Requirement Req) const { return Reqs.count(Req) > 0; }
134ef238923SStefan Gränitz 
135962a2479SLang Hames   using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
136962a2479SLang Hames 
137ef238923SStefan Gränitz   void finalizeAsync(FinalizeContinuation OnFinalize);
138ef238923SStefan Gränitz 
~DebugObject()139b26c953fSStefan Gränitz   virtual ~DebugObject() {
140962a2479SLang Hames     if (Alloc) {
141962a2479SLang Hames       std::vector<FinalizedAlloc> Allocs;
142962a2479SLang Hames       Allocs.push_back(std::move(Alloc));
143962a2479SLang Hames       if (Error Err = MemMgr.deallocate(std::move(Allocs)))
144b26c953fSStefan Gränitz         ES.reportError(std::move(Err));
145ee5e7a3aSStefan Gränitz     }
146962a2479SLang Hames   }
147ee5e7a3aSStefan Gränitz 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)148ef238923SStefan Gränitz   virtual void reportSectionTargetMemoryRange(StringRef Name,
149ef238923SStefan Gränitz                                               SectionRange TargetMem) {}
150ef238923SStefan Gränitz 
151ef238923SStefan Gränitz protected:
152962a2479SLang Hames   using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
153962a2479SLang Hames   using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
154ef238923SStefan Gränitz 
155962a2479SLang Hames   virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
156962a2479SLang Hames 
157962a2479SLang Hames   JITLinkMemoryManager &MemMgr;
158962a2479SLang Hames   const JITLinkDylib *JD = nullptr;
159ef238923SStefan Gränitz 
160ef238923SStefan Gränitz private:
161b26c953fSStefan Gränitz   ExecutionSession &ES;
162ef238923SStefan Gränitz   std::set<Requirement> Reqs;
163962a2479SLang Hames   FinalizedAlloc Alloc;
164ef238923SStefan Gränitz };
165ef238923SStefan Gränitz 
166ef238923SStefan Gränitz // Finalize working memory and take ownership of the resulting allocation. Start
167ef238923SStefan Gränitz // copying memory over to the target and pass on the result once we're done.
168ef238923SStefan Gränitz // Ownership of the allocation remains with us for the rest of our lifetime.
finalizeAsync(FinalizeContinuation OnFinalize)169ef238923SStefan Gränitz void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
170962a2479SLang Hames   assert(!Alloc && "Cannot finalize more than once");
171ef238923SStefan Gränitz 
172962a2479SLang Hames   if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
173962a2479SLang Hames     auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
174962a2479SLang Hames     ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr),
175962a2479SLang Hames                                     ExecutorAddrDiff(ROSeg.WorkingMem.size()));
176962a2479SLang Hames     SimpleSegAlloc->finalize(
177962a2479SLang Hames         [this, DebugObjRange,
178962a2479SLang Hames          OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
179962a2479SLang Hames           if (FA) {
180962a2479SLang Hames             Alloc = std::move(*FA);
181962a2479SLang Hames             OnFinalize(DebugObjRange);
182962a2479SLang Hames           } else
183962a2479SLang Hames             OnFinalize(FA.takeError());
184ef238923SStefan Gränitz         });
185962a2479SLang Hames   } else
186962a2479SLang Hames     OnFinalize(SimpleSegAlloc.takeError());
187ef238923SStefan Gränitz }
188ef238923SStefan Gränitz 
189ef238923SStefan Gränitz /// The current implementation of ELFDebugObject replicates the approach used in
190ef238923SStefan Gränitz /// RuntimeDyld: It patches executable and data section headers in the given
191ef238923SStefan Gränitz /// object buffer with load-addresses of their corresponding sections in target
192ef238923SStefan Gränitz /// memory.
193ef238923SStefan Gränitz ///
194ef238923SStefan Gränitz class ELFDebugObject : public DebugObject {
195ef238923SStefan Gränitz public:
196b26c953fSStefan Gränitz   static Expected<std::unique_ptr<DebugObject>>
197b26c953fSStefan Gränitz   Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
198ef238923SStefan Gränitz 
199ef238923SStefan Gränitz   void reportSectionTargetMemoryRange(StringRef Name,
200ef238923SStefan Gränitz                                       SectionRange TargetMem) override;
201ef238923SStefan Gränitz 
getBuffer() const2027d18cd93SStefan Gränitz   StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
2037d18cd93SStefan Gränitz 
204ef238923SStefan Gränitz protected:
205962a2479SLang Hames   Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
206ef238923SStefan Gränitz 
207265bc5afSStefan Gränitz   template <typename ELFT>
208ef238923SStefan Gränitz   Error recordSection(StringRef Name,
209265bc5afSStefan Gränitz                       std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
210ef238923SStefan Gränitz   DebugObjectSection *getSection(StringRef Name);
211ef238923SStefan Gränitz 
212ef238923SStefan Gränitz private:
213ef238923SStefan Gränitz   template <typename ELFT>
214ef238923SStefan Gränitz   static Expected<std::unique_ptr<ELFDebugObject>>
215962a2479SLang Hames   CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
216962a2479SLang Hames                  const JITLinkDylib *JD, ExecutionSession &ES);
217ef238923SStefan Gränitz 
2187d18cd93SStefan Gränitz   static std::unique_ptr<WritableMemoryBuffer>
2197d18cd93SStefan Gränitz   CopyBuffer(MemoryBufferRef Buffer, Error &Err);
220ef238923SStefan Gränitz 
ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)221ef238923SStefan Gränitz   ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
222962a2479SLang Hames                  JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
223962a2479SLang Hames                  ExecutionSession &ES)
224962a2479SLang Hames       : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
225ef238923SStefan Gränitz     set(Requirement::ReportFinalSectionLoadAddresses);
226ef238923SStefan Gränitz   }
227ef238923SStefan Gränitz 
228ef238923SStefan Gränitz   std::unique_ptr<WritableMemoryBuffer> Buffer;
229ef238923SStefan Gränitz   StringMap<std::unique_ptr<DebugObjectSection>> Sections;
230ef238923SStefan Gränitz };
231ef238923SStefan Gränitz 
232ef238923SStefan Gränitz static const std::set<StringRef> DwarfSectionNames = {
233ef238923SStefan Gränitz #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
234ef238923SStefan Gränitz   ELF_NAME,
235ef238923SStefan Gränitz #include "llvm/BinaryFormat/Dwarf.def"
236ef238923SStefan Gränitz #undef HANDLE_DWARF_SECTION
237ef238923SStefan Gränitz };
238ef238923SStefan Gränitz 
isDwarfSection(StringRef SectionName)239ef238923SStefan Gränitz static bool isDwarfSection(StringRef SectionName) {
240ef238923SStefan Gränitz   return DwarfSectionNames.count(SectionName) == 1;
241ef238923SStefan Gränitz }
242ef238923SStefan Gränitz 
2437d18cd93SStefan Gränitz std::unique_ptr<WritableMemoryBuffer>
CopyBuffer(MemoryBufferRef Buffer,Error & Err)2447d18cd93SStefan Gränitz ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
2457d18cd93SStefan Gränitz   ErrorAsOutParameter _(&Err);
246ef238923SStefan Gränitz   size_t Size = Buffer.getBufferSize();
247ef238923SStefan Gränitz   StringRef Name = Buffer.getBufferIdentifier();
2487d18cd93SStefan Gränitz   if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
249ef238923SStefan Gränitz     memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
2507d18cd93SStefan Gränitz     return Copy;
2517d18cd93SStefan Gränitz   }
2527d18cd93SStefan Gränitz 
2537d18cd93SStefan Gränitz   Err = errorCodeToError(make_error_code(errc::not_enough_memory));
2547d18cd93SStefan Gränitz   return nullptr;
255ef238923SStefan Gränitz }
256ef238923SStefan Gränitz 
257ef238923SStefan Gränitz template <typename ELFT>
258ef238923SStefan Gränitz Expected<std::unique_ptr<ELFDebugObject>>
CreateArchType(MemoryBufferRef Buffer,JITLinkMemoryManager & MemMgr,const JITLinkDylib * JD,ExecutionSession & ES)259962a2479SLang Hames ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
260962a2479SLang Hames                                JITLinkMemoryManager &MemMgr,
261962a2479SLang Hames                                const JITLinkDylib *JD, ExecutionSession &ES) {
262ef238923SStefan Gränitz   using SectionHeader = typename ELFT::Shdr;
263ef238923SStefan Gränitz 
2647d18cd93SStefan Gränitz   Error Err = Error::success();
2657d18cd93SStefan Gränitz   std::unique_ptr<ELFDebugObject> DebugObj(
266962a2479SLang Hames       new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
2677d18cd93SStefan Gränitz   if (Err)
2687d18cd93SStefan Gränitz     return std::move(Err);
2697d18cd93SStefan Gränitz 
2707d18cd93SStefan Gränitz   Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
271ef238923SStefan Gränitz   if (!ObjRef)
272ef238923SStefan Gränitz     return ObjRef.takeError();
273ef238923SStefan Gränitz 
274ef238923SStefan Gränitz   // TODO: Add support for other architectures.
275ef238923SStefan Gränitz   uint16_t TargetMachineArch = ObjRef->getHeader().e_machine;
276ef238923SStefan Gränitz   if (TargetMachineArch != ELF::EM_X86_64)
277ef238923SStefan Gränitz     return nullptr;
278ef238923SStefan Gränitz 
279ef238923SStefan Gränitz   Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
280ef238923SStefan Gränitz   if (!Sections)
281ef238923SStefan Gränitz     return Sections.takeError();
282ef238923SStefan Gränitz 
283ef238923SStefan Gränitz   bool HasDwarfSection = false;
284ef238923SStefan Gränitz   for (const SectionHeader &Header : *Sections) {
285ef238923SStefan Gränitz     Expected<StringRef> Name = ObjRef->getSectionName(Header);
286ef238923SStefan Gränitz     if (!Name)
287ef238923SStefan Gränitz       return Name.takeError();
288ef238923SStefan Gränitz     if (Name->empty())
289ef238923SStefan Gränitz       continue;
290ef238923SStefan Gränitz     HasDwarfSection |= isDwarfSection(*Name);
291ef238923SStefan Gränitz 
292ef238923SStefan Gränitz     auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
293ef238923SStefan Gränitz     if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
294ef238923SStefan Gränitz       return std::move(Err);
295ef238923SStefan Gränitz   }
296ef238923SStefan Gränitz 
297ef238923SStefan Gränitz   if (!HasDwarfSection) {
298ef238923SStefan Gränitz     LLVM_DEBUG(dbgs() << "Aborting debug registration for LinkGraph \""
299ef238923SStefan Gränitz                       << DebugObj->Buffer->getBufferIdentifier()
300ef238923SStefan Gränitz                       << "\": input object contains no debug info\n");
301ef238923SStefan Gränitz     return nullptr;
302ef238923SStefan Gränitz   }
303ef238923SStefan Gränitz 
304ef238923SStefan Gränitz   return std::move(DebugObj);
305ef238923SStefan Gränitz }
306ef238923SStefan Gränitz 
307ef238923SStefan Gränitz Expected<std::unique_ptr<DebugObject>>
Create(MemoryBufferRef Buffer,JITLinkContext & Ctx,ExecutionSession & ES)308b26c953fSStefan Gränitz ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
309b26c953fSStefan Gränitz                        ExecutionSession &ES) {
310ef238923SStefan Gränitz   unsigned char Class, Endian;
311ef238923SStefan Gränitz   std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
312ef238923SStefan Gränitz 
313ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS32) {
314ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
315962a2479SLang Hames       return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
316962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
317ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
318962a2479SLang Hames       return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
319962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
320ef238923SStefan Gränitz     return nullptr;
321ef238923SStefan Gränitz   }
322ef238923SStefan Gränitz   if (Class == ELF::ELFCLASS64) {
323ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2LSB)
324962a2479SLang Hames       return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
325962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
326ef238923SStefan Gränitz     if (Endian == ELF::ELFDATA2MSB)
327962a2479SLang Hames       return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
328962a2479SLang Hames                                      Ctx.getJITLinkDylib(), ES);
329ef238923SStefan Gränitz     return nullptr;
330ef238923SStefan Gränitz   }
331ef238923SStefan Gränitz   return nullptr;
332ef238923SStefan Gränitz }
333ef238923SStefan Gränitz 
finalizeWorkingMemory()334962a2479SLang Hames Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
335ef238923SStefan Gränitz   LLVM_DEBUG({
336ef238923SStefan Gränitz     dbgs() << "Section load-addresses in debug object for \""
337ef238923SStefan Gränitz            << Buffer->getBufferIdentifier() << "\":\n";
338ef238923SStefan Gränitz     for (const auto &KV : Sections)
339ef238923SStefan Gränitz       KV.second->dump(dbgs(), KV.first());
340ef238923SStefan Gränitz   });
341ef238923SStefan Gränitz 
342ef238923SStefan Gränitz   // TODO: This works, but what actual alignment requirements do we have?
343962a2479SLang Hames   unsigned PageSize = sys::Process::getPageSizeEstimate();
344ef238923SStefan Gränitz   size_t Size = Buffer->getBufferSize();
345ef238923SStefan Gränitz 
346ef238923SStefan Gränitz   // Allocate working memory for debug object in read-only segment.
347962a2479SLang Hames   auto Alloc = SimpleSegmentAlloc::Create(
348962a2479SLang Hames       MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}});
349962a2479SLang Hames   if (!Alloc)
350962a2479SLang Hames     return Alloc;
351ef238923SStefan Gränitz 
352ef238923SStefan Gränitz   // Initialize working memory with a copy of our object buffer.
353962a2479SLang Hames   auto SegInfo = Alloc->getSegInfo(MemProt::Read);
354962a2479SLang Hames   memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
355ef238923SStefan Gränitz   Buffer.reset();
356ef238923SStefan Gränitz 
357962a2479SLang Hames   return Alloc;
358ef238923SStefan Gränitz }
359ef238923SStefan Gränitz 
reportSectionTargetMemoryRange(StringRef Name,SectionRange TargetMem)360ef238923SStefan Gränitz void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
361ef238923SStefan Gränitz                                                     SectionRange TargetMem) {
362ef238923SStefan Gränitz   if (auto *DebugObjSection = getSection(Name))
363ef238923SStefan Gränitz     DebugObjSection->setTargetMemoryRange(TargetMem);
364ef238923SStefan Gränitz }
365ef238923SStefan Gränitz 
366265bc5afSStefan Gränitz template <typename ELFT>
recordSection(StringRef Name,std::unique_ptr<ELFDebugObjectSection<ELFT>> Section)367ef238923SStefan Gränitz Error ELFDebugObject::recordSection(
368265bc5afSStefan Gränitz     StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
369265bc5afSStefan Gränitz   if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
370265bc5afSStefan Gränitz     return Err;
371ef238923SStefan Gränitz   auto ItInserted = Sections.try_emplace(Name, std::move(Section));
372ef238923SStefan Gränitz   if (!ItInserted.second)
373ef238923SStefan Gränitz     return make_error<StringError>("Duplicate section",
374ef238923SStefan Gränitz                                    inconvertibleErrorCode());
375ef238923SStefan Gränitz   return Error::success();
376ef238923SStefan Gränitz }
377ef238923SStefan Gränitz 
getSection(StringRef Name)378ef238923SStefan Gränitz DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
379ef238923SStefan Gränitz   auto It = Sections.find(Name);
380ef238923SStefan Gränitz   return It == Sections.end() ? nullptr : It->second.get();
381ef238923SStefan Gränitz }
382ef238923SStefan Gränitz 
383ef238923SStefan Gränitz /// Creates a debug object based on the input object file from
384ef238923SStefan Gränitz /// ObjectLinkingLayerJITLinkContext.
385ef238923SStefan Gränitz ///
386ef238923SStefan Gränitz static Expected<std::unique_ptr<DebugObject>>
createDebugObjectFromBuffer(ExecutionSession & ES,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)387b26c953fSStefan Gränitz createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
388b26c953fSStefan Gränitz                             JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
389ef238923SStefan Gränitz   switch (G.getTargetTriple().getObjectFormat()) {
390ef238923SStefan Gränitz   case Triple::ELF:
391b26c953fSStefan Gränitz     return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
392ef238923SStefan Gränitz 
393ef238923SStefan Gränitz   default:
394ef238923SStefan Gränitz     // TODO: Once we add support for other formats, we might want to split this
395ef238923SStefan Gränitz     // into multiple files.
396ef238923SStefan Gränitz     return nullptr;
397ef238923SStefan Gränitz   }
398ef238923SStefan Gränitz }
399ef238923SStefan Gränitz 
DebugObjectManagerPlugin(ExecutionSession & ES,std::unique_ptr<DebugObjectRegistrar> Target)400ef238923SStefan Gränitz DebugObjectManagerPlugin::DebugObjectManagerPlugin(
401ef238923SStefan Gränitz     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
402ef238923SStefan Gränitz     : ES(ES), Target(std::move(Target)) {}
403ef238923SStefan Gränitz 
404b26c953fSStefan Gränitz DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
405ef238923SStefan Gränitz 
notifyMaterializing(MaterializationResponsibility & MR,LinkGraph & G,JITLinkContext & Ctx,MemoryBufferRef ObjBuffer)406ef238923SStefan Gränitz void DebugObjectManagerPlugin::notifyMaterializing(
407ef238923SStefan Gränitz     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
408ef238923SStefan Gränitz     MemoryBufferRef ObjBuffer) {
409c154cddaSStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
410c154cddaSStefan Gränitz   assert(PendingObjs.count(&MR) == 0 &&
411ef238923SStefan Gränitz          "Cannot have more than one pending debug object per "
412ef238923SStefan Gränitz          "MaterializationResponsibility");
413ef238923SStefan Gränitz 
414b26c953fSStefan Gränitz   if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
415ef238923SStefan Gränitz     // Not all link artifacts allow debugging.
416c154cddaSStefan Gränitz     if (*DebugObj != nullptr)
417c154cddaSStefan Gränitz       PendingObjs[&MR] = std::move(*DebugObj);
418ef238923SStefan Gränitz   } else {
419ef238923SStefan Gränitz     ES.reportError(DebugObj.takeError());
420ef238923SStefan Gränitz   }
421ef238923SStefan Gränitz }
422ef238923SStefan Gränitz 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)423ef238923SStefan Gränitz void DebugObjectManagerPlugin::modifyPassConfig(
4244e30b20bSLang Hames     MaterializationResponsibility &MR, LinkGraph &G,
425ef238923SStefan Gränitz     PassConfiguration &PassConfig) {
426ef238923SStefan Gränitz   // Not all link artifacts have associated debug objects.
427ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
428c154cddaSStefan Gränitz   auto It = PendingObjs.find(&MR);
429ef238923SStefan Gränitz   if (It == PendingObjs.end())
430ef238923SStefan Gränitz     return;
431ef238923SStefan Gränitz 
432ef238923SStefan Gränitz   DebugObject &DebugObj = *It->second;
433ef238923SStefan Gränitz   if (DebugObj.has(Requirement::ReportFinalSectionLoadAddresses)) {
434ef238923SStefan Gränitz     PassConfig.PostAllocationPasses.push_back(
435ef238923SStefan Gränitz         [&DebugObj](LinkGraph &Graph) -> Error {
436ef238923SStefan Gränitz           for (const Section &GraphSection : Graph.sections())
437ef238923SStefan Gränitz             DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
438ef238923SStefan Gränitz                                                     SectionRange(GraphSection));
439ef238923SStefan Gränitz           return Error::success();
440ef238923SStefan Gränitz         });
441ef238923SStefan Gränitz   }
442ef238923SStefan Gränitz }
443ef238923SStefan Gränitz 
notifyEmitted(MaterializationResponsibility & MR)444ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyEmitted(
445ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
446ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
447c154cddaSStefan Gränitz   auto It = PendingObjs.find(&MR);
448ef238923SStefan Gränitz   if (It == PendingObjs.end())
449ef238923SStefan Gränitz     return Error::success();
450ef238923SStefan Gränitz 
451ff52121bSStefan Gränitz   // During finalization the debug object is registered with the target.
452ff52121bSStefan Gränitz   // Materialization must wait for this process to finish. Otherwise we might
453ff52121bSStefan Gränitz   // start running code before the debugger processed the corresponding debug
454ff52121bSStefan Gränitz   // info.
455ff52121bSStefan Gränitz   std::promise<MSVCPError> FinalizePromise;
456ff52121bSStefan Gränitz   std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
457ff52121bSStefan Gränitz 
458cbcc1c9fSStefan Gränitz   It->second->finalizeAsync(
459962a2479SLang Hames       [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
460cbcc1c9fSStefan Gränitz         // Any failure here will fail materialization.
461ef238923SStefan Gränitz         if (!TargetMem) {
462ff52121bSStefan Gränitz           FinalizePromise.set_value(TargetMem.takeError());
463ef238923SStefan Gränitz           return;
464ef238923SStefan Gränitz         }
465ef238923SStefan Gränitz         if (Error Err = Target->registerDebugObject(*TargetMem)) {
466ff52121bSStefan Gränitz           FinalizePromise.set_value(std::move(Err));
467ef238923SStefan Gränitz           return;
468ef238923SStefan Gränitz         }
469ef238923SStefan Gränitz 
470cbcc1c9fSStefan Gränitz         // Once our tracking info is updated, notifyEmitted() can return and
471cbcc1c9fSStefan Gränitz         // finish materialization.
472cbcc1c9fSStefan Gränitz         FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
473cbcc1c9fSStefan Gränitz           assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
474ef238923SStefan Gränitz           std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
475cbcc1c9fSStefan Gränitz           RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
476cbcc1c9fSStefan Gränitz           PendingObjs.erase(&MR);
477cbcc1c9fSStefan Gränitz         }));
478ef238923SStefan Gränitz       });
479ef238923SStefan Gränitz 
480ff52121bSStefan Gränitz   return FinalizeErr.get();
481ef238923SStefan Gränitz }
482ef238923SStefan Gränitz 
notifyFailed(MaterializationResponsibility & MR)483ef238923SStefan Gränitz Error DebugObjectManagerPlugin::notifyFailed(
484ef238923SStefan Gränitz     MaterializationResponsibility &MR) {
485ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(PendingObjsLock);
486c154cddaSStefan Gränitz   PendingObjs.erase(&MR);
487ef238923SStefan Gränitz   return Error::success();
488ef238923SStefan Gränitz }
489ef238923SStefan Gränitz 
notifyTransferringResources(ResourceKey DstKey,ResourceKey SrcKey)490ef238923SStefan Gränitz void DebugObjectManagerPlugin::notifyTransferringResources(ResourceKey DstKey,
491ef238923SStefan Gränitz                                                            ResourceKey SrcKey) {
492c154cddaSStefan Gränitz   // Debug objects are stored by ResourceKey only after registration.
493c154cddaSStefan Gränitz   // Thus, pending objects don't need to be updated here.
494ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
495ef238923SStefan Gränitz   auto SrcIt = RegisteredObjs.find(SrcKey);
496ef238923SStefan Gränitz   if (SrcIt != RegisteredObjs.end()) {
497ef238923SStefan Gränitz     // Resources from distinct MaterializationResponsibilitys can get merged
498ef238923SStefan Gränitz     // after emission, so we can have multiple debug objects per resource key.
499ef238923SStefan Gränitz     for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
500ef238923SStefan Gränitz       RegisteredObjs[DstKey].push_back(std::move(DebugObj));
501ef238923SStefan Gränitz     RegisteredObjs.erase(SrcIt);
502ef238923SStefan Gränitz   }
503ef238923SStefan Gränitz }
504ef238923SStefan Gränitz 
notifyRemovingResources(ResourceKey Key)505c154cddaSStefan Gränitz Error DebugObjectManagerPlugin::notifyRemovingResources(ResourceKey Key) {
506c154cddaSStefan Gränitz   // Removing the resource for a pending object fails materialization, so they
507c154cddaSStefan Gränitz   // get cleaned up in the notifyFailed() handler.
508ef238923SStefan Gränitz   std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
509c154cddaSStefan Gränitz   RegisteredObjs.erase(Key);
510ef238923SStefan Gränitz 
511c154cddaSStefan Gränitz   // TODO: Implement unregister notifications.
512ef238923SStefan Gränitz   return Error::success();
513ef238923SStefan Gränitz }
514ef238923SStefan Gränitz 
515ef238923SStefan Gränitz } // namespace orc
516ef238923SStefan Gränitz } // namespace llvm
517