diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -698,6 +698,17 @@ archs), bugnumber) +def skipUnlessAppleSilicon(func): + """Decorate the item to skip tests unless running on Apple Silicon.""" + def not_apple_silicon(test): + if platform.system() != 'Darwin' or test.getArchitecture() not in [ + 'arm64', 'arm64e' + ]: + return "Test only runs on Apple Silicon" + return None + + return skipTestIfFn(not_apple_silicon)(func) + def skipUnlessSupportedTypeAttribute(attr): """Decorate the item to skip test unless Clang supports type __attribute__(attr).""" def compiler_doesnt_support_struct_attribute(self): diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp @@ -148,11 +148,20 @@ uint32_t i; if (UpdateSDKDirectoryInfosIfNeeded()) { const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - - // Check to see if the user specified a build string. If they did, then be - // sure to match it. std::vector check_sdk_info(num_sdk_infos, true); - ConstString build(m_sdk_build); + + // Prefer the user SDK build string. + ConstString build = GetSDKBuild(); + + // Fall back to the platform's build string. + if (!build) { + if (llvm::Optional os_build_str = GetOSBuildString()) { + build = ConstString(*os_build_str); + } + } + + // If we have a build string, only check platforms for which the build + // string matches. if (build) { for (i = 0; i < num_sdk_infos; ++i) check_sdk_info[i] = m_sdk_directory_infos[i].build == build; @@ -163,14 +172,14 @@ llvm::VersionTuple version = GetOSVersion(); if (!version.empty()) { if (UpdateSDKDirectoryInfosIfNeeded()) { - // First try for an exact match of major, minor and update + // First try for an exact match of major, minor and update. for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { if (m_sdk_directory_infos[i].version == version) return &m_sdk_directory_infos[i]; } } - // First try for an exact match of major and minor + // Try for an exact match of major and minor. for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { if (m_sdk_directory_infos[i].version.getMajor() == @@ -181,7 +190,7 @@ } } } - // Lastly try to match of major version only.. + // Lastly try to match of major version only. for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { if (m_sdk_directory_infos[i].version.getMajor() == @@ -192,7 +201,7 @@ } } } else if (build) { - // No version, just a build number, search for the first one that matches + // No version, just a build number, return the first one that matches. for (i = 0; i < num_sdk_infos; ++i) if (check_sdk_info[i]) return &m_sdk_directory_infos[i]; diff --git a/lldb/test/API/macosx/rosetta/Makefile b/lldb/test/API/macosx/rosetta/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/macosx/rosetta/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +override ARCH = x86_64 + +include Makefile.rules diff --git a/lldb/test/API/macosx/rosetta/TestRosetta.py b/lldb/test/API/macosx/rosetta/TestRosetta.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/macosx/rosetta/TestRosetta.py @@ -0,0 +1,55 @@ +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + + +def get_os_version(): + try: + os_version_str = subprocess.check_output(["sysctl", "kern.osversion" + ]).decode('utf-8') + except subprocess.CalledProcessError: + return None + m = re.match(r'kern\.osversion: (\w+)', os_version_str) + if m: + return m.group(1) + return None + + +def has_rosetta_shared_cache(os_version): + if not os_version: + return False + macos_device_support = os.path.join(os.path.expanduser("~"), 'Library', + 'Developer', 'Xcode', + 'macOS DeviceSupport') + for _, subdirs, _ in os.walk(macos_device_support): + for subdir in subdirs: + if os_version in subdir: + return True + return False + + +class TestRosetta(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessAppleSilicon + def test_rosetta(self): + """There can be many tests in a test case - describe this test here.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + + broadcaster = self.dbg.GetBroadcaster() + listener = lldbutil.start_listening_from( + broadcaster, lldb.SBDebugger.eBroadcastBitWarning) + + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", self.main_source_file) + + event = lldb.SBEvent() + os_version = get_os_version() + if not has_rosetta_shared_cache(os_version): + self.assertTrue(listener.GetNextEvent(event)) + else: + self.assertFalse(listener.GetNextEvent(event)) diff --git a/lldb/test/API/macosx/rosetta/main.c b/lldb/test/API/macosx/rosetta/main.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/macosx/rosetta/main.c @@ -0,0 +1,6 @@ +#include + +int main() { + int i = 0; // Set a breakpoint here + return i; +}