Home | History | Annotate | Download | only in Support
      1 //===- llvm/Support/Memory.h - Memory Support --------------------*- 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 declares the llvm::sys::Memory class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_SUPPORT_MEMORY_H
     15 #define LLVM_SUPPORT_MEMORY_H
     16 
     17 #include "llvm/Support/DataTypes.h"
     18 #include <string>
     19 #include <system_error>
     20 
     21 namespace llvm {
     22 namespace sys {
     23 
     24   /// This class encapsulates the notion of a memory block which has an address
     25   /// and a size. It is used by the Memory class (a friend) as the result of
     26   /// various memory allocation operations.
     27   /// @see Memory
     28   /// @brief Memory block abstraction.
     29   class MemoryBlock {
     30   public:
     31     MemoryBlock() : Address(nullptr), Size(0) { }
     32     MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { }
     33     void *base() const { return Address; }
     34     size_t size() const { return Size; }
     35   private:
     36     void *Address;    ///< Address of first byte of memory area
     37     size_t Size;      ///< Size, in bytes of the memory area
     38     friend class Memory;
     39   };
     40 
     41   /// This class provides various memory handling functions that manipulate
     42   /// MemoryBlock instances.
     43   /// @since 1.4
     44   /// @brief An abstraction for memory operations.
     45   class Memory {
     46   public:
     47     enum ProtectionFlags {
     48       MF_READ  = 0x1000000,
     49       MF_WRITE = 0x2000000,
     50       MF_EXEC  = 0x4000000
     51     };
     52 
     53     /// This method allocates a block of memory that is suitable for loading
     54     /// dynamically generated code (e.g. JIT). An attempt to allocate
     55     /// \p NumBytes bytes of virtual memory is made.
     56     /// \p NearBlock may point to an existing allocation in which case
     57     /// 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.
     60     /// \p Flags is used to set the initial protection flags for the block
     61     /// of the memory.
     62     /// \p EC [out] returns an object describing any error that occurs.
     63     ///
     64     /// This method may allocate more than the number of bytes requested.  The
     65     /// actual number of bytes allocated is indicated in the returned
     66     /// MemoryBlock.
     67     ///
     68     /// The start of the allocated block must be aligned with the
     69     /// system allocation granularity (64K on Windows, page size on Linux).
     70     /// If the address following \p NearBlock is not so aligned, it will be
     71     /// rounded up to the next allocation granularity boundary.
     72     ///
     73     /// \r a non-null MemoryBlock if the function was successful,
     74     /// otherwise a null MemoryBlock is with \p EC describing the error.
     75     ///
     76     /// @brief Allocate mapped memory.
     77     static MemoryBlock allocateMappedMemory(size_t NumBytes,
     78                                             const MemoryBlock *const NearBlock,
     79                                             unsigned Flags,
     80                                             std::error_code &EC);
     81 
     82     /// This method releases a block of memory that was allocated with the
     83     /// allocateMappedMemory method. It should not be used to release any
     84     /// memory block allocated any other way.
     85     /// \p Block describes the memory to be released.
     86     ///
     87     /// \r error_success if the function was successful, or an error_code
     88     /// describing the failure if an error occurred.
     89     ///
     90     /// @brief Release mapped memory.
     91     static std::error_code releaseMappedMemory(MemoryBlock &Block);
     92 
     93     /// This method sets the protection flags for a block of memory to the
     94     /// state specified by /p Flags.  The behavior is not specified if the
     95     /// memory was not allocated using the allocateMappedMemory method.
     96     /// \p Block describes the memory block to be protected.
     97     /// \p Flags specifies the new protection state to be assigned to the block.
     98     /// \p ErrMsg [out] returns a string describing any error that occurred.
     99     ///
    100     /// If \p Flags is MF_WRITE, the actual behavior varies
    101     /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
    102     /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
    103     ///
    104     /// \r error_success if the function was successful, or an error_code
    105     /// describing the failure if an error occurred.
    106     ///
    107     /// @brief Set memory protection state.
    108     static std::error_code protectMappedMemory(const MemoryBlock &Block,
    109                                                unsigned Flags);
    110 
    111     /// This method allocates a block of Read/Write/Execute memory that is
    112     /// suitable for executing dynamically generated code (e.g. JIT). An
    113     /// attempt to allocate \p NumBytes bytes of virtual memory is made.
    114     /// \p NearBlock may point to an existing allocation in which case
    115     /// an attempt is made to allocate more memory near the existing block.
    116     ///
    117     /// On success, this returns a non-null memory block, otherwise it returns
    118     /// a null memory block and fills in *ErrMsg.
    119     ///
    120     /// @brief Allocate Read/Write/Execute memory.
    121     static MemoryBlock AllocateRWX(size_t NumBytes,
    122                                    const MemoryBlock *NearBlock,
    123                                    std::string *ErrMsg = nullptr);
    124 
    125     /// This method releases a block of Read/Write/Execute memory that was
    126     /// allocated with the AllocateRWX method. It should not be used to
    127     /// release any memory block allocated any other way.
    128     ///
    129     /// On success, this returns false, otherwise it returns true and fills
    130     /// in *ErrMsg.
    131     /// @brief Release Read/Write/Execute memory.
    132     static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr);
    133 
    134 
    135     /// InvalidateInstructionCache - Before the JIT can run a block of code
    136     /// that has been emitted it must invalidate the instruction cache on some
    137     /// platforms.
    138     static void InvalidateInstructionCache(const void *Addr, size_t Len);
    139 
    140     /// setExecutable - Before the JIT can run a block of code, it has to be
    141     /// given read and executable privilege. Return true if it is already r-x
    142     /// or the system is able to change its previlege.
    143     static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr);
    144 
    145     /// setWritable - When adding to a block of code, the JIT may need
    146     /// to mark a block of code as RW since the protections are on page
    147     /// boundaries, and the JIT internal allocations are not page aligned.
    148     static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr);
    149 
    150     /// setRangeExecutable - Mark the page containing a range of addresses
    151     /// as executable.
    152     static bool setRangeExecutable(const void *Addr, size_t Size);
    153 
    154     /// setRangeWritable - Mark the page containing a range of addresses
    155     /// as writable.
    156     static bool setRangeWritable(const void *Addr, size_t Size);
    157   };
    158 }
    159 }
    160 
    161 #endif
    162