[Lldb-commits] [lldb] 6dd5212 - [lldb][Process/FreeBSDKernelCore] Improve DoUpdateThreadList() (#183981)

via lldb-commits lldb-commits at lists.llvm.org
Tue Mar 10 09:12:14 PDT 2026


Author: Minsoo Choo
Date: 2026-03-10T12:12:09-04:00
New Revision: 6dd52127a09564d0c3be12e2b26c83ceb43919c8

URL: https://github.com/llvm/llvm-project/commit/6dd52127a09564d0c3be12e2b26c83ceb43919c8
DIFF: https://github.com/llvm/llvm-project/commit/6dd52127a09564d0c3be12e2b26c83ceb43919c8.diff

LOG: [lldb][Process/FreeBSDKernelCore] Improve DoUpdateThreadList() (#183981)

This commit brings improves
`ProcessFreeBSDKernelCore::DoUpdateThreadList()` by porting features
from KGDB (`fbsd_kthr.c` specifically) and adding fixes. It includes:

1. Validate `stopped_cpus` before accessing `stoppcbs`
2. Check bounds for `mp_maxid`
3. Check errors when reading proc from memory
4. Detect new architectures from previous PRs (ppc64le, riscv64, arm)
which weren't handled correctly in `DoUpdateThreadList()`.

Fallbacks for finding offsets aren't ported since kernel exposes
hardcoded variables for offsets starting from FreeBSD 11. Fallbacks
aren't needed as LLDB 23 only supports FreeBSD 14 and later.

This commit also 

Fixes: 2430410b7d879fce3db76c21bb8c60ed22abd0b5(#180669),
4a602c03ea050d7adf666d5a440164ca6f78707c(#180670),
3d251288df0642762d1bd86efa05e190005c2539(#180674)

---------

Signed-off-by: Minsoo Choo <minsoochoo0122 at proton.me>

Added: 
    

Modified: 
    lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
index 5b40df5d97399..ae566624f9ee2 100644
--- a/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp
@@ -163,7 +163,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;
@@ -213,7 +216,33 @@ bool ProcessFreeBSDKernelCore::DoUpdateThreadList(ThreadList &old_thread_list,
         ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error);
     lldb::addr_t stoppcbs = FindSymbol("stoppcbs");
 
-    // from FreeBSD sys/param.h
+    // Read stopped_cpus bitmask and mp_maxid for CPU validation.
+    lldb::addr_t stopped_cpus = FindSymbol("stopped_cpus");
+    uint32_t mp_maxid = 0;
+
+    if (stopped_cpus != LLDB_INVALID_ADDRESS) {
+      // https://cgit.freebsd.org/src/tree/sys/kern/subr_smp.c
+      mp_maxid =
+          ReadSignedIntegerFromMemory(FindSymbol("mp_maxid"), 4, 0, error);
+      if (error.Fail())
+        stopped_cpus = LLDB_INVALID_ADDRESS;
+    }
+
+    uint32_t long_size_bytes = GetAddressByteSize();
+    uint32_t long_bit = long_size_bytes * 8;
+
+    if (auto type_system_or_err =
+            GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC)) {
+      CompilerType long_type =
+          (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeLong);
+      if (long_type.IsValid())
+        if (auto size = long_type.GetByteSize(nullptr))
+          long_size_bytes = *size;
+      long_bit = long_size_bytes * 8;
+    } else
+      llvm::consumeError(type_system_or_err.takeError());
+
+    // https://cgit.freebsd.org/src/tree/sys/sys/param.h
     constexpr size_t fbsd_maxcomlen = 19;
 
     // Iterate through a linked list of all processes. New processes are added
@@ -221,11 +250,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;
-    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);
+    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 && 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
@@ -276,12 +306,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 (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_size_bytes;
+            uint64_t mask = ReadUnsignedIntegerFromMemory(
+                mask_addr, long_size_bytes, 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);
         }
 


        


More information about the lldb-commits mailing list