aprantl updated this revision to Diff 254071.
aprantl added a comment.

I just had an off-list conversation with @jingham were we discussed what should 
be Platform versus Host in detail. The resulting solution looks even more 
convoluted at first, but it actually solves a bunch of problems that I had with 
either of the previous proposals. Jim argued that an interface that retrieves 
an SDK for the target should live in PlatformDarwin, since we are querying 
something about a Darwin platform, and in principle, this interface should also 
be available if you are (hypothetically) debugging a macOS process from a Linux 
host, even if it isn't implemented at the time. However, the one concrete 
implementation that we have, the one that calls `xcrun` must live in 
HostInfoMacOSX, because xcrun doesn't anywhere else.

With this in mind I arrived at this version of the patch where the 
implementation lives in HostInfoMacOSX, but the interface lives in 
PlatformDarwin, which forwards to the host if an implementation exists. Let me 
(Pavel & Jim) know what you think about this variant!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76471/new/

https://reviews.llvm.org/D76471

Files:
  lldb/include/lldb/Core/Module.h
  lldb/include/lldb/Host/HostInfoBase.h
  lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
  lldb/include/lldb/Target/Platform.h
  lldb/include/lldb/Utility/XcodeSDK.h
  lldb/source/Core/Module.cpp
  lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
  lldb/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
  lldb/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
  lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
  lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
  lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
  lldb/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Utility/CMakeLists.txt
  lldb/source/Utility/XcodeSDK.cpp
  lldb/unittests/Platform/PlatformDarwinTest.cpp
  lldb/unittests/Utility/CMakeLists.txt
  lldb/unittests/Utility/XcodeSDKTest.cpp

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 <tuple>
+
+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));
+}
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/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/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::Type, llvm::VersionTuple> 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/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/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/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 <atomic>
 
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<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:
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<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneOS);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneOS);
   }
 
 protected:
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<std::string> &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,8 @@
   }
 
   // Use the default SDK as a fallback.
-  if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
+  FileSpec fspec(HostInfo::GetXcodeSDK(lldb_private::XcodeSDK::Type::MacOSX));
+  if (fspec) {
     if (FileSystem::Instance().Exists(fspec))
       return ConstString(fspec.GetPath());
   }
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,11 @@
   static std::tuple<llvm::VersionTuple, llvm::StringRef>
   ParseVersionBuildDir(llvm::StringRef str);
 
-  enum SDKType : int {
-    MacOSX = 0,
-    iPhoneSimulator,
-    iPhoneOS,
-    AppleTVSimulator,
-    AppleTVOS,
-    WatchSimulator,
-    watchOS,
-    bridgeOS,
-    Linux,
-    numSDKTypes,
-    unknown = -1
-  };
-
   llvm::Expected<lldb_private::StructuredData::DictionarySP>
   FetchExtendedCrashInformation(lldb_private::Process &process) override;
 
-  static llvm::StringRef GetSDKNameForType(SDKType type);
-  static lldb_private::FileSpec GetXcodeSDK(SDKType type);
+  llvm::StringRef GetSDKPath(lldb_private::XcodeSDK::Type type) override;
+
   static lldb_private::FileSpec GetXcodeContentsDirectory();
   static lldb_private::FileSpec GetXcodeDeveloperDirectory();
 
@@ -151,14 +139,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 +149,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<std::string> &options,
-                                             SDKType sdk_type);
+  GetSDKDirectoryForModules(lldb_private::XcodeSDK::Type sdk_type);
 
+  void AddClangModuleCompilationOptionsForSDKType(
+      lldb_private::Target *target, std::vector<std::string> &options,
+      lldb_private::XcodeSDK::Type sdk_type);
 
   lldb_private::Status FindBundleBinaryInExecSearchPaths(
       const lldb_private::ModuleSpec &module_spec,
@@ -188,6 +169,8 @@
                                          llvm::StringRef component);
   static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path);
 
+  std::string m_developer_directory;
+  std::array<std::string, lldb_private::XcodeSDK::Type::numSDKTypes> 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<SDKEnumeratorInfo *>(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<std::string> &options, SDKType sdk_type) {
+    Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) {
   const std::vector<std::string> 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,70 +1761,13 @@
   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");
-}
-
-FileSpec PlatformDarwin::GetXcodeSDK(SDKType type) {
-  std::string xcrun_cmd =
-      "xcrun --show-sdk-path --sdk " + GetSDKNameForType(type).str();
-
-  int status = 0;
-  int signo = 0;
-  std::string output_str;
-  lldb_private::Status error =
-      Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo,
-                            &output_str, std::chrono::seconds(15));
-
-  // Check that xcrun return something useful.
-  if (status != 0 || output_str.empty())
-    return {};
-
-  // Convert to a StringRef so we can manipulate the string without modifying
-  // the underlying data.
-  llvm::StringRef output(output_str);
-
-  // Remove any trailing newline characters.
-  output = output.rtrim();
-
-  // Strip any leading newline characters and everything before them.
-  const size_t last_newline = output.rfind('\n');
-  if (last_newline != llvm::StringRef::npos)
-    output = output.substr(last_newline + 1);
-
-  // Whatever is left in output should be a valid path.
-  if (!FileSystem::Instance().Exists(output))
+llvm::StringRef PlatformDarwin::GetSDKPath(XcodeSDK::Type type) {
+  if (type >= XcodeSDK::Type::numSDKTypes || type <= XcodeSDK::Type::unknown)
     return {};
-
-  // Find the contents dir in the xcrun provided path.
-  std::string xcode_contents_dir = FindXcodeContentsDirectoryInPath(output);
-  if (xcode_contents_dir.empty())
-    return {};
-
-  return FileSpec(xcode_contents_dir);
+  if (m_sdk_path[type].empty()) {
+    m_sdk_path[type] = HostInfo::GetXcodeSDK((XcodeSDK::Type)type);
+  }
+  return m_sdk_path[type];
 }
 
 FileSpec PlatformDarwin::GetXcodeContentsDirectory() {
@@ -1899,7 +1798,8 @@
       }
     }
 
