1 //===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This memory manager allocates local storage and keeps a record of each
11 // allocation. Iterators are provided for all data and code allocations.
13 //===----------------------------------------------------------------------===//
15 #include "RemoteMemoryManager.h"
16 #include "llvm/ExecutionEngine/ExecutionEngine.h"
17 #include "llvm/ExecutionEngine/ObjectImage.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Format.h"
22 using std::error_code;
24 #define DEBUG_TYPE "lli"
26 RemoteMemoryManager::~RemoteMemoryManager() {
27 for (SmallVector<Allocation, 2>::iterator
28 I = AllocatedSections.begin(), E = AllocatedSections.end();
30 sys::Memory::releaseMappedMemory(I->MB);
33 uint8_t *RemoteMemoryManager::
34 allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
35 StringRef SectionName) {
36 // The recording memory manager is just a local copy of the remote target.
37 // The alignment requirement is just stored here for later use. Regular
38 // heap storage is sufficient here, but we're using mapped memory to work
39 // around a bug in MCJIT.
40 sys::MemoryBlock Block = allocateSection(Size);
41 // AllocatedSections will own this memory.
42 AllocatedSections.push_back( Allocation(Block, Alignment, true) );
43 // UnmappedSections has the same information but does not own the memory.
44 UnmappedSections.push_back( Allocation(Block, Alignment, true) );
45 return (uint8_t*)Block.base();
48 uint8_t *RemoteMemoryManager::
49 allocateDataSection(uintptr_t Size, unsigned Alignment,
50 unsigned SectionID, StringRef SectionName,
52 // The recording memory manager is just a local copy of the remote target.
53 // The alignment requirement is just stored here for later use. Regular
54 // heap storage is sufficient here, but we're using mapped memory to work
55 // around a bug in MCJIT.
56 sys::MemoryBlock Block = allocateSection(Size);
57 // AllocatedSections will own this memory.
58 AllocatedSections.push_back( Allocation(Block, Alignment, false) );
59 // UnmappedSections has the same information but does not own the memory.
60 UnmappedSections.push_back( Allocation(Block, Alignment, false) );
61 return (uint8_t*)Block.base();
64 sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
66 sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
68 sys::Memory::MF_READ |
69 sys::Memory::MF_WRITE,
71 assert(!ec && MB.base());
73 // FIXME: This is part of a work around to keep sections near one another
74 // when MCJIT performs relocations after code emission but before
75 // the generated code is moved to the remote target.
76 // Save this address as the basis for our next request
81 void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
82 const ObjectImage *Obj) {
83 // The client should have called setRemoteTarget() before triggering any
89 // FIXME: Make this function thread safe.
91 // Lay out our sections in order, with all the code sections first, then
92 // all the data sections.
93 uint64_t CurOffset = 0;
94 unsigned MaxAlign = Target->getPageAlignment();
95 SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
96 unsigned NumSections = UnmappedSections.size();
97 // We're going to go through the list twice to separate code and data, but
98 // it's a very small list, so that's OK.
99 for (size_t i = 0, e = NumSections; i != e; ++i) {
100 Allocation &Section = UnmappedSections[i];
101 if (Section.IsCode) {
102 unsigned Size = Section.MB.size();
103 unsigned Align = Section.Alignment;
104 DEBUG(dbgs() << "code region: size " << Size
105 << ", alignment " << Align << "\n");
106 // Align the current offset up to whatever is needed for the next
108 CurOffset = (CurOffset + Align - 1) / Align * Align;
109 // Save off the address of the new section and allocate its space.
110 Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
114 // Adjust to keep code and data aligned on separate pages.
115 CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
116 for (size_t i = 0, e = NumSections; i != e; ++i) {
117 Allocation &Section = UnmappedSections[i];
118 if (!Section.IsCode) {
119 unsigned Size = Section.MB.size();
120 unsigned Align = Section.Alignment;
121 DEBUG(dbgs() << "data region: size " << Size
122 << ", alignment " << Align << "\n");
123 // Align the current offset up to whatever is needed for the next
125 CurOffset = (CurOffset + Align - 1) / Align * Align;
126 // Save off the address of the new section and allocate its space.
127 Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
132 // Allocate space in the remote target.
134 if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
135 report_fatal_error(Target->getErrorMsg());
137 // Map the section addresses so relocations will get updated in the local
138 // copies of the sections.
139 for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
140 uint64_t Addr = RemoteAddr + Offsets[i].second;
141 EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
143 DEBUG(dbgs() << " Mapping local: " << Offsets[i].first.MB.base()
144 << " to remote: 0x" << format("%llx", Addr) << "\n");
146 MappedSections[Addr] = Offsets[i].first;
149 UnmappedSections.clear();
152 bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
153 // FIXME: Make this function thread safe.
154 for (DenseMap<uint64_t, Allocation>::iterator
155 I = MappedSections.begin(), E = MappedSections.end();
157 uint64_t RemoteAddr = I->first;
158 const Allocation &Section = I->second;
159 if (Section.IsCode) {
160 if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
161 report_fatal_error(Target->getErrorMsg());
162 DEBUG(dbgs() << " loading code: " << Section.MB.base()
163 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
165 if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
166 report_fatal_error(Target->getErrorMsg());
167 DEBUG(dbgs() << " loading data: " << Section.MB.base()
168 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
172 MappedSections.clear();
177 void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
178 void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
179 void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
180 void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
181 uint8_t *RemoteMemoryManager::getGOTBase() const {
182 llvm_unreachable("Unexpected!");
185 uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
186 llvm_unreachable("Unexpected!");
189 uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
190 unsigned Alignment) {
191 llvm_unreachable("Unexpected!");
194 void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
195 uint8_t *FunctionEnd) {
196 llvm_unreachable("Unexpected!");
198 uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
199 llvm_unreachable("Unexpected!");
202 uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
203 llvm_unreachable("Unexpected!");
206 void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
207 llvm_unreachable("Unexpected!");