[Lldb-commits] [lldb] [LLDB] Extract process arguments from core dump for Linux (PR #185338)

via lldb-commits lldb-commits at lists.llvm.org
Sun Mar 8 19:43:30 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Jasmine Tang (badumbatish)

<details>
<summary>Changes</summary>

This PR adds the ability for lldb to print out how to reproduce the crash by printing out the arguments used with the process (just like how GDB does it).

Calling `process status` also prints out said arguments for users, as suggested by #<!-- -->156427.

For impl, I'm extracting pr_psargs from prpsinfo (already parsed from before in ProcessElfCore::parseLinuxNotes). Afterwards i grep "Core file" to find where core file was loaded to print the message with and and do llvm_unreachable for process_status to find where to include the message.

I currently don't have any bsd based OSs so I didn't add any tests and implementations for it.

I planned and brainstormed this with Claude but the idea is verified and code is written by hand.

Demo of new patch
```
❯ ./build/bin/lldb  core_dump --core core_dump.core
Python Interactive Interpreter. To exit, type 'quit()', 'exit()'.
>>> >>> ... ...
now exiting InteractiveConsole...
(lldb) target create "core_dump" --core "core_dump.core"
Core file '/home/jjasmine/Developer/igalia/llvm-project/core_dump.core' (x86_64) was loaded.
Core was generated by `./core_dump arg1 arg2 hello world`.
(lldb) process status
Process 297263 stopped
Core was generated by `./core_dump arg1 arg2 hello world`.
* thread #<!-- -->1, name = 'core_dump', stop reason = SIGSEGV: sent by tkill system call (sender pid=297263, uid=1000)
      frame #<!-- -->0: 0x00007f7e46a80a2c libc.so.6`___lldb_unnamed_symbol_98920 + 268
libc.so.6`___lldb_unnamed_symbol_98920:
->  0x7f7e46a80a2c <+268>: movl   %eax, %r8d
    0x7f7e46a80a2f <+271>: negl   %r8d
    0x7f7e46a80a32 <+274>: cmpl   $0xfffff000, %eax ; imm = 0xFFFFF000
    0x7f7e46a80a37 <+279>: movl   $0x0, %eax
(lldb)
```

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


6 Files Affected:

- (modified) lldb/include/lldb/Target/Process.h (+14) 
- (modified) lldb/source/Commands/CommandObjectTarget.cpp (+4) 
- (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp (+8) 
- (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.h (+2) 
- (modified) lldb/source/Target/Process.cpp (+5-1) 
- (modified) lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py (+9) 


``````````diff
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index c4eb8cf3694b1..52a4e7dd57f1d 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1521,6 +1521,20 @@ class Process : public std::enable_shared_from_this<Process>,
   /// \return
   ///     File path to the core file.
   virtual FileSpec GetCoreFile() const { return {}; }
+  std::string GetCoreFileCommandString() {
+    if (!IsLiveDebugSession() && GetPluginName().contains("core")) {
+      ProcessInstanceInfo info;
+      if (GetProcessInfo(info)) {
+        const Args &args = info.GetArguments();
+        if (!args.empty()) {
+          std::string cmd;
+          args.GetCommandString(cmd);
+          return cmd;
+        }
+      }
+    }
+    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
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 59ccf390dea31..5f9a52c56fc1f 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -433,6 +433,10 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
             result.AppendMessageWithFormatv(
                 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
                 target_sp->GetArchitecture().GetArchitectureName());
+            std::string cmd = process_sp->GetCoreFileCommandString();
+            if (!cmd.empty())
+              result.AppendMessageWithFormatv("Core was generated by `{0}`.\n",
+                                              cmd);
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             on_error.release();
           }
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 3888b6d4f90ec..371292af38cde 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -25,6 +25,7 @@
 #include "lldb/Utility/State.h"
 
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Support/Debug.h"
 
 #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
@@ -987,6 +988,9 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
       thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));
       SetID(prpsinfo.pr_pid);
       m_executable_name = thread_data.name;
+      m_process_args_string.assign(
+          prpsinfo.pr_psargs,
+          strnlen(prpsinfo.pr_psargs, sizeof(prpsinfo.pr_psargs)));
       break;
     }
     case ELF::NT_SIGINFO: {
@@ -1169,5 +1173,9 @@ bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
                            add_exe_file_as_first_arg);
   }
+  if (!m_process_args_string.empty()) {
+    Args args(m_process_args_string);
+    info.SetArguments(args, true);
+  }
   return true;
 }
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 7eda33be8634c..aec13b8ee9ba4 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -155,6 +155,8 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
   // Executable name found from the ELF PRPSINFO
   std::string m_executable_name;
 
+  // Command line args string found from the ELF PRPSINFO (pr_psargs)
+  std::string m_process_args_string;
   // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
   llvm::Error ParseThreadContextsFromNoteSegment(
       const elf::ELFProgramHeader &segment_header,
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index b1a9a25171931..282d483828058 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5948,8 +5948,12 @@ void Process::GetStatus(Stream &strm) {
     } else {
       if (state == eStateConnected)
         strm.Printf("Connected to remote target.\n");
-      else
+      else {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
+        std::string cmd = GetCoreFileCommandString();
+        if (!cmd.empty())
+          strm.Printf("Core was generated by `%s`.\n", cmd.c_str());
+      }
     }
   } else {
     strm.Printf("Process %" PRIu64 " is running.\n", GetID());
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 743eae126457a..6ec2b9cf4716a 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -58,6 +58,15 @@ def test_x86_64(self):
         """Test that lldb can read the process information from an x86_64 linux core file."""
         self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions, "a.out")
 
+    @skipIfLLVMTargetMissing("X86")
+    def test_x86_64_core_generated(self):
+        """Test that lldb can read the argument used for the process from an x86_64 linux core file."""
+        result = lldb.SBCommandReturnObject()
+        self.dbg.GetCommandInterpreter().HandleCommand("target create linux-x86_64.out --core linux-x86_64.core", result)
+        out = result.GetOutput()
+        self.assertIn("Core was generated by `/test/test/test/test/test/test",
+                      out, "Command line arg from pr_psargs should be shown.")
+
     @skipIfLLVMTargetMissing("SystemZ")
     def test_s390x(self):
         """Test that lldb can read the process information from an s390x linux core file."""

``````````

</details>


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


More information about the lldb-commits mailing list