[Lldb-commits] [lldb] Add a new SBProcess:: GetCoreFile() API (PR #80767)

via lldb-commits lldb-commits at lists.llvm.org
Mon Feb 5 16:01:57 PST 2024


https://github.com/jeffreytan81 created https://github.com/llvm/llvm-project/pull/80767

We have a Python script that needs to locate coredump path during debugging so that we can retrieve certain metadata files associated with it. Currently, there is no API for this.

This patch adds a new `SBProcess::GetCoreFile()` to retrieve target dump file spec used for dump debugging. Note: this is different from the main executable module spec. To achieve this, the patch hoists m_core_file into PostMortemProcess for sharing.


>From e7af15ff3c1bdd42799b25f76145b8a19739eea5 Mon Sep 17 00:00:00 2001
From: jeffreytan81 <jeffreytan at fb.com>
Date: Mon, 5 Feb 2024 15:58:23 -0800
Subject: [PATCH] Add a new SBProcess:: GetCoreFile() API

---
 lldb/include/lldb/API/SBProcess.h             |  7 +++++++
 lldb/include/lldb/Target/PostMortemProcess.h  |  9 ++++++++
 lldb/include/lldb/Target/Process.h            |  7 +++++++
 lldb/include/lldb/Target/ProcessTrace.h       |  3 ++-
 lldb/source/API/SBProcess.cpp                 | 11 ++++++++++
 .../FreeBSDKernel/ProcessFreeBSDKernel.cpp    | 21 +++++++++++--------
 .../FreeBSDKernel/ProcessFreeBSDKernel.h      |  3 ++-
 .../Process/elf-core/ProcessElfCore.cpp       |  8 +++----
 .../Plugins/Process/elf-core/ProcessElfCore.h |  1 -
 .../Process/mach-core/ProcessMachCore.cpp     |  6 +++---
 .../Process/mach-core/ProcessMachCore.h       |  1 -
 .../Process/minidump/ProcessMinidump.cpp      |  2 +-
 .../Process/minidump/ProcessMinidump.h        |  1 -
 lldb/source/Target/ProcessTrace.cpp           |  7 ++++---
 .../postmortem/elf-core/TestLinuxCore.py      | 11 ++++++++++
 15 files changed, 73 insertions(+), 25 deletions(-)

diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index 8c1c81418f83d..13994ed300853 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -398,6 +398,13 @@ class LLDB_API SBProcess {
   /// valid.
   lldb::SBProcessInfo GetProcessInfo();
 
+  /// Return target dump file during postmortem debugging.
+  /// An empty file will be returned for live debugging.
+  ///
+  /// \return
+  ///     The target dump file spec.
+  lldb::SBFileSpec GetCoreFile();
+
   /// Allocate memory within the process.
   ///
   /// This function will allocate memory in the process's address space.
diff --git a/lldb/include/lldb/Target/PostMortemProcess.h b/lldb/include/lldb/Target/PostMortemProcess.h
index 7207fc99ef29a..9c9cd7fa599bc 100644
--- a/lldb/include/lldb/Target/PostMortemProcess.h
+++ b/lldb/include/lldb/Target/PostMortemProcess.h
@@ -24,7 +24,16 @@ class PostMortemProcess : public Process {
   using Process::Process;
 
 public:
+  PostMortemProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+                    const FileSpec &core_file)
+      : Process(target_sp, listener_sp), m_core_file(core_file) {}
+
   bool IsLiveDebugSession() const override { return false; }
+
+  FileSpec GetCoreFile() const override { return m_core_file; }
+
+protected:
+  FileSpec m_core_file;
 };
 
 } // namespace lldb_private
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 7048921d6034f..0ad626ffd3613 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1503,6 +1503,13 @@ class Process : public std::enable_shared_from_this<Process>,
 
   virtual bool IsLiveDebugSession() const { return true; };
 
