[Lldb-commits] [lldb] [lldb] Support dSYMs as modules (PR #77966)

via lldb-commits lldb-commits at lists.llvm.org
Fri Jan 12 11:20:17 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

<details>
<summary>Changes</summary>

Generally, separate debug info files are not object files. The exception
are dSYMs which are Mach-O and often contain enough information to be
used as a module.

This patch allows users to add dSYM symbol files as target modules to
support use cases where the executable isn't available. This scenario is
common when doing core file debugging and Jason has a follow up patch
that allows core file debugging without just the dSYM.

rdar://117773589

---
Full diff: https://github.com/llvm/llvm-project/pull/77966.diff


8 Files Affected:

- (modified) lldb/include/lldb/Symbol/ObjectFile.h (+4) 
- (modified) lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (+6) 
- (modified) lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (+2) 
- (modified) lldb/source/Symbol/ObjectFile.cpp (+33) 
- (modified) lldb/source/Target/Target.cpp (+3-30) 
- (added) lldb/test/API/macosx/dsym-module/Makefile (+3) 
- (added) lldb/test/API/macosx/dsym-module/TestTargetModuleAddDsym.py (+23) 
- (added) lldb/test/API/macosx/dsym-module/main.c (+5) 


``````````diff
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 6348d8103f85de..fb946ee71873de 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -698,6 +698,10 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
   /// file to be complete.
   virtual bool CanTrustAddressRanges() { return false; }
 
+  /// Can this object file serve as a valid target module. If a Status is passed
+  /// and the answer is no, it will be populated with the reason.
+  virtual bool CanBeTarget(Status *status = nullptr);
+
   static lldb::SymbolType GetSymbolTypeFromName(
       llvm::StringRef name,
       lldb::SymbolType symbol_type_hint = lldb::eSymbolTypeUndefined);
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index d7a2846200fcaf..d623476c4c7243 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6128,6 +6128,12 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
   return nullptr;
 }
 
+bool ObjectFileMachO::CanBeTarget(Status *status ) {
+  if (m_header.filetype == MH_DSYM)
+    return true;
+  return ObjectFile::CanBeTarget(status);
+}
+
 bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
   if (!section)
     return false;
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 0a47f3a7dd1861..7a2cda2b83ec21 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -160,6 +160,8 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
 
   lldb_private::Section *GetMachHeaderSection();
 
+  virtual bool CanBeTarget(lldb_private::Status *status = nullptr) override;
+
   // PluginInterface protocol
   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
 
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index d890ad92e83122..06457be6b606d6 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -764,6 +764,39 @@ uint32_t ObjectFile::GetCacheHash() {
   return *m_cache_hash;
 }
 
+bool ObjectFile::CanBeTarget(Status *status) {
+  switch (GetType()) {
+  case ObjectFile::eTypeCoreFile:      /// A core file that has a checkpoint of
+                                       /// a program's execution state
+  case ObjectFile::eTypeExecutable:    /// A normal executable
+  case ObjectFile::eTypeDynamicLinker: /// The platform's dynamic linker
+                                       /// executable
+  case ObjectFile::eTypeObjectFile:    /// An intermediate object file
+  case ObjectFile::eTypeSharedLibrary: /// A shared library that can be
+                                       /// used during execution
+    return true;
+  case ObjectFile::eTypeDebugInfo: /// An object file that contains only
+                                   /// debug information
+    if (status)
+      status->SetErrorString("debug info files aren't valid target "
+                             "modules, please specify an executable");
+    return false;
+  case ObjectFile::eTypeStubLibrary: /// A library that can be linked
+                                     /// against but not used for
+                                     /// execution
+    if (status)
+      status->SetErrorString("stub libraries aren't valid target "
+                             "modules, please specify an executable");
+    return false;
+  default:
+    if (status)
+      status->SetErrorString(
+          "unsupported file type, please specify an executable");
+    return false;
+  }
+  llvm_unreachable("Fully covered switch above!");
+}
+
 namespace llvm {
 namespace json {
 
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 302c2bad7021b9..e5e8658163fdba 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2254,37 +2254,10 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
     // there wasn't an equivalent module in the list already, and if there was,
     // let's remove it.
     if (module_sp) {
-      ObjectFile *objfile = module_sp->GetObjectFile();
-      if (objfile) {
-        switch (objfile->GetType()) {
-        case ObjectFile::eTypeCoreFile: /// A core file that has a checkpoint of
-                                        /// a program's execution state
-        case ObjectFile::eTypeExecutable:    /// A normal executable
-        case ObjectFile::eTypeDynamicLinker: /// The platform's dynamic linker
-                                             /// executable
-        case ObjectFile::eTypeObjectFile:    /// An intermediate object file
-        case ObjectFile::eTypeSharedLibrary: /// A shared library that can be
-                                             /// used during execution
-          break;
-        case ObjectFile::eTypeDebugInfo: /// An object file that contains only
-                                         /// debug information
-          if (error_ptr)
-            error_ptr->SetErrorString("debug info files aren't valid target "
-                                      "modules, please specify an executable");
-          return ModuleSP();
-        case ObjectFile::eTypeStubLibrary: /// A library that can be linked
-                                           /// against but not used for
-                                           /// execution
-          if (error_ptr)
-            error_ptr->SetErrorString("stub libraries aren't valid target "
-                                      "modules, please specify an executable");
-          return ModuleSP();
-        default:
-          if (error_ptr)
-            error_ptr->SetErrorString(
-                "unsupported file type, please specify an executable");
+      if (ObjectFile *objfile = module_sp->GetObjectFile()) {
+        if (!objfile->CanBeTarget(error_ptr))
           return ModuleSP();
-        }
+
         // GetSharedModule is not guaranteed to find the old shared module, for
         // instance in the common case where you pass in the UUID, it is only
         // going to find the one module matching the UUID.  In fact, it has no
diff --git a/lldb/test/API/macosx/dsym-module/Makefile b/lldb/test/API/macosx/dsym-module/Makefile
new file mode 100644
index 00000000000000..99998b20bcb050
--- /dev/null
+++ b/lldb/test/API/macosx/dsym-module/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/macosx/dsym-module/TestTargetModuleAddDsym.py b/lldb/test/API/macosx/dsym-module/TestTargetModuleAddDsym.py
new file mode 100644
index 00000000000000..05509a34e9f936
--- /dev/null
+++ b/lldb/test/API/macosx/dsym-module/TestTargetModuleAddDsym.py
@@ -0,0 +1,23 @@
+import os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+ at skipUnlessDarwin
+class TargetModuleAddDsymTest(TestBase):
+
+    @no_debug_info_test
+    def test_target_module_add(self):
+        """Test that you can add a dSYM as a module."""
+        self.build(debug_info="dsym")
+
+        exe_path = self.getBuildArtifact("a.out")
+        dsym_path = exe_path + ".dSYM"
+        sym_path = os.path.join(dsym_path, 'Contents','Resources','DWARF','a.out')
+
+        exe = self.getBuildArtifact("a.out")
+        self.dbg.CreateTarget(exe)
+
+        self.runCmd("target module add %s" % sym_path)
+        self.expect("image list", substrs=[sym_path])
+
diff --git a/lldb/test/API/macosx/dsym-module/main.c b/lldb/test/API/macosx/dsym-module/main.c
new file mode 100644
index 00000000000000..b5c9a5152d61d9
--- /dev/null
+++ b/lldb/test/API/macosx/dsym-module/main.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int main(int argc, char const *argv[]) {
+  return argc + 1;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/77966


More information about the lldb-commits mailing list