19b1d27b2SMichał Górnydiff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
29b1d27b2SMichał Górnyindex e3707365a9c3..c4a9c82f3c63 100644
39b1d27b2SMichał Górny--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
49b1d27b2SMichał Górny+++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
59b1d27b2SMichał Górny@@ -38,6 +38,8 @@ public:
69b1d27b2SMichał Górny
79b1d27b2SMichał Górny   size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
89b1d27b2SMichał Górny                       lldb_private::Status &error) override;
99b1d27b2SMichał Górny+  size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
109b1d27b2SMichał Górny+                       size_t size, Status &error) override;
119b1d27b2SMichał Górny
129b1d27b2SMichał Górny private:
139b1d27b2SMichał Górny   fvc_t *m_fvc;
149b1d27b2SMichał Górny@@ -185,6 +187,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
159b1d27b2SMichał Górny     // iterate through a linked list of all processes
169b1d27b2SMichał Górny     // allproc is a pointer to the first list element, p_list field
179b1d27b2SMichał Górny     // (found at offset_p_list) specifies the next element
189b1d27b2SMichał Górny+    lldb::addr_t prev = 0;
199b1d27b2SMichał Górny     for (lldb::addr_t proc =
209b1d27b2SMichał Górny              ReadPointerFromMemory(FindSymbol("allproc"), error);
219b1d27b2SMichał Górny          proc != 0 && proc != LLDB_INVALID_ADDRESS;
229b1d27b2SMichał Górny@@ -195,6 +198,8 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
239b1d27b2SMichał Górny       char comm[fbsd_maxcomlen + 1];
249b1d27b2SMichał Górny       ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
259b1d27b2SMichał Górny
269b1d27b2SMichał Górny+      bool interesting = false;
279b1d27b2SMichał Górny+
289b1d27b2SMichał Górny       // iterate through a linked list of all process' threads
299b1d27b2SMichał Górny       // the initial thread is found in process' p_threads, subsequent
309b1d27b2SMichał Górny       // elements are linked via td_plist field
319b1d27b2SMichał Górny@@ -231,6 +236,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
329b1d27b2SMichał Górny           // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
339b1d27b2SMichał Górny           pcb_addr = dumppcb;
349b1d27b2SMichał Górny           thread_desc += " (crashed)";
359b1d27b2SMichał Górny+          interesting = true;
369b1d27b2SMichał Górny         } else if (oncpu != -1) {
379b1d27b2SMichał Górny           // if we managed to read stoppcbs and pcb_size, use them to find
389b1d27b2SMichał Górny           // the correct PCB
399b1d27b2SMichał Górny@@ -239,13 +245,27 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
409b1d27b2SMichał Górny           else
419b1d27b2SMichał Górny             pcb_addr = LLDB_INVALID_ADDRESS;
429b1d27b2SMichał Górny           thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
439b1d27b2SMichał Górny+          interesting = true;
449b1d27b2SMichał Górny         }
459b1d27b2SMichał Górny
469b1d27b2SMichał Górny         ThreadSP thread_sp{
479b1d27b2SMichał Górny             new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)};
489b1d27b2SMichał Górny         new_thread_list.AddThread(thread_sp);
499b1d27b2SMichał Górny       }
509b1d27b2SMichał Górny+
519b1d27b2SMichał Górny+      if (interesting) {
529b1d27b2SMichał Górny+        printf("pid %d is interesting\n", pid);
539b1d27b2SMichał Górny+        if (prev != 0) {
549b1d27b2SMichał Górny+          printf("will link %d to %d\n", prev, proc);
559b1d27b2SMichał Górny+          if (!WritePointerToMemory(prev + offset_p_list, proc, error))
569b1d27b2SMichał Górny+            assert(0 && "write failed");
579b1d27b2SMichał Górny+        }
589b1d27b2SMichał Górny+        prev = proc;
599b1d27b2SMichał Górny+      }
609b1d27b2SMichał Górny     }
619b1d27b2SMichał Górny+    printf("last: %d\n", prev);
629b1d27b2SMichał Górny+    if (!WritePointerToMemory(prev + offset_p_list, 0, error))
639b1d27b2SMichał Górny+      assert(0 && "write failed");
649b1d27b2SMichał Górny   } else {
659b1d27b2SMichał Górny     const uint32_t num_threads = old_thread_list.GetSize(false);
669b1d27b2SMichał Górny     for (uint32_t i = 0; i < num_threads; ++i)
679b1d27b2SMichał Górny@@ -295,6 +315,18 @@ size_t ProcessFreeBSDKernelFVC::DoReadMemory(lldb::addr_t addr, void *buf,
689b1d27b2SMichał Górny   return rd;
699b1d27b2SMichał Górny }
709b1d27b2SMichał Górny
719b1d27b2SMichał Górny+size_t ProcessFreeBSDKernelFVC::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
729b1d27b2SMichał Górny+                       size_t size, Status &error) {
739b1d27b2SMichał Górny+  ssize_t rd = 0;
749b1d27b2SMichał Górny+  rd = fvc_write(m_fvc, vm_addr, buf, size);
759b1d27b2SMichał Górny+  printf("fvc_write(%p, %p, %d) -> %d\n", vm_addr, buf, size, rd);
769b1d27b2SMichał Górny+  if (rd < 0 || static_cast<size_t>(rd) != size) {
77*0642cd76SAdrian Prantl+    error = Status::FromErrorStringWithFormat("Writing memory failed: %s", GetError());
789b1d27b2SMichał Górny+    return rd > 0 ? rd : 0;
799b1d27b2SMichał Górny+  }
809b1d27b2SMichał Górny+  return rd;
819b1d27b2SMichał Górny+}
829b1d27b2SMichał Górny+
839b1d27b2SMichał Górny const char *ProcessFreeBSDKernelFVC::GetError() { return fvc_geterr(m_fvc); }
849b1d27b2SMichał Górny
859b1d27b2SMichał Górny #endif // LLDB_ENABLE_FBSDVMCORE
86