Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:55

0001 //===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file contains the declaration of a section-based memory manager used by
0010 // the MCJIT execution engine and RuntimeDyld.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
0015 #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
0016 
0017 #include "llvm/ADT/SmallVector.h"
0018 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
0019 #include "llvm/Support/Memory.h"
0020 #include <cstdint>
0021 #include <string>
0022 #include <system_error>
0023 
0024 namespace llvm {
0025 
0026 /// This is a simple memory manager which implements the methods called by
0027 /// the RuntimeDyld class to allocate memory for section-based loading of
0028 /// objects, usually those generated by the MCJIT execution engine.
0029 ///
0030 /// This memory manager allocates all section memory as read-write.  The
0031 /// RuntimeDyld will copy JITed section memory into these allocated blocks
0032 /// and perform any necessary linking and relocations.
0033 ///
0034 /// Any client using this memory manager MUST ensure that section-specific
0035 /// page permissions have been applied before attempting to execute functions
0036 /// in the JITed object.  Permissions can be applied either by calling
0037 /// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory
0038 /// directly.  Clients of MCJIT should call MCJIT::finalizeObject.
0039 class SectionMemoryManager : public RTDyldMemoryManager {
0040 public:
0041   /// This enum describes the various reasons to allocate pages from
0042   /// allocateMappedMemory.
0043   enum class AllocationPurpose {
0044     Code,
0045     ROData,
0046     RWData,
0047   };
0048 
0049   /// Implementations of this interface are used by SectionMemoryManager to
0050   /// request pages from the operating system.
0051   class MemoryMapper {
0052   public:
0053     /// This method attempts to allocate \p NumBytes bytes of virtual memory for
0054     /// \p Purpose.  \p NearBlock may point to an existing allocation, in which
0055     /// case an attempt is made to allocate more memory near the existing block.
0056     /// The actual allocated address is not guaranteed to be near the requested
0057     /// address.  \p Flags is used to set the initial protection flags for the
0058     /// block of the memory.  \p EC [out] returns an object describing any error
0059     /// that occurs.
0060     ///
0061     /// This method may allocate more than the number of bytes requested.  The
0062     /// actual number of bytes allocated is indicated in the returned
0063     /// MemoryBlock.
0064     ///
0065     /// The start of the allocated block must be aligned with the system
0066     /// allocation granularity (64K on Windows, page size on Linux).  If the
0067     /// address following \p NearBlock is not so aligned, it will be rounded up
0068     /// to the next allocation granularity boundary.
0069     ///
0070     /// \r a non-null MemoryBlock if the function was successful, otherwise a
0071     /// null MemoryBlock with \p EC describing the error.
0072     virtual sys::MemoryBlock
0073     allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes,
0074                          const sys::MemoryBlock *const NearBlock,
0075                          unsigned Flags, std::error_code &EC) = 0;
0076 
0077     /// This method sets the protection flags for a block of memory to the state
0078     /// specified by \p Flags.  The behavior is not specified if the memory was
0079     /// not allocated using the allocateMappedMemory method.
0080     /// \p Block describes the memory block to be protected.
0081     /// \p Flags specifies the new protection state to be assigned to the block.
0082     ///
0083     /// If \p Flags is MF_WRITE, the actual behavior varies with the operating
0084     /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture
0085     /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
0086     ///
0087     /// \r error_success if the function was successful, or an error_code
0088     /// describing the failure if an error occurred.
0089     virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block,
0090                                                 unsigned Flags) = 0;
0091 
0092     /// This method releases a block of memory that was allocated with the
0093     /// allocateMappedMemory method. It should not be used to release any memory
0094     /// block allocated any other way.
0095     /// \p Block describes the memory to be released.
0096     ///
0097     /// \r error_success if the function was successful, or an error_code
0098     /// describing the failure if an error occurred.
0099     virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0;
0100 
0101     virtual ~MemoryMapper();
0102   };
0103 
0104   /// Creates a SectionMemoryManager instance with \p MM as the associated
0105   /// memory mapper.  If \p MM is nullptr then a default memory mapper is used
0106   /// that directly calls into the operating system.
0107   SectionMemoryManager(MemoryMapper *MM = nullptr);
0108   SectionMemoryManager(const SectionMemoryManager &) = delete;
0109   void operator=(const SectionMemoryManager &) = delete;
0110   ~SectionMemoryManager() override;
0111 
0112   /// Allocates a memory block of (at least) the given size suitable for
0113   /// executable code.
0114   ///
0115   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
0116   /// a default alignment of 16 will be used.
0117   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
0118                                unsigned SectionID,
0119                                StringRef SectionName) override;
0120 
0121   /// Allocates a memory block of (at least) the given size suitable for
0122   /// executable code.
0123   ///
0124   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
0125   /// a default alignment of 16 will be used.
0126   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
0127                                unsigned SectionID, StringRef SectionName,
0128                                bool isReadOnly) override;
0129 
0130   /// Update section-specific memory permissions and other attributes.
0131   ///
0132   /// This method is called when object loading is complete and section page
0133   /// permissions can be applied.  It is up to the memory manager implementation
0134   /// to decide whether or not to act on this method.  The memory manager will
0135   /// typically allocate all sections as read-write and then apply specific
0136   /// permissions when this method is called.  Code sections cannot be executed
0137   /// until this function has been called.  In addition, any cache coherency
0138   /// operations needed to reliably use the memory are also performed.
0139   ///
0140   /// \returns true if an error occurred, false otherwise.
0141   bool finalizeMemory(std::string *ErrMsg = nullptr) override;
0142 
0143   /// Invalidate instruction cache for code sections.
0144   ///
0145   /// Some platforms with separate data cache and instruction cache require
0146   /// explicit cache flush, otherwise JIT code manipulations (like resolved
0147   /// relocations) will get to the data cache but not to the instruction cache.
0148   ///
0149   /// This method is called from finalizeMemory.
0150   virtual void invalidateInstructionCache();
0151 
0152 private:
0153   struct FreeMemBlock {
0154     // The actual block of free memory
0155     sys::MemoryBlock Free;
0156     // If there is a pending allocation from the same reservation right before
0157     // this block, store it's index in PendingMem, to be able to update the
0158     // pending region if part of this block is allocated, rather than having to
0159     // create a new one
0160     unsigned PendingPrefixIndex;
0161   };
0162 
0163   struct MemoryGroup {
0164     // PendingMem contains all blocks of memory (subblocks of AllocatedMem)
0165     // which have not yet had their permissions applied, but have been given
0166     // out to the user. FreeMem contains all block of memory, which have
0167     // neither had their permissions applied, nor been given out to the user.
0168     SmallVector<sys::MemoryBlock, 16> PendingMem;
0169     SmallVector<FreeMemBlock, 16> FreeMem;
0170 
0171     // All memory blocks that have been requested from the system
0172     SmallVector<sys::MemoryBlock, 16> AllocatedMem;
0173 
0174     sys::MemoryBlock Near;
0175   };
0176 
0177   uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size,
0178                            unsigned Alignment);
0179 
0180   std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
0181                                               unsigned Permissions);
0182 
0183   void anchor() override;
0184 
0185   MemoryGroup CodeMem;
0186   MemoryGroup RWDataMem;
0187   MemoryGroup RODataMem;
0188   MemoryMapper *MMapper;
0189   std::unique_ptr<MemoryMapper> OwnedMMapper;
0190 };
0191 
0192 } // end namespace llvm
0193 
0194 #endif // LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H