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/SDK.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(SDK sdk, ConstString 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. + SDK 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/SDK.h =================================================================== --- /dev/null +++ lldb/include/lldb/Utility/SDK.h @@ -0,0 +1,43 @@ +//===-- SDK.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 Apple SDKs that works like \p llvm::Triple. +class SDK { + ConstString m_name; + +public: + SDK() = default; + SDK(const char *name) : m_name(name, true) {} + SDK(ConstString name) : m_name(name) {} + + /// The merge function follows a strict order: + /// 1. SDK with the higher SDKType wins. + /// 2. The newer SDK wins. + void Merge(SDK other); + + SDK &operator=(SDK other); + bool operator==(SDK other); + + /// Return parsed SDK number, and SDK version number. + std::tuple Parse() const; + llvm::VersionTuple GetVersion() const; + int GetSDKType() const; +}; + +} // namespace lldb_private + +#endif Index: lldb/source/Core/Module.cpp =================================================================== --- lldb/source/Core/Module.cpp +++ lldb/source/Core/Module.cpp @@ -1596,6 +1596,21 @@ return m_source_mappings.RemapPath(path, new_path); } +void Module::RegisterSDK(SDK sdk, ConstString sysroot) { + if (m_sdk == sdk) + return; + m_sdk.Merge(sdk); + PlatformSP host_platform = Platform::GetHostPlatform(); + ConstString host_sdk_path = host_platform->GetSDKPath(sdk.GetSDKType()); + if (!host_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. + if (!m_source_mappings.Replace(sysroot, host_sdk_path, true)) + // In the general case, however, append it to the list. + m_source_mappings.Append(sysroot, host_sdk_path, false); +} + bool Module::MergeArchitecture(const ArchSpec &arch_spec) { if (!arch_spec.IsValid()) return false; Index: lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h =================================================================== --- lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -11,6 +11,7 @@ #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 "llvm/ADT/StringRef.h" @@ -96,6 +97,8 @@ llvm::Expected FetchExtendedCrashInformation(lldb_private::Process &process) override; + lldb_private::ConstString GetSDKPath(int type) override; + static llvm::StringRef GetSDKNameForType(SDKType type); static lldb_private::FileSpec GetXcodeSDK(SDKType type); static lldb_private::FileSpec GetXcodeContentsDirectory(); @@ -184,6 +187,7 @@ 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 @@ -1282,6 +1282,81 @@ return g_command_line_tools_filespec; } +SDK &SDK::operator=(SDK other) { + m_name = other.m_name; + return *this; +} + +bool SDK::operator==(SDK other) { + return m_name == other.m_name; +} + +static PlatformDarwin::SDKType ParseSDKName(llvm::StringRef &name) { + if (name.consume_front("MacOSX")) + return PlatformDarwin::MacOSX; + if (name.consume_front("iPhoneSimulator")) + return PlatformDarwin::iPhoneSimulator; + if (name.consume_front("iPhoneOS")) + return PlatformDarwin::iPhoneOS; + if (name.consume_front("AppleTVSimulator")) + return PlatformDarwin::AppleTVSimulator; + if (name.consume_front("AppleTVOS")) + return PlatformDarwin::AppleTVOS; + if (name.consume_front("WatchSimulator")) + return PlatformDarwin::WatchSimulator; + if (name.consume_front("WatchOS")) + return PlatformDarwin::watchOS; + if (name.consume_front("bridgeOS")) + return PlatformDarwin::bridgeOS; + if (name.consume_front("Linux")) + return PlatformDarwin::Linux; + static_assert(PlatformDarwin::Linux == PlatformDarwin::numSDKTypes - 1, + "New SDK type was added, update this list!"); + return PlatformDarwin::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 {}; +} + + +std::tuple SDK::Parse() const { + llvm::StringRef input = m_name.GetStringRef(); + PlatformDarwin::SDKType sdk = ParseSDKName(input); + llvm::VersionTuple version = ParseSDKVersion(input); + return {sdk, version}; +} + +llvm::VersionTuple SDK::GetVersion() const { + llvm::StringRef input = m_name.GetStringRef(); + ParseSDKName(input); + return ParseSDKVersion(input); +} + +int SDK::GetSDKType() const { + llvm::StringRef input = m_name.GetStringRef(); + return ParseSDKName(input); +} + +void SDK::Merge(SDK other) { + // The "bigger" SDK always wins. + if (Parse() < other.Parse()) + *this = other; +} + bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version) { switch (sdk_type) { @@ -1894,6 +1969,14 @@ llvm_unreachable("unhandled switch case"); } +ConstString PlatformDarwin::GetSDKPath(int type) { + if (type >= numSDKTypes || type <= unknown) + return {}; + if (!m_sdk_path[type]) + m_sdk_path[type] = GetXcodeSDK((SDKType)type).GetDirectory(); + return m_sdk_path[type]; +} + FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) { std::string xcrun_cmd = "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str(); 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/SDK.h" #include "llvm/Support/RWMutex.h" #include @@ -197,6 +198,10 @@ uint32_t GetProducerVersionUpdate(); + lldb_private::SDK GetSDK(); + + llvm::StringRef GetSysroot(); + uint64_t GetDWARFLanguageType(); bool GetIsOptimized(); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -667,6 +667,18 @@ return *m_language_type; } +SDK DWARFUnit::GetSDK() { + if (const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly()) + return SDK(die->GetAttributeValueAsString(this, DW_AT_APPLE_sdk, "")); + return {}; +} + +llvm::StringRef DWARFUnit::GetSysroot() { + if (const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly()) + return die->GetAttributeValueAsString(this, DW_AT_LLVM_sysroot, ""); + return {}; +} + bool DWARFUnit::GetIsOptimized() { if (m_is_optimized == eLazyBoolCalculate) { const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -648,6 +648,7 @@ const DWARFBaseDIE cu_die = dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly(); if (cu_die) { + module_sp->RegisterSDK(dwarf_cu.GetSDK(), ConstString(dwarf_cu.GetSysroot())); FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle()); if (cu_file_spec) { // If we have a full path to the compile unit, we don't need to