aprantl updated this revision to Diff 254696.
aprantl marked 7 inline comments as done.
aprantl added a comment.

Renamed SDK -> XcodeSDK where applicable. Sorry I missed this earlier.


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,84 @@
+//===-- 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::GetAnyMacOS().GetType(), XcodeSDK::MacOSX);
+  EXPECT_EQ(XcodeSDK("MacOSX.sdk").GetType(), XcodeSDK::MacOSX);
+  EXPECT_EQ(XcodeSDK("iPhoneSimulator.sdk").GetType(), XcodeSDK::iPhoneSimulator);
+  EXPECT_EQ(XcodeSDK("iPhoneOS.sdk").GetType(), XcodeSDK::iPhoneOS);
+  EXPECT_EQ(XcodeSDK("AppleTVSimulator.sdk").GetType(), XcodeSDK::AppleTVSimulator);
+  EXPECT_EQ(XcodeSDK("AppleTVOS.sdk").GetType(), XcodeSDK::AppleTVOS);
+  EXPECT_EQ(XcodeSDK("WatchSimulator.sdk").GetType(), XcodeSDK::WatchSimulator);
+  EXPECT_EQ(XcodeSDK("WatchOS.sdk").GetType(), XcodeSDK::watchOS);
+  EXPECT_EQ(XcodeSDK("Linux.sdk").GetType(), 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.GetType(), 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,163 @@
+//===-- 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::GetType() const {
+  llvm::StringRef input(m_name);
+  return ParseSDKName(input);
+}
+
+llvm::StringRef XcodeSDK::GetString() const { return m_name; }
+
+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->RegisterXcodeSDK(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::GetAnyMacOS()));
+  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 sdk) 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;
+  llvm::StringMap<std::string> 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,11 @@
   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))
-    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);
+llvm::StringRef PlatformDarwin::GetSDKPath(XcodeSDK sdk) {
+  std::string &path = m_sdk_path[sdk.GetString()];
+  if (path.empty())
+    path = HostInfo::GetXcodeSDK(sdk);
+  return path;
 }
 
 FileSpec PlatformDarwin::GetXcodeContentsDirectory() {
@@ -1899,7 +1796,8 @@
       }
     }
 
-    if (FileSpec fspec = GetXcodeSDK(SDKType::MacOSX)) {
+    FileSpec fspec(HostInfo::GetXcodeSDK(XcodeSDK::GetAnyMacOS()));
+    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,39 @@
     }
   }
 }
+
+std::string HostInfoMacOSX::GetXcodeSDK(XcodeSDK sdk) {
+  std::string xcrun_cmd = "xcrun --show-sdk-path --sdk " +
+                          XcodeSDK::GetSDKNameForType(sdk.GetType()).str();
+  llvm::VersionTuple version = sdk.GetVersion();
+  if (!version.empty())
+    xcrun_cmd += version.getAsString();
+
+  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::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) {
+  XcodeSDK sdk(sdk_name.str());
+  if (m_xcode_sdk == sdk)
+    return;
+  m_xcode_sdk.Merge(sdk);
+  PlatformSP module_platform =
+      Platform::GetPlatformForArchitecture(GetArchitecture(), nullptr);
+  ConstString sdk_path(module_platform->GetSDKPath(sdk));
+  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,63 @@
+//===-- 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)) {}
+  static XcodeSDK GetAnyMacOS() { return XcodeSDK("MacOSX.sdk"); }
+
+  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 GetType() const;
+  llvm::StringRef GetString() 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 sdk) {
+    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 sdk);
 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 sdk) { 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 RegisterXcodeSDK(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 (Xcode) SDK this module was compiled with.
+  XcodeSDK m_xcode_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