1 //===- SectionMemoryManager.h - 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 contains the declaration of a section-based memory manager used by 11 // the MCJIT execution engine and RuntimeDyld. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H 16 #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H 17 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ExecutionEngine/JITMemoryManager.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/Memory.h" 22 23 namespace llvm { 24 25 /// This is a simple memory manager which implements the methods called by 26 /// the RuntimeDyld class to allocate memory for section-based loading of 27 /// objects, usually those generated by the MCJIT execution engine. 28 /// 29 /// This memory manager allocates all section memory as read-write. The 30 /// RuntimeDyld will copy JITed section memory into these allocated blocks 31 /// and perform any necessary linking and relocations. 32 /// 33 /// Any client using this memory manager MUST ensure that section-specific 34 /// page permissions have been applied before attempting to execute functions 35 /// in the JITed object. Permissions can be applied either by calling 36 /// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions 37 /// directly. Clients of MCJIT should call MCJIT::finalizeObject. 38 class SectionMemoryManager : public JITMemoryManager { 39 SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; 40 void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; 41 42 public: 43 SectionMemoryManager() { } 44 virtual ~SectionMemoryManager(); 45 46 /// \brief Allocates a memory block of (at least) the given size suitable for 47 /// executable code. 48 /// 49 /// The value of \p Alignment must be a power of two. If \p Alignment is zero 50 /// a default alignment of 16 will be used. 51 virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 52 unsigned SectionID); 53 54 /// \brief Allocates a memory block of (at least) the given size suitable for 55 /// executable code. 56 /// 57 /// The value of \p Alignment must be a power of two. If \p Alignment is zero 58 /// a default alignment of 16 will be used. 59 virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 60 unsigned SectionID, 61 bool isReadOnly); 62 63 /// \brief Applies section-specific memory permissions. 64 /// 65 /// This method is called when object loading is complete and section page 66 /// permissions can be applied. It is up to the memory manager implementation 67 /// to decide whether or not to act on this method. The memory manager will 68 /// typically allocate all sections as read-write and then apply specific 69 /// permissions when this method is called. Code sections cannot be executed 70 /// until this function has been called. 71 /// 72 /// \returns true if an error occurred, false otherwise. 73 virtual bool applyPermissions(std::string *ErrMsg = 0); 74 75 /// This method returns the address of the specified function. As such it is 76 /// only useful for resolving library symbols, not code generated symbols. 77 /// 78 /// If \p AbortOnFailure is false and no function with the given name is 79 /// found, this function returns a null pointer. Otherwise, it prints a 80 /// message to stderr and aborts. 81 virtual void *getPointerToNamedFunction(const std::string &Name, 82 bool AbortOnFailure = true); 83 84 /// \brief Invalidate instruction cache for code sections. 85 /// 86 /// Some platforms with separate data cache and instruction cache require 87 /// explicit cache flush, otherwise JIT code manipulations (like resolved 88 /// relocations) will get to the data cache but not to the instruction cache. 89 /// 90 /// This method is not called by RuntimeDyld or MCJIT during the load 91 /// process. Clients may call this function when needed. See the lli 92 /// tool for example use. 93 virtual void invalidateInstructionCache(); 94 95 private: 96 struct MemoryGroup { 97 SmallVector<sys::MemoryBlock, 16> AllocatedMem; 98 SmallVector<sys::MemoryBlock, 16> FreeMem; 99 sys::MemoryBlock Near; 100 }; 101 102 uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size, 103 unsigned Alignment); 104 105 error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, 106 unsigned Permissions); 107 108 MemoryGroup CodeMem; 109 MemoryGroup RWDataMem; 110 MemoryGroup RODataMem; 111 112 public: 113 /// 114 /// Functions below are not used by MCJIT or RuntimeDyld, but must be 115 /// implemented because they are declared as pure virtuals in the base class. 116 /// 117 118 virtual void setMemoryWritable() { 119 llvm_unreachable("Unexpected call!"); 120 } 121 virtual void setMemoryExecutable() { 122 llvm_unreachable("Unexpected call!"); 123 } 124 virtual void setPoisonMemory(bool poison) { 125 llvm_unreachable("Unexpected call!"); 126 } 127 virtual void AllocateGOT() { 128 llvm_unreachable("Unexpected call!"); 129 } 130 virtual uint8_t *getGOTBase() const { 131 llvm_unreachable("Unexpected call!"); 132 return 0; 133 } 134 virtual uint8_t *startFunctionBody(const Function *F, 135 uintptr_t &ActualSize){ 136 llvm_unreachable("Unexpected call!"); 137 return 0; 138 } 139 virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, 140 unsigned Alignment) { 141 llvm_unreachable("Unexpected call!"); 142 return 0; 143 } 144 virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, 145 uint8_t *FunctionEnd) { 146 llvm_unreachable("Unexpected call!"); 147 } 148 virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { 149 llvm_unreachable("Unexpected call!"); 150 return 0; 151 } 152 virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { 153 llvm_unreachable("Unexpected call!"); 154 return 0; 155 } 156 virtual void deallocateFunctionBody(void *Body) { 157 llvm_unreachable("Unexpected call!"); 158 } 159 virtual uint8_t *startExceptionTable(const Function *F, 160 uintptr_t &ActualSize) { 161 llvm_unreachable("Unexpected call!"); 162 return 0; 163 } 164 virtual void endExceptionTable(const Function *F, uint8_t *TableStart, 165 uint8_t *TableEnd, uint8_t *FrameRegister) { 166 llvm_unreachable("Unexpected call!"); 167 } 168 virtual void deallocateExceptionTable(void *ET) { 169 llvm_unreachable("Unexpected call!"); 170 } 171 }; 172 173 } 174 175 #endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H 176 177