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