diff options
Diffstat (limited to 'erts/emulator/asmjit/core/virtmem.cpp')
-rw-r--r-- | erts/emulator/asmjit/core/virtmem.cpp | 339 |
1 files changed, 160 insertions, 179 deletions
diff --git a/erts/emulator/asmjit/core/virtmem.cpp b/erts/emulator/asmjit/core/virtmem.cpp index ba02fa7a78..43766ef2cd 100644 --- a/erts/emulator/asmjit/core/virtmem.cpp +++ b/erts/emulator/asmjit/core/virtmem.cpp @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" #ifndef ASMJIT_NO_JIT @@ -48,8 +30,7 @@ #include <TargetConditionals.h> #if TARGET_OS_OSX #include <sys/utsname.h> - // We also need this for sys_icache_invalidate(). - #include <libkern/OSCacheControl.h> + #include <libkern/OSCacheControl.h> // sys_icache_invalidate(). #endif // Older SDK doesn't define `MAP_JIT`. #ifndef MAP_JIT @@ -65,30 +46,35 @@ #include <atomic> -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__BIONIC__) #define ASMJIT_VM_SHM_DETECT 0 #else #define ASMJIT_VM_SHM_DETECT 1 #endif +// Android NDK doesn't provide `shm_open()` and `shm_unlink()`. +#if defined(__BIONIC__) + #define ASMJIT_VM_SHM_AVAILABLE 0 +#else + #define ASMJIT_VM_SHM_AVAILABLE 1 +#endif + #if defined(__APPLE__) && ASMJIT_ARCH_ARM >= 64 #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP #endif -ASMJIT_BEGIN_NAMESPACE +ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem) -// ============================================================================ -// [asmjit::VirtMem - Utilities] -// ============================================================================ +// Virtual Memory Utilities +// ======================== -static const uint32_t VirtMem_dualMappingFilter[2] = { - VirtMem::kAccessWrite | VirtMem::kMMapMaxAccessWrite, - VirtMem::kAccessExecute | VirtMem::kMMapMaxAccessExecute +static const MemoryFlags dualMappingFilter[2] = { + MemoryFlags::kAccessWrite | MemoryFlags::kMMapMaxAccessWrite, + MemoryFlags::kAccessExecute | MemoryFlags::kMMapMaxAccessExecute }; -// ============================================================================ -// [asmjit::VirtMem - Virtual Memory Management [Windows]] -// ============================================================================ +// Virtual Memory [Windows] +// ======================== #if defined(_WIN32) @@ -104,7 +90,7 @@ struct ScopedHandle { HANDLE value; }; -static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { +static void getVMInfo(Info& vmInfo) noexcept { SYSTEM_INFO systemInfo; ::GetSystemInfo(&systemInfo); @@ -112,15 +98,15 @@ static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { vmInfo.pageGranularity = systemInfo.dwAllocationGranularity; } -// Returns windows-specific protectFlags from \ref VirtMem::Flags. -static DWORD VirtMem_winProtectFlagsFromFlags(uint32_t flags) noexcept { +// Returns windows-specific protectFlags from \ref MemoryFlags. +static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept { DWORD protectFlags; // READ|WRITE|EXECUTE. - if (flags & VirtMem::kAccessExecute) - protectFlags = (flags & VirtMem::kAccessWrite) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; - else if (flags & VirtMem::kAccessRW) - protectFlags = (flags & VirtMem::kAccessWrite) ? PAGE_READWRITE : PAGE_READONLY; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) + protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + else if (Support::test(memoryFlags, MemoryFlags::kAccessRW)) + protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_READWRITE : PAGE_READONLY; else protectFlags = PAGE_NOACCESS; @@ -128,23 +114,23 @@ static DWORD VirtMem_winProtectFlagsFromFlags(uint32_t flags) noexcept { return protectFlags; } -static DWORD VirtMem_winDesiredAccessFromFlags(uint32_t flags) noexcept { - DWORD access = (flags & VirtMem::kAccessWrite) ? FILE_MAP_WRITE : FILE_MAP_READ; - if (flags & VirtMem::kAccessExecute) +static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept { + DWORD access = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? FILE_MAP_WRITE : FILE_MAP_READ; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) access |= FILE_MAP_EXECUTE; return access; } -static uint32_t VirtMem_hardenedRuntimeFlags() noexcept { - return 0; +static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { + return HardenedRuntimeFlags::kNone; } -Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { +Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { *p = nullptr; if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); - DWORD protectFlags = VirtMem_winProtectFlagsFromFlags(flags); + DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags); void* result = ::VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, protectFlags); if (!result) @@ -154,15 +140,15 @@ Error VirtMem::alloc(void** p, size_t size, uint32_t flags) noexcept { return kErrorOk; } -Error VirtMem::release(void* p, size_t size) noexcept { +Error release(void* p, size_t size) noexcept { DebugUtils::unused(size); if (ASMJIT_UNLIKELY(!::VirtualFree(p, 0, MEM_RELEASE))) return DebugUtils::errored(kErrorInvalidArgument); return kErrorOk; } -Error VirtMem::protect(void* p, size_t size, uint32_t flags) noexcept { - DWORD protectFlags = VirtMem_winProtectFlagsFromFlags(flags); +Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { + DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags); DWORD oldFlags; if (::VirtualProtect(p, size, protectFlags, &oldFlags)) @@ -171,11 +157,7 @@ Error VirtMem::protect(void* p, size_t size, uint32_t flags) noexcept { return DebugUtils::errored(kErrorInvalidArgument); } -// ============================================================================ -// [asmjit::VirtMem - Dual Mapping [Windows]] -// ============================================================================ - -Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) noexcept { +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { dm->rx = nullptr; dm->rw = nullptr; @@ -196,8 +178,8 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no void* ptr[2]; for (uint32_t i = 0; i < 2; i++) { - uint32_t accessFlags = flags & ~VirtMem_dualMappingFilter[i]; - DWORD desiredAccess = VirtMem_winDesiredAccessFromFlags(accessFlags); + MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i]; + DWORD desiredAccess = desiredAccessFromMemoryFlags(accessFlags); ptr[i] = ::MapViewOfFile(handle.value, desiredAccess, 0, 0, size); if (ptr[i] == nullptr) { @@ -212,7 +194,7 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t flags) no return kErrorOk; } -Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { +Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { DebugUtils::unused(size); bool failed = false; @@ -232,13 +214,12 @@ Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { #endif -// ============================================================================ -// [asmjit::VirtMem - Virtual Memory Management [Posix]] -// ============================================================================ +// Virtual Memory [Posix] +// ====================== #if !defined(_WIN32) -static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { +static void getVMInfo(Info& vmInfo) noexcept { uint32_t pageSize = uint32_t(::getpagesize()); vmInfo.pageSize = pageSize; @@ -246,14 +227,14 @@ static void VirtMem_getInfo(VirtMem::Info& vmInfo) noexcept { } #if !defined(SHM_ANON) -static const char* VirtMem_getTmpDir() noexcept { +static const char* getTmpDir() noexcept { const char* tmpDir = getenv("TMPDIR"); return tmpDir ? tmpDir : "/tmp"; } #endif // Translates libc errors specific to VirtualMemory mapping to `asmjit::Error`. -static Error VirtMem_asmjitErrorFromErrno(int e) noexcept { +static Error asmjitErrorFromErrno(int e) noexcept { switch (e) { case EACCES: case EAGAIN: @@ -275,16 +256,14 @@ static Error VirtMem_asmjitErrorFromErrno(int e) noexcept { } } -// Some operating systems don't allow /dev/shm to be executable. On Linux this -// happens when /dev/shm is mounted with 'noexec', which is enforced by systemd. -// Other operating systems like MacOS also restrict executable permissions regarding -// /dev/shm, so we use a runtime detection before attempting to allocate executable -// memory. Sometimes we don't need the detection as we know it would always result -// in `kShmStrategyTmpDir`. -enum ShmStrategy : uint32_t { - kShmStrategyUnknown = 0, - kShmStrategyDevShm = 1, - kShmStrategyTmpDir = 2 +// Some operating systems don't allow /dev/shm to be executable. On Linux this happens when /dev/shm is mounted with +// 'noexec', which is enforced by systemd. Other operating systems like MacOS also restrict executable permissions +// regarding /dev/shm, so we use a runtime detection before attempting to allocate executable memory. Sometimes we +// don't need the detection as we know it would always result in `ShmStrategy::kTmpDir`. +enum class ShmStrategy : uint32_t { + kUnknown = 0, + kDevShm = 1, + kTmpDir = 2 }; class AnonymousMemory { @@ -299,17 +278,17 @@ public: FileType _fileType; StringTmp<128> _tmpName; - ASMJIT_INLINE AnonymousMemory() noexcept + inline AnonymousMemory() noexcept : _fd(-1), _fileType(kFileTypeNone), _tmpName() {} - ASMJIT_INLINE ~AnonymousMemory() noexcept { + inline ~AnonymousMemory() noexcept { unlink(); close(); } - ASMJIT_INLINE int fd() const noexcept { return _fd; } + inline int fd() const noexcept { return _fd; } Error open(bool preferTmpOverDevShm) noexcept { #if defined(__linux__) && defined(__NR_memfd_create) @@ -329,7 +308,7 @@ public: if (e == ENOSYS) memfd_create_not_supported = 1; else - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } #endif @@ -341,13 +320,12 @@ public: if (ASMJIT_LIKELY(_fd >= 0)) return kErrorOk; else - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(errno)); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); #else - // POSIX API. We have to generate somehow a unique name. This is nothing - // cryptographic, just using a bit from the stack address to always have - // a different base for different threads (as threads have their own stack) - // and retries for avoiding collisions. We use `shm_open()` with flags that - // require creation of the file so we never open an existing shared memory. + // POSIX API. We have to generate somehow a unique name. This is nothing cryptographic, just using a bit from + // the stack address to always have a different base for different threads (as threads have their own stack) + // and retries for avoiding collisions. We use `shm_open()` with flags that require creation of the file so we + // never open an existing shared memory. static std::atomic<uint32_t> internalCounter; const char* kShmFormat = "/shm-id-%016llX"; @@ -358,8 +336,10 @@ public: bits -= uint64_t(OSUtils::getTickCount()) * 773703683; bits = ((bits >> 14) ^ (bits << 6)) + uint64_t(++internalCounter) * 10619863; - if (!ASMJIT_VM_SHM_DETECT || preferTmpOverDevShm) { - _tmpName.assign(VirtMem_getTmpDir()); + bool useTmp = !ASMJIT_VM_SHM_DETECT || preferTmpOverDevShm; + + if (useTmp) { + _tmpName.assign(getTmpDir()); _tmpName.appendFormat(kShmFormat, (unsigned long long)bits); _fd = ::open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, 0); if (ASMJIT_LIKELY(_fd >= 0)) { @@ -367,6 +347,7 @@ public: return kErrorOk; } } +#if ASMJIT_VM_SHM_AVAILABLE else { _tmpName.assignFormat(kShmFormat, (unsigned long long)bits); _fd = ::shm_open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); @@ -375,10 +356,11 @@ public: return kErrorOk; } } +#endif int e = errno; if (e != EEXIST) - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } return DebugUtils::errored(kErrorFailedToOpenAnonymousMemory); @@ -389,10 +371,17 @@ public: FileType type = _fileType; _fileType = kFileTypeNone; - if (type == kFileTypeShm) +#if ASMJIT_VM_SHM_AVAILABLE + if (type == kFileTypeShm) { ::shm_unlink(_tmpName.data()); - else if (type == kFileTypeTmp) + return; + } +#endif + + if (type == kFileTypeTmp) { ::unlink(_tmpName.data()); + return; + } } void close() noexcept { @@ -405,23 +394,25 @@ public: Error allocate(size_t size) noexcept { // TODO: Improve this by using `posix_fallocate()` when available. if (ftruncate(_fd, off_t(size)) != 0) - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(errno)); + return DebugUtils::errored(asmjitErrorFromErrno(errno)); return kErrorOk; } }; -// Returns `mmap()` protection flags from \ref VirtMem::Flags. -static int VirtMem_mmProtFromFlags(uint32_t flags) noexcept { +// Returns `mmap()` protection flags from \ref MemoryFlags. +static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { int protection = 0; - if (flags & VirtMem::kAccessRead) protection |= PROT_READ; - if (flags & VirtMem::kAccessWrite) protection |= PROT_READ | PROT_WRITE; - if (flags & VirtMem::kAccessExecute) protection |= PROT_READ | PROT_EXEC; + if (Support::test(memoryFlags, MemoryFlags::kAccessRead)) protection |= PROT_READ; + if (Support::test(memoryFlags, MemoryFlags::kAccessWrite)) protection |= PROT_READ | PROT_WRITE; + if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) protection |= PROT_READ | PROT_EXEC; return protection; } #if defined(__APPLE__) -static ASMJIT_INLINE bool VirtMem_hasHardenedRuntimeMacOS() noexcept { +// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags cannot +// be allocated without MAP_JIT flag. +static inline bool hasHardenedRuntimeMacOS() noexcept { #if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 // MacOS on AArch64 has always hardened runtime enabled. return true; @@ -453,7 +444,7 @@ static ASMJIT_INLINE bool VirtMem_hasHardenedRuntimeMacOS() noexcept { #endif } -static ASMJIT_INLINE bool VirtMem_hasMapJitSupportMacOS() noexcept { +static inline bool hasMapJitSupportMacOS() noexcept { #if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64 // MacOS for 64-bit AArch architecture always uses hardened runtime. Some documentation can be found here: // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon @@ -477,62 +468,61 @@ static ASMJIT_INLINE bool VirtMem_hasMapJitSupportMacOS() noexcept { } #endif // __APPLE__ -// Detects whether the current process is hardened, which means that pages that -// have WRITE and EXECUTABLE flags cannot be normally allocated. On MacOS such -// allocation requires MAP_JIT flag. -static ASMJIT_INLINE bool VirtMem_hasHardenedRuntime() noexcept { +// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags +// cannot be normally allocated. On MacOS such allocation requires MAP_JIT flag. +static inline bool hasHardenedRuntime() noexcept { #if defined(__APPLE__) - return VirtMem_hasHardenedRuntimeMacOS(); + return hasHardenedRuntimeMacOS(); #else return false; #endif } // Detects whether MAP_JIT is available. -static ASMJIT_INLINE bool VirtMem_hasMapJitSupport() noexcept { +static inline bool hasMapJitSupport() noexcept { #if defined(__APPLE__) - return VirtMem_hasMapJitSupportMacOS(); + return hasMapJitSupportMacOS(); #else return false; #endif } // Returns either MAP_JIT or 0 based on `flags` and the host operating system. -static ASMJIT_INLINE int VirtMem_mmMapJitFromFlags(uint32_t flags) noexcept { +static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #if defined(__APPLE__) - // Always use MAP_JIT flag if user asked for it (could be used for testing - // on non-hardened processes) and detect whether it must be used when the - // process is actually hardened (in that case it doesn't make sense to rely - // on user `flags`). - bool useMapJit = (flags & VirtMem::kMMapEnableMapJit) != 0 || VirtMem_hasHardenedRuntime(); + // Always use MAP_JIT flag if user asked for it (could be used for testing on non-hardened processes) and detect + // whether it must be used when the process is actually hardened (in that case it doesn't make sense to rely on + // user `memoryFlags`). + bool useMapJit = Support::test(memoryFlags, MemoryFlags::kMMapEnableMapJit) || hasHardenedRuntime(); if (useMapJit) - return VirtMem_hasMapJitSupport() ? int(MAP_JIT) : 0; + return hasMapJitSupport() ? int(MAP_JIT) : 0; else return 0; #else - DebugUtils::unused(flags); + DebugUtils::unused(memoryFlags); return 0; #endif } // Returns BSD-specific `PROT_MAX()` flags. -static ASMJIT_INLINE int VirtMem_mmMaxProtFromFlags(uint32_t flags) noexcept { +static inline int mmMaxProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept { #if defined(PROT_MAX) - static constexpr uint32_t kMaxProtShift = Support::constCtz(VirtMem::kMMapMaxAccessRead); - if (flags & (VirtMem::kMMapMaxAccessReadWrite | VirtMem::kMMapMaxAccessExecute)) - return PROT_MAX(VirtMem_mmProtFromFlags(flags >> kMaxProtShift)); + static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value; + + if (Support::test(memoryFlags, MemoryFlags::kMMapMaxAccessReadWrite | MemoryFlags::kMMapMaxAccessExecute)) + return PROT_MAX(mmProtFromMemoryFlags((MemoryFlags)(uint32_t(memoryFlags) >> kMaxProtShift))); else return 0; #else - DebugUtils::unused(flags); + DebugUtils::unused(memoryFlags); return 0; #endif } #if ASMJIT_VM_SHM_DETECT -static Error VirtMem_detectShmStrategy(uint32_t* strategyOut) noexcept { +static Error detectShmStrategy(ShmStrategy* strategyOut) noexcept { AnonymousMemory anonMem; - VirtMem::Info vmInfo = VirtMem::info(); + Info vmInfo = info(); ASMJIT_PROPAGATE(anonMem.open(false)); ASMJIT_PROPAGATE(anonMem.allocate(vmInfo.pageSize)); @@ -541,58 +531,57 @@ static Error VirtMem_detectShmStrategy(uint32_t* strategyOut) noexcept { if (ptr == MAP_FAILED) { int e = errno; if (e == EINVAL) { - *strategyOut = kShmStrategyTmpDir; + *strategyOut = ShmStrategy::kTmpDir; return kErrorOk; } - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } else { munmap(ptr, vmInfo.pageSize); - *strategyOut = kShmStrategyDevShm; + *strategyOut = ShmStrategy::kDevShm; return kErrorOk; } } #endif -static Error VirtMem_getShmStrategy(uint32_t* strategyOut) noexcept { +static Error getShmStrategy(ShmStrategy* strategyOut) noexcept { #if ASMJIT_VM_SHM_DETECT - // Initially don't assume anything. It has to be tested whether - // '/dev/shm' was mounted with 'noexec' flag or not. + // Initially don't assume anything. It has to be tested whether '/dev/shm' was mounted with 'noexec' flag or not. static std::atomic<uint32_t> globalShmStrategy; - uint32_t strategy = globalShmStrategy.load(); - if (strategy == kShmStrategyUnknown) { - ASMJIT_PROPAGATE(VirtMem_detectShmStrategy(&strategy)); - globalShmStrategy.store(strategy); + ShmStrategy strategy = static_cast<ShmStrategy>(globalShmStrategy.load()); + if (strategy == ShmStrategy::kUnknown) { + ASMJIT_PROPAGATE(detectShmStrategy(&strategy)); + globalShmStrategy.store(static_cast<uint32_t>(strategy)); } *strategyOut = strategy; return kErrorOk; #else - *strategyOut = kShmStrategyTmpDir; + *strategyOut = ShmStrategy::kTmpDir; return kErrorOk; #endif } -static uint32_t VirtMem_hardenedRuntimeFlags() noexcept { - uint32_t flags = 0; +static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept { + HardenedRuntimeFlags hrFlags = HardenedRuntimeFlags::kNone; - if (VirtMem_hasHardenedRuntime()) - flags |= VirtMem::kHardenedRuntimeEnabled; + if (hasHardenedRuntime()) + hrFlags |= HardenedRuntimeFlags::kEnabled; - if (VirtMem_hasMapJitSupport()) - flags |= VirtMem::kHardenedRuntimeMapJit; + if (hasMapJitSupport()) + hrFlags |= HardenedRuntimeFlags::kMapJit; - return flags; + return hrFlags; } -Error VirtMem::alloc(void** p, size_t size, uint32_t memoryFlags) noexcept { +Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept { *p = nullptr; if (size == 0) return DebugUtils::errored(kErrorInvalidArgument); - int protection = VirtMem_mmProtFromFlags(memoryFlags) | VirtMem_mmMaxProtFromFlags(memoryFlags); - int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | VirtMem_mmMapJitFromFlags(memoryFlags); + int protection = mmProtFromMemoryFlags(memoryFlags) | mmMaxProtFromMemoryFlags(memoryFlags); + int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | mmMapJitFromMemoryFlags(memoryFlags); void* ptr = mmap(nullptr, size, protection, mmFlags, -1, 0); if (ptr == MAP_FAILED) @@ -602,7 +591,7 @@ Error VirtMem::alloc(void** p, size_t size, uint32_t memoryFlags) noexcept { return kErrorOk; } -Error VirtMem::release(void* p, size_t size) noexcept { +Error release(void* p, size_t size) noexcept { if (ASMJIT_UNLIKELY(munmap(p, size) != 0)) return DebugUtils::errored(kErrorInvalidArgument); @@ -610,30 +599,26 @@ Error VirtMem::release(void* p, size_t size) noexcept { } -Error VirtMem::protect(void* p, size_t size, uint32_t memoryFlags) noexcept { - int protection = VirtMem_mmProtFromFlags(memoryFlags); +Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept { + int protection = mmProtFromMemoryFlags(memoryFlags); if (mprotect(p, size, protection) == 0) return kErrorOk; return DebugUtils::errored(kErrorInvalidArgument); } -// ============================================================================ -// [asmjit::VirtMem - Dual Mapping [Posix]] -// ============================================================================ - -Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t memoryFlags) noexcept { +Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept { dm->rx = nullptr; dm->rw = nullptr; if (off_t(size) <= 0) return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge); - bool preferTmpOverDevShm = (memoryFlags & kMappingPreferTmp) != 0; + bool preferTmpOverDevShm = Support::test(memoryFlags, MemoryFlags::kMappingPreferTmp); if (!preferTmpOverDevShm) { - uint32_t strategy; - ASMJIT_PROPAGATE(VirtMem_getShmStrategy(&strategy)); - preferTmpOverDevShm = (strategy == kShmStrategyTmpDir); + ShmStrategy strategy; + ASMJIT_PROPAGATE(getShmStrategy(&strategy)); + preferTmpOverDevShm = (strategy == ShmStrategy::kTmpDir); } AnonymousMemory anonMem; @@ -642,8 +627,8 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t memoryFla void* ptr[2]; for (uint32_t i = 0; i < 2; i++) { - uint32_t accessFlags = memoryFlags & ~VirtMem_dualMappingFilter[i]; - int protection = VirtMem_mmProtFromFlags(accessFlags) | VirtMem_mmMaxProtFromFlags(accessFlags); + MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i]; + int protection = mmProtFromMemoryFlags(accessFlags) | mmMaxProtFromMemoryFlags(accessFlags); ptr[i] = mmap(nullptr, size, protection, MAP_SHARED, anonMem.fd(), 0); if (ptr[i] == MAP_FAILED) { @@ -651,7 +636,7 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t memoryFla int e = errno; if (i == 1) munmap(ptr[0], size); - return DebugUtils::errored(VirtMem_asmjitErrorFromErrno(e)); + return DebugUtils::errored(asmjitErrorFromErrno(e)); } } @@ -660,7 +645,7 @@ Error VirtMem::allocDualMapping(DualMapping* dm, size_t size, uint32_t memoryFla return kErrorOk; } -Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { +Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { Error err = release(dm->rx, size); if (dm->rx != dm->rw) err |= release(dm->rw, size); @@ -674,13 +659,12 @@ Error VirtMem::releaseDualMapping(DualMapping* dm, size_t size) noexcept { } #endif -// ============================================================================ -// [asmjit::VirtMem - Instruction Cache] -// ============================================================================ +// Virtual Memory - Flush Instruction Cache +// ======================================== -void VirtMem::flushInstructionCache(void* p, size_t size) noexcept { +void flushInstructionCache(void* p, size_t size) noexcept { #if ASMJIT_ARCH_X86 - // X86 architecture doesn't require to do anything to flush instruction cache. + // X86/X86_64 architecture doesn't require to do anything to flush instruction cache. DebugUtils::unused(p, size); #elif defined(__APPLE__) sys_icache_invalidate(p, size); @@ -697,17 +681,16 @@ void VirtMem::flushInstructionCache(void* p, size_t size) noexcept { #endif } -// ============================================================================ -// [asmjit::VirtMem - Page Info] -// ============================================================================ +// Virtual Memory - Memory Info +// ============================ -VirtMem::Info VirtMem::info() noexcept { +Info info() noexcept { static std::atomic<uint32_t> vmInfoInitialized; - static VirtMem::Info vmInfo; + static Info vmInfo; if (!vmInfoInitialized.load()) { - VirtMem::Info localMemInfo; - VirtMem_getInfo(localMemInfo); + Info localMemInfo; + getVMInfo(localMemInfo); vmInfo = localMemInfo; vmInfoInitialized.store(1u); @@ -716,19 +699,17 @@ VirtMem::Info VirtMem::info() noexcept { return vmInfo; } -// ============================================================================ -// [asmjit::VirtMem - Hardened Runtime Info] -// ============================================================================ +// Virtual Memory - Hardened Runtime Info +// ====================================== -VirtMem::HardenedRuntimeInfo VirtMem::hardenedRuntimeInfo() noexcept { - return VirtMem::HardenedRuntimeInfo { VirtMem_hardenedRuntimeFlags() }; +HardenedRuntimeInfo hardenedRuntimeInfo() noexcept { + return HardenedRuntimeInfo { getHardenedRuntimeFlags() }; } -// ============================================================================ -// [asmjit::VirtMem - JIT Memory Protection] -// ============================================================================ +// Virtual Memory - Project JIT Memory +// =================================== -void VirtMem::protectJitMemory(VirtMem::ProtectJitAccess access) noexcept { +void protectJitMemory(ProtectJitAccess access) noexcept { #if defined(ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP) pthread_jit_write_protect_np(static_cast<uint32_t>(access)); #else @@ -736,6 +717,6 @@ void VirtMem::protectJitMemory(VirtMem::ProtectJitAccess access) noexcept { #endif } -ASMJIT_END_NAMESPACE +ASMJIT_END_SUB_NAMESPACE #endif |