1*962a2479SLang 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 //===----------------------------------------------------------------------===// 8*962a2479SLang Hames // 9*962a2479SLang Hames // FIXME: Update Plugin to poke the debug object into a new JITLink section, 10*962a2479SLang Hames // rather than creating a new allocation. 11*962a2479SLang Hames // 12*962a2479SLang 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; 44ef238923SStefan Gränitz virtual void dump(raw_ostream &OS, StringRef Name) {} 45ef238923SStefan Gränitz virtual ~DebugObjectSection() {} 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. 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> 68ef238923SStefan Gränitz void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) { 69ef238923SStefan Gränitz // Only patch load-addresses for executable and data sections. 70ef238923SStefan Gränitz if (isTextOrDataSection()) { 71ef238923SStefan Gränitz Header->sh_addr = static_cast<typename ELFT::uint>(Range.getStart()); 72ef238923SStefan Gränitz } 73ef238923SStefan Gränitz } 74ef238923SStefan Gränitz 75ef238923SStefan Gränitz template <typename ELFT> 76ef238923SStefan 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> 86265bc5afSStefan 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> 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 121*962a2479SLang Hames /// The plugin creates a debug object from when JITLink starts processing the 122*962a2479SLang Hames /// corresponding LinkGraph. It provides access to the pass configuration of 123*962a2479SLang Hames /// the LinkGraph and calls the finalization function, once the resulting link 124*962a2479SLang Hames /// artifact was emitted. 125ef238923SStefan Gränitz /// 126ef238923SStefan Gränitz class DebugObject { 127ef238923SStefan Gränitz public: 128*962a2479SLang Hames DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, 129*962a2479SLang Hames ExecutionSession &ES) 130*962a2479SLang Hames : MemMgr(MemMgr), JD(JD), ES(ES) {} 131ef238923SStefan Gränitz 132ef238923SStefan Gränitz void set(Requirement Req) { Reqs.insert(Req); } 133ef238923SStefan Gränitz bool has(Requirement Req) const { return Reqs.count(Req) > 0; } 134ef238923SStefan Gränitz 135*962a2479SLang Hames using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>; 136*962a2479SLang Hames 137ef238923SStefan Gränitz void finalizeAsync(FinalizeContinuation OnFinalize); 138ef238923SStefan Gränitz 139b26c953fSStefan Gränitz virtual ~DebugObject() { 140*962a2479SLang Hames if (Alloc) { 141*962a2479SLang Hames std::vector<FinalizedAlloc> Allocs; 142*962a2479SLang Hames Allocs.push_back(std::move(Alloc)); 143*962a2479SLang Hames if (Error Err = MemMgr.deallocate(std::move(Allocs))) 144b26c953fSStefan Gränitz ES.reportError(std::move(Err)); 145ee5e7a3aSStefan Gränitz } 146*962a2479SLang Hames } 147ee5e7a3aSStefan Gränitz 148ef238923SStefan Gränitz virtual void reportSectionTargetMemoryRange(StringRef Name, 149ef238923SStefan Gränitz SectionRange TargetMem) {} 150ef238923SStefan Gränitz 151ef238923SStefan Gränitz protected: 152*962a2479SLang Hames using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc; 153*962a2479SLang Hames using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc; 154ef238923SStefan Gränitz 155*962a2479SLang Hames virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0; 156*962a2479SLang Hames 157*962a2479SLang Hames JITLinkMemoryManager &MemMgr; 158*962a2479SLang Hames const JITLinkDylib *JD = nullptr; 159ef238923SStefan Gränitz 160ef238923SStefan Gränitz private: 161b26c953fSStefan Gränitz ExecutionSession &ES; 162ef238923SStefan Gränitz std::set<Requirement> Reqs; 163*962a2479SLang 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. 169ef238923SStefan Gränitz void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) { 170*962a2479SLang Hames assert(!Alloc && "Cannot finalize more than once"); 171ef238923SStefan Gränitz 172*962a2479SLang Hames if (auto SimpleSegAlloc = finalizeWorkingMemory()) { 173*962a2479SLang Hames auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read); 174*962a2479SLang Hames ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr), 175*962a2479SLang Hames ExecutorAddrDiff(ROSeg.WorkingMem.size())); 176*962a2479SLang Hames SimpleSegAlloc->finalize( 177*962a2479SLang Hames [this, DebugObjRange, 178*962a2479SLang Hames OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) { 179*962a2479SLang Hames if (FA) { 180*962a2479SLang Hames Alloc = std::move(*FA); 181*962a2479SLang Hames OnFinalize(DebugObjRange); 182*962a2479SLang Hames } else 183*962a2479SLang Hames OnFinalize(FA.takeError()); 184ef238923SStefan Gränitz }); 185*962a2479SLang Hames } else 186*962a2479SLang 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 2027d18cd93SStefan Gränitz StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); } 2037d18cd93SStefan Gränitz 204ef238923SStefan Gränitz protected: 205*962a2479SLang 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>> 215*962a2479SLang Hames CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr, 216*962a2479SLang 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 221ef238923SStefan Gränitz ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer, 222*962a2479SLang Hames JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, 223*962a2479SLang Hames ExecutionSession &ES) 224*962a2479SLang 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 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> 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>> 259*962a2479SLang Hames ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, 260*962a2479SLang Hames JITLinkMemoryManager &MemMgr, 261*962a2479SLang 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( 266*962a2479SLang 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>> 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) 315*962a2479SLang Hames return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(), 316*962a2479SLang Hames Ctx.getJITLinkDylib(), ES); 317ef238923SStefan Gränitz if (Endian == ELF::ELFDATA2MSB) 318*962a2479SLang Hames return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(), 319*962a2479SLang 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) 324*962a2479SLang Hames return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(), 325*962a2479SLang Hames Ctx.getJITLinkDylib(), ES); 326ef238923SStefan Gränitz if (Endian == ELF::ELFDATA2MSB) 327*962a2479SLang Hames return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(), 328*962a2479SLang Hames Ctx.getJITLinkDylib(), ES); 329ef238923SStefan Gränitz return nullptr; 330ef238923SStefan Gränitz } 331ef238923SStefan Gränitz return nullptr; 332ef238923SStefan Gränitz } 333ef238923SStefan Gränitz 334*962a2479SLang 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? 343*962a2479SLang 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. 347*962a2479SLang Hames auto Alloc = SimpleSegmentAlloc::Create( 348*962a2479SLang Hames MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}}); 349*962a2479SLang Hames if (!Alloc) 350*962a2479SLang Hames return Alloc; 351ef238923SStefan Gränitz 352ef238923SStefan Gränitz // Initialize working memory with a copy of our object buffer. 353*962a2479SLang Hames auto SegInfo = Alloc->getSegInfo(MemProt::Read); 354*962a2479SLang Hames memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size); 355ef238923SStefan Gränitz Buffer.reset(); 356ef238923SStefan Gränitz 357*962a2479SLang Hames return Alloc; 358ef238923SStefan Gränitz } 359ef238923SStefan Gränitz 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> 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 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>> 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 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 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 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 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( 459*962a2479SLang 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 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 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 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