-    if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
+    FileSpec fspec(HostInfo::GetXcodeSDK(XcodeSDK::Type::MacOSX));
+    if (fspec) {
       if (FileSystem::Instance().Exists(fspec)) {
         std::string xcode_contents_dir =
             FindXcodeContentsDirectoryInPath(fspec.GetPath());
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<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:
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<std::string> &options) override {
     return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
-        target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+        target, options, lldb_private::XcodeSDK::Type::iPhoneSimulator);
   }
 
 protected:
Index: lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
===================================================================
--- lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -8,6 +8,7 @@
 
 #include "lldb/Host/macosx/HostInfoMacOSX.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Utility/Args.h"
 #include "lldb/Utility/Log.h"
@@ -295,3 +296,36 @@
     }
   }
 }
+
+std::string HostInfoMacOSX::GetXcodeSDK(XcodeSDK::Type type) {
+  std::string xcrun_cmd =
+      "xcrun --show-sdk-path --sdk " + XcodeSDK::GetSDKNameForType(type).str();
+
+  int status = 0;
+  int signo = 0;
+  std::string output_str;
+  lldb_private::Status error =
+      Host::RunShellCommand(xcrun_cmd.c_str(), FileSpec(), &status, &signo,
+                            &output_str, std::chrono::seconds(15));
+
+  // Check that xcrun return something useful.
+  if (status != 0 || output_str.empty())
+    return {};
+
+  // Convert to a StringRef so we can manipulate the string without modifying
+  // the underlying data.
+  llvm::StringRef output(output_str);
+
+  // Remove any trailing newline characters.
+  output = output.rtrim();
+
+  // Strip any leading newline characters and everything before them.
+  const size_t last_newline = output.rfind('\n');
+  if (last_newline != llvm::StringRef::npos)
+    output = output.substr(last_newline + 1);
+
+  // Whatever is left in output should be a valid path.
+  if (!FileSystem::Instance().Exists(output))
+    return {};
+  return output.str();
+}
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/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 <tuple>
+
+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(std::move(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<Type, llvm::VersionTuple> 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/include/lldb/Target/Platform.h
===================================================================
--- lldb/include/lldb/Target/Platform.h
+++ lldb/include/lldb/Target/Platform.h
@@ -434,6 +434,10 @@
     return lldb_private::ConstString();
   }
 
+  virtual llvm::StringRef GetSDKPath(lldb_private::XcodeSDK::Type type) {
+    return {};
+  }
+
   const std::string &GetRemoteURL() const { return m_remote_url; }
 
   bool IsHost() const {
Index: lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
===================================================================
--- lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -11,6 +11,7 @@
 
 #include "lldb/Host/posix/HostInfoPosix.h"
 #include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "llvm/Support/VersionTuple.h"
 
 namespace lldb_private {
@@ -31,7 +32,10 @@
   static bool GetOSBuildString(std::string &s);
   static bool GetOSKernelDescription(std::string &s);
   static FileSpec GetProgramFileSpec();
+  static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path);
 
+  /// Query xcrun to find an Xcode SDK directory.
+  static std::string GetXcodeSDK(XcodeSDK::Type type);
 protected:
   static bool ComputeSupportExeDirectory(FileSpec &file_spec);
   static void ComputeHostArchitectureSupport(ArchSpec &arch_32,
Index: lldb/include/lldb/Host/HostInfoBase.h
===================================================================
--- lldb/include/lldb/Host/HostInfoBase.h
+++ lldb/include/lldb/Host/HostInfoBase.h
@@ -12,6 +12,7 @@
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/UserIDResolver.h"
+#include "lldb/Utility/XcodeSDK.h"
 #include "lldb/lldb-enumerations.h"
 #include "llvm/ADT/StringRef.h"
 
@@ -91,6 +92,9 @@
   static bool ComputePathRelativeToLibrary(FileSpec &file_spec,
                                            llvm::StringRef dir);
 
+  /// Return the directory containing a specific Xcode SDK.
+  static std::string GetXcodeSDK(XcodeSDK::Type type) { return {}; }
+
 protected:
   static bool ComputeSharedLibraryDirectory(FileSpec &file_spec);
   static bool ComputeSupportExeDirectory(FileSpec &file_spec);
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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to