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

Jasmine Tang via lldb-commits lldb-commits at lists.llvm.org
Fri Apr 17 10:51:43 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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/14] 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.";
     }

>From ac33826ca35c155ef0afdaf2e06f4ca0c9fa34a8 Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Sat, 4 Apr 2026 22:39:45 -0700
Subject: [PATCH 11/14] Transition process status show core args with -v only

---
 lldb/include/lldb/Target/Process.h               |  2 +-
 lldb/source/Commands/CommandObjectProcess.cpp    |  2 +-
 lldb/source/Target/Process.cpp                   |  5 +++--
 .../postmortem/elf-core/TestLinuxCore.py         | 16 ++++++++++++++--
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index fce7e13431119..3f4d6db2dd23c 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1317,7 +1317,7 @@ class Process : public std::enable_shared_from_this<Process>,
                 const EvaluateExpressionOptions &options,
                 DiagnosticManager &diagnostic_manager);
 
-  void GetStatus(Stream &ostrm);
+  void GetStatus(Stream &ostrm, bool is_verbose = false);
 
   size_t GetThreadStatus(Stream &ostrm, bool only_threads_with_stop_reason,
                          uint32_t start_frame, uint32_t num_frames,
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index ca210e145d07e..26075301887d7 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -1459,7 +1459,7 @@ class CommandObjectProcessStatus : public CommandObjectParsed {
     const uint32_t num_frames = 1;
     const uint32_t num_frames_with_source = 1;
     const bool stop_format = true;
-    process->GetStatus(strm);
+    process->GetStatus(strm, m_options.m_verbose);
     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
                              num_frames, num_frames_with_source, stop_format);
 
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e16547346b8f3..fe23650a25c5c 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5936,7 +5936,7 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
   return return_value;
 }
 
-void Process::GetStatus(Stream &strm) {
+void Process::GetStatus(Stream &strm, bool is_verbose) {
   const StateType state = GetState();
   if (StateIsStoppedState(state, false)) {
     if (state == eStateExited) {
@@ -5950,7 +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));
-        if (auto core_args = GetCoreFileArgs())
+        auto core_args = GetCoreFileArgs();
+        if (core_args && is_verbose)
           core_args->FormatAsMessage(strm);
       } else
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 2a8d8dc8954f2..dd6661efe0a77 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -69,7 +69,13 @@ def test_x86_64_core_args_truncated(self):
         )
         self.expect(
             "process status",
-            msg="Truncated pr_psargs should show truncation warning when process status is invoked.",
+            msg="Core args should not be shown at all when process status (without -v) is invoked.",
+            matching=False,
+            substrs=[core_arg_msg],
+        )
+        self.expect(
+            "process status -v",
+            msg="Truncated pr_psargs should show truncation warning when process status -v is invoked.",
             substrs=[core_arg_msg],
         )
 
@@ -85,7 +91,13 @@ def test_x86_64_core_args_not_truncated(self):
         )
         self.expect(
             "process status",
-            msg="Short pr_psargs should show the core args without truncation warning when process status is invoked.",
+            msg="Core args should not be shown at all when process status (without -v) is invoked.",
+            matching=False,
+            substrs=[core_arg_msg],
+        )
+        self.expect(
+            "process status -v",
+            msg="Short pr_psargs should show the core args without truncation warning when process status -v is invoked.",
             substrs=[core_arg_msg],
         )
 

>From 368649efa3b1d294eacb64ce3f8f6f453f3763ad Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Wed, 15 Apr 2026 19:04:54 -0700
Subject: [PATCH 12/14] Address PR reviews

---
 lldb/include/lldb/Target/Process.h            | 42 ++++++++++---------
 lldb/source/Commands/CommandObjectTarget.cpp  |  2 +-
 .../Process/elf-core/ProcessElfCore.cpp       | 18 ++++----
 .../Plugins/Process/elf-core/ProcessElfCore.h |  4 +-
 lldb/source/Target/Process.cpp                |  2 +-
 .../postmortem/elf-core/TestLinuxCore.py      |  2 +-
 6 files changed, 37 insertions(+), 33 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 3f4d6db2dd23c..af70d5086b7dc 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -346,26 +346,6 @@ 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>,
@@ -1543,6 +1523,28 @@ class Process : public std::enable_shared_from_this<Process>,
   ///     File path to the core file.
   virtual FileSpec GetCoreFile() const { return {}; }
 
