llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Minsoo Choo (mchoo7) <details> <summary>Changes</summary> This commit brings features in KGDB (`fbsd_kthr.c` specifically) that haven't been ported to LLDB, which includes: 1. Adding zombie threads to the thread list 2. Validate `stopped_cpus` before accessing `stoppcbs` 3. Check bounds for `mp_maxid` 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 the case where newly added architectures in previous PRs (ppc64le, riscv64, arm) weren't handled correctly in `DoUpdateThreadList()`. Fixes: 2430410b7d879fce3db76c21bb8c60ed22abd0b5(#<!-- -->180669), 4a602c03ea050d7adf666d5a440164ca6f78707c(#<!-- -->180670), 3d251288df0642762d1bd86efa05e190005c2539(#<!-- -->180674) --- Full diff: https://github.com/llvm/llvm-project/pull/183981.diff 2 Files Affected: - (modified) lldb/source/Plugins/Process/FreeBSD-Kernel-Core/ProcessFreeBSDKernelCore.cpp (+46-9) - (modified) llvm/docs/ReleaseNotes.md (+1) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/183981 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
