1249259Sdim//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===// 2249259Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6249259Sdim// 7249259Sdim//===----------------------------------------------------------------------===// 8249259Sdim// 9249259Sdim// This file contains the declaration of a section-based memory manager used by 10249259Sdim// the MCJIT execution engine and RuntimeDyld. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14249259Sdim#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H 15249259Sdim#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H 16249259Sdim 17249259Sdim#include "llvm/ADT/SmallVector.h" 18314564Sdim#include "llvm/ADT/StringRef.h" 19288943Sdim#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" 20249259Sdim#include "llvm/Support/Memory.h" 21314564Sdim#include <cstdint> 22314564Sdim#include <string> 23314564Sdim#include <system_error> 24249259Sdim 25249259Sdimnamespace llvm { 26314564Sdim 27249259Sdim/// This is a simple memory manager which implements the methods called by 28249259Sdim/// the RuntimeDyld class to allocate memory for section-based loading of 29249259Sdim/// objects, usually those generated by the MCJIT execution engine. 30249259Sdim/// 31249259Sdim/// This memory manager allocates all section memory as read-write. The 32249259Sdim/// RuntimeDyld will copy JITed section memory into these allocated blocks 33249259Sdim/// and perform any necessary linking and relocations. 34249259Sdim/// 35249259Sdim/// Any client using this memory manager MUST ensure that section-specific 36249259Sdim/// page permissions have been applied before attempting to execute functions 37249259Sdim/// in the JITed object. Permissions can be applied either by calling 38261991Sdim/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory 39249259Sdim/// directly. Clients of MCJIT should call MCJIT::finalizeObject. 40261991Sdimclass SectionMemoryManager : public RTDyldMemoryManager { 41314564Sdimpublic: 42327952Sdim /// This enum describes the various reasons to allocate pages from 43327952Sdim /// allocateMappedMemory. 44327952Sdim enum class AllocationPurpose { 45327952Sdim Code, 46327952Sdim ROData, 47327952Sdim RWData, 48327952Sdim }; 49327952Sdim 50327952Sdim /// Implementations of this interface are used by SectionMemoryManager to 51327952Sdim /// request pages from the operating system. 52327952Sdim class MemoryMapper { 53327952Sdim public: 54327952Sdim /// This method attempts to allocate \p NumBytes bytes of virtual memory for 55327952Sdim /// \p Purpose. \p NearBlock may point to an existing allocation, in which 56327952Sdim /// case an attempt is made to allocate more memory near the existing block. 57327952Sdim /// The actual allocated address is not guaranteed to be near the requested 58327952Sdim /// address. \p Flags is used to set the initial protection flags for the 59327952Sdim /// block of the memory. \p EC [out] returns an object describing any error 60327952Sdim /// that occurs. 61327952Sdim /// 62327952Sdim /// This method may allocate more than the number of bytes requested. The 63327952Sdim /// actual number of bytes allocated is indicated in the returned 64327952Sdim /// MemoryBlock. 65327952Sdim /// 66327952Sdim /// The start of the allocated block must be aligned with the system 67327952Sdim /// allocation granularity (64K on Windows, page size on Linux). If the 68327952Sdim /// address following \p NearBlock is not so aligned, it will be rounded up 69327952Sdim /// to the next allocation granularity boundary. 70327952Sdim /// 71327952Sdim /// \r a non-null MemoryBlock if the function was successful, otherwise a 72327952Sdim /// null MemoryBlock with \p EC describing the error. 73327952Sdim virtual sys::MemoryBlock 74327952Sdim allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes, 75327952Sdim const sys::MemoryBlock *const NearBlock, 76327952Sdim unsigned Flags, std::error_code &EC) = 0; 77327952Sdim 78327952Sdim /// This method sets the protection flags for a block of memory to the state 79327952Sdim /// specified by \p Flags. The behavior is not specified if the memory was 80327952Sdim /// not allocated using the allocateMappedMemory method. 81327952Sdim /// \p Block describes the memory block to be protected. 82327952Sdim /// \p Flags specifies the new protection state to be assigned to the block. 83327952Sdim /// 84327952Sdim /// If \p Flags is MF_WRITE, the actual behavior varies with the operating 85327952Sdim /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture 86327952Sdim /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386). 87327952Sdim /// 88327952Sdim /// \r error_success if the function was successful, or an error_code 89327952Sdim /// describing the failure if an error occurred. 90327952Sdim virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block, 91327952Sdim unsigned Flags) = 0; 92327952Sdim 93327952Sdim /// This method releases a block of memory that was allocated with the 94327952Sdim /// allocateMappedMemory method. It should not be used to release any memory 95327952Sdim /// block allocated any other way. 96327952Sdim /// \p Block describes the memory to be released. 97327952Sdim /// 98327952Sdim /// \r error_success if the function was successful, or an error_code 99327952Sdim /// describing the failure if an error occurred. 100327952Sdim virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0; 101327952Sdim 102327952Sdim virtual ~MemoryMapper(); 103327952Sdim }; 104327952Sdim 105327952Sdim /// Creates a SectionMemoryManager instance with \p MM as the associated 106327952Sdim /// memory mapper. If \p MM is nullptr then a default memory mapper is used 107327952Sdim /// that directly calls into the operating system. 108327952Sdim SectionMemoryManager(MemoryMapper *MM = nullptr); 109327952Sdim SectionMemoryManager(const SectionMemoryManager &) = delete; 110327952Sdim void operator=(const SectionMemoryManager &) = delete; 111288943Sdim ~SectionMemoryManager() override; 112249259Sdim 113341825Sdim /// Allocates a memory block of (at least) the given size suitable for 114249259Sdim /// executable code. 115249259Sdim /// 116249259Sdim /// The value of \p Alignment must be a power of two. If \p Alignment is zero 117249259Sdim /// a default alignment of 16 will be used. 118276479Sdim uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 119276479Sdim unsigned SectionID, 120276479Sdim StringRef SectionName) override; 121249259Sdim 122341825Sdim /// Allocates a memory block of (at least) the given size suitable for 123249259Sdim /// executable code. 124249259Sdim /// 125249259Sdim /// The value of \p Alignment must be a power of two. If \p Alignment is zero 126249259Sdim /// a default alignment of 16 will be used. 127276479Sdim uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 128276479Sdim unsigned SectionID, StringRef SectionName, 129276479Sdim bool isReadOnly) override; 130249259Sdim 131341825Sdim /// Update section-specific memory permissions and other attributes. 132249259Sdim /// 133249259Sdim /// This method is called when object loading is complete and section page 134249259Sdim /// permissions can be applied. It is up to the memory manager implementation 135249259Sdim /// to decide whether or not to act on this method. The memory manager will 136249259Sdim /// typically allocate all sections as read-write and then apply specific 137249259Sdim /// permissions when this method is called. Code sections cannot be executed 138261991Sdim /// until this function has been called. In addition, any cache coherency 139261991Sdim /// operations needed to reliably use the memory are also performed. 140249259Sdim /// 141249259Sdim /// \returns true if an error occurred, false otherwise. 142276479Sdim bool finalizeMemory(std::string *ErrMsg = nullptr) override; 143249259Sdim 144341825Sdim /// Invalidate instruction cache for code sections. 145249259Sdim /// 146249259Sdim /// Some platforms with separate data cache and instruction cache require 147249259Sdim /// explicit cache flush, otherwise JIT code manipulations (like resolved 148249259Sdim /// relocations) will get to the data cache but not to the instruction cache. 149249259Sdim /// 150261991Sdim /// This method is called from finalizeMemory. 151249259Sdim virtual void invalidateInstructionCache(); 152249259Sdim 153249259Sdimprivate: 154296417Sdim struct FreeMemBlock { 155296417Sdim // The actual block of free memory 156296417Sdim sys::MemoryBlock Free; 157296417Sdim // If there is a pending allocation from the same reservation right before 158296417Sdim // this block, store it's index in PendingMem, to be able to update the 159296417Sdim // pending region if part of this block is allocated, rather than having to 160296417Sdim // create a new one 161296417Sdim unsigned PendingPrefixIndex; 162296417Sdim }; 163296417Sdim 164249259Sdim struct MemoryGroup { 165296417Sdim // PendingMem contains all blocks of memory (subblocks of AllocatedMem) 166296417Sdim // which have not yet had their permissions applied, but have been given 167296417Sdim // out to the user. FreeMem contains all block of memory, which have 168296417Sdim // neither had their permissions applied, nor been given out to the user. 169296417Sdim SmallVector<sys::MemoryBlock, 16> PendingMem; 170296417Sdim SmallVector<FreeMemBlock, 16> FreeMem; 171296417Sdim 172296417Sdim // All memory blocks that have been requested from the system 173296417Sdim SmallVector<sys::MemoryBlock, 16> AllocatedMem; 174296417Sdim 175296417Sdim sys::MemoryBlock Near; 176249259Sdim }; 177249259Sdim 178327952Sdim uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size, 179249259Sdim unsigned Alignment); 180249259Sdim 181276479Sdim std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, 182276479Sdim unsigned Permissions); 183249259Sdim 184341825Sdim void anchor() override; 185341825Sdim 186249259Sdim MemoryGroup CodeMem; 187249259Sdim MemoryGroup RWDataMem; 188249259Sdim MemoryGroup RODataMem; 189327952Sdim MemoryMapper &MMapper; 190249259Sdim}; 191249259Sdim 192314564Sdim} // end namespace llvm 193249259Sdim 194249259Sdim#endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H 195