llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: None (GeorgeHuyubo) <details> <summary>Changes</summary> Add a new API in SBTarget to Load Core from a SBFile. This will enable a target to load core from a file descriptor. So that in coredumper, we don't need to write core file to disk, instead we can pass the input file descriptor to lldb directly. Test: ``` (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> file_object = open("/home/hyubo/210hda79ms32sr0h", "r") >>> fd=file_object.fileno() >>> file = lldb.SBFile(fd,'r', True) >>> error = lldb.SBError() >>> target = lldb.debugger.CreateTarget(None) >>> target.LoadCore(file,error) SBProcess: pid = 56415, state = stopped, threads = 1 ``` --- Patch is 48.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71769.diff 28 Files Affected: - (modified) lldb/include/lldb/API/SBTarget.h (+2) - (modified) lldb/include/lldb/Target/PostMortemProcess.h (+15) - (modified) lldb/include/lldb/Target/Process.h (+22-15) - (modified) lldb/include/lldb/Target/ProcessTrace.h (+2-2) - (modified) lldb/include/lldb/Target/Target.h (+2-1) - (modified) lldb/include/lldb/lldb-private-interfaces.h (+2-1) - (modified) lldb/source/API/SBTarget.cpp (+39-2) - (modified) lldb/source/Commands/CommandObjectTarget.cpp (+30-17) - (modified) lldb/source/Core/IOHandlerCursesGUI.cpp (+11-2) - (modified) lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp (+16-11) - (modified) lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h (+1-1) - (modified) lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (+2-2) - (modified) lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (+3-2) - (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp (+15-13) - (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.h (+4-4) - (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (+3-2) - (modified) lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (+3-2) - (modified) lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp (+14-11) - (modified) lldb/source/Plugins/Process/mach-core/ProcessMachCore.h (+3-4) - (modified) lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp (+9-7) - (modified) lldb/source/Plugins/Process/minidump/ProcessMinidump.h (+3-3) - (modified) lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp (+2-2) - (modified) lldb/source/Plugins/Process/scripted/ScriptedProcess.h (+1-1) - (modified) lldb/source/Target/Process.cpp (+5-6) - (modified) lldb/source/Target/ProcessTrace.cpp (+5-4) - (modified) lldb/source/Target/Target.cpp (+1-1) - (modified) lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py (+16) - (modified) lldb/unittests/Target/LocateModuleCallbackTest.cpp (+1-2) ``````````diff diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 83087623088c5b4..e49c32d0548501a 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -184,6 +184,8 @@ class LLDB_API SBTarget { SBProcess LoadCore(const char *core_file); SBProcess LoadCore(const char *core_file, lldb::SBError &error); + SBProcess LoadCore(SBFile &file); + SBProcess LoadCore(SBFile &file, lldb::SBError &error); /// Launch a new process with sensible defaults. /// diff --git a/lldb/include/lldb/Target/PostMortemProcess.h b/lldb/include/lldb/Target/PostMortemProcess.h index 7207fc99ef29a41..1f563e5f1ff6b88 100644 --- a/lldb/include/lldb/Target/PostMortemProcess.h +++ b/lldb/include/lldb/Target/PostMortemProcess.h @@ -10,6 +10,8 @@ #define LLDB_TARGET_POSTMORTEMPROCESS_H #include "lldb/Target/Process.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-forward.h" namespace lldb_private { @@ -24,7 +26,20 @@ class PostMortemProcess : public Process { using Process::Process; public: + PostMortemProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + lldb::FileSP file_sp) + : Process(target_sp, listener_sp), m_core_file(file_sp) {} + bool IsLiveDebugSession() const override { return false; } + + FileSpec GetCoreFile() const override { + const FileSpec file_spec; + m_core_file->GetFileSpec(const_cast<FileSpec &>(file_spec)); + return file_spec; + } + +protected: + lldb::FileSP m_core_file; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index a6d3e6c2d16926e..62284b29886a4ac 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -52,6 +52,7 @@ #include "lldb/Utility/TraceGDBRemotePackets.h" #include "lldb/Utility/UnimplementedError.h" #include "lldb/Utility/UserIDResolver.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "llvm/ADT/ArrayRef.h" @@ -354,12 +355,10 @@ class Process : public std::enable_shared_from_this<Process>, }; // This is all the event bits the public process broadcaster broadcasts. // The process shadow listener signs up for all these bits... - static constexpr int g_all_event_bits = eBroadcastBitStateChanged - | eBroadcastBitInterrupt - | eBroadcastBitSTDOUT - | eBroadcastBitSTDERR - | eBroadcastBitProfileData - | eBroadcastBitStructuredData; + static constexpr int g_all_event_bits = + eBroadcastBitStateChanged | eBroadcastBitInterrupt | eBroadcastBitSTDOUT | + eBroadcastBitSTDERR | eBroadcastBitProfileData | + eBroadcastBitStructuredData; enum { eBroadcastInternalStateControlStop = (1 << 0), @@ -390,12 +389,12 @@ class Process : public std::enable_shared_from_this<Process>, ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } - -/// A notification structure that can be used by clients to listen -/// for changes in a process's lifetime. -/// -/// \see RegisterNotificationCallbacks (const Notifications&) @see -/// UnregisterNotificationCallbacks (const Notifications&) + + /// A notification structure that can be used by clients to listen + /// for changes in a process's lifetime. + /// + /// \see RegisterNotificationCallbacks (const Notifications&) @see + /// UnregisterNotificationCallbacks (const Notifications&) typedef struct { void *baton; void (*initialize)(void *baton, Process *process); @@ -507,7 +506,7 @@ class Process : public std::enable_shared_from_this<Process>, static lldb::ProcessSP FindPlugin(lldb::TargetSP target_sp, llvm::StringRef plugin_name, lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path, + lldb::FileSP crash_file_sp, bool can_connect); /// Static function that can be used with the \b host function @@ -579,7 +578,7 @@ class Process : public std::enable_shared_from_this<Process>, /// of CommandObject like CommandObjectRaw, CommandObjectParsed, /// or CommandObjectMultiword. virtual CommandObject *GetPluginCommandObject() { return nullptr; } - + /// The underlying plugin might store the low-level communication history for /// this session. Dump it into the provided stream. virtual void DumpPluginHistory(Stream &s) { return; } @@ -614,7 +613,7 @@ class Process : public std::enable_shared_from_this<Process>, return error; } - /// The "ShadowListener" for a process is just an ordinary Listener that + /// The "ShadowListener" for a process is just an ordinary Listener that /// listens for all the Process event bits. It's convenient because you can /// specify it in the LaunchInfo or AttachInfo, so it will get events from /// the very start of the process. @@ -1469,6 +1468,14 @@ 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 037dea232cc024d..ee684a97a5be71c 100644 --- a/lldb/include/lldb/Target/ProcessTrace.h +++ b/lldb/include/lldb/Target/ProcessTrace.h @@ -27,7 +27,7 @@ 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, lldb::FileSP core_file_sp); ~ProcessTrace() override; @@ -74,7 +74,7 @@ class ProcessTrace : public PostMortemProcess { private: static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path, + lldb::FileSP core_file_sp, bool can_connect); }; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index c37682e2a03859f..a84b8a30dd15c65 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -35,6 +35,7 @@ #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Timeout.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-public.h" namespace lldb_private { @@ -627,7 +628,7 @@ class Target : public std::enable_shared_from_this<Target>, // used. const lldb::ProcessSP &CreateProcess(lldb::ListenerSP listener_sp, llvm::StringRef plugin_name, - const FileSpec *crash_file, + lldb::FileSP crash_file, bool can_connect); const lldb::ProcessSP &GetProcessSP() const; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index 53d5fbb84cc92d3..21fd34faee805d5 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -79,7 +79,8 @@ typedef lldb::PlatformSP (*PlatformCreateInstance)(bool force, const ArchSpec *arch); typedef lldb::ProcessSP (*ProcessCreateInstance)( lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const FileSpec *crash_file_path, bool can_connect); + lldb::FileSP crash_file_sp, + bool can_connect); typedef lldb::RegisterTypeBuilderSP (*RegisterTypeBuilderCreateInstance)( Target &target); typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)( diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 2d029554492a05c..46326039e8c1bf4 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -16,6 +16,7 @@ #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBExpressionOptions.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBModule.h" @@ -244,9 +245,45 @@ SBProcess SBTarget::LoadCore(const char *core_file, lldb::SBError &error) { TargetSP target_sp(GetSP()); if (target_sp) { FileSpec filespec(core_file); - FileSystem::Instance().Resolve(filespec); + auto file = FileSystem::Instance().Open( + filespec, lldb_private::File::eOpenOptionReadOnly); + if (!file) { + error.SetErrorStringWithFormat("Failed to open the core file: %s", + llvm::toString(file.takeError()).c_str()); + return sb_process; + } + ProcessSP process_sp( + target_sp->CreateProcess(target_sp->GetDebugger().GetListener(), "", + std::move(file.get()), false)); + if (process_sp) { + error.SetError(process_sp->LoadCore()); + if (error.Success()) + sb_process.SetSP(process_sp); + } else { + error.SetErrorString("Failed to create the process"); + } + } else { + error.SetErrorString("SBTarget is invalid"); + } + return sb_process; +} + +SBProcess SBTarget::LoadCore(SBFile &file) { + LLDB_INSTRUMENT_VA(this, file); + + lldb::SBError error; // Ignored + return LoadCore(file, error); +} + +SBProcess SBTarget::LoadCore(SBFile &file, lldb::SBError &error) { + LLDB_INSTRUMENT_VA(this, file, error); + + SBProcess sb_process; + TargetSP target_sp(GetSP()); + if (target_sp) { + FileSP file_sp = file.GetFile(); ProcessSP process_sp(target_sp->CreateProcess( - target_sp->GetDebugger().GetListener(), "", &filespec, false)); + target_sp->GetDebugger().GetListener(), "", file_sp, false)); if (process_sp) { error.SetError(process_sp->LoadCore()); if (error.Success()) diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 8f052d0a7b837e2..f86effdd2ecc389 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -427,8 +427,17 @@ class CommandObjectTargetCreate : public CommandObjectParsed { core_file_dir.SetDirectory(core_file.GetDirectory()); target_sp->AppendExecutableSearchPaths(core_file_dir); + auto file = FileSystem::Instance().Open( + core_file, lldb_private::File::eOpenOptionReadOnly); + if (!file) { + result.AppendErrorWithFormatv( + "Failed to open the core file '{0}': '{1}.'\n", + core_file.GetPath(), llvm::toString(file.takeError())); + } + ProcessSP process_sp(target_sp->CreateProcess( - GetDebugger().GetListener(), llvm::StringRef(), &core_file, false)); + GetDebugger().GetListener(), llvm::StringRef(), + std::move(file.get()), false)); if (process_sp) { // Seems weird that we Launch a core file, but that is what we @@ -2074,7 +2083,7 @@ class CommandObjectTargetModulesDumpSymtab result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all symtabs with {0} " "of {1} dumped.", num_dumped, num_modules)) break; @@ -2104,9 +2113,10 @@ class CommandObjectTargetModulesDumpSymtab result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump symtab list with {0} of {1} dumped.", - num_dumped, num_matches)) + if (INTERRUPT_REQUESTED( + GetDebugger(), + "Interrupted in dump symtab list with {0} of {1} dumped.", + num_dumped, num_matches)) break; num_dumped++; @@ -2167,9 +2177,10 @@ class CommandObjectTargetModulesDumpSections result.GetOutputStream().Format("Dumping sections for {0} modules.\n", num_modules); for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump all sections with {0} of {1} dumped", - image_idx, num_modules)) + if (INTERRUPT_REQUESTED( + GetDebugger(), + "Interrupted in dump all sections with {0} of {1} dumped", + image_idx, num_modules)) break; num_dumped++; @@ -2188,9 +2199,10 @@ class CommandObjectTargetModulesDumpSections FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump section list with {0} of {1} dumped.", - i, num_matches)) + if (INTERRUPT_REQUESTED( + GetDebugger(), + "Interrupted in dump section list with {0} of {1} dumped.", + i, num_matches)) break; Module *module = module_list.GetModulePointerAtIndex(i); @@ -2330,9 +2342,10 @@ class CommandObjectTargetModulesDumpClangAST } for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump clang ast list with {0} of {1} dumped.", - i, num_matches)) + if (INTERRUPT_REQUESTED( + GetDebugger(), + "Interrupted in dump clang ast list with {0} of {1} dumped.", i, + num_matches)) break; Module *m = module_list.GetModulePointerAtIndex(i); @@ -2469,10 +2482,10 @@ class CommandObjectTargetModulesDumpLineTable if (num_modules > 0) { uint32_t num_dumped = 0; for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all line tables with " - "{0} of {1} dumped", num_dumped, - num_modules)) + "{0} of {1} dumped", + num_dumped, num_modules)) break; if (DumpCompileUnitLineTable( diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index 22b8cc3582eae78..5b850fd5d5d7438 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -3174,8 +3174,17 @@ class TargetCreateFormDelegate : public FormDelegate { core_file_directory_spec.SetDirectory(core_file_spec.GetDirectory()); target_sp->AppendExecutableSearchPaths(core_file_directory_spec); - ProcessSP process_sp(target_sp->CreateProcess( - m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false)); + auto core_file = FileSystem::Instance().Open( + core_file_spec, lldb_private::File::eOpenOptionReadOnly); + + if (!core_file) { + SetError(llvm::toString(core_file.takeError()).c_str()); + return; + } + + ProcessSP process_sp( + target_sp->CreateProcess(m_debugger.GetListener(), llvm::StringRef(), + std::move(core_file.get()), false)); if (!process_sp) { SetError("Unable to find process plug-in for core file!"); diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp index 601f5df43dbba4e..c0c6cd8a9b2ee6b 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); + lldb::FileSP core_file_sp, fvc_t *fvc); ~ProcessFreeBSDKernelFVC(); @@ -50,7 +50,7 @@ class ProcessFreeBSDKernelFVC : public ProcessFreeBSDKernel { class ProcessFreeBSDKernelKVM : public ProcessFreeBSDKernel { public: ProcessFreeBSDKernelKVM(lldb::TargetSP target_sp, lldb::ListenerSP listener, - kvm_t *fvc); + lldb::FileSP core_file_sp, kvm_t *fvc); ~ProcessFreeBSDKernelKVM(); @@ -67,30 +67,33 @@ class ProcessFreeBSDKernelKVM : public ProcessFreeBSDKernel { } // namespace ProcessFreeBSDKernel::ProcessFreeBSDKernel(lldb::TargetSP target_sp, - ListenerSP listener_sp) - : PostMortemProcess(target_sp, listener_sp) {} + ListenerSP listener_sp, + lldb::FileSP crash_file_sp) + : PostMortemProcess(target_sp, listener_sp, crash_file_sp) {} lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp, ListenerSP listener_sp, - const FileSpec *crash_file, + lldb::FileSP crash_file_sp, bool can_connect) { ModuleSP executable = target_sp->GetExecutableModule(); if (crash_file && !can_connect && executable) { + const FileSpec file_spec; + crash_file_sp->GetFileSpec(const_cast<FileSpec &>(file_spec)); #if LLDB_ENABLE_FBSDVMCORE fvc_t *fvc = fvc_open(executable->GetFileSpec().GetPath().c_str(), - crash_file->GetPath().c_str(), nullptr, nullptr, nullptr); + file_spec->GetPath().c_str(), nullptr, nullptr, nullptr); if (fvc) - return std::make_shared<ProcessFreeBSDKernelFVC>(target_sp, listener_sp, + return std::make_shared<ProcessFreeBSDKernelFVC>(target_sp, listener_sp, crash_file_sp fvc); #endif #if defined(__FreeBSD__) kvm_t *kvm = kvm_open2(executable->GetFileSpec().GetPath().c_str(), - crash_file->GetPath().c_str(), O_RDONLY, nullptr, nullptr); + file_spec->GetPath().c_str(), O_RDONLY, nullptr, nullptr); if (kvm) - return std::make_shared<ProcessFreeBSDKernelKVM>(target_sp, listener_sp, + return std::make_shared<ProcessFreeBSDKernelKVM>(target_sp, listener_sp, crash_file_sp kvm); #endif } @@ -276,8 +279,9 @@ lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) { ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, ListenerSP listener_sp, + lldb::FileSP core_file_sp, fvc_t *fvc) - : ProcessFreeBSDKernel(target_sp, listener_sp), m_fvc(fvc) {} + : ProcessFreeBSDKernel(target_sp, listener_sp, core_file_sp), m_fvc(fvc) {} ProcessFreeBSDKernelFVC::~ProcessFreeBSDKernelFVC() { if (m_fvc) @@ -303,8 +307,9 @@ const... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/71769 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits