LLVM  12.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 
17 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Support/Memory.h"
20 #include <cstdint>
21 #include <string>
22 #include <system_error>
23 
24 namespace 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.
40 public:
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.
51  class MemoryMapper {
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);
108  SectionMemoryManager(const SectionMemoryManager &) = delete;
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 
152 private:
153  struct FreeMemBlock {
154  // The actual block of free memory
155  sys::MemoryBlock Free;
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 };
190 
191 } // end namespace llvm
192 
193 #endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
This class represents lattice values for constants.
Definition: AllocatorList.h:23
SectionMemoryManager(MemoryMapper *MM=nullptr)
Creates a SectionMemoryManager instance with MM as the associated memory mapper.
Implementations of this interface are used by SectionMemoryManager to request pages from the operatin...
AllocationPurpose
This enum describes the various reasons to allocate pages from allocateMappedMemory.
virtual void invalidateInstructionCache()
Invalidate instruction cache for code sections.
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.
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.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:883
This class encapsulates the notion of a memory block which has an address and a size.
Definition: Memory.h:32
void operator=(const SectionMemoryManager &)=delete
bool finalizeMemory(std::string *ErrMsg=nullptr) override
Update section-specific memory permissions and other attributes.
uint32_t Size
Definition: Profile.cpp:46
This is a simple memory manager which implements the methods called by the RuntimeDyld class to alloc...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57