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