Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -217,19 +220,46 @@ 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
// to the head of this list. Which means that earlier PIDs are actually at
// 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);
Comment thread
mchoo7 marked this conversation as resolved.
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
Expand Down Expand Up @@ -280,12 +310,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);
}

Expand Down