SectionMemoryManager.cpp revision 50f19a906a9d5e42d7707b54a11c0f0c9265fc1f
1//===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==// 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 file implements the section-based memory manager used by the MCJIT 11// execution engine and RuntimeDyld 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/Config/config.h" 16#include "llvm/ExecutionEngine/SectionMemoryManager.h" 17#include "llvm/Support/DynamicLibrary.h" 18#include "llvm/Support/MathExtras.h" 19 20#ifdef __linux__ 21 // These includes used by SectionMemoryManager::getPointerToNamedFunction() 22 // for Glibc trickery. See comments in this function for more information. 23 #ifdef HAVE_SYS_STAT_H 24 #include <sys/stat.h> 25 #endif 26 #include <fcntl.h> 27 #include <unistd.h> 28#endif 29 30namespace llvm { 31 32uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, 33 unsigned Alignment, 34 unsigned SectionID, 35 bool IsReadOnly) { 36 if (IsReadOnly) 37 return allocateSection(RODataMem, Size, Alignment); 38 return allocateSection(RWDataMem, Size, Alignment); 39} 40 41uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size, 42 unsigned Alignment, 43 unsigned SectionID) { 44 return allocateSection(CodeMem, Size, Alignment); 45} 46 47uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, 48 uintptr_t Size, 49 unsigned Alignment) { 50 if (!Alignment) 51 Alignment = 16; 52 53 assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two."); 54 55 uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1); 56 uintptr_t Addr = 0; 57 58 // Look in the list of free memory regions and use a block there if one 59 // is available. 60 for (int i = 0, e = MemGroup.FreeMem.size(); i != e; ++i) { 61 sys::MemoryBlock &MB = MemGroup.FreeMem[i]; 62 if (MB.size() >= RequiredSize) { 63 Addr = (uintptr_t)MB.base(); 64 uintptr_t EndOfBlock = Addr + MB.size(); 65 // Align the address. 66 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); 67 // Store cutted free memory block. 68 MemGroup.FreeMem[i] = sys::MemoryBlock((void*)(Addr + Size), 69 EndOfBlock - Addr - Size); 70 return (uint8_t*)Addr; 71 } 72 } 73 74 // No pre-allocated free block was large enough. Allocate a new memory region. 75 // Note that all sections get allocated as read-write. The permissions will 76 // be updated later based on memory group. 77 // 78 // FIXME: It would be useful to define a default allocation size (or add 79 // it as a constructor parameter) to minimize the number of allocations. 80 // 81 // FIXME: Initialize the Near member for each memory group to avoid 82 // interleaving. 83 error_code ec; 84 sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize, 85 &MemGroup.Near, 86 sys::Memory::MF_READ | 87 sys::Memory::MF_WRITE, 88 ec); 89 if (ec) { 90 // FIXME: Add error propogation to the interface. 91 return NULL; 92 } 93 94 // Save this address as the basis for our next request 95 MemGroup.Near = MB; 96 97 MemGroup.AllocatedMem.push_back(MB); 98 Addr = (uintptr_t)MB.base(); 99 uintptr_t EndOfBlock = Addr + MB.size(); 100 101 // Align the address. 102 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); 103 104 // The allocateMappedMemory may allocate much more memory than we need. In 105 // this case, we store the unused memory as a free memory block. 106 unsigned FreeSize = EndOfBlock-Addr-Size; 107 if (FreeSize > 16) 108 MemGroup.FreeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize)); 109 110 // Return aligned address 111 return (uint8_t*)Addr; 112} 113 114bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) 115{ 116 // FIXME: Should in-progress permissions be reverted if an error occurs? 117 error_code ec; 118 119 // Make code memory executable. 120 ec = applyMemoryGroupPermissions(CodeMem, 121 sys::Memory::MF_READ | sys::Memory::MF_EXEC); 122 if (ec) { 123 if (ErrMsg) { 124 *ErrMsg = ec.message(); 125 } 126 return true; 127 } 128 129 // Make read-only data memory read-only. 130 ec = applyMemoryGroupPermissions(RODataMem, 131 sys::Memory::MF_READ | sys::Memory::MF_EXEC); 132 if (ec) { 133 if (ErrMsg) { 134 *ErrMsg = ec.message(); 135 } 136 return true; 137 } 138 139 // Read-write data memory already has the correct permissions 140 141 // Some platforms with separate data cache and instruction cache require 142 // explicit cache flush, otherwise JIT code manipulations (like resolved 143 // relocations) will get to the data cache but not to the instruction cache. 144 invalidateInstructionCache(); 145 146 return false; 147} 148 149// Determine whether we can register EH tables. 150#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ 151 !defined(__USING_SJLJ_EXCEPTIONS__)) 152#define HAVE_EHTABLE_SUPPORT 1 153#else 154#define HAVE_EHTABLE_SUPPORT 0 155#endif 156 157#if HAVE_EHTABLE_SUPPORT 158extern "C" void __register_frame(void*); 159 160static const char *processFDE(const char *Entry) { 161 const char *P = Entry; 162 uint32_t Length = *((uint32_t*)P); 163 P += 4; 164 uint32_t Offset = *((uint32_t*)P); 165 if (Offset != 0) 166 __register_frame((void*)Entry); 167 return P + Length; 168} 169#endif 170 171void SectionMemoryManager::registerEHFrames(StringRef SectionData) { 172#if HAVE_EHTABLE_SUPPORT 173 const char *P = SectionData.data(); 174 const char *End = SectionData.data() + SectionData.size(); 175 do { 176 P = processFDE(P); 177 } while(P != End); 178#endif 179} 180 181error_code SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, 182 unsigned Permissions) { 183 184 for (int i = 0, e = MemGroup.AllocatedMem.size(); i != e; ++i) { 185 error_code ec; 186 ec = sys::Memory::protectMappedMemory(MemGroup.AllocatedMem[i], 187 Permissions); 188 if (ec) { 189 return ec; 190 } 191 } 192 193 return error_code::success(); 194} 195 196void SectionMemoryManager::invalidateInstructionCache() { 197 for (int i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) 198 sys::Memory::InvalidateInstructionCache(CodeMem.AllocatedMem[i].base(), 199 CodeMem.AllocatedMem[i].size()); 200} 201 202static int jit_noop() { 203 return 0; 204} 205 206void *SectionMemoryManager::getPointerToNamedFunction(const std::string &Name, 207 bool AbortOnFailure) { 208#if defined(__linux__) 209 //===--------------------------------------------------------------------===// 210 // Function stubs that are invoked instead of certain library calls 211 // 212 // Force the following functions to be linked in to anything that uses the 213 // JIT. This is a hack designed to work around the all-too-clever Glibc 214 // strategy of making these functions work differently when inlined vs. when 215 // not inlined, and hiding their real definitions in a separate archive file 216 // that the dynamic linker can't see. For more info, search for 217 // 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. 218 if (Name == "stat") return (void*)(intptr_t)&stat; 219 if (Name == "fstat") return (void*)(intptr_t)&fstat; 220 if (Name == "lstat") return (void*)(intptr_t)&lstat; 221 if (Name == "stat64") return (void*)(intptr_t)&stat64; 222 if (Name == "fstat64") return (void*)(intptr_t)&fstat64; 223 if (Name == "lstat64") return (void*)(intptr_t)&lstat64; 224 if (Name == "atexit") return (void*)(intptr_t)&atexit; 225 if (Name == "mknod") return (void*)(intptr_t)&mknod; 226#endif // __linux__ 227 228 // We should not invoke parent's ctors/dtors from generated main()! 229 // On Mingw and Cygwin, the symbol __main is resolved to 230 // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors 231 // (and register wrong callee's dtors with atexit(3)). 232 // We expect ExecutionEngine::runStaticConstructorsDestructors() 233 // is called before ExecutionEngine::runFunctionAsMain() is called. 234 if (Name == "__main") return (void*)(intptr_t)&jit_noop; 235 236 const char *NameStr = Name.c_str(); 237 void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); 238 if (Ptr) return Ptr; 239 240 // If it wasn't found and if it starts with an underscore ('_') character, 241 // try again without the underscore. 242 if (NameStr[0] == '_') { 243 Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); 244 if (Ptr) return Ptr; 245 } 246 247 if (AbortOnFailure) 248 report_fatal_error("Program used external function '" + Name + 249 "' which could not be resolved!"); 250 return 0; 251} 252 253SectionMemoryManager::~SectionMemoryManager() { 254 for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) 255 sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]); 256 for (unsigned i = 0, e = RWDataMem.AllocatedMem.size(); i != e; ++i) 257 sys::Memory::releaseMappedMemory(RWDataMem.AllocatedMem[i]); 258 for (unsigned i = 0, e = RODataMem.AllocatedMem.size(); i != e; ++i) 259 sys::Memory::releaseMappedMemory(RODataMem.AllocatedMem[i]); 260} 261 262} // namespace llvm 263 264