+  class CoreArgs {
+    std::string cmd;
+    bool might_be_truncated;
+
+  public:
+    CoreArgs() = default;
+    CoreArgs(const std::string &args, bool might_be_truncated)
+        : cmd(args), might_be_truncated(might_be_truncated) {}
+
+    void Format(Stream &stream) {
+      if (!cmd.empty()) {
+        stream << "Core was generated by '" << cmd << "'";
+        if (this->might_be_truncated)
+          stream << " (command might be truncated)";
+        stream << ".\n.";
+      }
+    }
+    bool empty() { return cmd.empty(); }
+
+    Args as_args() { return Args(cmd); }
+  };
+
   /// Provide arguments of a command that triggered a core dump.
   ///
   /// \return
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index da1db7c78e66e..c6f08a1b4d5e9 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -434,7 +434,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
                 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
                 target_sp->GetArchitecture().GetArchitectureName());
             if (auto core_args = process_sp->GetCoreFileArgs())
-              core_args->FormatAsMessage(result.GetOutputStream());
+              core_args->Format(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 f4e15e9cc5065..bda1c16f71aef 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -987,9 +987,13 @@ 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 = Args(llvm::StringRef(
-          prpsinfo.pr_psargs,
-          strnlen(prpsinfo.pr_psargs, sizeof(prpsinfo.pr_psargs))));
+      auto core_arg = llvm::StringRef(prpsinfo.pr_psargs,
+                                      strnlen(prpsinfo.pr_psargs,
+                                              sizeof(prpsinfo.pr_psargs)))
+                          .str();
+      // pr_psargs's char array used to represent arguments is only 80 character long
+      // (\0 included), hence 79.
+      m_process_args = CoreArgs(core_arg, core_arg.size() == 79);
       break;
     }
     case ELF::NT_SIGINFO: {
@@ -1161,12 +1165,10 @@ DataExtractor ProcessElfCore::GetAuxvData() {
           m_auxv.GetAddressByteSize() == GetAddressByteSize()));
   return DataExtractor(m_auxv);
 }
-std::optional<CoreArgs> ProcessElfCore::GetCoreFileArgs() {
+std::optional<Process::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);
+  return m_process_args;
 }
 
 bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
@@ -1180,6 +1182,6 @@ bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
                            add_exe_file_as_first_arg);
   }
   if (!m_process_args.empty())
-    info.SetArguments(m_process_args, true);
+    info.SetArguments(m_process_args.as_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 6db10b195e976..2b6b34075252f 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -97,7 +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;
+  std::optional<Process::CoreArgs> GetCoreFileArgs() override;
   bool GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override;
 
 protected:
@@ -158,7 +158,7 @@ class ProcessElfCore : public lldb_private::PostMortemProcess {
   std::string m_executable_name;
 
   // Command line args found from the ELF PRPSINFO (pr_psargs)
-  lldb_private::Args m_process_args;
+  Process::CoreArgs 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 fe23650a25c5c..da08071eec229 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5952,7 +5952,7 @@ void Process::GetStatus(Stream &strm, bool is_verbose) {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
         auto core_args = GetCoreFileArgs();
         if (core_args && is_verbose)
-          core_args->FormatAsMessage(strm);
+          core_args->Format(strm);
       } else
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
     }
diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index dd6661efe0a77..50eb432d12ae9 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -82,7 +82,7 @@ def test_x86_64_core_args_truncated(self):
     @skipIfLLVMTargetMissing("X86")
     def test_x86_64_core_args_not_truncated(self):
         """Test that a short pr_psargs does not show a truncation warning."""
-        core_arg_msg = "Core was generated by './a.out'."
+        core_arg_msg = "Core was generated by './a.out '."
         # This core file has pr_psargs='./a.out', which is short.
         self.expect(
             "target create --core linux-fpr_sse_x86_64.core",

>From 7b18df1aad8e4b7c55eabf448e35ba20caeb92aa Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Wed, 15 Apr 2026 19:11:10 -0700
Subject: [PATCH 13/14] Reformat codebase

---
 lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index bda1c16f71aef..6b029b6f13612 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -991,7 +991,8 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
                                       strnlen(prpsinfo.pr_psargs,
                                               sizeof(prpsinfo.pr_psargs)))
                           .str();
-      // pr_psargs's char array used to represent arguments is only 80 character long
+      // pr_psargs's char array used to represent arguments is only 80 character
+      // long
       // (\0 included), hence 79.
       m_process_args = CoreArgs(core_arg, core_arg.size() == 79);
       break;

>From 1342a01891eeb57638611385a4d91982f43f70ce Mon Sep 17 00:00:00 2001
From: Jasmine Tang <jjasmine at igalia.com>
Date: Fri, 17 Apr 2026 10:44:31 -0700
Subject: [PATCH 14/14] Fix PR with reviews

---
 lldb/include/lldb/Target/Process.h            | 27 ++++++++++---------
 .../Process/elf-core/ProcessElfCore.cpp       | 12 +++++----
 lldb/source/Target/Process.cpp                |  8 +++---
 .../postmortem/elf-core/TestLinuxCore.py      |  6 ++---
 llvm/docs/ReleaseNotes.md                     |  2 ++
 5 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index af70d5086b7dc..62c53f1d8fbd1 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1524,25 +1524,26 @@ class Process : public std::enable_shared_from_this<Process>,
   virtual FileSpec GetCoreFile() const { return {}; }
 
   class CoreArgs {
-    std::string cmd;
-    bool might_be_truncated;
+    std::string m_cmd;
+    bool m_might_be_truncated;
 
   public:
     CoreArgs() = default;
     CoreArgs(const std::string &args, bool might_be_truncated)
-        : cmd(args), might_be_truncated(might_be_truncated) {}
-
-    void Format(Stream &stream) {
-      if (!cmd.empty()) {
-        stream << "Core was generated by '" << cmd << "'";
-        if (this->might_be_truncated)
-          stream << " (command might be truncated)";
-        stream << ".\n.";
-      }
+        : m_cmd(args), m_might_be_truncated(might_be_truncated) {}
+
+    void Format(Stream &stream) const {
+      if (m_cmd.empty())
+        return;
+      stream << "Core was generated by '" << m_cmd << "'";
+      if (this->m_might_be_truncated)
+        stream << " (command might be truncated)";
+      stream << ".\n";
     }
-    bool empty() { return cmd.empty(); }
 
-    Args as_args() { return Args(cmd); }
+    bool empty() const { return m_cmd.empty(); }
+
+    Args as_args() const { return Args(m_cmd); }
   };
 
   /// Provide arguments of a command that triggered a core dump.
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 6b029b6f13612..cc40c6cffe2c7 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -992,9 +992,12 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
                                               sizeof(prpsinfo.pr_psargs)))
                           .str();
       // pr_psargs's char array used to represent arguments is only 80 character
