pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

llvm-netbsd: First round of RWX allocation support



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Tue Aug 1 18:48:53 2017 +0200
Changeset:	9ce499241948afd1068ab25a84b2634a891c045d

Modified Files:
	llvm-netbsd/distinfo
Added Files:
	llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
	llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc

Log Message:
llvm-netbsd: First round of RWX allocation support

Sponsored by <The NetBSD Foundation>

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=9ce499241948afd1068ab25a84b2634a891c045d

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 llvm-netbsd/distinfo                               |   2 +
 .../patches/patch-include_llvm_Support_Memory.h    |  88 +++++++++++++++
 .../patches/patch-lib_Support_Unix_Memory.inc      | 121 +++++++++++++++++++++
 3 files changed, 211 insertions(+)

diffs:
diff --git a/llvm-netbsd/distinfo b/llvm-netbsd/distinfo
index 7931384fd5..623e1142e6 100644
--- a/llvm-netbsd/distinfo
+++ b/llvm-netbsd/distinfo
@@ -12,3 +12,5 @@ Size (libcxx-3.6.2.src.tar.xz) = 944020 bytes
 SHA1 (llvm-3.6.2.src.tar.xz) = 7a00257eb2bc9431e4c77c3a36b033072c54bc7e
 RMD160 (llvm-3.6.2.src.tar.xz) = 521cbc5fe2925ea3c6e90c7a31f752a04045c972
 Size (llvm-3.6.2.src.tar.xz) = 12802380 bytes
