xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric //===----- EPCGenericRTDyldMemoryManager.cpp - EPC-bbasde MemMgr -----===//
2*349cc55cSDimitry Andric //
3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*349cc55cSDimitry Andric //
7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8*349cc55cSDimitry Andric 
9*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"
10*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h"
11*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
12*349cc55cSDimitry Andric #include "llvm/Support/Alignment.h"
13*349cc55cSDimitry Andric #include "llvm/Support/FormatVariadic.h"
14*349cc55cSDimitry Andric 
15*349cc55cSDimitry Andric #define DEBUG_TYPE "orc"
16*349cc55cSDimitry Andric 
17*349cc55cSDimitry Andric namespace llvm {
18*349cc55cSDimitry Andric namespace orc {
19*349cc55cSDimitry Andric 
20*349cc55cSDimitry Andric Expected<std::unique_ptr<EPCGenericRTDyldMemoryManager>>
21*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::CreateWithDefaultBootstrapSymbols(
22*349cc55cSDimitry Andric     ExecutorProcessControl &EPC) {
23*349cc55cSDimitry Andric   SymbolAddrs SAs;
24*349cc55cSDimitry Andric   if (auto Err = EPC.getBootstrapSymbols(
25*349cc55cSDimitry Andric           {{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},
26*349cc55cSDimitry Andric            {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
27*349cc55cSDimitry Andric            {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
28*349cc55cSDimitry Andric            {SAs.Deallocate,
29*349cc55cSDimitry Andric             rt::SimpleExecutorMemoryManagerDeallocateWrapperName},
30*349cc55cSDimitry Andric            {SAs.RegisterEHFrame,
31*349cc55cSDimitry Andric             rt::RegisterEHFrameSectionCustomDirectWrapperName},
32*349cc55cSDimitry Andric            {SAs.DeregisterEHFrame,
33*349cc55cSDimitry Andric             rt::DeregisterEHFrameSectionCustomDirectWrapperName}}))
34*349cc55cSDimitry Andric     return std::move(Err);
35*349cc55cSDimitry Andric   return std::make_unique<EPCGenericRTDyldMemoryManager>(EPC, std::move(SAs));
36*349cc55cSDimitry Andric }
37*349cc55cSDimitry Andric 
38*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::EPCGenericRTDyldMemoryManager(
39*349cc55cSDimitry Andric     ExecutorProcessControl &EPC, SymbolAddrs SAs)
40*349cc55cSDimitry Andric     : EPC(EPC), SAs(std::move(SAs)) {
41*349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Created remote allocator " << (void *)this << "\n");
42*349cc55cSDimitry Andric }
43*349cc55cSDimitry Andric 
44*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::~EPCGenericRTDyldMemoryManager() {
45*349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << (void *)this << "\n");
46*349cc55cSDimitry Andric   if (!ErrMsg.empty())
47*349cc55cSDimitry Andric     errs() << "Destroying with existing errors:\n" << ErrMsg << "\n";
48*349cc55cSDimitry Andric 
49*349cc55cSDimitry Andric   Error Err = Error::success();
50*349cc55cSDimitry Andric   if (auto Err2 = EPC.callSPSWrapper<
51*349cc55cSDimitry Andric                   rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>(
52*349cc55cSDimitry Andric           SAs.Reserve, Err, SAs.Instance, FinalizedAllocs)) {
53*349cc55cSDimitry Andric     // FIXME: Report errors through EPC once that functionality is available.
54*349cc55cSDimitry Andric     logAllUnhandledErrors(std::move(Err2), errs(), "");
55*349cc55cSDimitry Andric     return;
56*349cc55cSDimitry Andric   }
57*349cc55cSDimitry Andric 
58*349cc55cSDimitry Andric   if (Err)
59*349cc55cSDimitry Andric     logAllUnhandledErrors(std::move(Err), errs(), "");
60*349cc55cSDimitry Andric }
61*349cc55cSDimitry Andric 
62*349cc55cSDimitry Andric uint8_t *EPCGenericRTDyldMemoryManager::allocateCodeSection(
63*349cc55cSDimitry Andric     uintptr_t Size, unsigned Alignment, unsigned SectionID,
64*349cc55cSDimitry Andric     StringRef SectionName) {
65*349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(M);
66*349cc55cSDimitry Andric   LLVM_DEBUG({
67*349cc55cSDimitry Andric     dbgs() << "Allocator " << (void *)this << " allocating code section "
68*349cc55cSDimitry Andric            << SectionName << ": size = " << formatv("{0:x}", Size)
69*349cc55cSDimitry Andric            << " bytes, alignment = " << Alignment << "\n";
70*349cc55cSDimitry Andric   });
71*349cc55cSDimitry Andric   auto &Seg = Unmapped.back().CodeAllocs;
72*349cc55cSDimitry Andric   Seg.emplace_back(Size, Alignment);
73*349cc55cSDimitry Andric   return reinterpret_cast<uint8_t *>(
74*349cc55cSDimitry Andric       alignAddr(Seg.back().Contents.get(), Align(Alignment)));
75*349cc55cSDimitry Andric }
76*349cc55cSDimitry Andric 
77*349cc55cSDimitry Andric uint8_t *EPCGenericRTDyldMemoryManager::allocateDataSection(
78*349cc55cSDimitry Andric     uintptr_t Size, unsigned Alignment, unsigned SectionID,
79*349cc55cSDimitry Andric     StringRef SectionName, bool IsReadOnly) {
80*349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(M);
81*349cc55cSDimitry Andric   LLVM_DEBUG({
82*349cc55cSDimitry Andric     dbgs() << "Allocator " << (void *)this << " allocating "
83*349cc55cSDimitry Andric            << (IsReadOnly ? "ro" : "rw") << "-data section " << SectionName
84*349cc55cSDimitry Andric            << ": size = " << formatv("{0:x}", Size) << " bytes, alignment "
85*349cc55cSDimitry Andric            << Alignment << ")\n";
86*349cc55cSDimitry Andric   });
87*349cc55cSDimitry Andric 
88*349cc55cSDimitry Andric   auto &Seg =
89*349cc55cSDimitry Andric       IsReadOnly ? Unmapped.back().RODataAllocs : Unmapped.back().RWDataAllocs;
90*349cc55cSDimitry Andric 
91*349cc55cSDimitry Andric   Seg.emplace_back(Size, Alignment);
92*349cc55cSDimitry Andric   return reinterpret_cast<uint8_t *>(
93*349cc55cSDimitry Andric       alignAddr(Seg.back().Contents.get(), Align(Alignment)));
94*349cc55cSDimitry Andric }
95*349cc55cSDimitry Andric 
96*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::reserveAllocationSpace(
97*349cc55cSDimitry Andric     uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize,
98*349cc55cSDimitry Andric     uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) {
99*349cc55cSDimitry Andric 
100*349cc55cSDimitry Andric   {
101*349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(M);
102*349cc55cSDimitry Andric     // If there's already an error then bail out.
103*349cc55cSDimitry Andric     if (!ErrMsg.empty())
104*349cc55cSDimitry Andric       return;
105*349cc55cSDimitry Andric 
106*349cc55cSDimitry Andric     if (!isPowerOf2_32(CodeAlign) || CodeAlign > EPC.getPageSize()) {
107*349cc55cSDimitry Andric       ErrMsg = "Invalid code alignment in reserveAllocationSpace";
108*349cc55cSDimitry Andric       return;
109*349cc55cSDimitry Andric     }
110*349cc55cSDimitry Andric     if (!isPowerOf2_32(RODataAlign) || RODataAlign > EPC.getPageSize()) {
111*349cc55cSDimitry Andric       ErrMsg = "Invalid ro-data alignment in reserveAllocationSpace";
112*349cc55cSDimitry Andric       return;
113*349cc55cSDimitry Andric     }
114*349cc55cSDimitry Andric     if (!isPowerOf2_32(RWDataAlign) || RWDataAlign > EPC.getPageSize()) {
115*349cc55cSDimitry Andric       ErrMsg = "Invalid rw-data alignment in reserveAllocationSpace";
116*349cc55cSDimitry Andric       return;
117*349cc55cSDimitry Andric     }
118*349cc55cSDimitry Andric   }
119*349cc55cSDimitry Andric 
120*349cc55cSDimitry Andric   uint64_t TotalSize = 0;
121*349cc55cSDimitry Andric   TotalSize += alignTo(CodeSize, EPC.getPageSize());
122*349cc55cSDimitry Andric   TotalSize += alignTo(RODataSize, EPC.getPageSize());
123*349cc55cSDimitry Andric   TotalSize += alignTo(RWDataSize, EPC.getPageSize());
124*349cc55cSDimitry Andric 
125*349cc55cSDimitry Andric   LLVM_DEBUG({
126*349cc55cSDimitry Andric     dbgs() << "Allocator " << (void *)this << " reserving "
127*349cc55cSDimitry Andric            << formatv("{0:x}", TotalSize) << " bytes.\n";
128*349cc55cSDimitry Andric   });
129*349cc55cSDimitry Andric 
130*349cc55cSDimitry Andric   Expected<ExecutorAddr> TargetAllocAddr((ExecutorAddr()));
131*349cc55cSDimitry Andric   if (auto Err = EPC.callSPSWrapper<
132*349cc55cSDimitry Andric                  rt::SPSSimpleExecutorMemoryManagerReserveSignature>(
133*349cc55cSDimitry Andric           SAs.Reserve, TargetAllocAddr, SAs.Instance, TotalSize)) {
134*349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(M);
135*349cc55cSDimitry Andric     ErrMsg = toString(std::move(Err));
136*349cc55cSDimitry Andric     return;
137*349cc55cSDimitry Andric   }
138*349cc55cSDimitry Andric   if (!TargetAllocAddr) {
139*349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(M);
140*349cc55cSDimitry Andric     ErrMsg = toString(TargetAllocAddr.takeError());
141*349cc55cSDimitry Andric     return;
142*349cc55cSDimitry Andric   }
143*349cc55cSDimitry Andric 
144*349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(M);
145*349cc55cSDimitry Andric   Unmapped.push_back(AllocGroup());
146*349cc55cSDimitry Andric   Unmapped.back().RemoteCode = {
147*349cc55cSDimitry Andric       *TargetAllocAddr, ExecutorAddrDiff(alignTo(CodeSize, EPC.getPageSize()))};
148*349cc55cSDimitry Andric   Unmapped.back().RemoteROData = {
149*349cc55cSDimitry Andric       Unmapped.back().RemoteCode.End,
150*349cc55cSDimitry Andric       ExecutorAddrDiff(alignTo(RODataSize, EPC.getPageSize()))};
151*349cc55cSDimitry Andric   Unmapped.back().RemoteRWData = {
152*349cc55cSDimitry Andric       Unmapped.back().RemoteROData.End,
153*349cc55cSDimitry Andric       ExecutorAddrDiff(alignTo(RWDataSize, EPC.getPageSize()))};
154*349cc55cSDimitry Andric }
155*349cc55cSDimitry Andric 
156*349cc55cSDimitry Andric bool EPCGenericRTDyldMemoryManager::needsToReserveAllocationSpace() {
157*349cc55cSDimitry Andric   return true;
158*349cc55cSDimitry Andric }
159*349cc55cSDimitry Andric 
160*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::registerEHFrames(uint8_t *Addr,
161*349cc55cSDimitry Andric                                                      uint64_t LoadAddr,
162*349cc55cSDimitry Andric                                                      size_t Size) {
163*349cc55cSDimitry Andric   LLVM_DEBUG({
164*349cc55cSDimitry Andric     dbgs() << "Allocator " << (void *)this << " added unfinalized eh-frame "
165*349cc55cSDimitry Andric            << formatv("[ {0:x} {1:x} ]", LoadAddr, LoadAddr + Size) << "\n";
166*349cc55cSDimitry Andric   });
167*349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(M);
168*349cc55cSDimitry Andric   // Bail out early if there's already an error.
169*349cc55cSDimitry Andric   if (!ErrMsg.empty())
170*349cc55cSDimitry Andric     return;
171*349cc55cSDimitry Andric 
172*349cc55cSDimitry Andric   ExecutorAddr LA(LoadAddr);
173*349cc55cSDimitry Andric   for (auto &Alloc : llvm::reverse(Unfinalized)) {
174*349cc55cSDimitry Andric     if (Alloc.RemoteCode.contains(LA) || Alloc.RemoteROData.contains(LA) ||
175*349cc55cSDimitry Andric         Alloc.RemoteRWData.contains(LA)) {
176*349cc55cSDimitry Andric       Alloc.UnfinalizedEHFrames.push_back({LA, Size});
177*349cc55cSDimitry Andric       return;
178*349cc55cSDimitry Andric     }
179*349cc55cSDimitry Andric   }
180*349cc55cSDimitry Andric   ErrMsg = "eh-frame does not lie inside unfinalized alloc";
181*349cc55cSDimitry Andric }
182*349cc55cSDimitry Andric 
183*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::deregisterEHFrames() {
184*349cc55cSDimitry Andric   // This is a no-op for us: We've registered a deallocation action for it.
185*349cc55cSDimitry Andric }
186*349cc55cSDimitry Andric 
187*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::notifyObjectLoaded(
188*349cc55cSDimitry Andric     RuntimeDyld &Dyld, const object::ObjectFile &Obj) {
189*349cc55cSDimitry Andric   std::lock_guard<std::mutex> Lock(M);
190*349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " applied mappings:\n");
191*349cc55cSDimitry Andric   for (auto &ObjAllocs : Unmapped) {
192*349cc55cSDimitry Andric     mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
193*349cc55cSDimitry Andric                            ObjAllocs.RemoteCode.Start);
194*349cc55cSDimitry Andric     mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
195*349cc55cSDimitry Andric                            ObjAllocs.RemoteROData.Start);
196*349cc55cSDimitry Andric     mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
197*349cc55cSDimitry Andric                            ObjAllocs.RemoteRWData.Start);
198*349cc55cSDimitry Andric     Unfinalized.push_back(std::move(ObjAllocs));
199*349cc55cSDimitry Andric   }
200*349cc55cSDimitry Andric   Unmapped.clear();
201*349cc55cSDimitry Andric }
202*349cc55cSDimitry Andric 
203*349cc55cSDimitry Andric bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) {
204*349cc55cSDimitry Andric   LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " finalizing:\n");
205*349cc55cSDimitry Andric 
206*349cc55cSDimitry Andric   // If there's an error then bail out here.
207*349cc55cSDimitry Andric   std::vector<AllocGroup> Allocs;
208*349cc55cSDimitry Andric   {
209*349cc55cSDimitry Andric     std::lock_guard<std::mutex> Lock(M);
210*349cc55cSDimitry Andric     if (ErrMsg && !this->ErrMsg.empty()) {
211*349cc55cSDimitry Andric       *ErrMsg = std::move(this->ErrMsg);
212*349cc55cSDimitry Andric       return true;
213*349cc55cSDimitry Andric     }
214*349cc55cSDimitry Andric     std::swap(Allocs, Unfinalized);
215*349cc55cSDimitry Andric   }
216*349cc55cSDimitry Andric 
217*349cc55cSDimitry Andric   // Loop over unfinalized objects to make finalization requests.
218*349cc55cSDimitry Andric   for (auto &ObjAllocs : Allocs) {
219*349cc55cSDimitry Andric 
220*349cc55cSDimitry Andric     tpctypes::WireProtectionFlags SegProts[3] = {
221*349cc55cSDimitry Andric         tpctypes::toWireProtectionFlags(
222*349cc55cSDimitry Andric             static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
223*349cc55cSDimitry Andric                                                       sys::Memory::MF_EXEC)),
224*349cc55cSDimitry Andric         tpctypes::toWireProtectionFlags(sys::Memory::MF_READ),
225*349cc55cSDimitry Andric         tpctypes::toWireProtectionFlags(
226*349cc55cSDimitry Andric             static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
227*349cc55cSDimitry Andric                                                       sys::Memory::MF_WRITE))};
228*349cc55cSDimitry Andric 
229*349cc55cSDimitry Andric     ExecutorAddrRange *RemoteAddrs[3] = {&ObjAllocs.RemoteCode,
230*349cc55cSDimitry Andric                                          &ObjAllocs.RemoteROData,
231*349cc55cSDimitry Andric                                          &ObjAllocs.RemoteRWData};
232*349cc55cSDimitry Andric 
233*349cc55cSDimitry Andric     std::vector<Alloc> *SegSections[3] = {&ObjAllocs.CodeAllocs,
234*349cc55cSDimitry Andric                                           &ObjAllocs.RODataAllocs,
235*349cc55cSDimitry Andric                                           &ObjAllocs.RWDataAllocs};
236*349cc55cSDimitry Andric 
237*349cc55cSDimitry Andric     tpctypes::FinalizeRequest FR;
238*349cc55cSDimitry Andric     std::unique_ptr<char[]> AggregateContents[3];
239*349cc55cSDimitry Andric 
240*349cc55cSDimitry Andric     for (unsigned I = 0; I != 3; ++I) {
241*349cc55cSDimitry Andric       FR.Segments.push_back({});
242*349cc55cSDimitry Andric       auto &Seg = FR.Segments.back();
243*349cc55cSDimitry Andric       Seg.Prot = SegProts[I];
244*349cc55cSDimitry Andric       Seg.Addr = RemoteAddrs[I]->Start;
245*349cc55cSDimitry Andric       for (auto &SecAlloc : *SegSections[I]) {
246*349cc55cSDimitry Andric         Seg.Size = alignTo(Seg.Size, SecAlloc.Align);
247*349cc55cSDimitry Andric         Seg.Size += SecAlloc.Size;
248*349cc55cSDimitry Andric       }
249*349cc55cSDimitry Andric       AggregateContents[I] = std::make_unique<char[]>(Seg.Size);
250*349cc55cSDimitry Andric       size_t SecOffset = 0;
251*349cc55cSDimitry Andric       for (auto &SecAlloc : *SegSections[I]) {
252*349cc55cSDimitry Andric         SecOffset = alignTo(SecOffset, SecAlloc.Align);
253*349cc55cSDimitry Andric         memcpy(&AggregateContents[I][SecOffset],
254*349cc55cSDimitry Andric                reinterpret_cast<const char *>(
255*349cc55cSDimitry Andric                    alignAddr(SecAlloc.Contents.get(), Align(SecAlloc.Align))),
256*349cc55cSDimitry Andric                SecAlloc.Size);
257*349cc55cSDimitry Andric         SecOffset += SecAlloc.Size;
258*349cc55cSDimitry Andric         // FIXME: Can we reset SecAlloc.Content here, now that it's copied into
259*349cc55cSDimitry Andric         // the aggregated content?
260*349cc55cSDimitry Andric       }
261*349cc55cSDimitry Andric       Seg.Content = {AggregateContents[I].get(), SecOffset};
262*349cc55cSDimitry Andric     }
263*349cc55cSDimitry Andric 
264*349cc55cSDimitry Andric     for (auto &Frame : ObjAllocs.UnfinalizedEHFrames)
265*349cc55cSDimitry Andric       FR.Actions.push_back(
266*349cc55cSDimitry Andric           {{SAs.RegisterEHFrame,
267*349cc55cSDimitry Andric             {ExecutorAddr(Frame.Addr), ExecutorAddrDiff(Frame.Size)}},
268*349cc55cSDimitry Andric            {SAs.DeregisterEHFrame,
269*349cc55cSDimitry Andric             {ExecutorAddr(Frame.Addr), ExecutorAddrDiff(Frame.Size)}}});
270*349cc55cSDimitry Andric 
271*349cc55cSDimitry Andric     // We'll also need to make an extra allocation for the eh-frame wrapper call
272*349cc55cSDimitry Andric     // arguments.
273*349cc55cSDimitry Andric     Error FinalizeErr = Error::success();
274*349cc55cSDimitry Andric     if (auto Err = EPC.callSPSWrapper<
275*349cc55cSDimitry Andric                    rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>(
276*349cc55cSDimitry Andric             SAs.Finalize, FinalizeErr, SAs.Instance, std::move(FR))) {
277*349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(M);
278*349cc55cSDimitry Andric       this->ErrMsg = toString(std::move(Err));
279*349cc55cSDimitry Andric       dbgs() << "Serialization error: " << this->ErrMsg << "\n";
280*349cc55cSDimitry Andric       if (ErrMsg)
281*349cc55cSDimitry Andric         *ErrMsg = this->ErrMsg;
282*349cc55cSDimitry Andric       return true;
283*349cc55cSDimitry Andric     }
284*349cc55cSDimitry Andric     if (FinalizeErr) {
285*349cc55cSDimitry Andric       std::lock_guard<std::mutex> Lock(M);
286*349cc55cSDimitry Andric       this->ErrMsg = toString(std::move(FinalizeErr));
287*349cc55cSDimitry Andric       dbgs() << "Finalization error: " << this->ErrMsg << "\n";
288*349cc55cSDimitry Andric       if (ErrMsg)
289*349cc55cSDimitry Andric         *ErrMsg = this->ErrMsg;
290*349cc55cSDimitry Andric       return true;
291*349cc55cSDimitry Andric     }
292*349cc55cSDimitry Andric   }
293*349cc55cSDimitry Andric 
294*349cc55cSDimitry Andric   return false;
295*349cc55cSDimitry Andric }
296*349cc55cSDimitry Andric 
297*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::mapAllocsToRemoteAddrs(
298*349cc55cSDimitry Andric     RuntimeDyld &Dyld, std::vector<Alloc> &Allocs, ExecutorAddr NextAddr) {
299*349cc55cSDimitry Andric   for (auto &Alloc : Allocs) {
300*349cc55cSDimitry Andric     NextAddr.setValue(alignTo(NextAddr.getValue(), Alloc.Align));
301*349cc55cSDimitry Andric     LLVM_DEBUG({
302*349cc55cSDimitry Andric       dbgs() << "     " << static_cast<void *>(Alloc.Contents.get()) << " -> "
303*349cc55cSDimitry Andric              << format("0x%016" PRIx64, NextAddr.getValue()) << "\n";
304*349cc55cSDimitry Andric     });
305*349cc55cSDimitry Andric     Dyld.mapSectionAddress(reinterpret_cast<const void *>(alignAddr(
306*349cc55cSDimitry Andric                                Alloc.Contents.get(), Align(Alloc.Align))),
307*349cc55cSDimitry Andric                            NextAddr.getValue());
308*349cc55cSDimitry Andric     Alloc.RemoteAddr = NextAddr;
309*349cc55cSDimitry Andric     // Only advance NextAddr if it was non-null to begin with,
310*349cc55cSDimitry Andric     // otherwise leave it as null.
311*349cc55cSDimitry Andric     if (NextAddr)
312*349cc55cSDimitry Andric       NextAddr += ExecutorAddrDiff(Alloc.Size);
313*349cc55cSDimitry Andric   }
314*349cc55cSDimitry Andric }
315*349cc55cSDimitry Andric 
316*349cc55cSDimitry Andric } // end namespace orc
317*349cc55cSDimitry Andric } // end namespace llvm
318