Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h =================================================================== --- lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h +++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h @@ -46,6 +46,8 @@ protected: bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override; + + lldb::addr_t FindSymbol(const char* name); }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp =================================================================== --- lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp +++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp @@ -137,12 +137,92 @@ return false; } - const Symbol *pcb_sym = - GetTarget().GetExecutableModule()->FindFirstSymbolWithNameAndType( - ConstString("dumppcb")); - ThreadSP thread_sp(new ThreadFreeBSDKernel( - *this, 1, pcb_sym ? pcb_sym->GetFileAddress() : LLDB_INVALID_ADDRESS)); - new_thread_list.AddThread(thread_sp); + Status error; + + // struct field offsets are written as symbols so that we don't have + // to figure them out ourselves + int32_t offset_p_list = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_list"), 4, -1, error); + int32_t offset_p_pid = + ReadSignedIntegerFromMemory(FindSymbol("proc_off_p_pid"), 4, -1, error); + int32_t offset_p_threads = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_threads"), 4, -1, error); + int32_t offset_p_comm = ReadSignedIntegerFromMemory( + FindSymbol("proc_off_p_comm"), 4, -1, error); + + int32_t offset_td_tid = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_tid"), 4, -1, error); + int32_t offset_td_plist = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_plist"), 4, -1, error); + int32_t offset_td_pcb = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_pcb"), 4, -1, error); + int32_t offset_td_oncpu = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_oncpu"), 4, -1, error); + int32_t offset_td_name = ReadSignedIntegerFromMemory( + FindSymbol("thread_off_td_name"), 4, -1, error); + + // fail if we were not able to read any of the offsets + if (offset_p_list == -1 || offset_p_pid == -1 || offset_p_threads == -1 || + offset_p_comm == -1 || offset_td_tid == -1 || offset_td_plist == -1 || + offset_td_pcb == -1 || offset_td_oncpu == -1 || offset_td_name == -1) + return false; + + int32_t dumptid = + ReadSignedIntegerFromMemory(FindSymbol("dumptid"), 4, -1, error); + lldb::addr_t dumppcb = FindSymbol("dumppcb"); + + int32_t pcbsize = + ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error); + lldb::addr_t stoppcbs = FindSymbol("stoppcbs"); + + // from FreeBSD sys/param.h + constexpr size_t fbsd_maxcomlen = 19; + + for (lldb::addr_t proc = + ReadPointerFromMemory(FindSymbol("allproc"), error); + proc != 0 && proc != LLDB_INVALID_ADDRESS; + proc = ReadPointerFromMemory(proc + offset_p_list, error)) { + int32_t pid = + ReadSignedIntegerFromMemory(proc + offset_p_pid, 4, -1, error); + char comm[fbsd_maxcomlen + 1]; + ReadCStringFromMemory(proc + offset_p_comm, comm, fbsd_maxcomlen + 1, + error); + + for (lldb::addr_t td = + ReadPointerFromMemory(proc + offset_p_threads, error); + td != 0; td = ReadPointerFromMemory(td + offset_td_plist, error)) { + int32_t tid = + ReadSignedIntegerFromMemory(td + offset_td_tid, 4, -1, error); + lldb::addr_t pcb_addr = + ReadPointerFromMemory(td + offset_td_pcb, error); + // NB: -1 is a valid value here + int32_t oncpu = + ReadSignedIntegerFromMemory(td + offset_td_oncpu, 4, -2, error); + char thread_name[fbsd_maxcomlen + 1]; + ReadCStringFromMemory(td + offset_td_name, thread_name, + fbsd_maxcomlen + 1, error); + + if (tid == -1) + continue; + // roughly: + // 1. if the thread crashed, its PCB is going to be at "dumppcb" + // 2. if the thread was on CPU, its PCB is going to be on the CPU + // 3. otherwise, its PCB is in the thread struct + if (tid == dumptid) + pcb_addr = dumppcb; + else if (oncpu != -1) { + if (stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0) + pcb_addr = stoppcbs + oncpu * pcbsize; + else + pcb_addr = LLDB_INVALID_ADDRESS; + } + + ThreadSP thread_sp(new ThreadFreeBSDKernel( + *this, tid, pcb_addr, + llvm::formatv("(pid {0}) {1}/{2}", pid, comm, thread_name))); + new_thread_list.AddThread(thread_sp); + } + } } else { const uint32_t num_threads = old_thread_list.GetSize(false); for (uint32_t i = 0; i < num_threads; ++i) @@ -163,6 +243,12 @@ return m_dyld_up.get(); } +lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) { + ModuleSP mod_sp = GetTarget().GetExecutableModule(); + const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name)); + return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS; +} + #if LLDB_ENABLE_FBSDVMCORE ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp, Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h =================================================================== --- lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h +++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h @@ -14,7 +14,7 @@ class ThreadFreeBSDKernel : public lldb_private::Thread { public: ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid, - lldb::addr_t pcb_addr); + lldb::addr_t pcb_addr, std::string thread_name); ~ThreadFreeBSDKernel() override; @@ -25,10 +25,24 @@ lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + const char *GetName() override { + if (m_thread_name.empty()) + return nullptr; + return m_thread_name.c_str(); + } + + void SetName(const char *name) override { + if (name && name[0]) + m_thread_name.assign(name); + else + m_thread_name.clear(); + } + protected: bool CalculateStopInfo() override; private: + std::string m_thread_name; lldb::RegisterContextSP m_thread_reg_ctx_sp; lldb::addr_t m_pcb_addr; }; Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp =================================================================== --- lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp +++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp @@ -24,8 +24,9 @@ using namespace lldb_private; ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid, - lldb::addr_t pcb_addr) - : Thread(process, tid), m_pcb_addr(pcb_addr) {} + lldb::addr_t pcb_addr, + std::string thread_name) + : Thread(process, tid), m_thread_name(thread_name), m_pcb_addr(pcb_addr) {} ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {} @@ -61,9 +62,8 @@ m_pcb_addr); break; case llvm::Triple::x86: - m_thread_reg_ctx_sp = - std::make_shared( - *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr); + m_thread_reg_ctx_sp = std::make_shared( + *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr); break; case llvm::Triple::x86_64: m_thread_reg_ctx_sp =