Include the complete list of threads of all running processes in the FreeBSDKernel plugin. This makes it possible to inspect the states (including partial register dumps from PCB) of all kernel and userspace threads at the time of crash, or at the time of reading /dev/mem first. Differential Revision: https://reviews.llvm.org/D116255
86 lines
3.6 KiB
Diff
86 lines
3.6 KiB
Diff
diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
|
|
index e3707365a9c3..c4a9c82f3c63 100644
|
|
--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
|
|
+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
|
|
@@ -38,6 +38,8 @@ public:
|
|
|
|
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
|
|
lldb_private::Status &error) override;
|
|
+ size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
|
|
+ size_t size, Status &error) override;
|
|
|
|
private:
|
|
fvc_t *m_fvc;
|
|
@@ -185,6 +187,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
|
|
// iterate through a linked list of all processes
|
|
// allproc is a pointer to the first list element, p_list field
|
|
// (found at offset_p_list) specifies the next element
|
|
+ lldb::addr_t prev = 0;
|
|
for (lldb::addr_t proc =
|
|
ReadPointerFromMemory(FindSymbol("allproc"), error);
|
|
proc != 0 && proc != LLDB_INVALID_ADDRESS;
|
|
@@ -195,6 +198,8 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
|
|
char comm[fbsd_maxcomlen + 1];
|
|
ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
|
|
|
|
+ bool interesting = false;
|
|
+
|
|
// iterate through a linked list of all process' threads
|
|
// the initial thread is found in process' p_threads, subsequent
|
|
// elements are linked via td_plist field
|
|
@@ -231,6 +236,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
|
|
// NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
|
|
pcb_addr = dumppcb;
|
|
thread_desc += " (crashed)";
|
|
+ interesting = true;
|
|
} else if (oncpu != -1) {
|
|
// if we managed to read stoppcbs and pcb_size, use them to find
|
|
// the correct PCB
|
|
@@ -239,13 +245,27 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
|
|
else
|
|
pcb_addr = LLDB_INVALID_ADDRESS;
|
|
thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
|
|
+ interesting = true;
|
|
}
|
|
|
|
ThreadSP thread_sp{
|
|
new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)};
|
|
new_thread_list.AddThread(thread_sp);
|
|
}
|
|
+
|
|
+ if (interesting) {
|
|
+ printf("pid %d is interesting\n", pid);
|
|
+ if (prev != 0) {
|
|
+ printf("will link %d to %d\n", prev, proc);
|
|
+ if (!WritePointerToMemory(prev + offset_p_list, proc, error))
|
|
+ assert(0 && "write failed");
|
|
+ }
|
|
+ prev = proc;
|
|
+ }
|
|
}
|
|
+ printf("last: %d\n", prev);
|
|
+ if (!WritePointerToMemory(prev + offset_p_list, 0, error))
|
|
+ assert(0 && "write failed");
|
|
} else {
|
|
const uint32_t num_threads = old_thread_list.GetSize(false);
|
|
for (uint32_t i = 0; i < num_threads; ++i)
|
|
@@ -295,6 +315,18 @@ size_t ProcessFreeBSDKernelFVC::DoReadMemory(lldb::addr_t addr, void *buf,
|
|
return rd;
|
|
}
|
|
|
|
+size_t ProcessFreeBSDKernelFVC::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
|
|
+ size_t size, Status &error) {
|
|
+ ssize_t rd = 0;
|
|
+ rd = fvc_write(m_fvc, vm_addr, buf, size);
|
|
+ printf("fvc_write(%p, %p, %d) -> %d\n", vm_addr, buf, size, rd);
|
|
+ if (rd < 0 || static_cast<size_t>(rd) != size) {
|
|
+ error.SetErrorStringWithFormat("Writing memory failed: %s", GetError());
|
|
+ return rd > 0 ? rd : 0;
|
|
+ }
|
|
+ return rd;
|
|
+}
|
|
+
|
|
const char *ProcessFreeBSDKernelFVC::GetError() { return fvc_geterr(m_fvc); }
|
|
|
|
#endif // LLDB_ENABLE_FBSDVMCORE
|