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