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