LLVM  8.0.1
SectionMemoryManager.h
Go to the documentation of this file.
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"
21 #include "llvm/Support/Memory.h"
22 #include <cstdint>
23 #include <string>
24 #include <system_error>
25 
26 namespace 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.
42 public:
43  /// This enum describes the various reasons to allocate pages from
44  /// allocateMappedMemory.
45  enum class AllocationPurpose {
46  Code,
47  ROData,
48  RWData,
49  };
50 
51  /// Implementations of this interface are used by SectionMemoryManager to
52  /// request pages from the operating system.
53  class MemoryMapper {
54  public:
55  /// This method attempts to allocate \p NumBytes bytes of virtual memory for
56  /// \p Purpose. \p NearBlock may point to an existing allocation, in which
57  /// case an attempt is made to allocate more memory near the existing block.
58  /// The actual allocated address is not guaranteed to be near the requested
59  /// address. \p Flags is used to set the initial protection flags for the
60  /// block of the memory. \p EC [out] returns an object describing any error
61  /// that occurs.
62  ///
63  /// This method may allocate more than the number of bytes requested. The
64  /// actual number of bytes allocated is indicated in the returned
65  /// MemoryBlock.
66  ///
67  /// The start of the allocated block must be aligned with the system
68  /// allocation granularity (64K on Windows, page size on Linux). If the
69  /// address following \p NearBlock is not so aligned, it will be rounded up
70  /// to the next allocation granularity boundary.
71  ///
72  /// \r a non-null MemoryBlock if the function was successful, otherwise a
73  /// null MemoryBlock with \p EC describing the error.
74  virtual sys::MemoryBlock
75  allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes,
76  const sys::MemoryBlock *const NearBlock,
77  unsigned Flags, std::error_code &EC) = 0;
78 
79  /// This method sets the protection flags for a block of memory to the state
80  /// specified by \p Flags. The behavior is not specified if the memory was
81  /// not allocated using the allocateMappedMemory method.
82  /// \p Block describes the memory block to be protected.
83  /// \p Flags specifies the new protection state to be assigned to the block.
84  ///
85  /// If \p Flags is MF_WRITE, the actual behavior varies with the operating
86  /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture
87  /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
88  ///
89  /// \r error_success if the function was successful, or an error_code
90  /// describing the failure if an error occurred.
91  virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block,
92  unsigned Flags) = 0;
93 
94  /// This method releases a block of memory that was allocated with the
95  /// allocateMappedMemory method. It should not be used to release any memory
96  /// block allocated any other way.
97  /// \p Block describes the memory to be released.
98  ///
99  /// \r error_success if the function was successful, or an error_code
100  /// describing the failure if an error occurred.
101  virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0;
102 
103  virtual ~MemoryMapper();
104  };
105 
106  /// Creates a SectionMemoryManager instance with \p MM as the associated
107  /// memory mapper. If \p MM is nullptr then a default memory mapper is used
108  /// that directly calls into the operating system.
109  SectionMemoryManager(MemoryMapper *MM = nullptr);
110  SectionMemoryManager(const SectionMemoryManager &) = delete;
111  void operator=(const SectionMemoryManager &) = delete;
112  ~SectionMemoryManager() override;
113 
114  /// Allocates a memory block of (at least) the given size suitable for
115  /// executable code.
116  ///
117  /// The value of \p Alignment must be a power of two. If \p Alignment is zero
118  /// a default alignment of 16 will be used.
119  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
120  unsigned SectionID,
121  StringRef SectionName) override;
122 
123  /// Allocates a memory block of (at least) the given size suitable for
124  /// executable code.
125  ///
126  /// The value of \p Alignment must be a power of two. If \p Alignment is zero
127  /// a default alignment of 16 will be used.
128  uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
129  unsigned SectionID, StringRef SectionName,
130  bool isReadOnly) override;
131 
132  /// Update section-specific memory permissions and other attributes.
133  ///
134  /// This method is called when object loading is complete and section page
135  /// permissions can be applied. It is up to the memory manager implementation
136  /// to decide whether or not to act on this method. The memory manager will
137  /// typically allocate all sections as read-write and then apply specific
138  /// permissions when this method is called. Code sections cannot be executed
139  /// until this function has been called. In addition, any cache coherency
140  /// operations needed to reliably use the memory are also performed.
141  ///
142  /// \returns true if an error occurred, false otherwise.
143  bool finalizeMemory(std::string *ErrMsg = nullptr) override;
144 
145  /// Invalidate instruction cache for code sections.
146  ///
147  /// Some platforms with separate data cache and instruction cache require
148  /// explicit cache flush, otherwise JIT code manipulations (like resolved
149  /// relocations) will get to the data cache but not to the instruction cache.
150  ///
151  /// This method is called from finalizeMemory.
152  virtual void invalidateInstructionCache();
153 
154 private:
155  struct FreeMemBlock {
156  // The actual block of free memory
157  sys::MemoryBlock Free;
158  // If there is a pending allocation from the same reservation right before
159  // this block, store it's index in PendingMem, to be able to update the
160  // pending region if part of this block is allocated, rather than having to
161  // create a new one
162  unsigned PendingPrefixIndex;
163  };
164 
165  struct MemoryGroup {
166  // PendingMem contains all blocks of memory (subblocks of AllocatedMem)
167  // which have not yet had their permissions applied, but have been given
168  // out to the user. FreeMem contains all block of memory, which have
169  // neither had their permissions applied, nor been given out to the user.
172 
173  // All memory blocks that have been requested from the system
175 
176  sys::MemoryBlock Near;
177  };
178 
179  uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size,
180  unsigned Alignment);
181 
182  std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
183  unsigned Permissions);
184 
185  void anchor() override;
186 
187  MemoryGroup CodeMem;
188  MemoryGroup RWDataMem;
189  MemoryGroup RODataMem;
190  MemoryMapper &MMapper;
191 };
192 
193 } // end namespace llvm
194 
195 #endif // LLVM_EXECUTION_ENGINE_SECTION_MEMORY_MANAGER_H
This class represents lattice values for constants.
Definition: AllocatorList.h:24
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:847
This class encapsulates the notion of a memory block which has an address and a size.
Definition: Memory.h:29
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:47
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:49