mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 04:24:37 +03:00
Hardened runtime detection enhancements
A new HardenedRuntimeFlags::kDualMapping flag has been introduced to detect whether dual mapping is provided by the target platform. This flag can be set even when hardened runtime is not enforced in cases, in which dual mapping is not available. This fixes running unit tests on Apple hardware where dual mapping is not available, but MAP_JIT is (AArch64 hardware). Additionally, this changeset fixes using -msse2 flag on non-x86 targets, where compiler don't mind "-msse2" flag, but warns about it. This makes the build 100% clean.
This commit is contained in:
@@ -686,11 +686,29 @@ if (NOT ASMJIT_EMBED)
|
||||
|
||||
if (NOT (ASMJIT_NO_BUILDER OR ASMJIT_NO_COMPILER))
|
||||
# Vectorcall tests and XMM tests require at least SSE2 in 32-bit mode (in 64-bit mode it's implicit).
|
||||
set(sse2_flags "")
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
asmjit_detect_cflags(sse2_flags "-arch:SSE2")
|
||||
else()
|
||||
asmjit_detect_cflags(sse2_flags "-msse2")
|
||||
# Some compilers don't like passing -msse2 for 64-bit targets, and some compilers targeting non-x86
|
||||
# would pass "-msse2" compile flag check, but with a warning not detected by CMake. Thus, verify that
|
||||
# our target is really 32-bit X86 and only use -msse2 or -arch:SSE2 flags when necessary.
|
||||
set(ASMJIT_SSE2_CFLAGS "")
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#if defined(_M_IX86) || defined(__X86__) || defined(__i386__)
|
||||
int target_is_32_bit_x86() { return 1; }
|
||||
#else
|
||||
// Compile error...
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
return target_is_32_bit_x86();
|
||||
}
|
||||
" ASMJIT_TARGET_IS_32_BIT_X86)
|
||||
|
||||
if (ASMJIT_TARGET_IS_32_BIT_X86)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
asmjit_detect_cflags(ASMJIT_SSE2_CFLAGS "-arch:SSE2")
|
||||
else()
|
||||
asmjit_detect_cflags(ASMJIT_SSE2_CFLAGS "-msse2")
|
||||
endif()
|
||||
endif()
|
||||
asmjit_add_target(asmjit_test_compiler TEST
|
||||
SOURCES test/asmjit_test_compiler.cpp
|
||||
@@ -698,7 +716,7 @@ if (NOT ASMJIT_EMBED)
|
||||
test/asmjit_test_compiler_a64.cpp
|
||||
test/asmjit_test_compiler_x86.cpp
|
||||
LIBRARIES asmjit::asmjit
|
||||
CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${sse2_flags}
|
||||
CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${ASMJIT_SSE2_CFLAGS}
|
||||
CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG}
|
||||
CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL})
|
||||
endif()
|
||||
|
||||
@@ -1399,11 +1399,12 @@ static void test_jit_allocator_alloc_release() noexcept {
|
||||
|
||||
using Opt = JitAllocatorOptions;
|
||||
|
||||
VirtMem::HardenedRuntimeInfo hri = VirtMem::hardenedRuntimeInfo();
|
||||
|
||||
TestParams testParams[] = {
|
||||
{ "Default" , Opt::kNone, 0, 0 },
|
||||
{ "16MB blocks" , Opt::kNone, 16 * 1024 * 1024, 0 },
|
||||
{ "256B granularity" , Opt::kNone, 0, 256 },
|
||||
{ "kUseDualMapping" , Opt::kUseDualMapping , 0, 0 },
|
||||
{ "kUseMultiplePools" , Opt::kUseMultiplePools, 0, 0 },
|
||||
{ "kFillUnusedMemory" , Opt::kFillUnusedMemory, 0, 0 },
|
||||
{ "kImmediateRelease" , Opt::kImmediateRelease, 0, 0 },
|
||||
@@ -1411,6 +1412,7 @@ static void test_jit_allocator_alloc_release() noexcept {
|
||||
{ "kUseLargePages" , Opt::kUseLargePages, 0, 0 },
|
||||
{ "kUseLargePages | kFillUnusedMemory" , Opt::kUseLargePages | Opt::kFillUnusedMemory, 0, 0 },
|
||||
{ "kUseLargePages | kAlignBlockSizeToLargePage", Opt::kUseLargePages | Opt::kAlignBlockSizeToLargePage, 0, 0 },
|
||||
{ "kUseDualMapping" , Opt::kUseDualMapping , 0, 0 },
|
||||
{ "kUseDualMapping | kFillUnusedMemory" , Opt::kUseDualMapping | Opt::kFillUnusedMemory, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -1427,6 +1429,12 @@ static void test_jit_allocator_alloc_release() noexcept {
|
||||
}
|
||||
|
||||
for (uint32_t testId = 0; testId < ASMJIT_ARRAY_SIZE(testParams); testId++) {
|
||||
// Don't try to allocate dual-mapping if dual mapping is not possible - it would fail the test.
|
||||
if (Support::test(testParams[testId].options, JitAllocatorOptions::kUseDualMapping) &&
|
||||
!Support::test(hri.flags, VirtMem::HardenedRuntimeFlags::kDualMapping)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
INFO("JitAllocator(%s)", testParams[testId].name);
|
||||
|
||||
JitAllocator::CreateParams params {};
|
||||
|
||||
@@ -141,6 +141,11 @@ static size_t detectLargePageSize() noexcept {
|
||||
return ::GetLargePageMinimum();
|
||||
}
|
||||
|
||||
static bool hasDualMappingSupport() noexcept {
|
||||
// TODO: This assumption works on X86 platforms, this may not work on AArch64.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns windows-specific protectFlags from \ref MemoryFlags.
|
||||
static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
|
||||
DWORD protectFlags;
|
||||
@@ -165,7 +170,12 @@ static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
|
||||
}
|
||||
|
||||
static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
|
||||
return HardenedRuntimeFlags::kNone;
|
||||
HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone;
|
||||
|
||||
if (hasDualMappingSupport())
|
||||
flags |= HardenedRuntimeFlags::kDualMapping;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept {
|
||||
@@ -703,8 +713,8 @@ static bool hasHardenedRuntime() noexcept {
|
||||
|
||||
// Detects whether MAP_JIT is available.
|
||||
static inline bool hasMapJitSupport() noexcept {
|
||||
#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
|
||||
// OSX on AArch64 always uses hardened runtime + MAP_JIT:
|
||||
#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_X86 == 0
|
||||
// Apple platforms always use hardened runtime + MAP_JIT on non-x86 hardware:
|
||||
// - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon
|
||||
return true;
|
||||
#elif defined(__APPLE__) && TARGET_OS_OSX
|
||||
@@ -746,6 +756,15 @@ static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool hasDualMappingSupport() noexcept {
|
||||
#if defined(__APPLE__) && TARGET_OS_OSX && ASMJIT_ARCH_X86 == 0
|
||||
// Apple platforms don't allow dual-mapping on non-x86 hardware.
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
|
||||
HardenedRuntimeFlags flags = HardenedRuntimeFlags::kNone;
|
||||
|
||||
@@ -755,6 +774,9 @@ static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
|
||||
if (hasMapJitSupport())
|
||||
flags |= HardenedRuntimeFlags::kMapJit;
|
||||
|
||||
if (hasDualMappingSupport())
|
||||
flags |= HardenedRuntimeFlags::kDualMapping;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -215,8 +215,11 @@ enum class HardenedRuntimeFlags : uint32_t {
|
||||
//! architecture.
|
||||
kEnabled = 0x00000001u,
|
||||
|
||||
//! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on OSX).
|
||||
kMapJit = 0x00000002u
|
||||
//! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific, only available on Apple platforms).
|
||||
kMapJit = 0x00000002u,
|
||||
|
||||
//! Read+Write+Executa can be allocated with dual mapping approach (one region with RW and the other with RX).
|
||||
kDualMapping = 0x00000004u
|
||||
};
|
||||
ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user