+  /// Provide a way to retrieve the core dump file that is loaded for debugging.
+  /// Only available if IsLiveDebugSession() returns true.
+  ///
+  /// \return
+  ///     File path to the core file.
+  virtual FileSpec GetCoreFile() const { return {}; }
+
   /// Before lldb detaches from a process, it warns the user that they are
   /// about to lose their debug session. In some cases, this warning doesn't
   /// need to be emitted -- for instance, with core file debugging where the
diff --git a/lldb/include/lldb/Target/ProcessTrace.h b/lldb/include/lldb/Target/ProcessTrace.h
index 037dea232cc02..7a025100f6803 100644
--- a/lldb/include/lldb/Target/ProcessTrace.h
+++ b/lldb/include/lldb/Target/ProcessTrace.h
@@ -27,7 +27,8 @@ class ProcessTrace : public PostMortemProcess {
 
   static llvm::StringRef GetPluginDescriptionStatic();
 
-  ProcessTrace(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+  ProcessTrace(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+               const FileSpec &core_file);
 
   ~ProcessTrace() override;
 
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 4864ea0e7d026..a9fe915324683 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -1244,6 +1244,17 @@ lldb::SBProcessInfo SBProcess::GetProcessInfo() {
   return sb_proc_info;
 }
 
+lldb::SBFileSpec SBProcess::GetCoreFile() {
+  LLDB_INSTRUMENT_VA(this);
+
+  ProcessSP process_sp(GetSP());
+  FileSpec core_file;
+  if (process_sp) {
+    core_file = process_sp->GetCoreFile();
+  }
+  return SBFileSpec(core_file);
+}
+
 lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions,
                                        lldb::SBError &sb_error) {
   LLDB_INSTRUMENT_VA(this, size, permissions, sb_error);
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
index 601f5df43dbba..997b590851103 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
@@ -32,7 +32,7 @@ namespace {
 class ProcessFreeBSDKernelFVC : public ProcessFreeBSDKernel {
 public:
   ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, lldb::ListenerSP listener,
-                          fvc_t *fvc);
+                          fvc_t *fvc, const FileSpec &core_file);
 
   ~ProcessFreeBSDKernelFVC();
 
@@ -67,8 +67,9 @@ class ProcessFreeBSDKernelKVM : public ProcessFreeBSDKernel {
 } // namespace
 
 ProcessFreeBSDKernel::ProcessFreeBSDKernel(lldb::TargetSP target_sp,
-                                           ListenerSP listener_sp)
-    : PostMortemProcess(target_sp, listener_sp) {}
+                                           ListenerSP listener_sp,
+                                           const FileSpec &core_file)
+    : PostMortemProcess(target_sp, listener_sp, core_file) {}
 
 lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp,
                                                      ListenerSP listener_sp,
@@ -82,7 +83,7 @@ lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp,
                  crash_file->GetPath().c_str(), nullptr, nullptr, nullptr);
     if (fvc)
       return std::make_shared<ProcessFreeBSDKernelFVC>(target_sp, listener_sp,
-                                                       fvc);
+                                                       fvc, *crash_file);
 #endif
 
 #if defined(__FreeBSD__)
@@ -91,7 +92,7 @@ lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp,
                   crash_file->GetPath().c_str(), O_RDONLY, nullptr, nullptr);
     if (kvm)
       return std::make_shared<ProcessFreeBSDKernelKVM>(target_sp, listener_sp,
-                                                       kvm);
+                                                       kvm, *crash_file);
 #endif
   }
   return nullptr;
