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/ADT/StringRef.h" 20#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 21#include "llvm/Support/Memory.h" 22#include <cstdint> 23#include <string> 24#include <system_error> 25 26namespace llvm { 27 28/// This is a simple memory manager which implements the methods called by 29/// the RuntimeDyld class to allocate memory for section-based loading of 30/// objects, usually those generated by the MCJIT execution engine. 31/// 32/// This memory manager allocates all section memory as read-write. The 33/// RuntimeDyld will copy JITed section memory into these allocated blocks 34/// and perform any necessary linking and relocations. 35/// 36/// Any client using this memory manager MUST ensure that section-specific 37/// page permissions have been applied before attempting to execute functions 38/// in the JITed object. Permissions can be applied either by calling 39/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory 40/// directly. Clients of MCJIT should call MCJIT::finalizeObject. 41class SectionMemoryManager : public RTDyldMemoryManager { 42public: 43 SectionMemoryManager() = default; 44 SectionMemoryManager(const SectionMemoryManager&) = delete; 45 void operator=(const SectionMemoryManager&) = delete; 46 ~SectionMemoryManager() override; 47 48 /// \brief Allocates a memory block of (at least) the given size suitable for 49 /// executable code. 50 /// 51 /// The value of \p Alignment must be a power of two. If \p Alignment is zero 52 /// a default alignment of 16 will be used. 53 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 54 unsigned SectionID, 55 StringRef SectionName) override; 56 57 /// \brief Allocates a memory block of (at least) the given size suitable for 58 /// executable code. 59 /// 60 /// The value of \p Alignment must be a power of two. If \p Alignment is zero 61 /// a default alignment of 16 will be used. 62 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 63 unsigned SectionID, StringRef SectionName, 64 bool isReadOnly) override; 65 66 /// \brief Update section-specific memory permissions and other attributes. 67 /// 68 /// This method is called when object loading is complete and section page 69 /// permissions can be applied. It is up to the memory manager implementation 70 /// to decide whether or not to act on this method. The memory manager will 71 /// typically allocate all sections as read-write and then apply specific 72 /// permissions when this method is called. Code sections cannot be executed 73 /// until this function has been called. In addition, any cache coherency 74 /// operations needed to reliably use the memory are also performed. 75 /// 76 /// \returns true if an error occurred, false otherwise. 77 bool finalizeMemory(std::string *ErrMsg = nullptr) override; 78 79 /// \brief Invalidate instruction cache for code sections. 80 /// 81 /// Some platforms with separate data cache and instruction cache require 82 /// explicit cache flush, otherwise JIT code manipulations (like resolved 83 /// relocations) will get to the data cache but not to the instruction cache. 84 /// 85 /// This method is called from finalizeMemory. 86 virtual void invalidateInstructionCache(); 87 88private: 89 struct FreeMemBlock { 90 // The actual block of free memory 91 sys::MemoryBlock Free; 92 // If there is a pending allocation from the same reservation right before 93 // this block, store it's index in PendingMem, to be able to update the 94 // pending region if part of this block is allocated, rather than having to 95 // create a new one 96 unsigned PendingPrefixIndex; 97 }; 98 99 struct MemoryGroup { 100 // PendingMem contains all blocks of memory (subblocks of AllocatedMem) 101 // which have not yet had their permissions applied, but have been given 102 // out to the user. FreeMem contains all block of memory, which have 103 // neither had their permissions applied, nor been given out to the user. 104 SmallVector<sys::MemoryBlock, 16> PendingMem; 105 SmallVector<FreeMemBlock, 16> FreeMem; 106 107 // All memory blocks that have been requested from the system 108 SmallVector<sys::MemoryBlock, 16> AllocatedMem; 109 110 sys::MemoryBlock Near; 111 }; 112 113 uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size, 114 unsigned Alignment); 115 116 std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, 117 unsigned Permissions); 118 119 MemoryGroup CodeMem; 120 MemoryGroup RWDataMem; 121 MemoryGroup RODataMem; 122}; 123 124} // end namespace llvm 125 126#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H 127