[Lldb-commits] [lldb] [lldb][Process/FreeBSDKernelCore] Add command for refreshing thread list (PR #188692)
Minsoo Choo via lldb-commits
lldb-commits at lists.llvm.org
Sun Mar 29 07:02:13 PDT 2026
https://github.com/mchoo7 updated https://github.com/llvm/llvm-project/pull/188692
>From 50ffd88d7d3f7d461eb850ba5d6461bfbc440234 Mon Sep 17 00:00:00 2001
From: Minsoo Choo <minsoochoo0122 at proton.me>
Date: Wed, 25 Mar 2026 22:12:30 +0900
Subject: [PATCH 1/2] [lldb][Process/FreeBSDKernelCore] Add command for
refreshing thread list
Signed-off-by: Minsoo Choo <minsoochoo0122 at proton.me>
---
.../ProcessFreeBSDKernelCore.cpp | 64 +++++++++++++++++++
.../ProcessFreeBSDKernelCore.h | 6 ++
2 files changed, 70 insertions(+)
diff --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index da8e22caaa80f..57196564c4bef 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -9,6 +9,8 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Utility/LLDBLog.h"
@@ -60,6 +62,52 @@ static PluginProperties &GetGlobalPluginProperties() {
return g_settings;
}
+class CommandObjectProcessFreeBSDKernelCoreRefreshThreads
+ : public CommandObjectParsed {
+public:
+ CommandObjectProcessFreeBSDKernelCoreRefreshThreads(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "process plugin refresh-threads",
+ "Refresh the thread list from the FreeBSD kernel core dump. "
+ "This flushes the memory cache and re-reads the kernel's "
+ "allproc/zombie lists to rebuild the thread list from scratch.",
+ "process plugin refresh-threads") {}
+
+ ~CommandObjectProcessFreeBSDKernelCoreRefreshThreads() override = default;
+
+protected:
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ // TODO: Return early for elf-core based implementation.
+
+ auto *process = static_cast<ProcessFreeBSDKernelCore *>(
+ m_interpreter.GetExecutionContext().GetProcessPtr());
+ if (!process) {
+ result.AppendError("no process");
+ return;
+ }
+
+ // Clear the memory cache so DoUpdateThreadList() will re-read
+ // allproc, zombproc, and all thread/proc structures fresh from
+ // the core dump instead of getting stale cached values.
+ process->m_memory_cache.Clear();
+
+ // Explicitly clear the thread list after Flush() to guarantee that
+ // UpdateThreadListIfNeeded() sees size == 0 and enters the rebuild
+ // path regardless of stop-ID state.
+ process->GetThreadList().Clear();
+
+ // Rebuild the process thread list.
+ process->UpdateThreadListIfNeeded();
+
+ const uint32_t num_threads = process->GetThreadList().GetSize(false);
+ result.AppendMessageWithFormat(
+ "Thread list refreshed, %u thread%s found.\n", num_threads,
+ num_threads == 1 ? "" : "s");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+};
+
ProcessFreeBSDKernelCore::ProcessFreeBSDKernelCore(lldb::TargetSP target_sp,
ListenerSP listener_sp,
kvm_t *kvm,
@@ -112,6 +160,22 @@ bool ProcessFreeBSDKernelCore::CanDebug(lldb::TargetSP target_sp,
return true;
}
+CommandObject *ProcessFreeBSDKernelCore::GetPluginCommandObject() {
+ if (!m_command_sp) {
+ CommandInterpreter &interp =
+ GetTarget().GetDebugger().GetCommandInterpreter();
+ m_command_sp = std::make_unique<CommandObjectMultiword>(
+ interp, "process plugin",
+ "Commands for the FreeBSD kernel process plug-in.",
+ "process plugin <subcommand> [<subcommand-options>]");
+ m_command_sp->LoadSubCommand(
+ "refresh-threads",
+ CommandObjectSP(
+ new CommandObjectProcessFreeBSDKernelCoreRefreshThreads(interp)));
+ }
+ return m_command_sp.get();
+}
+
Status ProcessFreeBSDKernelCore::DoLoadCore() {
// The core is already loaded by CreateInstance().
SetKernelDisplacement();
diff --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.h b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.h
index d82e55ea74bd9..ac30d9e194305 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.h
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.h
@@ -43,6 +43,8 @@ class ProcessFreeBSDKernelCore : public lldb_private::PostMortemProcess {
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
+ lldb_private::CommandObject *GetPluginCommandObject() override;
+
lldb_private::Status DoLoadCore() override;
lldb_private::DynamicLoader *GetDynamicLoader() override;
@@ -55,6 +57,8 @@ class ProcessFreeBSDKernelCore : public lldb_private::PostMortemProcess {
lldb_private::Status &error) override;
protected:
+ friend class CommandObjectProcessFreeBSDKernelCoreRefreshThreads;
+
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;
@@ -70,6 +74,8 @@ class ProcessFreeBSDKernelCore : public lldb_private::PostMortemProcess {
const char *GetError();
+ std::unique_ptr<lldb_private::CommandObjectMultiword> m_command_sp;
+
bool m_printed_unread_message = false;
kvm_t *m_kvm;
>From c4e23c531cbe00b5895e61e83f131c2fff5fff3e Mon Sep 17 00:00:00 2001
From: Minsoo Choo <minsoochoo0122 at proton.me>
Date: Sun, 29 Mar 2026 22:39:04 +0900
Subject: [PATCH 2/2] fixup! [lldb][Process/FreeBSDKernelCore] Add command for
refreshing thread list
Signed-off-by: Minsoo Choo <minsoochoo0122 at proton.me>
---
.../ProcessFreeBSDKernelCore.cpp | 49 ++++++++++---------
1 file changed, 26 insertions(+), 23 deletions(-)
diff --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index 57196564c4bef..c633ef02844b9 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -69,10 +69,14 @@ class CommandObjectProcessFreeBSDKernelCoreRefreshThreads
CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "process plugin refresh-threads",
- "Refresh the thread list from the FreeBSD kernel core dump. "
- "This flushes the memory cache and re-reads the kernel's "
- "allproc/zombie lists to rebuild the thread list from scratch.",
- "process plugin refresh-threads") {}
+ "Refresh the thread list from the FreeBSD kernel core. The thread "
+ "list and related data structures may be being read from live "
+ "memory (/dev/mem), which may have changed since the last refresh. "
+ "This command clears LLDB's thread list and memory cache then "
+ "re-reads the kernel's allproc/zombie lists to rebuild the thread "
+ "list from scratch.",
+ "process plugin refresh-threads",
+ eCommandRequiresProcess | eCommandTryTargetAPILock) {}
~CommandObjectProcessFreeBSDKernelCoreRefreshThreads() override = default;
@@ -80,29 +84,28 @@ class CommandObjectProcessFreeBSDKernelCoreRefreshThreads
void DoExecute(Args &command, CommandReturnObject &result) override {
// TODO: Return early for elf-core based implementation.
- auto *process = static_cast<ProcessFreeBSDKernelCore *>(
+ auto process = static_cast<ProcessFreeBSDKernelCore *>(
m_interpreter.GetExecutionContext().GetProcessPtr());
- if (!process) {
- result.AppendError("no process");
- return;
- }
- // Clear the memory cache so DoUpdateThreadList() will re-read
- // allproc, zombproc, and all thread/proc structures fresh from
- // the core dump instead of getting stale cached values.
+ // Clear the memory cache so DoUpdateThreadList() will re-read allproc,
+ // zombproc, and all thread/proc structures fresh from the core dump instead
+ // of getting stale cached values.
process->m_memory_cache.Clear();
- // Explicitly clear the thread list after Flush() to guarantee that
- // UpdateThreadListIfNeeded() sees size == 0 and enters the rebuild
- // path regardless of stop-ID state.
- process->GetThreadList().Clear();
-
- // Rebuild the process thread list.
- process->UpdateThreadListIfNeeded();
-
- const uint32_t num_threads = process->GetThreadList().GetSize(false);
- result.AppendMessageWithFormat(
- "Thread list refreshed, %u thread%s found.\n", num_threads,
+ // Clear both thread lists to guarantee that UpdateThreadListIfNeeded() sees
+ // size == 0 and enters the rebuild path regardless of stop-ID state.
+ // UpdateThreadListIfNeeded() passes m_thread_list_real as old_thread_list
+ // to DoUpdateThreadList(), and DoUpdateThreadList() only rebuilds from
+ // scratch when old_thread_list is empty. m_thread_list is the public copy
+ // that is sync'd from m_thread_list_real afterwards.
+ process->m_thread_list_real.Clear();
+ process->m_thread_list.Clear();
+
+ // This calls UpdateThreadListIfNeeded() to rebuild the process thread list.
+ const uint32_t num_threads =
+ process->GetThreadList().GetSize(/*can_update=*/true);
+ result.AppendMessageWithFormatv(
+ "Thread list refreshed, {0} thread{1} found.", num_threads,
num_threads == 1 ? "" : "s");
result.SetStatus(eReturnStatusSuccessFinishResult);
}
More information about the lldb-commits
mailing list