-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Add a new SBProcess:: GetCoreFile() API #80767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lldb Author: None (jeffreytan81) ChangesWe 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 Full diff: https://github.com/llvm/llvm-project/pull/80767.diff 15 Files Affected:
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)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
I'm not sure I understand. Why do you need to get the path to the core file through the SBAPI? Didn't you also load it through the SBAPI too? |
lldb/include/lldb/API/SBProcess.h
Outdated
/// 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(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We load the core file in SBTarget. I would move this into SBTarget.h/.cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems correct to get this from the Process, because it's a property of the process. Before/after the Process exists, there is no core file FileSpec to return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@clayborg, I agree with what @jasonmolenda says here. If you look at the existing implementation, the core file passed in is not stored in Target object but inside the created process object. SBTarget::GetCoreFile()
would require us redundantly store the core file path inside target.
lldb/include/lldb/API/SBProcess.h
Outdated
/// Return target dump file during postmortem debugging. | ||
/// An empty file will be returned for live debugging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Get the file specification for the core file that is currently being used
/// for the process. If the process is not loaded from a core file, then an
/// invalid file specification will be returned.
lldb/include/lldb/API/SBProcess.h
Outdated
/// An empty file will be returned for live debugging. | ||
/// | ||
/// \return | ||
/// The target dump file spec. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"The path to the core file for this target or an invalid file spec if the process isn't loaded from a core file.
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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to SBTarget for consistency at the public API layer since we load the core file in SBTarget. If others believe that this should stay in SBProcess, let me know as I can go with what makes most sense, but the target seems the right location as I am thinking about it right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We pass the filepath to SBTarget::LoadCore
but I don't think this is a property of the Target, it seems like a property of the Process to me. I suppose someone could create a Process with a core file, then close that Process, then create a new Process with a different core file, all in the same Target if the ArchSpecs were the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking: this is like asking for the PID of a live process.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert whitespace only change
exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, | ||
exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert whitespace only change
/// | ||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert whitespace only change
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert whitespace only change
This seems like a useful addition to me, I've had some users of corefiles who have asked for an SBProcess::IsCore() type of method. (and others asking for ways to access metadata from the corefile itself via the Process, although I've never thought about how to do that, maybe some SBStructuredData thing because there are so many different forms of metadata that Process plugins might have available) |
@bulbazord, the scenario is that user directly uses "lldb -c <path_to_core>" to load core file, then the python script is invoked later to fetch metadata, resolve binaries/symbols etc... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fine to leave the accessor on the SBProcess class.
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. --------- Co-authored-by: jeffreytan81 <[email protected]> (cherry picked from commit 0123cef)
…-filespec Add a new SBProcess:: GetCoreFile() API (llvm#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.