-      // long
-      // (\0 included), hence 79.
-      m_process_args = CoreArgs(core_arg, core_arg.size() == 79);
+      // long (\0 included), for a total of 79.
+      // We set core_arg's m_might_be_truncated = true if its size
+      // is the maximum (79).
+      m_process_args =
+          CoreArgs(core_arg, /*might_be_truncated=*/core_arg.size() ==
+                                 sizeof(prpsinfo.pr_psargs) - 1);
       break;
     }
     case ELF::NT_SIGINFO: {
@@ -1182,7 +1185,6 @@ bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
                            add_exe_file_as_first_arg);
   }
-  if (!m_process_args.empty())
-    info.SetArguments(m_process_args.as_args(), true);
+  info.SetArguments(m_process_args.as_args(), /*first_arg_is_executable=*/true);
   return true;
 }
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index da08071eec229..94b09a64bb309 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5948,13 +5948,11 @@ void Process::GetStatus(Stream &strm, bool is_verbose) {
     } else {
       if (state == eStateConnected)
         strm.Printf("Connected to remote target.\n");
-      else if (!IsLiveDebugSession()) {
+      else {
         strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
-        auto core_args = GetCoreFileArgs();
-        if (core_args && is_verbose)
+        if (auto core_args = GetCoreFileArgs(); core_args && is_verbose)
           core_args->Format(strm);
-      } else
-        strm.Printf("Process %" PRIu64 " %s\n", GetID(), StateAsCString(state));
+      }
     }
   } 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 50eb432d12ae9..959339c2c6ca0 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -61,7 +61,7 @@ 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."""
-        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)."
+        core_arg_msg = "\nCore was generated by '/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/tes' (command might be truncated).\n"
         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.",
@@ -82,8 +82,8 @@ def test_x86_64_core_args_truncated(self):
     @skipIfLLVMTargetMissing("X86")
     def test_x86_64_core_args_not_truncated(self):
         """Test that a short pr_psargs does not show a truncation warning."""
-        core_arg_msg = "Core was generated by './a.out '."
-        # This core file has pr_psargs='./a.out', which is short.
+        core_arg_msg = "\nCore was generated by './a.out '.\n"
+        # 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.",
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 91b150c9fe982..81cd4165bb684 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -235,6 +235,8 @@ Changes to LLDB
 
 * On Arm Linux, the tpidruro register can now be read. Writing to this register is not supported.
 * Thread local variables are now supported on Arm Linux if the program being debugged is using glibc.
+* When an ELF core file is loaded, LLDB now shows the command line that created the core file.
+  If you need to see it again, use the command process status -v.
 
 Changes to BOLT
 ---------------



More information about the lldb-commits mailing list