@@ -276,8 +277,9 @@ lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) {
 
 ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp,
                                                  ListenerSP listener_sp,
-                                                 fvc_t *fvc)
-    : ProcessFreeBSDKernel(target_sp, listener_sp), m_fvc(fvc) {}
+                                                 fvc_t *fvc,
+                                                 const FileSpec &core_file)
+    : ProcessFreeBSDKernel(target_sp, listener_sp, crash_file), m_fvc(fvc) {}
 
 ProcessFreeBSDKernelFVC::~ProcessFreeBSDKernelFVC() {
   if (m_fvc)
@@ -303,8 +305,9 @@ const char *ProcessFreeBSDKernelFVC::GetError() { return fvc_geterr(m_fvc); }
 
 ProcessFreeBSDKernelKVM::ProcessFreeBSDKernelKVM(lldb::TargetSP target_sp,
                                                  ListenerSP listener_sp,
-                                                 kvm_t *fvc)
-    : ProcessFreeBSDKernel(target_sp, listener_sp), m_kvm(fvc) {}
+                                                 kvm_t *fvc,
+                                                 const FileSpec &core_file)
+    : ProcessFreeBSDKernel(target_sp, listener_sp, core_file), m_kvm(fvc) {}
 
 ProcessFreeBSDKernelKVM::~ProcessFreeBSDKernelKVM() {
   if (m_kvm)
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
index 5bd463126307c..06c9d062441e5 100644
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
@@ -13,7 +13,8 @@
 
 class ProcessFreeBSDKernel : public lldb_private::PostMortemProcess {
 public:
-  ProcessFreeBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener);
+  ProcessFreeBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener,
+                       const lldb_private::FileSpec &core_file);
 
   static lldb::ProcessSP
   CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener,
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 7723009787f7f..fbd0a4be40c06 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -99,7 +99,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
 ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
                                lldb::ListenerSP listener_sp,
                                const FileSpec &core_file)
