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
Details
- Reviewers
delcypher - Commits
- rG3fb0de820796: [Darwin] Fix OS version checks inside simulators
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
@delcypher
I addressed your remaining comments here: https://reviews.llvm.org/D79979#2156659
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
655 | Wait. Why do we go from Simulator OS version -> darwin kernel version -> macOS version? Can't we just compute the macOS version from the simulator OS version using a known offset? |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
655 | Yes, this is correct. The naming scheme change for macOS 11 complicates the mapping (there are two cases now) and this way we can avoid duplicating this logic. |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
655 | I see. I guess there's a trade-off here:
Con: We need to duplicate handling of the versioning for the macOS 11 transition.
Pro: Allows re-using the logic for the handling of the versioning for the macOS 11 transition. I'm not convinced that avoiding duplication of the macOS 11 versioning code is worth the complication it introduces. However, taking a step back. I think the problem here is that we've decided to use the macOS version numbers as the canonical representation for version checks in the runtime. Given that macOS now has this change in versioning at macOS 11 I don't really think it's the right choice anymore. Some ideas for alternatives:
if (OS_VERSION(10.15, 13.0, 6.0, 13.0) > GetOSVersion()) { //.. os specific action. } Here OS_VERSION is a macro (or some kind of template magic) that expands to the Version for the platform we are compiling for at compile time. The syntax probably isn't quite right here but the above is meant to just illustrate the idea. This makes GetOSVersion() really simple because we never need to get kernel versions involved. The implementation would be something like: if (SANITIZER_IOSSIM) { if (auto vers = GetEnv("SIMULATOR_RUNTIME_VERSION")) { u16 major, minor; ParseVersion(vers, &major, &minor); return OSVersion(major, minor, 0); } // Emit warning here... } // Get OS from systl kern.osproductversion char vers[100]; size_t len = sizeof(vers); int res = internal_sysctlbyname("kern.osproductversion", vers, &len, nullptr, 0); CHECK_EQ(res, 0); return OSVersion(major, minor, 0); @yln @kubamracek What do you think? |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
655 | I agree that what you outlined above, i.e., something along the lines: if (OS_VERSION(10.15, 13.0, 6.0, 13.0) > GetOSVersion()) { //.. os specific action. } would be much better. This is also pretty much what availability checking code supported by language constructs (Swift, objc) looks like. I would like to keep the scope of this patch small: fix OS version checking in the simulators.
I will try to change the patch to go from OS version -> macOS version directly. |
Looks really good. I just have a few nits.
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
642 | Do we use _ in the name of types? | |
645 | I think we usually use uptr rather than size_t. | |
646 | Suggestion: You could add a sanity check here. CHECK_GE(*major, 10); if (*major == 10) { CHECK_GE(*minor, /*whatever our minimum version is */); } | |
653 | Suggestion. You could do uptr env_var_len = internal_strlen(vers_env); CHECK_LT(env_var_len, sizeof(vers_str)); as a sanity check. | |
655 | Cool. You combined my sketch with the patch. This looks great. |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
666 | Oh you have an early return (which is great) but if you do the sanity check you have to do it here too. |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
653 | The check CHECK_LT(len, sizeof(vers_str)); below (which applies to both sides of the if-else) should accomplish the same. strlcpy() returns the total length of the string it tried to create (essentially strlen(src)), which should be smaller than the dst buffer. | |
682–684 | Switching this over to VersStr as well and adding assert for the length. |
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | ||
---|---|---|
646 | This specific code behaves predictably for any version numbers (even if it's producing invalid numbers for invalid inputs). It's more a constraint of application in compiler-rt that we don't support anything pre 10.9, but the code is okay with anything. In the previous iteration of this I had a similar-looking CHECK, because the mapping was defined in a way where we had an "invalid case": darwin_kernel_vers >= 20 -> macOS 11+ // -20 + 11 darwin_kernel_vers >= 4 -> macos 10.x // -4 Invalid, smaller versions: -4 would wrap around // guard with CHECK Hope this makes sense. |
LGTM except for the lint checks failing. Please fix those before landing.
compiler-rt/lib/sanitizer_common/tests/sanitizer_mac_test.cpp | ||
---|---|---|
34 | Could you fix these lint checks before you land this? |
clang-format not found in user's PATH; not linting file.