diff --git a/lldb/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py b/lldb/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py new file mode 100644 --- /dev/null +++ b/lldb/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py @@ -0,0 +1,60 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test.gdbclientutils import * +from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase + + +class TestPlatformMacOSX(GDBRemoteTestBase): + + mydir = TestBase.compute_mydir(__file__) + + class MyResponder(MockGDBServerResponder): + + def __init__(self, host): + self.host_ostype = host + MockGDBServerResponder.__init__(self) + + def respond(self, packet): + if packet == "qProcessInfo": + return self.qProcessInfo() + return MockGDBServerResponder.respond(self, packet) + + def qHostInfo(self): + return "cputype:16777223;cpusubtype:2;ostype:%s;vendor:apple;os_version:10.15.4;maccatalyst_version:13.4;endian:little;ptrsize:8;" % self.host_ostype + + def qProcessInfo(self): + return "pid:a860;parent-pid:d2a0;real-uid:1f5;real-gid:14;effective-uid:1f5;effective-gid:14;cputype:100000c;cpusubtype:2;ptrsize:8;ostype:ios;vendor:apple;endian:little;" + + def vCont(self): + return "vCont;" + + def platform_test(self, host, expected_triple, expected_platform): + self.server.responder = self.MyResponder(host) + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + target = self.dbg.CreateTargetWithFileAndArch(None, None) + process = self.connect(target) + + triple = target.GetTriple() + self.assertEqual(triple, expected_triple) + + platform = target.GetPlatform() + self.assertEqual(platform.GetName(), expected_platform) + + @skipIfRemote + def test_ios(self): + self.platform_test(host="ios", + expected_triple="arm64e-apple-ios-", + expected_platform="remote-ios") + + @skipIfRemote + @skipUnlessDarwin + @skipUnlessArch("arm64") + def test_macos(self): + self.platform_test(host="macosx", + expected_triple="arm64e-apple-ios-", + expected_platform="host") diff --git a/lldb/lldb/unittests/Platform/PlatformMacOSXTest.cpp b/lldb/lldb/unittests/Platform/PlatformMacOSXTest.cpp new file mode 100644 --- /dev/null +++ b/lldb/lldb/unittests/Platform/PlatformMacOSXTest.cpp @@ -0,0 +1,52 @@ +//===-- PlatformMacOSXTest.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "Plugins/Platform/MacOSX/PlatformMacOSX.h" +#include "TestingSupport/SubsystemRAII.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Platform.h" + +using namespace lldb; +using namespace lldb_private; + +class PlatformMacOSXTest : public ::testing::Test { + SubsystemRAII subsystems; +}; + +static bool containsArch(const std::vector &archs, + const ArchSpec &arch) { + return std::find_if(archs.begin(), archs.end(), [&](const ArchSpec &other) { + return arch.IsExactMatch(other); + }) != archs.end(); +} + +TEST_F(PlatformMacOSXTest, TestGetSupportedArchitectures) { + PlatformMacOSX platform; + + const ArchSpec x86_macosx_arch("x86_64-apple-macosx"); + + EXPECT_TRUE(containsArch(platform.GetSupportedArchitectures(x86_macosx_arch), + x86_macosx_arch)); + EXPECT_TRUE( + containsArch(platform.GetSupportedArchitectures({}), x86_macosx_arch)); + +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + const ArchSpec arm64_macosx_arch("arm64-apple-macosx"); + const ArchSpec arm64_ios_arch("arm64-apple-ios"); + + EXPECT_TRUE(containsArch( + platform.GetSupportedArchitectures(arm64_macosx_arch), arm64_ios_arch)); + EXPECT_TRUE( + containsArch(platform.GetSupportedArchitectures({}), arm64_ios_arch)); + EXPECT_FALSE(containsArch(platform.GetSupportedArchitectures(arm64_ios_arch), + arm64_ios_arch)); +#endif +} diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -137,8 +137,6 @@ PlatformMacOSX::GetSupportedArchitectures(const ArchSpec &process_host_arch) { std::vector result; #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - // macOS for ARM64 support both native and translated x86_64 processes - // When cmdline lldb is run on iOS, watchOS, etc, it is still // using "PlatformMacOSX". llvm::Triple::OSType host_os = GetHostOSType(); @@ -152,6 +150,16 @@ result.push_back(ArchSpec("x86_64-apple-ios-macabi")); result.push_back(ArchSpec("arm64-apple-ios-macabi")); result.push_back(ArchSpec("arm64e-apple-ios-macabi")); + + // On Apple Silicon, the host platform is compatible with iOS triples to + // support unmodified "iPhone and iPad Apps on Apple Silicon Macs". Because + // the binaries are identical, we must rely on the host architecture to + // tell them apart and mark the host platform as compatible or not. + if (!process_host_arch || + process_host_arch.GetTriple().getOS() == llvm::Triple::MacOSX) { + result.push_back(ArchSpec("arm64-apple-ios")); + result.push_back(ArchSpec("arm64e-apple-ios")); + } } #else x86GetSupportedArchitectures(result); diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py b/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/TestPlatformMacOSX.py @@ -0,0 +1,60 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test.gdbclientutils import * +from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase + + +class TestPlatformMacOSX(GDBRemoteTestBase): + + mydir = TestBase.compute_mydir(__file__) + + class MyResponder(MockGDBServerResponder): + + def __init__(self, host): + self.host_ostype = host + MockGDBServerResponder.__init__(self) + + def respond(self, packet): + if packet == "qProcessInfo": + return self.qProcessInfo() + return MockGDBServerResponder.respond(self, packet) + + def qHostInfo(self): + return "cputype:16777223;cpusubtype:2;ostype:%s;vendor:apple;os_version:10.15.4;maccatalyst_version:13.4;endian:little;ptrsize:8;" % self.host_ostype + + def qProcessInfo(self): + return "pid:a860;parent-pid:d2a0;real-uid:1f5;real-gid:14;effective-uid:1f5;effective-gid:14;cputype:100000c;cpusubtype:2;ptrsize:8;ostype:ios;vendor:apple;endian:little;" + + def vCont(self): + return "vCont;" + + def platform_test(self, host, expected_triple, expected_platform): + self.server.responder = self.MyResponder(host) + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + target = self.dbg.CreateTargetWithFileAndArch(None, None) + process = self.connect(target) + + triple = target.GetTriple() + self.assertEqual(triple, expected_triple) + + platform = target.GetPlatform() + self.assertEqual(platform.GetName(), expected_platform) + + @skipIfRemote + def test_ios(self): + self.platform_test(host="ios", + expected_triple="arm64e-apple-ios-", + expected_platform="remote-ios") + + @skipIfRemote + @skipUnlessDarwin + @skipUnlessArch("arm64") + def test_macos(self): + self.platform_test(host="macosx", + expected_triple="arm64e-apple-ios-", + expected_platform="host") diff --git a/lldb/unittests/Platform/CMakeLists.txt b/lldb/unittests/Platform/CMakeLists.txt --- a/lldb/unittests/Platform/CMakeLists.txt +++ b/lldb/unittests/Platform/CMakeLists.txt @@ -1,6 +1,7 @@ add_lldb_unittest(LLDBPlatformTests PlatformAppleSimulatorTest.cpp PlatformDarwinTest.cpp + PlatformMacOSXTest.cpp PlatformSiginfoTest.cpp LINK_LIBS diff --git a/lldb/unittests/Platform/PlatformMacOSXTest.cpp b/lldb/unittests/Platform/PlatformMacOSXTest.cpp new file mode 100644 --- /dev/null +++ b/lldb/unittests/Platform/PlatformMacOSXTest.cpp @@ -0,0 +1,52 @@ +//===-- PlatformMacOSXTest.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "Plugins/Platform/MacOSX/PlatformMacOSX.h" +#include "TestingSupport/SubsystemRAII.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Platform.h" + +using namespace lldb; +using namespace lldb_private; + +class PlatformMacOSXTest : public ::testing::Test { + SubsystemRAII subsystems; +}; + +static bool containsArch(const std::vector &archs, + const ArchSpec &arch) { + return std::find_if(archs.begin(), archs.end(), [&](const ArchSpec &other) { + return arch.IsExactMatch(other); + }) != archs.end(); +} + +TEST_F(PlatformMacOSXTest, TestGetSupportedArchitectures) { + PlatformMacOSX platform; + + const ArchSpec x86_macosx_arch("x86_64-apple-macosx"); + + EXPECT_TRUE(containsArch(platform.GetSupportedArchitectures(x86_macosx_arch), + x86_macosx_arch)); + EXPECT_TRUE( + containsArch(platform.GetSupportedArchitectures({}), x86_macosx_arch)); + +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + const ArchSpec arm64_macosx_arch("arm64-apple-macosx"); + const ArchSpec arm64_ios_arch("arm64-apple-ios"); + + EXPECT_TRUE(containsArch( + platform.GetSupportedArchitectures(arm64_macosx_arch), arm64_ios_arch)); + EXPECT_TRUE( + containsArch(platform.GetSupportedArchitectures({}), arm64_ios_arch)); + EXPECT_FALSE(containsArch(platform.GetSupportedArchitectures(arm64_ios_arch), + arm64_ios_arch)); +#endif +}