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