| 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 = Status::FromErrorStringWithFormat("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 |