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

Jasmine Tang via lldb-commits lldb-commits at lists.llvm.org
Tue Mar 31 23:52:14 PDT 2026


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

>From bef702f9c9a9f487c3cb9e86f874befbaff85b34 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Sun, 8 Mar 2026 19:07:56 -0700
Subject: [PATCH 01/10] Precommit for core arg

---
 .../functionalities/postmortem/elf-core/TestLinuxCore.py  | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 743eae126457a..d75675b92864a 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -58,6 +58,14 @@ 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.assertNotIn("Core was generated by", out, "Command line arg from pr_psargs should not be shown yet")
+
     @skipIfLLVMTargetMissing("SystemZ")
     def test_s390x(self):
         """Test that lldb can read the process information from an s390x linux core file."""

>From f69d577cc2649ba0ebde5741494831ee4dde2e74 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Sun, 8 Mar 2026 19:09:23 -0700
Subject: [PATCH 02/10] Implemented lldb core arg for linux

---
 lldb/include/lldb/Target/Process.h                 | 14 ++++++++++++++
 lldb/source/Commands/CommandObjectTarget.cpp       |  4 ++++
 .../Plugins/Process/elf-core/ProcessElfCore.cpp    |  7 +++++++
 .../Plugins/Process/elf-core/ProcessElfCore.h      |  2 ++
 lldb/source/Target/Process.cpp                     |  6 +++++-
 .../postmortem/elf-core/TestLinuxCore.py           | 10 ++++++++--
 6 files changed, 40 insertions(+), 3 deletions(-)

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..056398c02f0ed 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -987,6 +987,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 +1172,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 d75675b92864a..d39e19d867915 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -62,9 +62,15 @@ def test_x86_64(self):
     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)
+        self.dbg.GetCommandInterpreter().HandleCommand(
+            "target create linux-x86_64.out --core linux-x86_64.core", result
+        )
         out = result.GetOutput()
-        self.assertNotIn("Core was generated by", out, "Command line arg from pr_psargs should not be shown yet")
+        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):

>From 92737f32c269ef414fd01f7c2bb501a8fbfd4540 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Mon, 9 Mar 2026 17:13:17 -0700
Subject: [PATCH 03/10] Address PR Reviews

---
 lldb/include/lldb/Target/Process.h           | 26 +++++++++++---------
 lldb/source/Commands/CommandObjectTarget.cpp |  4 ++-
 lldb/source/Target/Process.cpp               |  8 +++---
 3 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 52a4e7dd57f1d..ad80947031543 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -47,6 +47,7 @@
 #include "lldb/Target/Trace.h"
 #include "lldb/Utility/AddressableBits.h"
 #include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Args.h"
 #include "lldb/Utility/Broadcaster.h"
 #include "lldb/Utility/Event.h"
 #include "lldb/Utility/Listener.h"
@@ -1521,18 +1522,19 @@ 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;
-        }
-      }
-    }
+
+  /// Provide arguments of a command that triggers a core dump
+  /// Only available when we have a core file
+  ///
+  /// \return
+  ///     Args of a core dump
+  Args GetCoreFileCommandString() {
+    if (!GetCoreFile())
+      return {};
+
+    ProcessInstanceInfo info;
+    if (GetProcessInfo(info))
+      return info.GetArguments();
     return {};
   }
 
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 5f9a52c56fc1f..b4559ac02be5f 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -433,7 +433,9 @@ 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();
+            Args args = process_sp->GetCoreFileCommandString();
+            std::string cmd;
+            args.GetCommandString(cmd);
             if (!cmd.empty())
               result.AppendMessageWithFormatv("Core was generated by `{0}`.\n",
                                               cmd);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 282d483828058..478434f169741 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5946,11 +5946,13 @@ void Process::GetStatus(Stream &strm) {
                   GetID(), exit_status, exit_status,
                   exit_description ? exit_description : "");
     } else {
-      if (state == eStateConnected)
+      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();
+        Args args = GetCoreFileCommandString();
+        std::string cmd;
+        args.GetCommandString(cmd);
         if (!cmd.empty())
           strm.Printf("Core was generated by `%s`.\n", cmd.c_str());
       }

