LLVM 20.0.0git
SectionMemoryManager.h
Go to the documentation of this file.
1//===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the declaration of a section-based memory manager used by
10// the MCJIT execution engine and RuntimeDyld.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
15#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
16
19#include "llvm/Support/Memory.h"
20#include <cstdint>
21#include <string>
22#include <system_error>
23
24namespace llvm {
25
26/// This is a simple memory manager which implements the methods called by
27/// the RuntimeDyld class to allocate memory for section-based loading of
28/// objects, usually those generated by the MCJIT execution engine.
29///
30/// This memory manager allocates all section memory as read-write. The
31/// RuntimeDyld will copy JITed section memory into these allocated blocks
32/// and perform any necessary linking and relocations.
33///
34/// Any client using this memory manager MUST ensure that section-specific
35/// page permissions have been applied before attempting to execute functions
36/// in the JITed object. Permissions can be applied either by calling
37/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
38/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
40public:
41 /// This enum describes the various reasons to allocate pages from
42 /// allocateMappedMemory.
43 enum class AllocationPurpose {
44 Code,
45 ROData,
46 RWData,
47 };
48
49 /// Implementations of this interface are used by SectionMemoryManager to
50 /// request pages from the operating system.
52 public:
53 /// This method attempts to allocate \p NumBytes bytes of virtual memory for
54 /// \p Purpose. \p NearBlock may point to an existing allocation, in which
55 /// case an attempt is made to allocate more memory near the existing block.
56 /// The actual allocated address is not guaranteed to be near the requested
57 /// address. \p Flags is used to set the initial protection flags for the
58 /// block of the memory. \p EC [out] returns an object describing any error
59 /// that occurs.
60 ///
61 /// This method may allocate more than the number of bytes requested. The
62 /// actual number of bytes allocated is indicated in the returned
63 /// MemoryBlock.
64 ///
65 /// The start of the allocated block must be aligned with the system
66 /// allocation granularity (64K on Windows, page size on Linux). If the
67 /// address following \p NearBlock is not so aligned, it will be rounded up
68 /// to the next allocation granularity boundary.
69 ///
70 /// \r a non-null MemoryBlock if the function was successful, otherwise a
71 /// null MemoryBlock with \p EC describing the error.
72 virtual sys::MemoryBlock
73 allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes,
74 const sys::MemoryBlock *const NearBlock,
75 unsigned Flags, std::error_code &EC) = 0;
76
77 /// This method sets the protection flags for a block of memory to the state
78 /// specified by \p Flags. The behavior is not specified if the memory was
79 /// not allocated using the allocateMappedMemory method.
80 /// \p Block describes the memory block to be protected.
81 /// \p Flags specifies the new protection state to be assigned to the block.
82 ///
83 /// If \p Flags is MF_WRITE, the actual behavior varies with the operating
84 /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture
85 /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
86 ///
87 /// \r error_success if the function was successful, or an error_code
88 /// describing the failure if an error occurred.
89 virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block,
90 unsigned Flags) = 0;
91
92 /// This method releases a block of memory that was allocated with the
93 /// allocateMappedMemory method. It should not be used to release any memory
94 /// block allocated any other way.
95 /// \p Block describes the memory to be released.
96 ///
97 /// \r error_success if the function was successful, or an error_code
98 /// describing the failure if an error occurred.
99 virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0;
100
101 virtual ~MemoryMapper();
102 };
103
104 /// Creates a SectionMemoryManager instance with \p MM as the associated
105 /// memory mapper. If \p MM is nullptr then a default memory mapper is used
106 /// that directly calls into the operating system.
107 SectionMemoryManager(MemoryMapper *MM = nullptr);
109 void operator=(const SectionMemoryManager &) = delete;
110 ~SectionMemoryManager() override;
111
112 /// Allocates a memory block of (at least) the given size suitable for
113 /// executable code.
114 ///
115 /// The value of \p Alignment must be a power of two. If \p Alignment is zero
116 /// a default alignment of 16 will be used.
117 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
118 unsigned SectionID,
119 StringRef SectionName) override;
120
121 /// Allocates a memory block of (at least) the given size suitable for
122 /// executable code.
123 ///
124 /// The value of \p Alignment must be a power of two. If \p Alignment is zero
125 /// a default alignment of 16 will be used.
126 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
127 unsigned SectionID, StringRef SectionName,
128 bool isReadOnly) override;
129
130 /// Update section-specific memory permissions and other attributes.
131 ///
132 /// This method is called when object loading is complete and section page
133 /// permissions can be applied. It is up to the memory manager implementation
134 /// to decide whether or not to act on this method. The memory manager will
135 /// typically allocate all sections as read-write and then apply specific
136 /// permissions when this method is called. Code sections cannot be executed
137 /// until this function has been called. In addition, any cache coherency
138 /// operations needed to reliably use the memory are also performed.
139 ///
140 /// \returns true if an error occurred, false otherwise.
141 bool finalizeMemory(std::string *ErrMsg = nullptr) override;
142
143 /// Invalidate instruction cache for code sections.
144 ///
145 /// Some platforms with separate data cache and instruction cache require
146 /// explicit cache flush, otherwise JIT code manipulations (like resolved
147 /// relocations) will get to the data cache but not to the instruction cache.
148 ///
149 /// This method is called from finalizeMemory.
150 virtual void invalidateInstructionCache();
151
152private:
153 struct FreeMemBlock {
154 // The actual block of free memory
156 // If there is a pending allocation from the same reservation right before
157 // this block, store it's index in PendingMem, to be able to update the
158 // pending region if part of this block is allocated, rather than having to
159 // create a new one
160 unsigned PendingPrefixIndex;
161 };
162
163 struct MemoryGroup {
164 // PendingMem contains all blocks of memory (subblocks of AllocatedMem)
165 // which have not yet had their permissions applied, but have been given
166 // out to the user. FreeMem contains all block of memory, which have
167 // neither had their permissions applied, nor been given out to the user.
170
171 // All memory blocks that have been requested from the system
173
174 sys::MemoryBlock Near;
175 };
176
177 uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size,
178 unsigned Alignment);
179
180 std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
181 unsigned Permissions);
182
183 void anchor() override;
184
185 MemoryGroup CodeMem;
186 MemoryGroup RWDataMem;
187 MemoryGroup RODataMem;
188 MemoryMapper *MMapper;
189 std::unique_ptr<MemoryMapper> OwnedMMapper;
190};
191
192} // end namespace llvm
193
194#endif // LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
uint64_t Size
This file defines the SmallVector class.
Implementations of this interface are used by SectionMemoryManager to request pages from the operatin...
virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block, unsigned Flags)=0
This method sets the protection flags for a block of memory to the state specified by Flags.
virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M)=0
This method releases a block of memory that was allocated with the allocateMappedMemory method.
virtual sys::MemoryBlock allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes, const sys::MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)=0
This method attempts to allocate NumBytes bytes of virtual memory for Purpose.
This is a simple memory manager which implements the methods called by the RuntimeDyld class to alloc...
AllocationPurpose
This enum describes the various reasons to allocate pages from allocateMappedMemory.
virtual void invalidateInstructionCache()
Invalidate instruction cache for code sections.
void operator=(const SectionMemoryManager &)=delete
uint8_t * allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool isReadOnly) override
Allocates a memory block of (at least) the given size suitable for executable code.
uint8_t * allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override
Allocates a memory block of (at least) the given size suitable for executable code.
SectionMemoryManager(const SectionMemoryManager &)=delete
bool finalizeMemory(std::string *ErrMsg=nullptr) override
Update section-specific memory permissions and other attributes.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
This class encapsulates the notion of a memory block which has an address and a size.
Definition: Memory.h:32
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18