[Darwin] Fix OS version checks inside simulators

compiler-rt checks OS versions by querying the Darwin kernel version.
This is not necessarily correct inside the simulators if the simulator
runtime is not aligned with the host macOS.  Let's instead check the
`SIMULATOR_RUNTIME_VERSION` env var.

rdar://63031937

Reviewed By: delcypher

Differential Revision: https://reviews.llvm.org/D83977
This commit is contained in:
Julian Lettner 2020-07-24 11:24:34 -07:00
parent 8b2fcc42b8
commit 3fb0de8207
2 changed files with 95 additions and 36 deletions

View File

@ -606,21 +606,65 @@ HandleSignalMode GetHandleSignalMode(int signum) {
return result;
}
// This corresponds to Triple::getMacOSXVersion() in the Clang driver.
static MacosVersion GetMacosAlignedVersionInternal() {
u16 kernel_major = GetDarwinKernelVersion().major;
// Darwin 0-3 -> unsupported
// Darwin 4-19 -> macOS 10.x
// Darwin 20+ -> macOS 11+
CHECK_GE(kernel_major, 4);
u16 major, minor;
if (kernel_major < 20) {
major = 10;
minor = kernel_major - 4;
using VersStr = char[64];
static void GetOSVersion(VersStr vers) {
uptr len = sizeof(VersStr);
if (SANITIZER_IOSSIM) {
const char *vers_env = GetEnv("SIMULATOR_RUNTIME_VERSION");
if (!vers_env) {
Report("ERROR: Running in simulator but SIMULATOR_RUNTIME_VERSION env "
"var is not set.\n");
Die();
}
len = internal_strlcpy(vers, vers_env, len);
} else {
major = 11 + kernel_major - 20;
minor = 0;
int res =
internal_sysctlbyname("kern.osproductversion", vers, &len, nullptr, 0);
CHECK_EQ(res, 0);
}
CHECK_LT(len, sizeof(VersStr));
}
void ParseVersion(const char *vers, u16 *major, u16 *minor) {
// Format: <major>.<minor>[.<patch>]\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:
// macOS 10.15 -- iOS 13 -- tvOS 13 -- watchOS 6
static void MapToMacos(u16 *major, u16 *minor) {
if (TARGET_OS_OSX)
return;
if (SANITIZER_IOS || SANITIZER_TVOS)
*major += 2;
else if (SANITIZER_WATCHOS)
*major += 9;
else
UNREACHABLE("unsupported platform");
if (*major >= 16) { // macOS 11+
*major -= 5;
} else { // macOS 10.15 and below
*minor = *major;
*major = 10;
}
}
static MacosVersion GetMacosAlignedVersionInternal() {
VersStr vers;
GetOSVersion(vers);
u16 major, minor;
ParseVersion(vers, &major, &minor);
MapToMacos(&major, &minor);
return MacosVersion(major, minor);
}
@ -639,24 +683,15 @@ MacosVersion GetMacosAlignedVersion() {
return *reinterpret_cast<MacosVersion *>(&result);
}
void ParseVersion(const char *vers, u16 *major, u16 *minor) {
// Format: <major>.<minor>.<patch>\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);
VersStr vers;
uptr len = sizeof(VersStr);
int res = internal_sysctlbyname("kern.osrelease", vers, &len, nullptr, 0);
CHECK_EQ(res, 0);
CHECK_LT(len, sizeof(VersStr));
u16 major, minor;
ParseVersion(buf, &major, &minor);
ParseVersion(vers, &major, &minor);
return DarwinKernelVersion(major, minor);
}

View File

@ -22,6 +22,38 @@
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);
}
// TODO(yln): Run sanitizer unit tests for the simulators (rdar://65680742)
#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 +63,7 @@ TEST(SanitizerMac, GetMacosAlignedVersion) {
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();