36#define DEBUG_TYPE "orc"
51 : Name(Name), WorkingMem(
std::
move(Alloc)),
52 MemMgr(Ctx.getMemoryManager()), ES(ES) {}
55 assert(!FinalizeFuture.valid());
57 std::vector<FinalizedAlloc> Allocs;
58 Allocs.push_back(std::move(Alloc));
59 if (
Error Err = MemMgr.deallocate(std::move(Allocs)))
60 ES.reportError(std::move(Err));
66 return SegInfo.WorkingMem;
70 FinalizeFuture = FinalizePromise.get_future();
71 return std::move(WorkingMem);
79 assert(FinalizeFuture.valid() &&
80 "FinalizeFuture is not valid. Perhaps there is no pending target "
81 "memory transaction?");
82 return FinalizeFuture.get();
86 FinalizePromise.set_value(TargetMem);
90 FinalizePromise.set_value(std::move(Err));
94 if (FinalizeFuture.valid()) {
102 [ES = &this->ES](
Error Err) { ES->reportError(std::move(Err)); });
109 template <
typename ELFT>
118 std::promise<MSVCPExpected<ExecutorAddrRange>> FinalizePromise;
119 std::future<MSVCPExpected<ExecutorAddrRange>> FinalizeFuture;
124template <
typename ELFT>
126 using SectionHeader =
typename ELFT::Shdr;
138 for (
const SectionHeader &Header : *Sections) {
146 const_cast<SectionHeader &
>(Header).sh_addr =
147 static_cast<typename ELFT::uint
>(LoadAddress.
getValue());
151 dbgs() <<
"Section load-addresses in debug object for \"" << Name
153 for (
const SectionHeader &Header : *Sections) {
155 if (uint64_t Addr = Header.sh_addr) {
167 unsigned char Class, Endian;
193 bool RequireDebugSections,
195 : ES(ES), RequireDebugSections(RequireDebugSections) {
199 {recordAddr(rt::RegisterJITLoaderGDBAllocActionName,
200 &RegistrationAction)});
206#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
208#include "llvm/BinaryFormat/Dwarf.def"
209#undef HANDLE_DWARF_SECTION
221 if (
G.getTargetTriple().getObjectFormat() !=
Triple::ELF)
224 unsigned char Class, Endian;
227 return ES.reportError(
229 "Skipping debug object registration: Invalid arch "
230 "0x%02x in ELF LinkGraph %s",
231 Class,
G.getName().c_str()));
233 return ES.reportError(
235 "Skipping debug object registration: Invalid endian "
236 "0x%02x in ELF LinkGraph %s",
237 Endian,
G.getName().c_str()));
246 Ctx.getMemoryManager(), ES.getSymbolStringPool(), ES.getTargetTriple(),
247 Ctx.getJITLinkDylib(), {{MemProt::Read, Segment}});
249 ES.reportError(
Alloc.takeError());
253 std::lock_guard<std::mutex> Lock(PendingObjsLock);
254 assert(PendingObjs.count(&MR) == 0 &&
"One debug object per materialization");
255 PendingObjs[&MR] = std::make_unique<DebugObject>(
256 InputObj.getBufferIdentifier(), std::move(*
Alloc), Ctx, ES);
259 memcpy(Buffer.
data(), InputObj.getBufferStart(),
Size);
263ELFDebugObjectPlugin::getPendingDebugObj(MaterializationResponsibility &MR) {
264 std::lock_guard<std::mutex> Lock(PendingObjsLock);
265 auto It = PendingObjs.find(&MR);
266 return It == PendingObjs.end() ? nullptr : It->second.get();
272 if (!getPendingDebugObj(MR))
276 size_t SectionsPatched = 0;
277 bool HasDebugSections =
false;
279 assert(DebugObj &&
"Don't inject passes if we have no debug object");
285 [&
G, &SectionsPatched, &HasDebugSections](
StringRef Name) {
286 Section *S =
G.findSectionByName(Name);
293 SectionsPatched += 1;
295 HasDebugSections =
true;
301 if (!SectionsPatched) {
302 LLVM_DEBUG(
dbgs() <<
"Skipping debug registration for LinkGraph '"
303 <<
G.getName() <<
"': no debug info\n");
307 if (RequireDebugSections && !HasDebugSections) {
308 LLVM_DEBUG(
dbgs() <<
"Skipping debug registration for LinkGraph '"
309 <<
G.getName() <<
"': no debug info\n");
323 std::lock_guard<std::mutex> Lock(PendingObjsLock);
324 auto It = PendingObjs.find(&MR);
325 if (It == PendingObjs.end()) {
350 assert(DebugObj &&
"Don't inject passes if we have no debug object");
358 return R.takeError();
363 std::lock_guard<std::mutex> LockPending(PendingObjsLock);
364 std::lock_guard<std::mutex> LockRegistered(RegisteredObjsLock);
365 auto It = PendingObjs.find(&MR);
366 RegisteredObjs[
K].push_back(std::move(It->second));
367 PendingObjs.erase(It);
377 G.allocActions().push_back(
378 {
cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddrRange>>(
379 RegistrationAction, *R)),
386 std::lock_guard<std::mutex> Lock(PendingObjsLock);
387 auto It = PendingObjs.find(&MR);
388 It->second->releasePendingResources();
389 PendingObjs.erase(It);
398 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
399 auto SrcIt = RegisteredObjs.find(SrcKey);
400 if (SrcIt != RegisteredObjs.end()) {
403 for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
404 RegisteredObjs[DstKey].push_back(std::move(DebugObj));
405 RegisteredObjs.erase(SrcIt);
413 std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
414 RegisteredObjs.erase(
Key);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isDwarfSection(const MCObjectFileInfo *FI, const MCSection *Section)
Provides a library for accessing information about this process and other processes on the operating ...
size_t size() const
Get the array size.
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.
reference get()
Returns a reference to the stored T value.
size_t getBufferSize() const
StringRef getBuffer() const
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Represent a constant reference to a string, i.e.
Holds context for a single jitLink invocation.
Represents a finalized allocation.
Manages allocations of JIT memory.
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
orc::ExecutorAddr getStart() const
Represents an object file section.
A utility class for making simple allocations using JITLinkMemoryManager.
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)
MutableArrayRef< char > getBuffer()
Error visitSectionLoadAddresses(GetLoadAddressFn Callback)
void releasePendingResources()
Expected< ExecutorAddrRange > awaitTargetMem()
void reportTargetMem(ExecutorAddrRange TargetMem)
bool hasPendingTargetMem() const
SimpleSegmentAlloc collectTargetAlloc()
void failMaterialization(Error Err)
DebugObject(StringRef Name, SimpleSegmentAlloc Alloc, JITLinkContext &Ctx, ExecutionSession &ES)
llvm::unique_function< ExecutorAddr(StringRef)> GetLoadAddressFn
Error visitSections(GetLoadAddressFn Callback)
void trackFinalizedAlloc(FinalizedAlloc FA)
JITLinkMemoryManager::FinalizedAlloc FinalizedAlloc
Error notifyFailed(MaterializationResponsibility &MR) override
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
~ELFDebugObjectPlugin() override
void notifyMaterializing(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx, MemoryBufferRef InputObj) override
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &LG, jitlink::PassConfiguration &PassConfig) override
ELFDebugObjectPlugin(ExecutionSession &ES, bool RequireDebugSections, Error &Err)
Create the plugin for the given session and set additional options.
An ExecutionSession represents a running JIT program.
Represents an address in the executor process.
uint64_t getValue() const
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.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
unique_function is a type-erasing functor similar to std::function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< unsigned char, unsigned char > getElfArchType(StringRef Object)
static const std::set< StringRef > DwarfSectionNames
static bool isDwarfSection(StringRef SectionName)
LLVM_ABI void lookupAndApply(unique_function< void(Error)> OnApplied, LookupKind K, const JITDylibSearchOrder &SearchOrder, ArrayRef< LookupPrepareFn > PrepareFns)
Resolve the symbols contributed by every prepare function with a single lookup, then let each of thei...
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
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
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.
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PostFixupPasses
Post-fixup passes.
Describes a segment to be allocated.
Represents an address range in the exceutor process.