+SHA1 (patch-include_llvm_Support_Memory.h) = eb54dbd4068b686115bd775892754f6f96e49e4d
+SHA1 (patch-lib_Support_Unix_Memory.inc) = 692fbd706767efc6675163ca714f8d2d89ea0d68
diff --git a/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h b/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
new file mode 100644
index 0000000000..d17b5dc355
--- /dev/null
+++ b/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
@@ -0,0 +1,88 @@
+$NetBSD$
+
+--- include/llvm/Support/Memory.h.orig	2017-07-05 18:41:26.000000000 +0000
++++ include/llvm/Support/Memory.h
+@@ -28,14 +28,16 @@ namespace sys {
+   /// @brief Memory block abstraction.
+   class MemoryBlock {
+   public:
+-    MemoryBlock() : Address(nullptr), Size(0) { }
+-    MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { }
++    MemoryBlock() : Address(nullptr), AuxAddress(nullptr), Size(0) { }
++    MemoryBlock(void *addr, size_t size) : Address(addr), AuxAddress(nullptr), Size(size) { }
+     void *base() const { return Address; }
+     size_t size() const { return Size; }
+ 
+   private:
+     void *Address;    ///< Address of first byte of memory area
++    void *AuxAddress; ///< Auxilary Address of first byte of memory area, this is required implementation detail on some platforms
+     size_t Size;      ///< Size, in bytes of the memory area
++    int MaxProtection;///< Maximum allowable Protection, of memory area
+     friend class Memory;
+   };
+ 
+@@ -61,13 +63,15 @@ namespace sys {
+     /// \p Flags is used to set the initial protection flags for the block
+     /// of the memory.
+     /// \p EC [out] returns an object describing any error that occurs.
++    /// \p MaxFlags is used to set the maximal protection flags for the block
++    /// of the memory. This value is OR'ed with \p Flags.
+     ///
+     /// This method may allocate more than the number of bytes requested.  The
+     /// actual number of bytes allocated is indicated in the returned
+     /// MemoryBlock.
+     ///
+     /// The start of the allocated block must be aligned with the
+-    /// system allocation granularity (64K on Windows, page size on Linux).
++    /// system allocation granularity (64K on Windows, page size on Linux, etc).
+     /// If the address following \p NearBlock is not so aligned, it will be
+     /// rounded up to the next allocation granularity boundary.
+     ///
+@@ -78,7 +82,8 @@ namespace sys {
+     static MemoryBlock allocateMappedMemory(size_t NumBytes,
+                                             const MemoryBlock *const NearBlock,
+                                             unsigned Flags,
+-                                            std::error_code &EC);
++                                            std::error_code &EC,
++                                            unsigned MaxFlags = 0);
+ 
+     /// This method releases a block of memory that was allocated with the
+     /// allocateMappedMemory method. It should not be used to release any
+@@ -102,6 +107,9 @@ namespace sys {
+     /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
+     /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
+     ///
++    /// The specified \p Flags parameter must by allowed by the maximal
++    /// protection block of the memory.
++    ///
+     /// \r error_success if the function was successful, or an error_code
+     /// describing the failure if an error occurred.
+     ///
+@@ -132,6 +140,27 @@ namespace sys {
+     /// @brief Release Read/Write/Execute memory.
+     static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr);
+ 
++    /// This method allocates a block of Read/Write and future option for
++    /// Executable memory that is
++    /// suitable for executing dynamically generated code (e.g. JIT). An
++    /// attempt to allocate \p NumBytes bytes of virtual memory is made.
++    /// \p NearBlock may point to an existing allocation in which case
++    /// an attempt is made to allocate more memory near the existing block.
++    ///
++    /// This function should be combined with makeExecutable.
++    ///
++    /// \r a non-null MemoryBlock if the function was successful,
++    /// otherwise a null MemoryBlock is with \p EC describing the error.
++    ///
++    /// @brief Allocate Read/Write with future option for Execute memory.
++    static MemoryBlock allocateJITExecutableMemory(size_t NumBytes,
++                                                   const MemoryBlock *NearBlock,
++                                                   std::error_code &EC);
++
++    /// makeExecutable - Mark the page containing a range of addresses
++    /// as executable.
++    static std::error_code makeExecutable(const MemoryBlock &Block);
++
+     /// InvalidateInstructionCache - Before the JIT can run a block of code
+     /// that has been emitted it must invalidate the instruction cache on some
+     /// platforms.
diff --git a/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc b/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc
new file mode 100644
index 0000000000..9a44bdc431
--- /dev/null
+++ b/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc
@@ -0,0 +1,121 @@
+$NetBSD$
+
+--- lib/Support/Unix/Memory.inc.orig	2017-07-05 18:38:14.000000000 +0000
++++ lib/Support/Unix/Memory.inc
+@@ -82,7 +82,8 @@ MemoryBlock
+ Memory::allocateMappedMemory(size_t NumBytes,
+                              const MemoryBlock *const NearBlock,
+                              unsigned PFlags,
+-                             std::error_code &EC) {
++                             std::error_code &EC,
++                             unsigned MaxPFlags) {
+   EC = std::error_code();
+   if (NumBytes == 0)
+     return MemoryBlock();
+@@ -102,25 +103,103 @@ Memory::allocateMappedMemory(size_t NumB
+ 
+   int Protect = getPosixProtectionFlags(PFlags);
+ 
++  MaxPFlags |= PFlags;
++
++  // NetBSD with PaX MPROTECT must reserve additional allowable protection bits
++#if defined(__NetBSD__) && defined(PROT_MPROTECT)
++  Protect |= PROT_MPROTECT(getPosixProtectionFlags(MaxPFlags & (~PFlags)));
++#endif
++
+   // Use any near hint and the page size to set a page-aligned starting address
+   uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
+                                       NearBlock->size() : 0;
+   if (Start && Start % PageSize)
+     Start += PageSize - Start % PageSize;
+ 
+-  void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
+-                      Protect, MMFlags, fd, 0);
++  const bool WXmapping = ((PFlags & (MF_WRITE | MF_EXEC)) == (MF_WRITE | MF_EXEC));
++ 
++  void *Addr;
++
++  if (WXmapping) {
++#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
++    Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
++                  Protect & ~PROT_WRITE, MMFlags, fd, 0);
++#elif defined(__NetBSD__) && defined(PROT_MPROTECT)
++    Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
++                  Protect & ~PROT_EXEC, MMFlags, fd, 0);
++#else
++    Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
++                  Protect, MMFlags, fd, 0);
++#endif
++  } else {
++    Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
++                  Protect, MMFlags, fd, 0);
++  }
++
+   if (Addr == MAP_FAILED) {
+     if (NearBlock) //Try again without a near hint
+-      return allocateMappedMemory(NumBytes, nullptr, PFlags, EC);
++      return allocateMappedMemory(NumBytes, nullptr, PFlags, EC, MaxPFlags);
+ 
+     EC = std::error_code(errno, std::generic_category());
+     return MemoryBlock();
+   }
+ 
++#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
++  if (WXmapping) {
++    kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
++                                  (vm_size_t)(PageSize*NumPages), 0,
++                                  VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
++    if (KERN_SUCCESS != kr) {
++      // is errno set?
++      EC = std::error_code(errno, std::generic_category());
++      return MemoryBlock();
++    }
++
++    kr = vm_protect(mach_task_self(), (vm_address_t)pa,
++                    (vm_size_t)(PageSize*NumPages), 0,
++                    VM_PROT_READ | VM_PROT_WRITE);
++    if (KERN_SUCCESS != kr) {
++      // is errno set?
++      EC = std::error_code(errno, std::generic_category());
++      return MemoryBlock();
++    }
++  }
++#elif defined(__NetBSD__) && defined(PROT_MPROTECT)
++  void *codeseg = nullptr;
++  if (WXmapping) {
++    codeseg =
++        ::mremap(Addr, PageSize * NumPages, NULL, PageSize * NumPages,
++                 MAP_REMAPDUP);
++    if (codeseg == MAP_FAILED) {
++      ::munmap(Addr, PageSize * NumPages);
++
++      if (NearBlock) // Try again without a near hint
++        return allocateMappedMemory(NumBytes, nullptr, PFlags, EC, MaxPFlags);
++
++      EC = std::error_code(errno, std::generic_category());
++      return MemoryBlock();
++    }
++    if (::mprotect(codeseg, PageSize * NumPages, PROT_READ | PROT_EXEC) == -1) {
++      ::munmap(Addr, PageSize * NumPages);
++      ::munmap(codeseg, PageSize * NumPages);
++      if (NearBlock) // Try again without a near hint
++        return allocateMappedMemory(NumBytes, nullptr, PFlags, EC, MaxPFlags);
++
++      EC = std::error_code(errno, std::generic_category());
++      return MemoryBlock();
++    }
++  }
++#endif
++
+   MemoryBlock Result;
+   Result.Address = Addr;
++#if defined(__NetBSD__) && defined(PROT_MPROTECT)
++  Result.AuxAddress = codeseg;
++#else
++  Result.AuxAddress = nullptr;
++#endif
+   Result.Size = NumPages*PageSize;
++  Result.MaxProtection = MaxPFlags;
+ 
+   if (PFlags & MF_EXEC)
+     Memory::InvalidateInstructionCache(Result.Address, Result.Size);


Home | Main Index | Thread Index | Old Index