>From 181c6a0f55032dc25dd89a81116799386557ef6b Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Fri, 13 Mar 2026 14:41:42 -0700
Subject: [PATCH 04/10] Addresses PR reviews #2

---
 lldb/include/lldb/Target/Process.h            |  8 ++--
 lldb/source/Commands/CommandObjectTarget.cpp  |  9 ++--
 .../Process/elf-core/ProcessElfCore.cpp       |  9 ++--
 .../Plugins/Process/elf-core/ProcessElfCore.h |  5 ++-
 lldb/source/Target/Process.cpp                |  9 ++--
 .../postmortem/elf-core/TestLinuxCore.py      | 41 +++++++++++++++++--
 6 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index ad80947031543..068398b2d10b9 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1523,12 +1523,12 @@ class Process : public std::enable_shared_from_this<Process>,
   ///     File path to the core file.
   virtual FileSpec GetCoreFile() const { return {}; }
 
-  /// Provide arguments of a command that triggers a core dump
-  /// Only available when we have a core file
+  /// Provide arguments of a command that triggered a core dump.
   ///
   /// \return
-  ///     Args of a core dump
-  Args GetCoreFileCommandString() {
+  ///   The arguments that created the core dump. 
+  ///   If this process is a live debug session, returns an empty list of arguments.
+  Args GetCoreFileArgs() {
     if (!GetCoreFile())
       return {};
 
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index b4559ac02be5f..2fe68a4cc4ae8 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -433,11 +433,14 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
             result.AppendMessageWithFormatv(
                 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
                 target_sp->GetArchitecture().GetArchitectureName());
-            Args args = process_sp->GetCoreFileCommandString();
             std::string cmd;
-            args.GetCommandString(cmd);
+            process_sp->GetCoreFileArgs().GetCommandString(cmd);
+            std::string msg = "Core was generated by '{0}'";
+            if (cmd.size() == 79)
+              msg += " (command might be truncated).";
+            msg += ".";
             if (!cmd.empty())
-              result.AppendMessageWithFormatv("Core was generated by `{0}`.\n",
+              result.AppendMessageWithFormatv(msg.c_str(),
                                               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 056398c02f0ed..4a60996ae03df 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -987,9 +987,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(
+      m_process_args = Args(llvm::StringRef(
           prpsinfo.pr_psargs,
-          strnlen(prpsinfo.pr_psargs, sizeof(prpsinfo.pr_psargs)));
+          strnlen(prpsinfo.pr_psargs, sizeof(prpsinfo.pr_psargs))));
       break;
     }
     case ELF::NT_SIGINFO: {
@@ -1172,9 +1172,8 @@ 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);
+  if (!m_process_args.empty()) {
+    info.SetArguments(m_process_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 aec13b8ee9ba4..3e1595c484da5 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "lldb/Target/PostMortemProcess.h"
+#include "lldb/Utility/Args.h"
 #include "lldb/Utility/Status.h"
 
 #include "Plugins/ObjectFile/ELF/ELFHeader.h"
@@ -155,8 +156,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;
+  // Command line args found from the ELF PRPSINFO (pr_psargs)
+  lldb_private::Args m_process_args;
   // 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 478434f169741..9110735ae7644 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5950,11 +5950,14 @@ void Process::GetStatus(Stream &strm) {
         strm.Printf("Connected to remote target.\n");
       } else {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
-        Args args = GetCoreFileCommandString();
         std::string cmd;
-        args.GetCommandString(cmd);
+        GetCoreFileArgs().GetCommandString(cmd);
+        std::string msg = "Core was generated by '%s'";
+        if (cmd.size() == 79)
+          msg += " (command might be truncated)";
+        msg += ".\n";
         if (!cmd.empty())
-          strm.Printf("Core was generated by `%s`.\n", cmd.c_str());
+          strm.Printf(msg.c_str(), cmd.c_str());
       }
     }
   } else {
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index d39e19d867915..1f89b3a8cb28b 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -59,17 +59,50 @@ def test_x86_64(self):
         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."""
+    def test_x86_64_core_args_truncated(self):
+        """Test that a truncated pr_psargs shows a truncation warning."""
         result = lldb.SBCommandReturnObject()
         self.dbg.GetCommandInterpreter().HandleCommand(
             "target create linux-x86_64.out --core linux-x86_64.core", result
         )
         out = result.GetOutput()
+        core_arg_msg = "Core was generated by '/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/tes' (command might be truncated)."
         self.assertIn(
-            "Core was generated by `/test/test/test/test/test/test",
+            core_arg_msg,
             out,
-            "Command line arg from pr_psargs should be shown.",
+            "Truncated pr_psargs should show truncation warning when core file is loaded.",
+        )
+        self.dbg.GetCommandInterpreter().HandleCommand("process status", result)
+        out = result.GetOutput()
+        self.assertIn(
+            core_arg_msg,
+            out,
+            "Truncated pr_psargs should show truncation warning when process status is invoked.",
+        )
+
+    @skipIfLLVMTargetMissing("X86")
+    def test_x86_64_core_args_not_truncated(self):
+        """Test that a short pr_psargs does not show a truncation warning."""
+        result = lldb.SBCommandReturnObject()
+        self.dbg.GetCommandInterpreter().HandleCommand(
+            # this core file has pr_psargs='./a.out', which is short
+            # and should not trigger the truncation warning.
+            "target create --core linux-fpr_sse_x86_64.core",
+            result,
+        )
+        out = result.GetOutput()
+        core_arg_msg = "Core was generated by './a.out'."
+        self.assertIn(
+            core_arg_msg,
+            out,
+            "Short pr_psargs should show the core args without truncation warning when core file is loaded.",
+        )
+        self.dbg.GetCommandInterpreter().HandleCommand("process status", result)
+        out = result.GetOutput()
+        self.assertIn(
+            core_arg_msg,
+            out,
+            "Short pr_psargs should show the core args without truncation warning when process status is invoked.",
         )
 
     @skipIfLLVMTargetMissing("SystemZ")

>From 6c4e534db84d265ef2aed2ba19823a5221aa85d5 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Fri, 13 Mar 2026 15:11:40 -0700
Subject: [PATCH 05/10] Reformat

---
 lldb/include/lldb/Target/Process.h           | 5 +++--
 lldb/source/Commands/CommandObjectTarget.cpp | 3 +--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 068398b2d10b9..c1bb6599a5c05 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1526,8 +1526,9 @@ class Process : public std::enable_shared_from_this<Process>,
   /// Provide arguments of a command that triggered a core dump.
   ///
   /// \return
-  ///   The arguments that created the core dump. 
-  ///   If this process is a live debug session, returns an empty list of arguments.
+  ///   The arguments that created the core dump.
+  ///   If this process is a live debug session, returns an empty list of
+  ///   arguments.
   Args GetCoreFileArgs() {
     if (!GetCoreFile())
       return {};
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 2fe68a4cc4ae8..5e036525020af 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -440,8 +440,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
               msg += " (command might be truncated).";
             msg += ".";
             if (!cmd.empty())
-              result.AppendMessageWithFormatv(msg.c_str(),
-                                              cmd);
+              result.AppendMessageWithFormatv(msg.c_str(), cmd);
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             on_error.release();
           }

>From df29bc19595fa5906403c86cd213d4422d1e9fc6 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 31 Mar 2026 22:28:37 -0700
Subject: [PATCH 06/10] Change to self.expect for testing core args

---
 .../postmortem/elf-core/TestLinuxCore.py      | 50 +++++++------------
 1 file changed, 17 insertions(+), 33 deletions(-)

diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 1f89b3a8cb28b..2a8d8dc8954f2 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -61,48 +61,32 @@ def test_x86_64(self):
     @skipIfLLVMTargetMissing("X86")
     def test_x86_64_core_args_truncated(self):
         """Test that a truncated pr_psargs shows a truncation warning."""
-        result = lldb.SBCommandReturnObject()
-        self.dbg.GetCommandInterpreter().HandleCommand(
-            "target create linux-x86_64.out --core linux-x86_64.core", result
-        )
-        out = result.GetOutput()
         core_arg_msg = "Core was generated by '/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/tes' (command might be truncated)."
-        self.assertIn(
-            core_arg_msg,
-            out,
-            "Truncated pr_psargs should show truncation warning when core file is loaded.",
+        self.expect(
+            "target create linux-x86_64.out --core linux-x86_64.core",
+            msg="Truncated pr_psargs should show truncation warning when core file is loaded.",
+            substrs=[core_arg_msg],
         )
-        self.dbg.GetCommandInterpreter().HandleCommand("process status", result)
-        out = result.GetOutput()
-        self.assertIn(
-            core_arg_msg,
-            out,
-            "Truncated pr_psargs should show truncation warning when process status is invoked.",
+        self.expect(
+            "process status",
+            msg="Truncated pr_psargs should show truncation warning when process status is invoked.",
+            substrs=[core_arg_msg],
         )
 
     @skipIfLLVMTargetMissing("X86")
     def test_x86_64_core_args_not_truncated(self):
         """Test that a short pr_psargs does not show a truncation warning."""
-        result = lldb.SBCommandReturnObject()
-        self.dbg.GetCommandInterpreter().HandleCommand(
-            # this core file has pr_psargs='./a.out', which is short
-            # and should not trigger the truncation warning.
-            "target create --core linux-fpr_sse_x86_64.core",
-            result,
-        )
-        out = result.GetOutput()
         core_arg_msg = "Core was generated by './a.out'."
-        self.assertIn(
-            core_arg_msg,
-            out,
-            "Short pr_psargs should show the core args without truncation warning when core file is loaded.",
+        # This core file has pr_psargs='./a.out', which is short.
+        self.expect(
+            "target create --core linux-fpr_sse_x86_64.core",
+            msg="Short pr_psargs should show the core args without truncation warning when core file is loaded.",
+            substrs=[core_arg_msg],
         )
-        self.dbg.GetCommandInterpreter().HandleCommand("process status", result)
-        out = result.GetOutput()
-        self.assertIn(
-            core_arg_msg,
-            out,
-            "Short pr_psargs should show the core args without truncation warning when process status is invoked.",
+        self.expect(
+            "process status",
+            msg="Short pr_psargs should show the core args without truncation warning when process status is invoked.",
+            substrs=[core_arg_msg],
         )
 
     @skipIfLLVMTargetMissing("SystemZ")

>From e3779472cf464ddac39bda7045676c6b5a2ff85e Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 31 Mar 2026 22:32:59 -0700
Subject: [PATCH 07/10] Fix nit around brace of conditionals and
 eStateConnected

---
 lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp | 3 +--
 lldb/source/Target/Process.cpp                          | 7 ++++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 4a60996ae03df..8130079f83d22 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -1172,8 +1172,7 @@ bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
                            add_exe_file_as_first_arg);
   }
-  if (!m_process_args.empty()) {
+  if (!m_process_args.empty())
     info.SetArguments(m_process_args, true);
-  }
   return true;
 }
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 9110735ae7644..d2881a8a8725e 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5946,9 +5946,9 @@ void Process::GetStatus(Stream &strm) {
                   GetID(), exit_status, exit_status,
                   exit_description ? exit_description : "");
     } else {
-      if (state == eStateConnected) {
+      if (state == eStateConnected)
         strm.Printf("Connected to remote target.\n");
-      } else {
+      else if (!IsLiveDebugSession()) {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
         std::string cmd;
         GetCoreFileArgs().GetCommandString(cmd);
@@ -5958,7 +5958,8 @@ void Process::GetStatus(Stream &strm) {
         msg += ".\n";
         if (!cmd.empty())
           strm.Printf(msg.c_str(), cmd.c_str());
-      }
+      } else
+        strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
     }
   } else {
     strm.Printf("Process %" PRIu64 " is running.\n", GetID());

>From 7839775dca236a0607979a82ee3f188d5faf25c1 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 31 Mar 2026 22:42:51 -0700
Subject: [PATCH 08/10] Transition to better control flow for core arg
 truncated warning

---
 lldb/source/Commands/CommandObjectTarget.cpp | 11 ++++++-----
 lldb/source/Target/Process.cpp               | 11 ++++++-----
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 5e036525020af..1073137d9a578 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -435,12 +435,13 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
                 target_sp->GetArchitecture().GetArchitectureName());
             std::string cmd;
             process_sp->GetCoreFileArgs().GetCommandString(cmd);
-            std::string msg = "Core was generated by '{0}'";
-            if (cmd.size() == 79)
-              msg += " (command might be truncated).";
-            msg += ".";
-            if (!cmd.empty())
+            if (!cmd.empty()) {
+              std::string msg = "Core was generated by '{0}'";
+              if (cmd.size() == 79)
+                msg += " (command might be truncated).";
+              msg += ".";
               result.AppendMessageWithFormatv(msg.c_str(), cmd);
+            }
             result.SetStatus(eReturnStatusSuccessFinishNoResult);
             on_error.release();
           }
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index d2881a8a8725e..53a31a039fa2e 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5952,12 +5952,13 @@ void Process::GetStatus(Stream &strm) {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
         std::string cmd;
         GetCoreFileArgs().GetCommandString(cmd);
-        std::string msg = "Core was generated by '%s'";
-        if (cmd.size() == 79)
-          msg += " (command might be truncated)";
-        msg += ".\n";
-        if (!cmd.empty())
+        if (!cmd.empty()) {
+          std::string msg = "Core was generated by '%s'";
+          if (cmd.size() == 79)
+            msg += " (command might be truncated)";
+          msg += ".\n";
           strm.Printf(msg.c_str(), cmd.c_str());
+        }
       } else
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
     }

>From 945d28b1b35a7b3ca88ae9003e4fc784b885675a Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 31 Mar 2026 23:18:48 -0700
Subject: [PATCH 09/10] Transition to dedicated CoreArgs class

---
 lldb/include/lldb/Target/Process.h            | 33 ++++++++++++-------
 lldb/source/Commands/CommandObjectTarget.cpp  | 11 ++-----
 .../Process/elf-core/ProcessElfCore.cpp       |  7 ++++
 .../Plugins/Process/elf-core/ProcessElfCore.h |  1 +
 lldb/source/Target/Process.cpp                | 11 ++-----
 5 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index c1bb6599a5c05..5f964ed17d607 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -346,6 +346,26 @@ inline bool operator!=(const ProcessModID &lhs, const ProcessModID &rhs) {
   return (!lhs.StopIDEqual(rhs) || !lhs.MemoryIDEqual(rhs));
 }
 
+class CoreArgs {
+  const Args &args;
+  bool might_truncate;
+
+public:
+  CoreArgs(const Args &args, bool might_truncate)
+      : args(args), might_truncate(might_truncate) {}
+
+  void FormatAsMessage(Stream &stream) {
+    std::string cmd;
+    args.GetCommandString(cmd);
+    if (!cmd.empty()) {
+      stream << "Core was generated by '" << cmd << "'";
+      if (!this->might_truncate)
+        stream << " (command might be truncated)";
+      stream << ".\n.";
+    }
+  }
+};
+
 /// \class Process Process.h "lldb/Target/Process.h"
 /// A plug-in interface definition class for debugging a process.
 class Process : public std::enable_shared_from_this<Process>,
@@ -1527,17 +1547,8 @@ class Process : public std::enable_shared_from_this<Process>,
   ///
   /// \return
   ///   The arguments that created the core dump.
-  ///   If this process is a live debug session, returns an empty list of
-  ///   arguments.
-  Args GetCoreFileArgs() {
-    if (!GetCoreFile())
-      return {};
-
-    ProcessInstanceInfo info;
-    if (GetProcessInfo(info))
-      return info.GetArguments();
-    return {};
-  }
+  ///   If this process is a live debug session, returns a std::nullopt.
+  virtual std::optional<CoreArgs> GetCoreFileArgs() { return std::nullopt; }
 
   /// 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 1073137d9a578..da1db7c78e66e 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -433,15 +433,8 @@ 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->GetCoreFileArgs().GetCommandString(cmd);
-            if (!cmd.empty()) {
-              std::string msg = "Core was generated by '{0}'";
-              if (cmd.size() == 79)
-                msg += " (command might be truncated).";
-              msg += ".";
-              result.AppendMessageWithFormatv(msg.c_str(), cmd);
-            }
+            if (auto core_args = process_sp->GetCoreFileArgs())
+              core_args->FormatAsMessage(result.GetOutputStream());
             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 8130079f83d22..f4e15e9cc5065 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -1161,6 +1161,13 @@ DataExtractor ProcessElfCore::GetAuxvData() {
           m_auxv.GetAddressByteSize() == GetAddressByteSize()));
   return DataExtractor(m_auxv);
 }
+std::optional<CoreArgs> ProcessElfCore::GetCoreFileArgs() {
+  if (m_process_args.empty())
+    return std::nullopt;
+  std::string cmd;
+  m_process_args.GetCommandString(cmd);
+  return CoreArgs(m_process_args, cmd.size() == 79);
+}
 
 bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
   info.Clear();
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
index 3e1595c484da5..6db10b195e976 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -97,6 +97,7 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
   // Returns AUXV structure found in the core file
   lldb_private::DataExtractor GetAuxvData() override;
 
+  std::optional<lldb_private::CoreArgs> GetCoreFileArgs() override;
   bool GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override;
 
 protected:
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 53a31a039fa2e..e16547346b8f3 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5950,15 +5950,8 @@ void Process::GetStatus(Stream &strm) {
         strm.Printf("Connected to remote target.\n");
       else if (!IsLiveDebugSession()) {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
-        std::string cmd;
-        GetCoreFileArgs().GetCommandString(cmd);
-        if (!cmd.empty()) {
-          std::string msg = "Core was generated by '%s'";
-          if (cmd.size() == 79)
-            msg += " (command might be truncated)";
-          msg += ".\n";
-          strm.Printf(msg.c_str(), cmd.c_str());
-        }
+        if (auto core_args = GetCoreFileArgs())
+          core_args->FormatAsMessage(strm);
       } else
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
     }

>From 92741337f9ed83d2cf19dce745c9a71d3e5c5180 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Tue, 31 Mar 2026 23:51:55 -0700
Subject: [PATCH 10/10] Fix might_truncate bug in FormatAsMessage

---
 lldb/include/lldb/Target/Process.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 5f964ed17d607..fce7e13431119 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -359,7 +359,7 @@ class CoreArgs {
     args.GetCommandString(cmd);
     if (!cmd.empty()) {
       stream << "Core was generated by '" << cmd << "'";
-      if (!this->might_truncate)
+      if (this->might_truncate)
         stream << " (command might be truncated)";
       stream << ".\n.";
     }



More information about the lldb-commits mailing list