From ba6b1b4353e33a7a36bcbad1d1c1157826197fd2 Mon Sep 17 00:00:00 2001 From: Julian Lettner Date: Thu, 14 May 2020 14:52:35 -0700 Subject: [PATCH] [Darwin] Improve runtime OS version checks Use a struct to represent numerical versions instead of encoding release names in an enumeration. This avoids the need to extend the enumeration every time there is a new release. Rename `GetMacosVersion() -> GetMacosAlignedVersion()` to better reflect how this is used on non-MacOS platforms. Reviewed By: delcypher Differential Revision: https://reviews.llvm.org/D79970 --- compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | 68 +++++++--------------- compiler-rt/lib/sanitizer_common/sanitizer_mac.h | 36 +++++------- .../sanitizer_common/sanitizer_symbolizer_mac.cpp | 2 +- compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp | 4 +- 4 files changed, 40 insertions(+), 70 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp index 7550545..9a0053a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -388,7 +388,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, // pthread_get_stacksize_np() returns an incorrect stack size for the main // thread on Mavericks. See // https://github.com/google/sanitizers/issues/261 - if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization && + if ((GetMacosAlignedVersion() >= MacosVersion(10, 9)) && at_initialization && stacksize == (1 << 19)) { struct rlimit rl; CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0); @@ -607,53 +607,27 @@ HandleSignalMode GetHandleSignalMode(int signum) { return result; } -MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED; - -MacosVersion GetMacosVersionInternal() { - int mib[2] = { CTL_KERN, KERN_OSRELEASE }; - char version[100]; - uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]); - for (uptr i = 0; i < maxlen; i++) version[i] = '\0'; - // Get the version length. - CHECK_NE(internal_sysctl(mib, 2, 0, &len, 0, 0), -1); - CHECK_LT(len, maxlen); - CHECK_NE(internal_sysctl(mib, 2, version, &len, 0, 0), -1); - - // Expect .(.) - CHECK_GE(len, 3); - const char *p = version; - int major = internal_simple_strtoll(p, &p, /*base=*/10); - if (*p != '.') return MACOS_VERSION_UNKNOWN; - p += 1; - int minor = internal_simple_strtoll(p, &p, /*base=*/10); - if (*p != '.') return MACOS_VERSION_UNKNOWN; - - switch (major) { - case 11: return MACOS_VERSION_LION; - case 12: return MACOS_VERSION_MOUNTAIN_LION; - case 13: return MACOS_VERSION_MAVERICKS; - case 14: return MACOS_VERSION_YOSEMITE; - case 15: return MACOS_VERSION_EL_CAPITAN; - case 16: return MACOS_VERSION_SIERRA; - case 17: return MACOS_VERSION_HIGH_SIERRA; - case 18: return MACOS_VERSION_MOJAVE; - case 19: return MACOS_VERSION_CATALINA; - default: - if (major < 9) return MACOS_VERSION_UNKNOWN; - return MACOS_VERSION_UNKNOWN_NEWER; - } +static MacosVersion GetMacosAlignedVersionInternal() { + u16 kernel_major = GetDarwinKernelVersion().major; + const u16 version_offset = 4; + CHECK_GE(kernel_major, version_offset); + u16 macos_major = kernel_major - version_offset; + return MacosVersion(10, macos_major); } -MacosVersion GetMacosVersion() { - atomic_uint32_t *cache = - reinterpret_cast(&cached_macos_version); - MacosVersion result = - static_cast(atomic_load(cache, memory_order_acquire)); - if (result == MACOS_VERSION_UNINITIALIZED) { - result = GetMacosVersionInternal(); - atomic_store(cache, result, memory_order_release); +static_assert(sizeof(MacosVersion) == sizeof(atomic_uint32_t::Type), + "MacosVersion cache size"); +static atomic_uint32_t cached_macos_version; + +MacosVersion GetMacosAlignedVersion() { + atomic_uint32_t::Type result = + atomic_load(&cached_macos_version, memory_order_acquire); + if (!result) { + MacosVersion version = GetMacosAlignedVersionInternal(); + result = *reinterpret_cast(&version); + atomic_store(&cached_macos_version, result, memory_order_release); } - return result; + return *reinterpret_cast(&result); } DarwinKernelVersion GetDarwinKernelVersion() { @@ -719,7 +693,7 @@ void LogFullErrorReport(const char *buffer) { #if !SANITIZER_GO // Log with os_trace. This will make it into the crash log. #if SANITIZER_OS_TRACE - if (GetMacosVersion() >= MACOS_VERSION_YOSEMITE) { + if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) { // os_trace requires the message (format parameter) to be a string literal. if (internal_strncmp(SanitizerToolName, "AddressSanitizer", sizeof("AddressSanitizer") - 1) == 0) @@ -866,7 +840,7 @@ bool DyldNeedsEnvVariable() { if (!&dyldVersionNumber) return true; // If running on OS X 10.11+ or iOS 9.0+, dyld will interpose even if // DYLD_INSERT_LIBRARIES is not set. However, checking OS version via - // GetMacosVersion() doesn't work for the simulator. Let's instead check + // GetMacosAlignedVersion() doesn't work for the simulator. Let's instead check // `dyldVersionNumber`, which is exported by dyld, against a known version // number from the first OS release where this appeared. return dyldVersionNumber < kMinDyldVersionWithAutoInterposition; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.h b/compiler-rt/lib/sanitizer_common/sanitizer_mac.h index 34dc2c0..806aba9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.h @@ -30,37 +30,33 @@ struct MemoryMappingLayoutData { bool current_instrumented; }; -enum MacosVersion { - MACOS_VERSION_UNINITIALIZED = 0, - MACOS_VERSION_UNKNOWN, - MACOS_VERSION_LION, // macOS 10.7; oldest currently supported - MACOS_VERSION_MOUNTAIN_LION, - MACOS_VERSION_MAVERICKS, - MACOS_VERSION_YOSEMITE, - MACOS_VERSION_EL_CAPITAN, - MACOS_VERSION_SIERRA, - MACOS_VERSION_HIGH_SIERRA, - MACOS_VERSION_MOJAVE, - MACOS_VERSION_CATALINA, - MACOS_VERSION_UNKNOWN_NEWER -}; - -struct DarwinKernelVersion { +template +struct VersionBase { u16 major; u16 minor; - DarwinKernelVersion(u16 major, u16 minor) : major(major), minor(minor) {} + VersionBase(u16 major, u16 minor) : major(major), minor(minor) {} - bool operator==(const DarwinKernelVersion &other) const { + bool operator==(const VersionType &other) const { return major == other.major && minor == other.minor; } - bool operator>=(const DarwinKernelVersion &other) const { + bool operator>=(const VersionType &other) const { return major >= other.major || (major == other.major && minor >= other.minor); } }; -MacosVersion GetMacosVersion(); +struct MacosVersion : VersionBase { + MacosVersion(u16 ten, u16 major) : VersionBase(ten, major) { + CHECK_EQ(ten, 10); + } +}; + +struct DarwinKernelVersion : VersionBase { + DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {} +}; + +MacosVersion GetMacosAlignedVersion(); DarwinKernelVersion GetDarwinKernelVersion(); char **GetEnviron(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp index cc23340..29cbf62 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp @@ -123,7 +123,7 @@ class AtosSymbolizerProcess : public SymbolizerProcess { argv[i++] = path_to_binary; argv[i++] = "-p"; argv[i++] = &pid_str_[0]; - if (GetMacosVersion() == MACOS_VERSION_MAVERICKS) { + if (GetMacosAlignedVersion() == MacosVersion(10, 9)) { // On Mavericks atos prints a deprecation warning which we suppress by // passing -d. The warning isn't present on other OSX versions, even the // newer ones. diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp index f92ecc5..eea52a3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp @@ -258,7 +258,7 @@ void InitializePlatform() { pthread_introspection_hook_install(&my_pthread_introspection_hook); #endif - if (GetMacosVersion() >= MACOS_VERSION_MOJAVE) { + if (GetMacosAlignedVersion() >= MacosVersion(10, 14)) { // Libsystem currently uses a process-global key; this might change. const unsigned kTLSLongjmpXorKeySlot = 0x7; longjmp_xor_key = (uptr)pthread_getspecific(kTLSLongjmpXorKeySlot); @@ -267,7 +267,7 @@ void InitializePlatform() { #ifdef __aarch64__ # define LONG_JMP_SP_ENV_SLOT \ - ((GetMacosVersion() >= MACOS_VERSION_MOJAVE) ? 12 : 13) + ((GetMacosAlignedVersion() >= MacosVersion(10, 14)) ? 12 : 13) #else # define LONG_JMP_SP_ENV_SLOT 2 #endif -- 2.7.4