[lldb] [llvm] [lldb][Process/FreeBSDKernelCore] Improve DoUpdateThreadList() (PR #183981)
Minsoo Choo via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 09:50:04 PST 2026
https://github.com/mchoo7 updated https://github.com/llvm/llvm-project/pull/183981
>From 5e6aa6996f885bc232b3a5b5e42a363f526ea6d4 Mon Sep 17 00:00:00 2001
From: Minsoo Choo <minsoochoo0122 at proton.me>
Date: Sun, 1 Mar 2026 00:06:31 -0500
Subject: [PATCH 1/2] [lldb][Process/FreeBSDKernelCore] Improve
DoUpdateThreadList()
Signed-off-by: Minsoo Choo <minsoochoo0122 at proton.me>
---
.../ProcessFreeBSDKernelCore.cpp | 55 ++++++++++++++++---
llvm/docs/ReleaseNotes.md | 1 +
2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index 577d8e0d50cf1..7369b5ffdcb66 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -167,7 +167,10 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
// LLDB but we can construct a process without threads to provide minimal
// memory reading support.
switch (GetTarget().GetArchitecture().GetMachine()) {
+ case llvm::Triple::arm:
case llvm::Triple::aarch64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
break;
@@ -217,6 +220,13 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error);
lldb::addr_t stoppcbs = FindSymbol("stoppcbs");
+ // Read stopped_cpus bitmask and mp_maxid for CPU validation
+ lldb::addr_t stopped_cpus = FindSymbol("stopped_cpus");
+ int32_t mp_maxid =
+ ReadSignedIntegerFromMemory(FindSymbol("mp_maxid"), 4, 0, error);
+ uint32_t long_size = GetAddressByteSize(); // approximation of sizeof(long)
+ uint32_t long_bits = long_size * 8;
+
// from FreeBSD sys/param.h
constexpr size_t fbsd_maxcomlen = 19;
@@ -225,11 +235,23 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
// the end of the list, so we have to walk it backwards. First collect all
// the processes in the list order.
std::vector<lldb::addr_t> process_addrs;
- for (lldb::addr_t proc =
- ReadPointerFromMemory(FindSymbol("allproc"), error);
- proc != 0 && proc != LLDB_INVALID_ADDRESS;
- proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
- process_addrs.push_back(proc);
+
+ lldb::addr_t zombproc_addr = FindSymbol("zombproc");
+ if (zombproc_addr != LLDB_INVALID_ADDRESS) {
+ for (lldb::addr_t proc = ReadPointerFromMemory(zombproc_addr, error);
+ proc != 0 && proc != LLDB_INVALID_ADDRESS;
+ proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
+ process_addrs.push_back(proc);
+ }
+ }
+
+ lldb::addr_t allproc_addr = FindSymbol("allproc");
+ if (allproc_addr != LLDB_INVALID_ADDRESS) {
+ for (lldb::addr_t proc = ReadPointerFromMemory(allproc_addr, error);
+ proc != 0 && proc != LLDB_INVALID_ADDRESS;
+ proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
+ process_addrs.push_back(proc);
+ }
}
// Processes are in the linked list in descending PID order, so we must walk
@@ -280,12 +302,27 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
pcb_addr = dumppcb;
thread_desc += " (crashed)";
} else if (oncpu != -1) {
- // If we managed to read stoppcbs and pcb_size, use them to find
- // the correct PCB.
- if (stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0)
+ // Verify the CPU is actually in the stopped set before using
+ // its stoppcbs entry.
+ bool is_stopped = false;
+ if (stopped_cpus != LLDB_INVALID_ADDRESS && oncpu >= 0 &&
+ oncpu <= mp_maxid) {
+ uint32_t bit = oncpu % long_bits;
+ uint32_t word = oncpu / long_bits;
+ lldb::addr_t mask_addr = stopped_cpus + word * long_size;
+ uint64_t mask =
+ ReadUnsignedIntegerFromMemory(mask_addr, long_size, 0, error);
+ if (error.Success())
+ is_stopped = (mask & (1ULL << bit)) != 0;
+ }
+
+ // If we managed to read stoppcbs and pcb_size and the cpu is marked
+ // as stopped, use them to find the correct PCB.
+ if (is_stopped && stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0) {
pcb_addr = stoppcbs + oncpu * pcbsize;
- else
+ } else {
pcb_addr = LLDB_INVALID_ADDRESS;
+ }
thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
}
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 2e0c5c5cb9370..4dd6bf57ee3a2 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -230,6 +230,7 @@ Changes to LLDB
`plugin.process.freebsd-kernel-core.read-only` must be set to `false`. This setting is available when
using `/dev/mem` or a kernel dump. However, since `kvm_write()` does not support writing to kernel dumps,
writes to a kernel dump will still fail when the setting is false.
+* Zombie processes are now shown in the thread list as well.
### Linux
>From d4a32202b34919a6b738732fbbdfa095b66c8d7a Mon Sep 17 00:00:00 2001
From: Minsoo Choo <minsoochoo0122 at proton.me>
Date: Mon, 2 Mar 2026 12:24:47 -0500
Subject: [PATCH 2/2] fixup! [lldb][Process/FreeBSDKernelCore] Improve
DoUpdateThreadList()
Signed-off-by: Minsoo Choo <minsoochoo0122 at proton.me>
---
.../ProcessFreeBSDKernelCore.cpp | 46 ++++++++-----------
llvm/docs/ReleaseNotes.md | 1 -
2 files changed, 20 insertions(+), 27 deletions(-)
diff --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index 7369b5ffdcb66..7711eae43284e 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -222,12 +222,17 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
// Read stopped_cpus bitmask and mp_maxid for CPU validation
lldb::addr_t stopped_cpus = FindSymbol("stopped_cpus");
- int32_t mp_maxid =
- ReadSignedIntegerFromMemory(FindSymbol("mp_maxid"), 4, 0, error);
- uint32_t long_size = GetAddressByteSize(); // approximation of sizeof(long)
- uint32_t long_bits = long_size * 8;
- // from FreeBSD sys/param.h
+ // from sys/kern/subr_smp.c
+ uint32_t mp_maxid =
+ ReadUnsignedIntegerFromMemory(FindSymbol("mp_maxid"), 4, 0, error);
+ TypeSystem &type_system =
+ *GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC);
+ uint32_t long_bytes =
+ *type_system.GetBasicTypeFromAST(eBasicTypeLong).GetByteSize(nullptr);
+ uint32_t long_bit = long_bytes * 8;
+
+ // from sys/param.h
constexpr size_t fbsd_maxcomlen = 19;
// Iterate through a linked list of all processes. New processes are added
@@ -235,23 +240,12 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
// the end of the list, so we have to walk it backwards. First collect all
// the processes in the list order.
std::vector<lldb::addr_t> process_addrs;
-
- lldb::addr_t zombproc_addr = FindSymbol("zombproc");
- if (zombproc_addr != LLDB_INVALID_ADDRESS) {
- for (lldb::addr_t proc = ReadPointerFromMemory(zombproc_addr, error);
- proc != 0 && proc != LLDB_INVALID_ADDRESS;
- proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
- process_addrs.push_back(proc);
- }
- }
-
- lldb::addr_t allproc_addr = FindSymbol("allproc");
- if (allproc_addr != LLDB_INVALID_ADDRESS) {
+ if (lldb::addr_t allproc_addr = FindSymbol("allproc");
+ allproc_addr != LLDB_INVALID_ADDRESS) {
for (lldb::addr_t proc = ReadPointerFromMemory(allproc_addr, error);
- proc != 0 && proc != LLDB_INVALID_ADDRESS;
- proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
+ proc != 0 && proc != LLDB_INVALID_ADDRESS && error.Success();
+ proc = ReadPointerFromMemory(proc + offset_p_list, error))
process_addrs.push_back(proc);
- }
}
// Processes are in the linked list in descending PID order, so we must walk
@@ -305,13 +299,13 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
// Verify the CPU is actually in the stopped set before using
// its stoppcbs entry.
bool is_stopped = false;
- if (stopped_cpus != LLDB_INVALID_ADDRESS && oncpu >= 0 &&
- oncpu <= mp_maxid) {
- uint32_t bit = oncpu % long_bits;
- uint32_t word = oncpu / long_bits;
- lldb::addr_t mask_addr = stopped_cpus + word * long_size;
+ if (oncpu >= 0 && static_cast<uint32_t>(oncpu) <= mp_maxid &&
+ stopped_cpus != LLDB_INVALID_ADDRESS) {
+ uint32_t bit = oncpu % long_bit;
+ uint32_t word = oncpu / long_bit;
+ lldb::addr_t mask_addr = stopped_cpus + word * long_bytes;
uint64_t mask =
- ReadUnsignedIntegerFromMemory(mask_addr, long_size, 0, error);
+ ReadUnsignedIntegerFromMemory(mask_addr, long_bytes, 0, error);
if (error.Success())
is_stopped = (mask & (1ULL << bit)) != 0;
}
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 4dd6bf57ee3a2..2e0c5c5cb9370 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -230,7 +230,6 @@ Changes to LLDB
`plugin.process.freebsd-kernel-core.read-only` must be set to `false`. This setting is available when
using `/dev/mem` or a kernel dump. However, since `kvm_write()` does not support writing to kernel dumps,
writes to a kernel dump will still fail when the setting is false.
-* Zombie processes are now shown in the thread list as well.
### Linux
More information about the llvm-commits
mailing list