Index: lldb/include/lldb/Core/Module.h =================================================================== --- lldb/include/lldb/Core/Module.h +++ lldb/include/lldb/Core/Module.h @@ -20,6 +20,7 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" +#include "lldb/Utility/XcodeSDK.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" @@ -509,6 +510,12 @@ m_mod_time = mod_time; } + /// This callback will be called by SymbolFile implementations when + /// parsing a compile unit that contains SDK information. + /// \param sdk will be merged with \p m_sdk. + /// \param sysroot will be added to the path remapping dictionary. + void RegisterSDK(llvm::StringRef sdk, llvm::StringRef sysroot); + /// Tells whether this module is capable of being the main executable for a /// process. /// @@ -971,6 +978,10 @@ /// module that doesn't match where the sources currently are. PathMappingList m_source_mappings = ModuleList::GetGlobalModuleListProperties().GetSymlinkMappings(); + + /// The SDK this module was compiled with. + XcodeSDK m_sdk; + lldb::SectionListUP m_sections_up; ///< Unified section list for module that /// is used by the ObjectFile and and /// ObjectFile instances for the debug info Index: lldb/include/lldb/Target/Platform.h =================================================================== --- lldb/include/lldb/Target/Platform.h +++ lldb/include/lldb/Target/Platform.h @@ -434,6 +434,8 @@ return lldb_private::ConstString(); } + virtual ConstString GetSDKPath(int type) { return {}; } + const std::string &GetRemoteURL() const { return m_remote_url; } bool IsHost() const { Index: lldb/include/lldb/Utility/XcodeSDK.h =================================================================== --- /dev/null +++ lldb/include/lldb/Utility/XcodeSDK.h @@ -0,0 +1,61 @@ +//===-- XcodeSDK.h ----------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_SDK_H +#define LLDB_UTILITY_SDK_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" +#include + +namespace lldb_private { + +/// An abstraction for Xcode-style SDKs that works like \ref ArchSpec. +class XcodeSDK { + std::string m_name; + +public: + XcodeSDK() = default; + XcodeSDK(std::string &&name) : m_name(name) {} + + enum Type : int { + MacOSX = 0, + iPhoneSimulator, + iPhoneOS, + AppleTVSimulator, + AppleTVOS, + WatchSimulator, + watchOS, + bridgeOS, + Linux, + numSDKTypes, + unknown = -1 + }; + static llvm::StringRef GetNameForType(Type type); + + /// The merge function follows a strict order to maintain monotonicity: + /// 1. SDK with the higher SDKType wins. + /// 2. The newer SDK wins. + void Merge(XcodeSDK other); + + XcodeSDK &operator=(XcodeSDK other); + bool operator==(XcodeSDK other); + + /// Return parsed SDK number, and SDK version number. + std::tuple Parse() const; + llvm::VersionTuple GetVersion() const; + Type GetSDKType() const; + + static bool SDKSupportsModules(Type type, llvm::VersionTuple version); + static bool SDKSupportsModules(Type desired_type, const FileSpec &sdk_path); + static llvm::StringRef GetSDKNameForType(Type type); +}; + +} // namespace lldb_private + +#endif Index: lldb/source/Core/Module.cpp =================================================================== --- lldb/source/Core/Module.cpp +++ lldb/source/Core/Module.cpp @@ -1596,6 +1596,24 @@ return m_source_mappings.RemapPath(path, new_path); } +void Module::RegisterSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) { + XcodeSDK sdk(sdk_name.str()); + if (m_sdk == sdk) + return; + m_sdk.Merge(sdk); + PlatformSP module_platform = + Platform::GetPlatformForArchitecture(GetArchitecture(), nullptr); + ConstString sdk_path = module_platform->GetSDKPath(sdk.GetSDKType()); + if (!sdk_path) + return; + // If merged SDK changed for a previously registered source path, update it. + // This could happend with -fdebug-prefix-map, otherwise it's unlikely. + ConstString sysroot_cs(sysroot); + if (!m_source_mappings.Replace(sysroot_cs, sdk_path, true)) + // In the general case, however, append it to the list. + m_source_mappings.Append(sysroot_cs, sdk_path, false); +} + bool Module::MergeArchitecture(const ArchSpec &arch_spec) { if (!arch_spec.IsValid()) return false; Index: lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h @@ -69,7 +69,7 @@ AddClangModuleCompilationOptions(lldb_private::Target *target, std::vector &options) override { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); + target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator); } protected: Index: lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h @@ -69,7 +69,7 @@ AddClangModuleCompilationOptions(lldb_private::Target *target, std::vector &options) override { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); + target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator); } protected: Index: lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -11,8 +11,10 @@ #include "Plugins/Platform/POSIX/PlatformPOSIX.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/XcodeSDK.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" @@ -84,25 +86,12 @@ static std::tuple ParseVersionBuildDir(llvm::StringRef str); - enum SDKType : int { - MacOSX = 0, - iPhoneSimulator, - iPhoneOS, - AppleTVSimulator, - AppleTVOS, - WatchSimulator, - watchOS, - bridgeOS, - Linux, - numSDKTypes, - unknown = -1 - }; - llvm::Expected FetchExtendedCrashInformation(lldb_private::Process &process) override; - static llvm::StringRef GetSDKNameForType(SDKType type); - static lldb_private::FileSpec GetXcodeSDK(SDKType type); + lldb_private::ConstString GetSDKPath(int type) override; + + static lldb_private::FileSpec GetXcodeSDK(lldb_private::XcodeSDK::Type type); static lldb_private::FileSpec GetXcodeContentsDirectory(); static lldb_private::FileSpec GetXcodeDeveloperDirectory(); @@ -151,14 +140,9 @@ const lldb_private::FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); - static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version); - - static bool SDKSupportsModules(SDKType desired_type, - const lldb_private::FileSpec &sdk_path); - struct SDKEnumeratorInfo { lldb_private::FileSpec found_path; - SDKType sdk_type; + lldb_private::XcodeSDK::Type sdk_type; }; static lldb_private::FileSystem::EnumerateDirectoryResult @@ -166,17 +150,15 @@ llvm::StringRef path); static lldb_private::FileSpec - FindSDKInXcodeForModules(SDKType sdk_type, + FindSDKInXcodeForModules(lldb_private::XcodeSDK::Type sdk_type, const lldb_private::FileSpec &sdks_spec); static lldb_private::FileSpec - GetSDKDirectoryForModules(PlatformDarwin::SDKType sdk_type); - - void - AddClangModuleCompilationOptionsForSDKType(lldb_private::Target *target, - std::vector &options, - SDKType sdk_type); + GetSDKDirectoryForModules(lldb_private::XcodeSDK::Type sdk_type); + void AddClangModuleCompilationOptionsForSDKType( + lldb_private::Target *target, std::vector &options, + lldb_private::XcodeSDK::Type sdk_type); lldb_private::Status FindBundleBinaryInExecSearchPaths( const lldb_private::ModuleSpec &module_spec, @@ -188,6 +170,10 @@ llvm::StringRef component); static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path); + std::string m_developer_directory; + std::array + m_sdk_path; private: DISALLOW_COPY_AND_ASSIGN(PlatformDarwin); Index: lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1220,56 +1220,12 @@ return g_command_line_tools_filespec; } -bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, - llvm::VersionTuple version) { - switch (sdk_type) { - case SDKType::MacOSX: - return version >= llvm::VersionTuple(10, 10); - case SDKType::iPhoneOS: - case SDKType::iPhoneSimulator: - case SDKType::AppleTVOS: - case SDKType::AppleTVSimulator: - return version >= llvm::VersionTuple(8); - case SDKType::watchOS: - case SDKType::WatchSimulator: - return version >= llvm::VersionTuple(6); - default: - return false; - } - - return false; -} - -bool PlatformDarwin::SDKSupportsModules(SDKType desired_type, - const FileSpec &sdk_path) { - ConstString last_path_component = sdk_path.GetLastPathComponent(); - - if (last_path_component) { - const llvm::StringRef sdk_name = last_path_component.GetStringRef(); - - const std::string sdk_name_lower = sdk_name.lower(); - const llvm::StringRef sdk_string = GetSDKNameForType(desired_type); - if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) - return false; - - auto version_part = sdk_name.drop_front(sdk_string.size()); - version_part.consume_back(".sdk"); - - llvm::VersionTuple version; - if (version.tryParse(version_part)) - return false; - return SDKSupportsModules(desired_type, version); - } - - return false; -} - FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator( void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) { SDKEnumeratorInfo *enumerator_info = static_cast(baton); FileSpec spec(path); - if (SDKSupportsModules(enumerator_info->sdk_type, spec)) { + if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) { enumerator_info->found_path = spec; return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; } @@ -1277,7 +1233,7 @@ return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; } -FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type, +FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type, const FileSpec &sdks_spec) { // Look inside Xcode for the required installed iOS SDK version @@ -1303,19 +1259,19 @@ return FileSpec(); } -FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) { +FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) { FileSpec sdks_spec = GetXcodeContentsDirectory(); sdks_spec.AppendPathComponent("Developer"); sdks_spec.AppendPathComponent("Platforms"); switch (sdk_type) { - case SDKType::MacOSX: + case XcodeSDK::Type::MacOSX: sdks_spec.AppendPathComponent("MacOSX.platform"); break; - case SDKType::iPhoneSimulator: + case XcodeSDK::Type::iPhoneSimulator: sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); break; - case SDKType::iPhoneOS: + case XcodeSDK::Type::iPhoneOS: sdks_spec.AppendPathComponent("iPhoneOS.platform"); break; default: @@ -1325,11 +1281,11 @@ sdks_spec.AppendPathComponent("Developer"); sdks_spec.AppendPathComponent("SDKs"); - if (sdk_type == SDKType::MacOSX) { + if (sdk_type == XcodeSDK::Type::MacOSX) { llvm::VersionTuple version = HostInfo::GetOSVersion(); if (!version.empty()) { - if (SDKSupportsModules(SDKType::MacOSX, version)) { + if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) { // If the Xcode SDKs are not available then try to use the // Command Line Tools one which is only for MacOSX. if (!FileSystem::Instance().Exists(sdks_spec)) { @@ -1498,7 +1454,7 @@ } void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - Target *target, std::vector &options, SDKType sdk_type) { + Target *target, std::vector &options, XcodeSDK::Type sdk_type) { const std::vector apple_arguments = { "-x", "objective-c++", "-fobjc-arc", "-fblocks", "-D_ISO646_H", "-D__ISO646_H", @@ -1509,7 +1465,7 @@ StreamString minimum_version_option; bool use_current_os_version = false; switch (sdk_type) { - case SDKType::iPhoneOS: + case XcodeSDK::Type::iPhoneOS: #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) use_current_os_version = true; #else @@ -1517,11 +1473,11 @@ #endif break; - case SDKType::iPhoneSimulator: + case XcodeSDK::Type::iPhoneSimulator: use_current_os_version = false; break; - case SDKType::MacOSX: + case XcodeSDK::Type::MacOSX: #if defined(__i386__) || defined(__x86_64__) use_current_os_version = true; #else @@ -1548,15 +1504,15 @@ // Only add the version-min options if we got a version from somewhere if (!version.empty()) { switch (sdk_type) { - case SDKType::iPhoneOS: + case XcodeSDK::Type::iPhoneOS: minimum_version_option.PutCString("-mios-version-min="); minimum_version_option.PutCString(version.getAsString()); break; - case SDKType::iPhoneSimulator: + case XcodeSDK::Type::iPhoneSimulator: minimum_version_option.PutCString("-mios-simulator-version-min="); minimum_version_option.PutCString(version.getAsString()); break; - case SDKType::MacOSX: + case XcodeSDK::Type::MacOSX: minimum_version_option.PutCString("-mmacosx-version-min="); minimum_version_option.PutCString(version.getAsString()); break; @@ -1805,36 +1761,17 @@ return {}; } -llvm::StringRef PlatformDarwin::GetSDKNameForType(SDKType type) { - switch (type) { - case MacOSX: - return "macosx"; - case iPhoneSimulator: - return "iphonesimulator"; - case iPhoneOS: - return "iphoneos"; - case AppleTVSimulator: - return "appletvsimulator"; - case AppleTVOS: - return "appletvos"; - case WatchSimulator: - return "watchsimulator"; - case watchOS: - return "watchos"; - case bridgeOS: - return "bridgeos"; - case Linux: - return "linux"; - case numSDKTypes: - case unknown: - return ""; - } - llvm_unreachable("unhandled switch case"); +ConstString PlatformDarwin::GetSDKPath(int type) { + if (type >= XcodeSDK::Type::numSDKTypes || type <= XcodeSDK::Type::unknown) + return {}; + if (!m_sdk_path[type]) + m_sdk_path[type] = GetXcodeSDK((XcodeSDK::Type)type).GetDirectory(); + return m_sdk_path[type]; } -FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) { +FileSpec PlatformDarwin::GetXcodeSDK(XcodeSDK::Type type) { std::string xcrun_cmd = - "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str(); + "xcrun --show-sdk-path --sdk " + XcodeSDK::GetSDKNameForType(type).str(); int status = 0; int signo = 0; @@ -1899,7 +1836,7 @@ } } - if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) { + if (FileSpec fspec = GetXcodeSDK(XcodeSDK::Type::MacOSX)) { if (FileSystem::Instance().Exists(fspec)) { std::string xcode_contents_dir = FindXcodeContentsDirectoryInPath(fspec.GetPath()); Index: lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h @@ -73,7 +73,7 @@ AddClangModuleCompilationOptions(lldb_private::Target *target, std::vector &options) override { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::MacOSX); + target, options, lldb_private::XcodeSDK::Type::MacOSX); } private: Index: lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -208,7 +208,7 @@ } // Use the default SDK as a fallback. - if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) { + if (FileSpec fspec = GetXcodeSDK(lldb_private::XcodeSDK::Type::MacOSX)) { if (FileSystem::Instance().Exists(fspec)) return ConstString(fspec.GetPath()); } Index: lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h @@ -45,7 +45,7 @@ AddClangModuleCompilationOptions(lldb_private::Target *target, std::vector &options) override { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneOS); + target, options, lldb_private::XcodeSDK::Type::iPhoneOS); } protected: Index: lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h @@ -71,7 +71,7 @@ AddClangModuleCompilationOptions(lldb_private::Target *target, std::vector &options) override { return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); + target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator); } protected: Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -12,6 +12,7 @@ #include "DWARFDIE.h" #include "DWARFDebugInfoEntry.h" #include "lldb/lldb-enumerations.h" +#include "lldb/Utility/XcodeSDK.h" #include "llvm/Support/RWMutex.h" #include Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -664,6 +664,11 @@ const DWARFBaseDIE cu_die = dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly(); if (cu_die) { + const char *sdk = + cu_die.GetAttributeValueAsString(DW_AT_APPLE_sdk, ""); + const char *sysroot = + cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, ""); + module_sp->RegisterSDK(sdk, sysroot); FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle()); MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp); Index: lldb/source/Utility/CMakeLists.txt =================================================================== --- lldb/source/Utility/CMakeLists.txt +++ lldb/source/Utility/CMakeLists.txt @@ -57,6 +57,7 @@ UserIDResolver.cpp VASprintf.cpp VMRange.cpp + XcodeSDK.cpp LINK_LIBS ${LLDB_SYSTEM_LIBS} Index: lldb/source/Utility/XcodeSDK.cpp =================================================================== --- /dev/null +++ lldb/source/Utility/XcodeSDK.cpp @@ -0,0 +1,161 @@ +//===-- XcodeSDK.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 "lldb/Utility/FileSpec.h" +#include "lldb/Utility/XcodeSDK.h" + +#include "lldb/lldb-types.h" + +using namespace lldb; +using namespace lldb_private; + +XcodeSDK &XcodeSDK::operator=(XcodeSDK other) { + m_name = other.m_name; + return *this; +} + +bool XcodeSDK::operator==(XcodeSDK other) { + return m_name == other.m_name; +} + +static XcodeSDK::Type ParseSDKName(llvm::StringRef &name) { + if (name.consume_front("MacOSX")) + return XcodeSDK::MacOSX; + if (name.consume_front("iPhoneSimulator")) + return XcodeSDK::iPhoneSimulator; + if (name.consume_front("iPhoneOS")) + return XcodeSDK::iPhoneOS; + if (name.consume_front("AppleTVSimulator")) + return XcodeSDK::AppleTVSimulator; + if (name.consume_front("AppleTVOS")) + return XcodeSDK::AppleTVOS; + if (name.consume_front("WatchSimulator")) + return XcodeSDK::WatchSimulator; + if (name.consume_front("WatchOS")) + return XcodeSDK::watchOS; + if (name.consume_front("bridgeOS")) + return XcodeSDK::bridgeOS; + if (name.consume_front("Linux")) + return XcodeSDK::Linux; + static_assert(XcodeSDK::Linux == XcodeSDK::numSDKTypes - 1, + "New SDK type was added, update this list!"); + return XcodeSDK::unknown; +} + +static llvm::VersionTuple ParseSDKVersion(llvm::StringRef &name) { + unsigned i = 0; + while (i < name.size() && name[i] >= '0' && name[i] <= '9') + ++i; + if (name[i++] != '.') + return {}; + while (i < name.size() && name[i] >= '0' && name[i] <= '9') + ++i; + if (name[i++] != '.') + return {}; + + llvm::VersionTuple version; + version.tryParse(name.slice(0, i - 1)); + name = name.drop_front(i); + return version; +} + + +std::tuple XcodeSDK::Parse() const { + llvm::StringRef input(m_name); + XcodeSDK::Type sdk = ParseSDKName(input); + llvm::VersionTuple version = ParseSDKVersion(input); + return {sdk, version}; +} + +llvm::VersionTuple XcodeSDK::GetVersion() const { + llvm::StringRef input(m_name); + ParseSDKName(input); + return ParseSDKVersion(input); +} + +XcodeSDK::Type XcodeSDK::GetSDKType() const { + llvm::StringRef input(m_name); + return ParseSDKName(input); +} + +void XcodeSDK::Merge(XcodeSDK other) { + // The "bigger" SDK always wins. + if (Parse() < other.Parse()) + *this = other; +} + +llvm::StringRef XcodeSDK::GetSDKNameForType(XcodeSDK::Type type) { + switch (type) { + case MacOSX: + return "macosx"; + case iPhoneSimulator: + return "iphonesimulator"; + case iPhoneOS: + return "iphoneos"; + case AppleTVSimulator: + return "appletvsimulator"; + case AppleTVOS: + return "appletvos"; + case WatchSimulator: + return "watchsimulator"; + case watchOS: + return "watchos"; + case bridgeOS: + return "bridgeos"; + case Linux: + return "linux"; + case numSDKTypes: + case unknown: + return ""; + } + llvm_unreachable("unhandled switch case"); +} + +bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type sdk_type, + llvm::VersionTuple version) { + switch (sdk_type) { + case Type::MacOSX: + return version >= llvm::VersionTuple(10, 10); + case Type::iPhoneOS: + case Type::iPhoneSimulator: + case Type::AppleTVOS: + case Type::AppleTVSimulator: + return version >= llvm::VersionTuple(8); + case Type::watchOS: + case Type::WatchSimulator: + return version >= llvm::VersionTuple(6); + default: + return false; + } + + return false; +} + +bool XcodeSDK::SDKSupportsModules(XcodeSDK::Type desired_type, + const FileSpec &sdk_path) { + ConstString last_path_component = sdk_path.GetLastPathComponent(); + + if (last_path_component) { + const llvm::StringRef sdk_name = last_path_component.GetStringRef(); + + const std::string sdk_name_lower = sdk_name.lower(); + const llvm::StringRef sdk_string = GetSDKNameForType(desired_type); + if (!llvm::StringRef(sdk_name_lower).startswith(sdk_string)) + return false; + + auto version_part = sdk_name.drop_front(sdk_string.size()); + version_part.consume_back(".sdk"); + + llvm::VersionTuple version; + if (version.tryParse(version_part)) + return false; + return SDKSupportsModules(desired_type, version); + } + + return false; +} Index: lldb/unittests/Platform/PlatformDarwinTest.cpp =================================================================== --- lldb/unittests/Platform/PlatformDarwinTest.cpp +++ lldb/unittests/Platform/PlatformDarwinTest.cpp @@ -21,10 +21,6 @@ public: using PlatformDarwin::FindComponentInPath; using PlatformDarwin::FindXcodeContentsDirectoryInPath; - static bool SDKSupportsModules(SDKType desired_type, - const lldb_private::FileSpec &sdk_path) { - return PlatformDarwin::SDKSupportsModules(desired_type, sdk_path); - } }; TEST(PlatformDarwinTest, TestParseVersionBuildDir) { @@ -53,24 +49,6 @@ std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("3.4.5"); EXPECT_EQ(llvm::VersionTuple(3, 4, 5), V); - - std::string base = "/Applications/Xcode.app/Contents/Developer/Platforms/"; - EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules( - PlatformDarwin::SDKType::iPhoneSimulator, - FileSpec( - base + - "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk"))); - EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules( - PlatformDarwin::SDKType::iPhoneSimulator, - FileSpec( - base + - "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.2.sdk"))); - EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules( - PlatformDarwin::SDKType::MacOSX, - FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk"))); - EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules( - PlatformDarwin::SDKType::MacOSX, - FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk"))); } TEST(PlatformDarwinTest, FindXcodeContentsDirectoryInPath) { @@ -111,29 +89,6 @@ no_capitalization)); } -TEST(PlatformDarwinTest, GetSDKNameForType) { - EXPECT_EQ("macosx", - PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::MacOSX)); - EXPECT_EQ("iphonesimulator", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::iPhoneSimulator)); - EXPECT_EQ("iphoneos", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::iPhoneOS)); - EXPECT_EQ("appletvsimulator", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::AppleTVSimulator)); - EXPECT_EQ("appletvos", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::AppleTVOS)); - EXPECT_EQ("watchsimulator", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::WatchSimulator)); - EXPECT_EQ("watchos", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::watchOS)); - EXPECT_EQ("linux", - PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::Linux)); - EXPECT_EQ("", PlatformDarwin::GetSDKNameForType( - PlatformDarwin::SDKType::numSDKTypes)); - EXPECT_EQ( - "", PlatformDarwin::GetSDKNameForType(PlatformDarwin::SDKType::unknown)); -} - TEST(PlatformDarwinTest, FindComponentInPath) { EXPECT_EQ("/path/to/foo", PlatformDarwinTester::FindComponentInPath("/path/to/foo/", "foo")); Index: lldb/unittests/Utility/CMakeLists.txt =================================================================== --- lldb/unittests/Utility/CMakeLists.txt +++ lldb/unittests/Utility/CMakeLists.txt @@ -42,6 +42,7 @@ UUIDTest.cpp VASprintfTest.cpp VMRangeTest.cpp + XcodeSDKTest.cpp LINK_LIBS lldbUtility Index: lldb/unittests/Utility/XcodeSDKTest.cpp =================================================================== --- /dev/null +++ lldb/unittests/Utility/XcodeSDKTest.cpp @@ -0,0 +1,83 @@ +//===-- XcodeSDKTest.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 "lldb/Utility/FileSpec.h" +#include "lldb/Utility/XcodeSDK.h" + +#include "llvm/ADT/StringRef.h" + +#include + +using namespace lldb_private; + +TEST(XcodeSDKTest, ParseTest) { + EXPECT_EQ(XcodeSDK("MacOSX.sdk").GetSDKType(), XcodeSDK::MacOSX); + EXPECT_EQ(XcodeSDK("iPhoneSimulator.sdk").GetSDKType(), XcodeSDK::iPhoneSimulator); + EXPECT_EQ(XcodeSDK("iPhoneOS.sdk").GetSDKType(), XcodeSDK::iPhoneOS); + EXPECT_EQ(XcodeSDK("AppleTVSimulator.sdk").GetSDKType(), XcodeSDK::AppleTVSimulator); + EXPECT_EQ(XcodeSDK("AppleTVOS.sdk").GetSDKType(), XcodeSDK::AppleTVOS); + EXPECT_EQ(XcodeSDK("WatchSimulator.sdk").GetSDKType(), XcodeSDK::WatchSimulator); + EXPECT_EQ(XcodeSDK("WatchOS.sdk").GetSDKType(), XcodeSDK::watchOS); + EXPECT_EQ(XcodeSDK("Linux.sdk").GetSDKType(), XcodeSDK::Linux); + EXPECT_EQ(XcodeSDK("MacOSX.sdk").GetVersion(), llvm::VersionTuple()); + EXPECT_EQ(XcodeSDK("MacOSX10.9.sdk").GetVersion(), llvm::VersionTuple(10, 9)); + EXPECT_EQ(XcodeSDK("MacOSX10.15.4.sdk").GetVersion(), llvm::VersionTuple(10, 15)); +} + +TEST(XcodeSDKTest, MergeTest) { + XcodeSDK sdk("MacOSX.sdk"); + sdk.Merge(XcodeSDK("WatchOS.sdk")); + // This doesn't make any particular sense and shouldn't happen in practice, we + // just want to guarantee a well-defined behavior when choosing one + // SDK to fit all CUs in an lldb::Module. + // -> The higher number wins. + EXPECT_EQ(sdk.GetSDKType(), XcodeSDK::watchOS); + sdk.Merge(XcodeSDK("WatchOS1.1.sdk")); + EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(1, 1)); + sdk.Merge(XcodeSDK("WatchOS2.0.sdk")); + EXPECT_EQ(sdk.GetVersion(), llvm::VersionTuple(2, 0)); +} + +TEST(XcodeSDKTest, SDKSupportsModules) { + std::string base = "/Applications/Xcode.app/Contents/Developer/Platforms/"; + EXPECT_TRUE(XcodeSDK::SDKSupportsModules( + XcodeSDK::Type::iPhoneSimulator, + FileSpec( + base + + "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk"))); + EXPECT_FALSE(XcodeSDK::SDKSupportsModules( + XcodeSDK::Type::iPhoneSimulator, + FileSpec( + base + + "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.2.sdk"))); + EXPECT_TRUE(XcodeSDK::SDKSupportsModules( + XcodeSDK::Type::MacOSX, + FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk"))); + EXPECT_FALSE(XcodeSDK::SDKSupportsModules( + XcodeSDK::Type::MacOSX, + FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk"))); +} + +TEST(XcodeSDKTest, GetSDKNameForType) { + EXPECT_EQ("macosx", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::MacOSX)); + EXPECT_EQ("iphonesimulator", + XcodeSDK::GetSDKNameForType(XcodeSDK::Type::iPhoneSimulator)); + EXPECT_EQ("iphoneos", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::iPhoneOS)); + EXPECT_EQ("appletvsimulator", + XcodeSDK::GetSDKNameForType(XcodeSDK::Type::AppleTVSimulator)); + EXPECT_EQ("appletvos", + XcodeSDK::GetSDKNameForType(XcodeSDK::Type::AppleTVOS)); + EXPECT_EQ("watchsimulator", + XcodeSDK::GetSDKNameForType(XcodeSDK::Type::WatchSimulator)); + EXPECT_EQ("watchos", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::watchOS)); + EXPECT_EQ("linux", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::Linux)); + EXPECT_EQ("", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::numSDKTypes)); + EXPECT_EQ("", XcodeSDK::GetSDKNameForType(XcodeSDK::Type::unknown)); +}