diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index 98f0025303ac..7025c3804aa6 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -862,18 +862,30 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) { return FindSDKInXcodeForModules(sdk_type, sdks_spec); } +// Discovering the correct version and build can help us +// identify the most likely SDK directory when looking for +// files. +// +// The directory name can be one of many formats, such as +// 10.0 (21R329) universal +// 17.0 (23A200) arm64e +// 17.0 (20A352) +// Watch4,2 10.0 (21R329) std::tuple PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { llvm::StringRef build; - llvm::StringRef version_str; - llvm::StringRef build_str; - std::tie(version_str, build_str) = dir.split(' '); llvm::VersionTuple version; - if (!version.tryParse(version_str) || - build_str.empty()) { - if (build_str.consume_front("(")) { - size_t pos = build_str.find(')'); - build = build_str.slice(0, pos); + + llvm::SmallVector parts; + dir.split(parts, ' '); + for (llvm::StringRef part : parts) { + // Look for an OS version number, eg "17.0" + if (isdigit(part[0])) + version.tryParse(part); + // Look for a build number, eg "(20A352)" + if (part.consume_front("(")) { + size_t pos = part.find(')'); + build = part.slice(0, pos); } } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp index 393f3a3b7983..a9a60d8070f0 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp @@ -23,62 +23,82 @@ using namespace lldb_private; PlatformDarwinDevice::~PlatformDarwinDevice() = default; FileSystem::EnumerateDirectoryResult -PlatformDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback( +PlatformDarwinDevice::GetContainedFilesIntoVectorOfFileSpecsCallback( void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { - ((PlatformDarwinDevice::SDKDirectoryInfoCollection *)baton) - ->push_back(PlatformDarwinDevice::SDKDirectoryInfo(FileSpec(path))); + ((std::vector *)baton)->push_back(FileSpec(path)); return FileSystem::eEnumerateDirectoryResultNext; } +void PlatformDarwinDevice::AddSharedCacheDirectory( + llvm::StringRef dir, llvm::StringRef log_msg_descriptor) { + Log *log = GetLog(LLDBLog::Host); + const bool find_directories = true; + const bool find_files = false; + const bool find_other = false; + std::vector shared_cache_expanded_directories; + FileSystem::Instance().EnumerateDirectory( + dir, find_directories, find_files, find_other, + GetContainedFilesIntoVectorOfFileSpecsCallback, + &shared_cache_expanded_directories); + + /// shared_cache_expanded_directories will have the directories under \a dir. + /// Those that have a /Symbols/ subdir are shared cache dirs. + /// Those that have //Symbols/ subdirs are shared cache dirs. + + for (const FileSpec &sc_directory : shared_cache_expanded_directories) { + FileSpec sc_directory_symbols = sc_directory; + sc_directory_symbols.AppendPathComponent("Symbols"); + if (FileSystem::Instance().Exists(sc_directory_symbols)) { + SDKDirectoryInfo thisdir(sc_directory, + sc_directory.GetFilename().GetStringRef()); + m_sdk_directory_infos.push_back(thisdir); + LLDB_LOGF(log, + "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " + "added %s %s", + log_msg_descriptor.str().c_str(), + sc_directory.GetPath().c_str()); + } + + // See if we have arch subdirs under sc_directory, and if there is + // a Symbols subdir under those. + std::vector subdirs; + FileSystem::Instance().EnumerateDirectory( + sc_directory.GetPath().c_str(), find_directories, find_files, + find_other, GetContainedFilesIntoVectorOfFileSpecsCallback, &subdirs); + for (const FileSpec &subdir : subdirs) { + FileSpec subdir_directory_symbols = subdir; + subdir_directory_symbols.AppendPathComponent("Symbols"); + if (FileSystem::Instance().Exists(subdir_directory_symbols)) { + SDKDirectoryInfo thisdir(subdir, + sc_directory.GetFilename().GetStringRef()); + m_sdk_directory_infos.push_back(thisdir); + LLDB_LOGF(log, + "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " + "added %s %s", + log_msg_descriptor.str().c_str(), subdir.GetPath().c_str()); + } + } + } +} + bool PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() { Log *log = GetLog(LLDBLog::Host); std::lock_guard guard(m_sdk_dir_mutex); if (m_sdk_directory_infos.empty()) { + // A --sysroot option was supplied - add it to our list of SDKs to check - if (!m_sdk_sysroot.empty()) { - FileSpec sdk_sysroot_fspec(m_sdk_sysroot.c_str()); - FileSystem::Instance().Resolve(sdk_sysroot_fspec); - const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec); - m_sdk_directory_infos.push_back(sdk_sysroot_directory_info); - LLDB_LOGF(log, - "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added " - "--sysroot SDK directory %s", - m_sdk_sysroot.c_str()); - return true; - } + if (!m_sdk_sysroot.empty()) + AddSharedCacheDirectory(m_sdk_sysroot.c_str(), "--sysroot SDK directory"); + const char *device_support_dir = GetDeviceSupportDirectory(); LLDB_LOGF(log, "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got " "DeviceSupport directory %s", device_support_dir); if (device_support_dir) { - const bool find_directories = true; - const bool find_files = false; - const bool find_other = false; + AddSharedCacheDirectory(device_support_dir, "builtin SDK directory"); - SDKDirectoryInfoCollection builtin_sdk_directory_infos; - FileSystem::Instance().EnumerateDirectory( - m_device_support_directory, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &builtin_sdk_directory_infos); - - // Only add SDK directories that have symbols in them, some SDKs only - // contain developer disk images and no symbols, so they aren't useful to - // us. - FileSpec sdk_symbols_symlink_fspec; - for (const auto &sdk_directory_info : builtin_sdk_directory_infos) { - sdk_symbols_symlink_fspec = sdk_directory_info.directory; - sdk_symbols_symlink_fspec.AppendPathComponent("Symbols"); - if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) { - m_sdk_directory_infos.push_back(sdk_directory_info); - LLDB_LOGF(log, - "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "added builtin SDK directory %s", - sdk_symbols_symlink_fspec.GetPath().c_str()); - } - } - - const uint32_t num_installed = m_sdk_directory_infos.size(); + // "macOS DeviceSupport", "iOS DeviceSupport", etc. llvm::StringRef dirname = GetDeviceSupportDirectoryName(); std::string local_sdk_cache_str = "~/Library/Developer/Xcode/"; local_sdk_cache_str += std::string(dirname); @@ -89,45 +109,14 @@ bool PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() { "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " "searching %s for additional SDKs", local_sdk_cache.GetPath().c_str()); - char path[PATH_MAX]; - if (local_sdk_cache.GetPath(path, sizeof(path))) { - FileSystem::Instance().EnumerateDirectory( - path, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &m_sdk_directory_infos); - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - // First try for an exact match of major, minor and update - for (uint32_t i = num_installed; i < num_sdk_infos; ++i) { - m_sdk_directory_infos[i].user_cached = true; - LLDB_LOGF(log, - "PlatformDarwinDevice::" - "UpdateSDKDirectoryInfosIfNeeded " - "user SDK directory %s", - m_sdk_directory_infos[i].directory.GetPath().c_str()); - } - } + AddSharedCacheDirectory(local_sdk_cache.GetPath().c_str(), + "system developer dir directory"); } const char *addtional_platform_dirs = getenv("PLATFORM_SDK_DIRECTORY"); - if (addtional_platform_dirs) { - SDKDirectoryInfoCollection env_var_sdk_directory_infos; - FileSystem::Instance().EnumerateDirectory( - addtional_platform_dirs, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &env_var_sdk_directory_infos); - FileSpec sdk_symbols_symlink_fspec; - for (const auto &sdk_directory_info : env_var_sdk_directory_infos) { - sdk_symbols_symlink_fspec = sdk_directory_info.directory; - sdk_symbols_symlink_fspec.AppendPathComponent("Symbols"); - if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) { - m_sdk_directory_infos.push_back(sdk_directory_info); - LLDB_LOGF(log, - "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "added env var SDK directory %s", - sdk_symbols_symlink_fspec.GetPath().c_str()); - } - } - } + if (addtional_platform_dirs) + AddSharedCacheDirectory(addtional_platform_dirs, + "env var SDK directory"); } } return !m_sdk_directory_infos.empty(); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h index d8ea1807edf1..115cda9fe51d 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h @@ -30,24 +30,35 @@ protected: lldb_private::Process *process); struct SDKDirectoryInfo { - SDKDirectoryInfo(const FileSpec &sdk_dir_spec); + SDKDirectoryInfo(const FileSpec &sdk_dir_spec, llvm::StringRef dirname_str); FileSpec directory; ConstString build; llvm::VersionTuple version; - bool user_cached; }; typedef std::vector SDKDirectoryInfoCollection; + /// Look for expanded shared cache directories under the given dir. + /// Expanded shared cache directories found under the given dir will + /// be added to \a m_sdk_directory_infos. + /// + /// \param[in] dir + /// Directory to search under. + /// + /// \param[in] log_msg_descriptor + /// Text to describe the origin of this directory, in logging. + void AddSharedCacheDirectory(llvm::StringRef dir, + llvm::StringRef log_msg_descriptor); + bool UpdateSDKDirectoryInfosIfNeeded(); const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion(); const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion(); static FileSystem::EnumerateDirectoryResult - GetContainedFilesIntoVectorOfStringsCallback(void *baton, - llvm::sys::fs::file_type ft, - llvm::StringRef path); + GetContainedFilesIntoVectorOfFileSpecsCallback(void *baton, + llvm::sys::fs::file_type ft, + llvm::StringRef path); const char *GetDeviceSupportDirectory(); const char *GetDeviceSupportDirectoryForOSVersion(); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index c519561b9e08..ba7f97383f15 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -28,10 +28,12 @@ using namespace lldb; using namespace lldb_private; +/// sdk_dir FileSpec may be .../17.0 (15A100) +/// or it may be .../17.0 (15A100)/arm64e +/// In both of these cases, dirname_str should be "17.0 (15A100)" PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( - const lldb_private::FileSpec &sdk_dir) - : directory(sdk_dir), build(), user_cached(false) { - llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); + const lldb_private::FileSpec &sdk_dir, llvm::StringRef dirname_str) + : directory(sdk_dir), build() { llvm::StringRef build_str; std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); build.SetString(build_str); diff --git a/lldb/unittests/Platform/PlatformMacOSXTest.cpp b/lldb/unittests/Platform/PlatformMacOSXTest.cpp index 123fdbc39d67..ab6972ee264c 100644 --- a/lldb/unittests/Platform/PlatformMacOSXTest.cpp +++ b/lldb/unittests/Platform/PlatformMacOSXTest.cpp @@ -51,4 +51,33 @@ TEST_F(PlatformMacOSXTest, TestGetSupportedArchitectures) { arm64_ios_arch)); #endif } + +struct NameAndResult { + std::string dir; + llvm::VersionTuple version; + std::string build; +}; + +TEST_F(PlatformMacOSXTest, TestDeviceSupportDirectoryNames) { + PlatformMacOSX platform; + + NameAndResult tests[] = { + {"10.0 (21R329) universal", llvm::VersionTuple(10, 0), "21R329"}, + {"17.0 (23X1010104078) universal", llvm::VersionTuple(17, 0), + "23X1010104078"}, + {"17.0 (23A200) arm64e", llvm::VersionTuple(17, 0), "23A200"}, + {"17.0 (20A352)", llvm::VersionTuple(17, 0), "20A352"}, + {"Watch4,2 10.0 (21R329)", llvm::VersionTuple(10, 0), "21R329"}, + {"iPhone11,2 26.0 (23A276)", llvm::VersionTuple(26, 0), "23A276"}, + {"iPhone13,2 17.0 (18C22)", llvm::VersionTuple(17, 0), "18C22"}, + }; + for (size_t i = 0; i < std::size(tests); i++) { + llvm::VersionTuple version; + llvm::StringRef build_str; + std::tie(version, build_str) = platform.ParseVersionBuildDir(tests[i].dir); + EXPECT_EQ(tests[i].version, version); + EXPECT_EQ(tests[i].build, build_str); + } +} + #endif