15#define DEBUG_TYPE "orc"
22Expected<std::unique_ptr<EPCGenericRTDyldMemoryManager>>
26 if (
auto Err = EPC.getBootstrapSymbols(
27 {{SAs.Instance, rt::sps_ci::SimpleNativeMemoryMapInstanceName},
28 {SAs.Reserve, rt::sps_ci::MemMgrReserve::Name},
29 {SAs.Initialize, rt::sps_ci::MemMgrInitialize::Name},
30 {SAs.Release, rt::sps_ci::MemMgrRelease::Name},
31 {SAs.RegisterEHFrame, rt::RegisterEHFrameSectionAllocActionName},
32 {SAs.DeregisterEHFrame,
33 rt::DeregisterEHFrameSectionAllocActionName}}))
34 return std::move(Err);
35 return std::make_unique<EPCGenericRTDyldMemoryManager>(EPC, std::move(SAs));
40 : EPC(EPC), SAs(
std::
move(SAs)) {
41 LLVM_DEBUG(
dbgs() <<
"Created remote allocator " << (
void *)
this <<
"\n");
45 LLVM_DEBUG(
dbgs() <<
"Destroyed remote allocator " << (
void *)
this <<
"\n");
47 errs() <<
"Destroying with existing errors:\n" << ErrMsg <<
"\n";
51 SAs.Reserve, Err, SAs.Instance, FinalizedAllocs)) {
64 std::lock_guard<std::mutex> Lock(M);
66 dbgs() <<
"Allocator " << (
void *)
this <<
" allocating code section "
68 <<
" bytes, alignment = " << Alignment <<
"\n";
70 auto &Seg = Unmapped.back().CodeAllocs;
71 Seg.emplace_back(
Size, Alignment);
72 return reinterpret_cast<uint8_t *
>(
79 std::lock_guard<std::mutex> Lock(M);
81 dbgs() <<
"Allocator " << (
void *)
this <<
" allocating "
82 << (IsReadOnly ?
"ro" :
"rw") <<
"-data section " <<
SectionName
83 <<
": size = " <<
formatv(
"{0:x}",
Size) <<
" bytes, alignment "
84 << Alignment <<
")\n";
88 IsReadOnly ? Unmapped.back().RODataAllocs : Unmapped.back().RWDataAllocs;
90 Seg.emplace_back(
Size, Alignment);
91 return reinterpret_cast<uint8_t *
>(
100 std::lock_guard<std::mutex> Lock(M);
105 if (CodeAlign > EPC.getPageSize()) {
106 ErrMsg =
"Invalid code alignment in reserveAllocationSpace";
109 if (RODataAlign > EPC.getPageSize()) {
110 ErrMsg =
"Invalid ro-data alignment in reserveAllocationSpace";
113 if (RWDataAlign > EPC.getPageSize()) {
114 ErrMsg =
"Invalid rw-data alignment in reserveAllocationSpace";
119 uint64_t TotalSize = 0;
121 TotalSize +=
alignTo(RODataSize, EPC.getPageSize());
122 TotalSize +=
alignTo(RWDataSize, EPC.getPageSize());
125 dbgs() <<
"Allocator " << (
void *)
this <<
" reserving "
126 <<
formatv(
"{0:x}", TotalSize) <<
" bytes.\n";
131 SAs.Reserve, TargetAllocAddr, SAs.Instance, TotalSize)) {
132 std::lock_guard<std::mutex> Lock(M);
136 if (!TargetAllocAddr) {
137 std::lock_guard<std::mutex> Lock(M);
138 ErrMsg =
toString(TargetAllocAddr.takeError());
142 std::lock_guard<std::mutex> Lock(M);
143 Unmapped.push_back(SectionAllocGroup());
144 Unmapped.back().RemoteCode = {
146 Unmapped.back().RemoteROData = {
147 Unmapped.back().RemoteCode.End,
149 Unmapped.back().RemoteRWData = {
150 Unmapped.back().RemoteROData.End,
162 dbgs() <<
"Allocator " << (
void *)
this <<
" added unfinalized eh-frame "
163 <<
formatv(
"[ {0:x} {1:x} ]", LoadAddr, LoadAddr +
Size) <<
"\n";
165 std::lock_guard<std::mutex> Lock(M);
172 if (SecAllocGroup.RemoteCode.contains(LA) ||
173 SecAllocGroup.RemoteROData.contains(LA) ||
174 SecAllocGroup.RemoteRWData.contains(LA)) {
175 SecAllocGroup.UnfinalizedEHFrames.push_back({LA,
Size});
179 ErrMsg =
"eh-frame does not lie inside unfinalized alloc";
188 std::lock_guard<std::mutex> Lock(M);
189 LLVM_DEBUG(
dbgs() <<
"Allocator " << (
void *)
this <<
" applied mappings:\n");
190 for (
auto &ObjAllocs : Unmapped) {
191 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
192 ObjAllocs.RemoteCode.Start);
193 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
194 ObjAllocs.RemoteROData.Start);
195 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
196 ObjAllocs.RemoteRWData.Start);
197 Unfinalized.push_back(std::move(ObjAllocs));
203 LLVM_DEBUG(
dbgs() <<
"Allocator " << (
void *)
this <<
" finalizing:\n");
206 std::vector<SectionAllocGroup> SecAllocGroups;
208 std::lock_guard<std::mutex> Lock(M);
209 if (ErrMsg && !this->ErrMsg.empty()) {
210 *ErrMsg = std::move(this->ErrMsg);
217 for (
auto &SecAllocGroup : SecAllocGroups) {
223 &SecAllocGroup.RemoteROData,
224 &SecAllocGroup.RemoteRWData};
226 std::vector<SectionAlloc> *SegSections[3] = {&SecAllocGroup.CodeAllocs,
227 &SecAllocGroup.RODataAllocs,
228 &SecAllocGroup.RWDataAllocs};
231 std::unique_ptr<char[]> AggregateContents[3];
233 for (
unsigned I = 0;
I != 3; ++
I) {
236 Seg.RAG = SegMemProts[
I];
237 Seg.Addr = RemoteAddrs[
I]->
Start;
238 for (
auto &SecAlloc : *SegSections[
I]) {
239 Seg.Size =
alignTo(Seg.Size, SecAlloc.Align);
240 Seg.Size += SecAlloc.Size;
242 AggregateContents[
I] = std::make_unique<char[]>(Seg.Size);
243 size_t SecOffset = 0;
244 for (
auto &SecAlloc : *SegSections[
I]) {
245 SecOffset =
alignTo(SecOffset, SecAlloc.Align);
246 memcpy(&AggregateContents[
I][SecOffset],
247 reinterpret_cast<const char *
>(
250 SecOffset += SecAlloc.Size;
254 Seg.Content = {AggregateContents[
I].get(), SecOffset};
257 for (
auto &Frame : SecAllocGroup.UnfinalizedEHFrames)
261 SAs.RegisterEHFrame, Frame)),
264 SAs.DeregisterEHFrame, Frame))});
270 SAs.Initialize, InitializeKey, SAs.Instance, std::move(FR))) {
271 std::lock_guard<std::mutex> Lock(M);
272 this->ErrMsg =
toString(std::move(Err));
273 dbgs() <<
"Serialization error: " << this->ErrMsg <<
"\n";
275 *ErrMsg = this->ErrMsg;
278 if (!InitializeKey) {
279 std::lock_guard<std::mutex> Lock(M);
281 dbgs() <<
"Finalization error: " << this->ErrMsg <<
"\n";
283 *ErrMsg = this->ErrMsg;
291void EPCGenericRTDyldMemoryManager::mapAllocsToRemoteAddrs(
292 RuntimeDyld &Dyld, std::vector<SectionAlloc> &Allocs,
294 for (
auto &
Alloc : Allocs) {
297 dbgs() <<
" " <<
static_cast<void *
>(
Alloc.Contents.get()) <<
" -> "
303 Alloc.RemoteAddr = NextAddr;
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.
LLVM_ABI void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress)
Map a section to its target address space value.
Represent a constant reference to a string, i.e.
This class is the base class for all object file types.
uint8_t * allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) override
Allocate a memory block of (at least) the given size suitable for data.
bool finalizeMemory(std::string *ErrMsg=nullptr) override
This method is called when object loading is complete and section page permissions can be applied.
bool needsToReserveAllocationSpace() override
Override to return true to enable the reserveAllocationSpace callback.
static Expected< std::unique_ptr< EPCGenericRTDyldMemoryManager > > CreateWithDefaultBootstrapSymbols(ExecutorProcessControl &EPC)
Create an EPCGenericRTDyldMemoryManager using the given EPC, looking up the default symbol names in t...
EPCGenericRTDyldMemoryManager(ExecutorProcessControl &EPC, SymbolAddrs SAs)
Create an EPCGenericRTDyldMemoryManager using the given EPC and symbol addrs.
void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign, uintptr_t RODataSize, Align RODataAlign, uintptr_t RWDataSize, Align RWDataAlign) override
Inform the memory manager about the total amount of memory required to allocate all sections to be lo...
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override
Register the EH frames with the runtime so that c++ exceptions work.
~EPCGenericRTDyldMemoryManager() override
void notifyObjectLoaded(RuntimeDyld &Dyld, const object::ObjectFile &Obj) override
This method is called after an object has been loaded into memory but before relocations are applied ...
void deregisterEHFrames() override
uint8_t * allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override
Allocate a memory block of (at least) the given size suitable for executable code.
Represents an address in the executor process.
uint64_t getValue() const
void setValue(uint64_t Addr)
ExecutorProcessControl supports interaction with a JIT target process.
A utility class for serializing to a blob from a variadic list.
static Expected< WrapperFunctionCall > Create(ExecutorAddr FnAddr, const ArgTs &...Args)
Create a WrapperFunctionCall using the given SPS serializer to serialize the arguments.
MemProt
Describes Read/Write/Exec permissions for memory.
uint64_t ExecutorAddrDiff
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Symbol addresses for memory access.
Represents an address range in the exceutor process.
shared::SPSExpected< shared::SPSExecutorAddr >( shared::SPSExecutorAddr, shared::SPSFinalizeRequest) SPSSig
shared::SPSError(shared::SPSExecutorAddr, shared::SPSSequence< shared::SPSExecutorAddr >) SPSSig
shared::SPSExpected< shared::SPSExecutorAddr >( shared::SPSExecutorAddr, uint64_t) SPSSig
std::vector< SegFinalizeRequest > Segments
shared::AllocActions Actions