diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -606,9 +606,32 @@ return result; } +void ParseVersion(const char *vers, u16 *major, u16 *minor) { + // Format: .[.]\0 + CHECK_GE(internal_strlen(vers), 3); + const char *p = vers; + *major = internal_simple_strtoll(p, &p, /*base=*/10); + CHECK_EQ(*p, '.'); + p += 1; + *minor = internal_simple_strtoll(p, &p, /*base=*/10); +} + +// Aligned versions example: +// Darwin 19 -- macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6 +static u16 GetDarwinKernelMajorFromOSMajor(u16 os_major) { + u16 offset; + if (SANITIZER_IOS || SANITIZER_TVOS) + offset = 6; + else if (SANITIZER_WATCHOS) + offset = 13; + else // macOS + UNREACHABLE("GetDarwinKernelMajorFromOSMajor() does not support macOS"); + + return os_major + offset; +} + // This corresponds to Triple::getMacOSXVersion() in the Clang driver. -static MacosVersion GetMacosAlignedVersionInternal() { - u16 kernel_major = GetDarwinKernelVersion().major; +static MacosVersion GetMacosVersionFromDarwinMajor(u16 kernel_major) { // Darwin 0-3 -> unsupported // Darwin 4-19 -> macOS 10.x // Darwin 20+ -> macOS 11+ @@ -624,6 +647,22 @@ return MacosVersion(major, minor); } +static MacosVersion GetMacosAlignedVersionInternal() { + if (SANITIZER_IOSSIM) { + if (auto vers = GetEnv("SIMULATOR_RUNTIME_VERSION")) { + u16 major, minor; + ParseVersion(vers, &major, &minor); + u16 kernel_major = GetDarwinKernelMajorFromOSMajor(major); + return GetMacosVersionFromDarwinMajor(kernel_major); + } + Report("WARNING: Running in simulator but SIMULATOR_RUNTIME_VERSION env " + "var is not set.\n"); + } + + u16 kernel_major = GetDarwinKernelVersion().major; + return GetMacosVersionFromDarwinMajor(kernel_major); +} + static_assert(sizeof(MacosVersion) == sizeof(atomic_uint32_t::Type), "MacosVersion cache size"); static atomic_uint32_t cached_macos_version; @@ -639,24 +678,14 @@ return *reinterpret_cast(&result); } -void ParseVersion(const char *vers, u16 *major, u16 *minor) { - // Format: ..\0 - CHECK_GE(internal_strlen(vers), 5); - const char *p = vers; - *major = internal_simple_strtoll(p, &p, /*base=*/10); - CHECK_EQ(*p, '.'); - p += 1; - *minor = internal_simple_strtoll(p, &p, /*base=*/10); -} - DarwinKernelVersion GetDarwinKernelVersion() { - char buf[100]; - size_t len = sizeof(buf); - int res = internal_sysctlbyname("kern.osrelease", buf, &len, nullptr, 0); + char vers[100]; + size_t len = sizeof(vers); + int res = internal_sysctlbyname("kern.osrelease", vers, &len, nullptr, 0); CHECK_EQ(res, 0); u16 major, minor; - ParseVersion(buf, &major, &minor); + ParseVersion(vers, &major, &minor); return DarwinKernelVersion(major, minor); } diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mac_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mac_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mac_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mac_test.cpp @@ -22,6 +22,35 @@ namespace __sanitizer { +void ParseVersion(const char *vers, u16 *major, u16 *minor); + +TEST(SanitizerMac, ParseVersion) { + u16 major, minor; + + ParseVersion("11.22.33", &major, &minor); + EXPECT_EQ(major, 11); EXPECT_EQ(minor, 22); + + ParseVersion("1.2", &major, &minor); + EXPECT_EQ(major, 1); EXPECT_EQ(minor, 2); +} + +#if SANITIZER_IOSSIM +TEST(SanitizerMac, GetMacosAlignedVersion) { + const char *vers_str; + if (SANITIZER_IOS || SANITIZER_TVOS) { + vers_str = "13.0"; + } else if (SANITIZER_WATCHOS) { + vers_str = "6.5"; + } else { + FAIL() << "unsupported simulator runtime"; + } + setenv("SIMULATOR_RUNTIME_VERSION", vers_str, /*overwrite=*/1); + + MacosVersion vers = GetMacosAlignedVersion(); + EXPECT_EQ(vers.major, 10); + EXPECT_EQ(vers.minor, 15); +} +#else TEST(SanitizerMac, GetMacosAlignedVersion) { MacosVersion vers = GetMacosAlignedVersion(); u16 kernel_major = GetDarwinKernelVersion().major; @@ -31,15 +60,7 @@ EXPECT_EQ(vers.major, expected_major); EXPECT_EQ(vers.minor, expected_minor); } - -void ParseVersion(const char *vers, u16 *major, u16 *minor); - -TEST(SanitizerMac, ParseVersion) { - u16 major, minor; - ParseVersion("11.22.33", &major, &minor); - EXPECT_EQ(major, 11); - EXPECT_EQ(minor, 22); -} +#endif TEST(SanitizerMac, GetDarwinKernelVersion) { DarwinKernelVersion vers = GetDarwinKernelVersion();