mgorny created this revision.
mgorny added reviewers: krytarowski, labath.
Herald added subscribers: teemperor, abidh.
Herald added a project: LLDB.

Implement the full logic providing the ability to run, single-step
or suspend each thread separately.  This replaces the old code that
propagated the status of first thread to all of them.  It uses newer
APIs PT_RESUME/PT_SUSPEND and PT_SETSTEP/PT_CLEARSTEP.

It also uses the PT_SET_SIGINFO call to allow sending signal to a single
thread, in addition to sending it to entire process.  Due to API
limitations, sending signal to 1<x<n threads is not supported, neither
is sending two different signals simultaneously.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D64647

Files:
  lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
  lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
  lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h

Index: lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -48,6 +48,10 @@
 private:
   // Interface for friend classes
 
+  Status Resume();
+  Status SingleStep();
+  Status Suspend();
+
   void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
   void SetStoppedByBreakpoint();
   void SetStoppedByTrace();
Index: lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -17,6 +17,11 @@
 #include "lldb/Utility/RegisterValue.h"
 #include "lldb/Utility/State.h"
 
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+// clang-format on
+
 #include <sstream>
 
 using namespace lldb;
@@ -30,6 +35,38 @@
 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
 ), m_stop_description() {}
 
+Status NativeThreadNetBSD::Resume() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (!ret.Success())
+    return ret;
+  ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
+                                           nullptr, GetID());
+  if (ret.Success())
+    SetRunning();
+  return ret;
+}
+
+Status NativeThreadNetBSD::SingleStep() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (!ret.Success())
+    return ret;
+  ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
+                                           nullptr, -GetID());
+  if (ret.Success())
+    SetStepping();
+  return ret;
+}
+
+Status NativeThreadNetBSD::Suspend() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (ret.Success())
+    SetStopped();
+  return ret;
+}
+
 void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
                                             const siginfo_t *info) {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
Index: lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -328,53 +328,84 @@
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
   LLDB_LOG(log, "pid {0}", GetID());
 
-  const auto &thread = m_threads[0];
-  const ResumeAction *const action =
-      resume_actions.GetActionForThread(thread->GetID(), true);
+  Status ret;
+  int signal = LLDB_INVALID_SIGNAL_NUMBER;
+  int signaled_lwp;
+  size_t signaled_threads = 0;
+
+  for (const auto &abs_thread : m_threads) {
+    assert(abs_thread && "thread list should not contain NULL threads");
+    NativeThreadNetBSD& thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
+
+    const ResumeAction *const action =
+        resume_actions.GetActionForThread(thread.GetID(), true);
+
+    if (action == nullptr) {
+      LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+               thread.GetID());
+      continue;
+    }
 
-  if (action == nullptr) {
-    LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
-             thread->GetID());
-    return Status();
-  }
+    LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}",
+             action->state, GetID(), thread.GetID());
 
-  Status error;
+    if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
+      if (signal != LLDB_INVALID_SIGNAL_NUMBER && signal != action->signal)
+        return Status("NetBSD does not support passing multiple signals simultaneously");
 
-  switch (action->state) {
-  case eStateRunning: {
-    // Run the thread, possibly feeding it the signal.
-    error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
-                                               action->signal);
-    if (!error.Success())
-      return error;
-    for (const auto &thread : m_threads)
-      static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
-    SetState(eStateRunning, true);
-    break;
-  }
-  case eStateStepping:
-    // Run the thread, possibly feeding it the signal.
-    error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
-                                               action->signal);
-    if (!error.Success())
-      return error;
-    for (const auto &thread : m_threads)
-      static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
-    SetState(eStateStepping, true);
-    break;
+      signal = action->signal;
+      signaled_lwp = thread.GetID();
+      signaled_threads++;
+    }
 
-  case eStateSuspended:
-  case eStateStopped:
-    llvm_unreachable("Unexpected state");
+    switch (action->state) {
+    case eStateRunning:
+      ret = thread.Resume();
+      break;
+    case eStateStepping:
+      ret = thread.SingleStep();
+      break;
+    case eStateSuspended:
+    case eStateStopped:
+      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
+        return Status("Passing signal to suspended thread unsupported");
 
-  default:
-    return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
-                  "for pid %" PRIu64 ", tid %" PRIu64,
-                  __FUNCTION__, StateAsCString(action->state), GetID(),
-                  thread->GetID());
+      ret = thread.Suspend();
+      break;
+
+    default:
+      return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
+                    "for pid %" PRIu64 ", tid %" PRIu64,
+                    __FUNCTION__, StateAsCString(action->state), GetID(),
+                    thread.GetID());
+    }
+
+    if (ret.Success())
+      SetState(action->state, true);
+    else
+      return ret;
   }
 
-  return Status();
+  if (signal != LLDB_INVALID_SIGNAL_NUMBER) {
+    assert(signaled_threads > 0);
+
+    ptrace_siginfo_t siginfo;
+    siginfo.psi_siginfo.si_signo = signal;
+    siginfo.psi_siginfo.si_code = SI_NOINFO;
+    if (signaled_threads == m_threads.size()) // signal aimed at all threads
+      siginfo.psi_lwpid = 0;
+    else if (signaled_threads == 1)
+      siginfo.psi_lwpid = signaled_lwp;
+    else
+      return Status("NetBSD does not support passing signal to more than one thread simultaneously");
+
+    ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo, sizeof(siginfo));
+    if (!ret.Success())
+      return ret;
+  } else
+    signal = 0;
+
+  return PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void*>(1), signal);
 }
 
 Status NativeProcessNetBSD::Halt() {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to