From 05df9cc70367a60cb34bee773389ab2522984f8b Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 5 Aug 2020 13:57:14 -0700 Subject: [PATCH] Correctly detect legacy iOS simulator Mach-O objectfiles The code in ObjectFileMachO didn't disambiguate between ios and ios-simulator object files for Mach-O objects using the legacy ambiguous LC_VERSION_MIN load commands. This used to not matter before taught ArchSpec that ios and ios-simulator are no longer compatible. rdar://problem/66545307 Differential Revision: https://reviews.llvm.org/D85358 --- .../Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 16 +++++++++++-- lldb/source/Utility/ArchSpec.cpp | 27 +++++++++++----------- .../API/macosx/simulator/TestSimulatorPlatform.py | 16 +++++++++---- lldb/unittests/Utility/ArchSpecTest.cpp | 19 +++++++++++++++ 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 383cc5b..e7701c3 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5007,8 +5007,8 @@ void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header, struct version_min_command version_min; switch (load_cmd.cmd) { - case llvm::MachO::LC_VERSION_MIN_IPHONEOS: case llvm::MachO::LC_VERSION_MIN_MACOSX: + case llvm::MachO::LC_VERSION_MIN_IPHONEOS: case llvm::MachO::LC_VERSION_MIN_TVOS: case llvm::MachO::LC_VERSION_MIN_WATCHOS: { if (load_cmd.cmdsize != sizeof(version_min)) @@ -5024,7 +5024,19 @@ void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header, auto triple = base_triple; triple.setOSName(os.str()); - os_name.clear(); + + // Disambiguate legacy simulator platforms. + if (load_cmd.cmd != llvm::MachO::LC_VERSION_MIN_MACOSX && + (base_triple.getArch() == llvm::Triple::x86_64 || + base_triple.getArch() == llvm::Triple::x86)) { + // The combination of legacy LC_VERSION_MIN load command and + // x86 architecture always indicates a simulator environment. + // The combination of LC_VERSION_MIN and arm architecture only + // appears for native binaries. Back-deploying simulator + // binaries on Apple Silicon Macs use the modern unambigous + // LC_BUILD_VERSION load commands; no special handling required. + triple.setEnvironment(llvm::Triple::Simulator); + } add_triple(triple); break; } diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index 6e4f1b5..9cbd5df 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -1057,20 +1057,6 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { return true; } - if (lhs_triple_os != rhs_triple_os) { - const bool rhs_os_specified = rhs.TripleOSWasSpecified(); - const bool lhs_os_specified = TripleOSWasSpecified(); - // Both architectures had the OS specified, so if they aren't equal then - // we return false - if (rhs_os_specified && lhs_os_specified) - return false; - - // Only fail if both os types are not unknown - if (lhs_triple_os != llvm::Triple::UnknownOS && - rhs_triple_os != llvm::Triple::UnknownOS) - return false; - } - // x86_64-apple-ios-macabi and x86_64-apple-ios are not compatible. if (lhs_triple_os == llvm::Triple::IOS && rhs_triple_os == llvm::Triple::IOS && @@ -1079,6 +1065,19 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { lhs_triple_env != rhs_triple_env) return false; + if (lhs_triple_os != rhs_triple_os) { + const bool lhs_os_specified = TripleOSWasSpecified(); + const bool rhs_os_specified = rhs.TripleOSWasSpecified(); + // If both OS types are specified and different, fail. + if (lhs_os_specified && rhs_os_specified) + return false; + + // If the pair of os+env is both unspecified, match any other os+env combo. + if (!exact_match && ((!lhs_os_specified && !lhs_triple.hasEnvironment()) || + (!rhs_os_specified && !rhs_triple.hasEnvironment()))) + return true; + } + return IsCompatibleEnvironment(lhs_triple_env, rhs_triple_env); } diff --git a/lldb/test/API/macosx/simulator/TestSimulatorPlatform.py b/lldb/test/API/macosx/simulator/TestSimulatorPlatform.py index 9b5aed1..26264868 100644 --- a/lldb/test/API/macosx/simulator/TestSimulatorPlatform.py +++ b/lldb/test/API/macosx/simulator/TestSimulatorPlatform.py @@ -6,7 +6,6 @@ import json import unittest2 -@skipIfDarwin # rdar://problem/64552748 class TestSimulatorPlatformLaunching(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -41,14 +40,16 @@ class TestSimulatorPlatformLaunching(TestBase): def run_with(self, arch, os, vers, env, expected_load_command): - self.build(dictionary={'TRIPLE': arch+'-apple-'+os+vers+'-'+env}) + env_list = [env] if env else [] + triple = '-'.join([arch, 'apple', os + vers] + env_list) + self.build(dictionary={'TRIPLE': triple}) self.check_load_commands(expected_load_command) log = self.getBuildArtifact('packets.log') self.expect("log enable gdb-remote packets -f "+log) lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("hello.c")) - self.expect('image list -b -t', - patterns=['a\.out '+arch+'-apple-'+os+vers+'.*-'+env]) + triple_re = '-'.join([arch, 'apple', os + vers+'.*'] + env_list) + self.expect('image list -b -t', patterns=['a\.out '+triple_re]) self.check_debugserver(log, os+env, vers) @skipUnlessDarwin @@ -103,6 +104,13 @@ class TestSimulatorPlatformLaunching(TestBase): @skipUnlessDarwin @skipIfDarwinEmbedded + def test_lc_version_min_macosx(self): + """Test running a back-deploying non-simulator MacOS X binary""" + self.run_with(arch=self.getArchitecture(), + os='macosx', vers='10.9', env='', + expected_load_command='LC_VERSION_MIN_MACOSX') + @skipUnlessDarwin + @skipIfDarwinEmbedded @apple_simulator_test('iphone') @skipIf(archs=['arm64','arm64e']) def test_lc_version_min_iphoneos(self): diff --git a/lldb/unittests/Utility/ArchSpecTest.cpp b/lldb/unittests/Utility/ArchSpecTest.cpp index ad0a8ac..1ef646a 100644 --- a/lldb/unittests/Utility/ArchSpecTest.cpp +++ b/lldb/unittests/Utility/ArchSpecTest.cpp @@ -305,6 +305,25 @@ TEST(ArchSpecTest, Compatibility) { ArchSpec B("x86_64-apple-ios-simulator"); ASSERT_FALSE(A.IsExactMatch(B)); ASSERT_FALSE(A.IsCompatibleMatch(B)); + ASSERT_FALSE(B.IsExactMatch(A)); + ASSERT_FALSE(B.IsCompatibleMatch(A)); + } + { + ArchSpec A("x86_64-apple-ios"); + ArchSpec B("x86_64-apple-ios-simulator"); + ASSERT_FALSE(A.IsExactMatch(B)); + ASSERT_FALSE(A.IsCompatibleMatch(B)); + ASSERT_FALSE(B.IsExactMatch(A)); + ASSERT_FALSE(B.IsCompatibleMatch(A)); + } + { + // FIXME: This is surprisingly not equivalent to "x86_64-*-*". + ArchSpec A("x86_64"); + ArchSpec B("x86_64-apple-ios-simulator"); + ASSERT_FALSE(A.IsExactMatch(B)); + ASSERT_TRUE(A.IsCompatibleMatch(B)); + ASSERT_FALSE(B.IsExactMatch(A)); + ASSERT_TRUE(B.IsCompatibleMatch(A)); } { ArchSpec A("arm64-apple-ios"); -- 2.7.4