32#define DEBUG_TYPE "orc"
47template <
typename ELFT>
53 : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
61 typename ELFT::Shdr *Header;
64template <
typename ELFT>
68 static_cast<typename ELFT::uint
>(
Range.getStart().getValue());
71template <
typename ELFT>
73 const char *Name)
const {
77 if (HeaderPtr < Start || HeaderPtr +
sizeof(
typename ELFT::Shdr) > End)
79 formatv(
"{0} section header at {1:x16} not within bounds of the "
80 "given debug object buffer [{2:x16} - {3:x16}]",
81 Name, &Header->sh_addr, Start, End),
83 if (Header->sh_offset + Header->sh_size > Buffer.
size())
85 formatv(
"{0} section data [{1:x16} - {2:x16}] not within bounds of "
86 "the given debug object buffer [{3:x16} - {4:x16}]",
87 Name, Start + Header->sh_offset,
88 Start + Header->sh_offset + Header->sh_size, Start, End),
93template <
typename ELFT>
95 if (
uint64_t Addr = Header->sh_addr) {
96 OS <<
formatv(
" {0:x16} {1}\n", Addr, Name);
146 std::vector<FinalizedAlloc> Allocs;
147 Allocs.push_back(std::move(Alloc));
148 if (
Error Err =
MemMgr.deallocate(std::move(Allocs)))
149 ES.reportError(std::move(Err));
178 assert(!this->Alloc &&
"Cannot finalize more than once");
182 SimpleSegAlloc->finalize(
183 [
this, DebugObjRange,
189 this->Alloc = std::move(*FA);
190 OnFinalize(DebugObjRange);
197 OnFinalize(SimpleSegAlloc.takeError());
219 template <
typename ELFT>
225 template <
typename ELFT>
230 static std::unique_ptr<WritableMemoryBuffer>
240 std::unique_ptr<WritableMemoryBuffer> Buffer;
245#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
247#include "llvm/BinaryFormat/Dwarf.def"
248#undef HANDLE_DWARF_SECTION
255std::unique_ptr<WritableMemoryBuffer>
269template <
typename ELFT>
270Expected<std::unique_ptr<ELFDebugObject>>
271ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
272 JITLinkMemoryManager &MemMgr,
277 std::unique_ptr<ELFDebugObject> DebugObj(
278 new ELFDebugObject(CopyBuffer(Buffer, Err),
MemMgr,
JD,
ES));
280 return std::move(Err);
286 Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
290 for (
const SectionHeader &Header : *Sections) {
291 Expected<StringRef>
Name = ObjRef->getSectionName(Header);
293 return Name.takeError();
306 auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
307 if (
Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
308 return std::move(Err);
311 return std::move(DebugObj);
314Expected<std::unique_ptr<DebugObject>>
317 unsigned char Class, Endian;
322 return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
323 Ctx.getJITLinkDylib(),
ES);
325 return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
326 Ctx.getJITLinkDylib(),
ES);
331 return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
332 Ctx.getJITLinkDylib(),
ES);
334 return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
335 Ctx.getJITLinkDylib(),
ES);
343 dbgs() <<
"Section load-addresses in debug object for \""
344 << Buffer->getBufferIdentifier() <<
"\":\n";
345 for (
const auto &KV : Sections)
346 KV.second->dump(
dbgs(), KV.first());
351 size_t Size = Buffer->getBufferSize();
355 MemMgr,
ES.getSymbolStringPool(),
ES.getTargetTriple(),
JD,
356 {{MemProt::Read, {Size, Align(PageSize)}}});
371 DebugObjSection->setTargetMemoryRange(TargetMem);
374template <
typename ELFT>
377 if (
Error Err =
Section->validateInBounds(this->getBuffer(), Name.data()))
379 bool Inserted = Sections.try_emplace(Name, std::move(
Section)).second;
381 LLVM_DEBUG(
dbgs() <<
"Skipping debug registration for section '" << Name
382 <<
"' in object " << Buffer->getBufferIdentifier()
383 <<
" (duplicate name)\n");
388 auto It = Sections.find(Name);
389 return It == Sections.end() ? nullptr : It->second.get();
398 switch (
G.getTargetTriple().getObjectFormat()) {
410 bool RequireDebugSections,
411 bool AutoRegisterCode,
Error &Err)
412 : ES(ES), RequireDebugSections(RequireDebugSections),
413 AutoRegisterCode(AutoRegisterCode) {
416 Err = ES.getExecutorProcessControl().getBootstrapSymbols(
425 std::lock_guard<std::mutex> Lock(PendingObjsLock);
426 assert(PendingObjs.count(&MR) == 0 &&
427 "Cannot have more than one pending debug object per "
428 "MaterializationResponsibility");
432 if (*DebugObj ==
nullptr)
435 LLVM_DEBUG(
dbgs() <<
"Skipping debug registration for LinkGraph '"
436 <<
G.getName() <<
"': no debug info\n");
439 PendingObjs[&MR] = std::move(*DebugObj);
441 ES.reportError(DebugObj.takeError());
449 std::lock_guard<std::mutex> Lock(PendingObjsLock);
450 auto It = PendingObjs.find(&MR);
451 if (It == PendingObjs.end())
474 std::lock_guard<std::mutex> LockPending(PendingObjsLock);
475 std::lock_guard<std::mutex> LockRegistered(RegisteredObjsLock);
476 auto It = PendingObjs.find(&MR);
477 RegisteredObjs[K].push_back(std::move(It->second));
478 PendingObjs.erase(It);
494 return R.takeError();
499 G.allocActions().push_back(
500 {
cantFail(WrapperFunctionCall::Create<
501 SPSArgList<SPSExecutorAddrRange, bool>>(
502 RegistrationAction, *R, AutoRegisterCode)),
510 std::lock_guard<std::mutex> Lock(PendingObjsLock);
511 PendingObjs.erase(&MR);
520 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
521 auto SrcIt = RegisteredObjs.find(SrcKey);
522 if (SrcIt != RegisteredObjs.end()) {
525 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
526 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
527 RegisteredObjs.erase(SrcIt);
535 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
536 RegisteredObjs.erase(
Key);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
Provides a library for accessing information about this process and other processes on the operating ...
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
size_t getBufferSize() const
StringRef getBufferIdentifier() const
const char * getBufferStart() const
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
const unsigned char * bytes_end() const
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
static LLVM_ABI std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)
Allocate a new MemoryBuffer of the specified size that is not initialized.
Holds context for a single jitLink invocation.
Represents a finalized allocation.
Represents an allocation which has not been finalized yet.
Manages allocations of JIT memory.
iterator_range< section_iterator > sections()
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
Represents an object file section.
static LLVM_ABI void Create(JITLinkMemoryManager &MemMgr, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, const JITLinkDylib *JD, SegmentMap Segments, OnCreatedFunction OnCreated)
static Expected< ELFFile > create(StringRef Object)
virtual void setTargetMemoryRange(SectionRange Range)=0
virtual void dump(raw_ostream &OS, StringRef Name)
virtual ~DebugObjectSection()=default
The plugin creates a debug object from when JITLink starts processing the corresponding LinkGraph.
JITLinkMemoryManager & MemMgr
Expected< ExecutorAddrRange > awaitTargetMem()
void reportTargetMem(ExecutorAddrRange TargetMem)
void finalizeAsync(FinalizeContinuation OnAsync)
bool hasFlags(DebugObjectFlags F) const
void failMaterialization(Error Err)
virtual Expected< SimpleSegmentAlloc > finalizeWorkingMemory()=0
std::function< void(Expected< ExecutorAddrRange >)> FinalizeContinuation
void clearFlags(DebugObjectFlags F)
std::future< MSVCPExpected< ExecutorAddrRange > > FinalizeFuture
virtual void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem)
void setFlags(DebugObjectFlags F)
JITLinkMemoryManager::FinalizedAlloc FinalizedAlloc
JITLinkMemoryManager::InFlightAlloc InFlightAlloc
std::promise< MSVCPExpected< ExecutorAddrRange > > FinalizePromise
DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, ExecutionSession &ES)
Error notifyFailed(MaterializationResponsibility &MR) override
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
~ELFDebugObjectPlugin() override
ELFDebugObjectPlugin(ExecutionSession &ES, bool RequireDebugSections, bool AutoRegisterCode, Error &Err)
Create the plugin to submit DebugObjects for JITLink artifacts.
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override
void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx, MemoryBufferRef InputObject) override
Error validateInBounds(StringRef Buffer, const char *Name) const
void setTargetMemoryRange(SectionRange Range) override
void dump(raw_ostream &OS, StringRef Name) override
ELFDebugObjectSection(const typename ELFT::Shdr *Header)
The current implementation of ELFDebugObject replicates the approach used in RuntimeDyld: It patches ...
Error recordSection(StringRef Name, std::unique_ptr< ELFDebugObjectSection< ELFT > > Section)
DebugObjectSection * getSection(StringRef Name)
Expected< SimpleSegmentAlloc > finalizeWorkingMemory() override
void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem) override
StringRef getBuffer() const
static Expected< std::unique_ptr< DebugObject > > Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES)
An ExecutionSession represents a running JIT program.
Represents a JIT'd dynamic library.
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Error withResourceKeyDo(Func &&F) const
Runs the given callback under the session lock, passing in the associated ResourceKey.
This class implements an extremely fast bulk output stream that can only output to a stream.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
Expected< const typename ELFT::Shdr * > getSection(typename ELFT::ShdrRange Sections, uint32_t Index)
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
LLVM_ABI const char * RegisterJITLoaderGDBAllocActionName
static const std::set< StringRef > DwarfSectionNames
static Expected< std::unique_ptr< DebugObject > > createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G, JITLinkContext &Ctx, MemoryBufferRef ObjBuffer)
Creates a debug object based on the input object file from ObjectLinkingLayerJITLinkContext.
static bool isDwarfSection(StringRef SectionName)
@ ReportFinalSectionLoadAddresses
This is an optimization pass for GlobalISel generic memory operations.
std::error_code make_error_code(BitcodeError E)
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Implement std::hash so that hash_code can be used in STL containers.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PreFixupPasses
Pre-fixup passes.
LinkGraphPassList PostFixupPasses
Post-fixup passes.
Represents an address range in the exceutor process.