-    : PostMortemProcess(target_sp, listener_sp), m_core_file(core_file) {}
+    : PostMortemProcess(target_sp, listener_sp, core_file) {}
 
 // Destructor
 ProcessElfCore::~ProcessElfCore() {
@@ -224,7 +224,7 @@ Status ProcessElfCore::DoLoadCore() {
   ArchSpec core_arch(m_core_module_sp->GetArchitecture());
   target_arch.MergeFrom(core_arch);
   GetTarget().SetArchitecture(target_arch);
- 
+
   SetUnixSignals(UnixSignals::Create(GetArchitecture()));
 
   // Ensure we found at least one thread that was stopped on a signal.
@@ -261,7 +261,7 @@ Status ProcessElfCore::DoLoadCore() {
       exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
                                             FileSpec::Style::native);
       if (exe_module_spec.GetFileSpec()) {
-        exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, 
+        exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec,
                                                       true /* notify */);
         if (exe_module_sp)
           GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
@@ -865,7 +865,7 @@ llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
 /// - NT_SIGINFO - Information about the signal that terminated the process
 /// - NT_AUXV - Process auxiliary vector
 /// - NT_FILE - Files mapped into memory
-/// 
+///
 /// Additionally, for each thread in the process the core file will contain at
 /// least the NT_PRSTATUS note, containing the thread id and general purpose
 /// registers. It may include additional notes for other register sets (floating
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 1454e8735a677..2cec635bbacfe 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -127,7 +127,6 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
       VMRangeToPermissions;
 
   lldb::ModuleSP m_core_module_sp;
-  lldb_private::FileSpec m_core_file;
   std::string m_dyld_plugin_name;
 
   // True if m_thread_contexts contains valid entries
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index a2ea19388b75f..ead35b47694e0 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -111,8 +111,8 @@ bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
 ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
                                  ListenerSP listener_sp,
                                  const FileSpec &core_file)
-    : PostMortemProcess(target_sp, listener_sp), m_core_aranges(),
-      m_core_range_infos(), m_core_module_sp(), m_core_file(core_file),
+    : PostMortemProcess(target_sp, listener_sp, core_file), m_core_aranges(),
+      m_core_range_infos(), m_core_module_sp(),
       m_dyld_addr(LLDB_INVALID_ADDRESS),
       m_mach_kernel_addr(LLDB_INVALID_ADDRESS) {}
 
@@ -404,7 +404,7 @@ bool ProcessMachCore::LoadBinariesViaMetadata() {
 
   // LoadCoreFileImges may have set the dynamic loader, e.g. in
   // PlatformDarwinKernel::LoadPlatformBinaryAndSetup().
-  // If we now have a dynamic loader, save its name so we don't 
+  // If we now have a dynamic loader, save its name so we don't
   // un-set it later.
   if (m_dyld_up)
     m_dyld_plugin_name = GetDynamicLoader()->GetPluginName();
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
index c8820209e3f38..8996ae116614b 100644
--- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
@@ -130,7 +130,6 @@ class ProcessMachCore : public lldb_private::PostMortemProcess {
   VMRangeToFileOffset m_core_aranges;
   VMRangeToPermissions m_core_range_infos;
   lldb::ModuleSP m_core_module_sp;
-  lldb_private::FileSpec m_core_file;
   lldb::addr_t m_dyld_addr;
   lldb::addr_t m_mach_kernel_addr;
   llvm::StringRef m_dyld_plugin_name;
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index b72307c7e4b96..13599f4a1553f 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -156,7 +156,7 @@ ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
                                  lldb::ListenerSP listener_sp,
                                  const FileSpec &core_file,
                                  DataBufferSP core_data)
-    : PostMortemProcess(target_sp, listener_sp), m_core_file(core_file),
+    : PostMortemProcess(target_sp, listener_sp, core_file),
       m_core_data(std::move(core_data)), m_active_exception(nullptr),
       m_is_wow64(false) {}
 
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 0e4e52c0113fb..3f3123a0a8b5d 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -107,7 +107,6 @@ class ProcessMinidump : public PostMortemProcess {
   JITLoaderList &GetJITLoaders() override;
 
 private:
-  FileSpec m_core_file;
   lldb::DataBufferSP m_core_data;
   llvm::ArrayRef<minidump::Thread> m_thread_list;
   const minidump::ExceptionStream *m_active_exception;
diff --git a/lldb/source/Target/ProcessTrace.cpp b/lldb/source/Target/ProcessTrace.cpp
index 3a41f257627c2..4718a7ca50a7c 100644
--- a/lldb/source/Target/ProcessTrace.cpp
+++ b/lldb/source/Target/ProcessTrace.cpp
@@ -36,15 +36,16 @@ ProcessSP ProcessTrace::CreateInstance(TargetSP target_sp,
                                        bool can_connect) {
   if (can_connect)
     return nullptr;
-  return std::make_shared<ProcessTrace>(target_sp, listener_sp);
+  return std::make_shared<ProcessTrace>(target_sp, listener_sp, *crash_file);
 }
 
 bool ProcessTrace::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {
   return plugin_specified_by_name;
 }
 
-ProcessTrace::ProcessTrace(TargetSP target_sp, ListenerSP listener_sp)
-    : PostMortemProcess(target_sp, listener_sp) {}
+ProcessTrace::ProcessTrace(TargetSP target_sp, ListenerSP listener_sp,
+                           const FileSpec &core_file)
+    : PostMortemProcess(target_sp, listener_sp, core_file) {}
 
 ProcessTrace::~ProcessTrace() {
   Clear();
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index d6907075820ec..7ec5e0d7c8309 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -633,6 +633,17 @@ def test_arm_core(self):
 
         self.expect("register read --all")
 
+    def test_get_core_file_api(self):
+        """
+        Test SBProcess::GetCoreFile() API can successfully get the core file.
+        """
+        core_file_name = "linux-x86_64.core"
+        target = self.dbg.CreateTarget("linux-x86_64.out")
+        process = target.LoadCore(core_file_name)
+        self.assertTrue(process, PROCESS_IS_VALID)
+        self.assertEqual(process.GetCoreFile().GetFilename(), core_file_name)
+        self.dbg.DeleteTarget(target)
+
     def check_memory_regions(self, process, region_count):
         region_list = process.GetMemoryRegions()
         self.assertEqual(region_list.GetSize(), region_count)



More information about the lldb-commits mailing list