Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/asmjit/asmjit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkobalicek <kobalicek.petr@gmail.com>2022-10-09 14:06:28 +0300
committerkobalicek <kobalicek.petr@gmail.com>2022-10-09 20:30:14 +0300
commit15a603661871b86c048e697f0e6cd17374dcecc0 (patch)
tree894df409646c076dfb42e456aa7975b24cb890fb
parentbb3dc125fa04f98351b2c0dba4dd5193793e98aa (diff)
Fixed iOS compilation (reworked MAP_JIT detection, and pthread_jit_write_protect_np() support)
-rw-r--r--src/asmjit/core/virtmem.cpp92
-rw-r--r--src/asmjit/core/virtmem.h8
2 files changed, 43 insertions, 57 deletions
diff --git a/src/asmjit/core/virtmem.cpp b/src/asmjit/core/virtmem.cpp
index 43766ef..0bad6b5 100644
--- a/src/asmjit/core/virtmem.cpp
+++ b/src/asmjit/core/virtmem.cpp
@@ -53,13 +53,11 @@
#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
+#if !defined(_WIN32) && !defined(__BIONIC__)
+ #define ASMJIT_HAS_SHM_OPEN_AND_UNLINK
#endif
-#if defined(__APPLE__) && ASMJIT_ARCH_ARM >= 64
+#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
#define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP
#endif
@@ -347,7 +345,7 @@ public:
return kErrorOk;
}
}
-#if ASMJIT_VM_SHM_AVAILABLE
+#ifdef ASMJIT_HAS_SHM_OPEN_AND_UNLINK
else {
_tmpName.assignFormat(kShmFormat, (unsigned long long)bits);
_fd = ::shm_open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
@@ -371,7 +369,7 @@ public:
FileType type = _fileType;
_fileType = kFileTypeNone;
-#if ASMJIT_VM_SHM_AVAILABLE
+#ifdef ASMJIT_HAS_SHM_OPEN_AND_UNLINK
if (type == kFileTypeShm) {
::shm_unlink(_tmpName.data());
return;
@@ -409,12 +407,29 @@ static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
return protection;
}
-#if defined(__APPLE__)
-// 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 defined(__APPLE__) && TARGET_OS_OSX
+static int getOSXVersion() noexcept {
+ // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave).
+ static std::atomic<uint32_t> globalVersion;
+
+ int ver = globalVersion.load();
+ if (!ver) {
+ struct utsname osname {};
+ uname(&osname);
+ ver = atoi(osname.release);
+ globalVersion.store(ver);
+ }
+
+ return ver;
+}
+#endif // __APPLE__ && TARGET_OS_OSX
+
+// Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags
+// cannot be normally allocated. On OSX + AArch64 such allocation requires MAP_JIT flag, other platforms don't
+// support this combination.
+static bool hasHardenedRuntime() noexcept {
#if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
- // MacOS on AArch64 has always hardened runtime enabled.
+ // OSX on AArch64 has always hardened runtime enabled.
return true;
#else
static std::atomic<uint32_t> globalHardenedFlag;
@@ -427,7 +442,7 @@ static inline bool hasHardenedRuntimeMacOS() noexcept {
uint32_t flag = globalHardenedFlag.load();
if (flag == kHardenedFlagUnknown) {
- size_t pageSize = ::getpagesize();
+ uint32_t pageSize = uint32_t(::getpagesize());
void* ptr = mmap(nullptr, pageSize, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED) {
@@ -444,45 +459,16 @@ static inline bool hasHardenedRuntimeMacOS() noexcept {
#endif
}
-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
- return true;
-#elif TARGET_OS_OSX
- // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave) and IOS.
- static std::atomic<uint32_t> globalVersion;
-
- int ver = globalVersion.load();
- if (!ver) {
- struct utsname osname {};
- uname(&osname);
- ver = atoi(osname.release);
- globalVersion.store(ver);
- }
- return ver >= 18;
-#else
- // Assume it's available.
- return true;
-#endif
-}
-#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 inline bool hasHardenedRuntime() noexcept {
-#if defined(__APPLE__)
- return hasHardenedRuntimeMacOS();
-#else
- return false;
-#endif
-}
-
// Detects whether MAP_JIT is available.
static inline bool hasMapJitSupport() noexcept {
-#if defined(__APPLE__)
- return hasMapJitSupportMacOS();
+#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
+ // OSX on AArch64 always uses hardened runtime + MAP_JIT:
+ // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon
+ return true;
+#elif defined(__APPLE__) && TARGET_OS_OSX
+ return getOSXVersion() >= 18;
#else
+ // MAP_JIT is not available (it's only available on OSX).
return false;
#endif
}
@@ -564,15 +550,15 @@ static Error getShmStrategy(ShmStrategy* strategyOut) noexcept {
}
static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
- HardenedRuntimeFlags hrFlags = HardenedRuntimeFlags::kNone;
+ HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone;
if (hasHardenedRuntime())
- hrFlags |= HardenedRuntimeFlags::kEnabled;
+ flags |= HardenedRuntimeFlags::kEnabled;
if (hasMapJitSupport())
- hrFlags |= HardenedRuntimeFlags::kMapJit;
+ flags |= HardenedRuntimeFlags::kMapJit;
- return hrFlags;
+ return flags;
}
Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept {
diff --git a/src/asmjit/core/virtmem.h b/src/asmjit/core/virtmem.h
index 50f0945..3118f0b 100644
--- a/src/asmjit/core/virtmem.h
+++ b/src/asmjit/core/virtmem.h
@@ -67,7 +67,7 @@ enum class MemoryFlags : uint32_t {
//! in MAC bundles. This flag is not turned on by default, because when a process uses `fork()` the child process
//! has no access to the pages mapped with `MAP_JIT`, which could break code that doesn't expect this behavior.
//!
- //! \note This flag can only be used with \ref VirtMem::alloc().
+ //! \note This flag can only be used with \ref VirtMem::alloc(), `MAP_JIT` only works on OSX and not on iOS.
kMMapEnableMapJit = 0x00000010u,
//! Pass `PROT_MAX(PROT_READ)` to mmap() on platforms that support `PROT_MAX`.
@@ -157,13 +157,13 @@ enum class HardenedRuntimeFlags : uint32_t {
//! Hardened runtime is enabled - it's not possible to have "Write & Execute" memory protection. The runtime
//! enforces W^X (either write or execute).
//!
- //! \note If the runtime is hardened it means that an operating system specific protection is used. For example on
- //! MacOS platform it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()`
+ //! \note If the runtime is hardened it means that an operating system specific protection is used. For example
+ //! on Apple OSX it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()`
//! to temporarily swap access permissions for the current thread. Dual mapping is also a possibility on X86/X64
//! architecture.
kEnabled = 0x00000001u,
- //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific).
+ //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on OSX).
kMapJit = 0x00000002u
};
ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags)