Battery of NetBSD support improvements

Summary:
Include initial support for:
 - single step mode (PT_STEP)
 - single step trap handling (TRAP_TRACE)
 - exec() trap (TRAP_EXEC)
 - add placeholder interfaces for FPR
 - initial code for NetBSD core(5) files
 - minor tweaks

While there improve style of altered elf-core/ files.

This code raises the number of passing tests on NetBSD to around 50% (600+/1200+).

The introduced code is subject to improve afterwards for additional features and bug fixes.

Sponsored by <The NetBSD Foundation>

Reviewers: labath, joerg, emaste, kettenis

Reviewed By: labath

Subscribers: srhines, #lldb

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D31450

llvm-svn: 299109
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 9c09727..298faa4 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -235,6 +235,24 @@
       }
       SetState(StateType::eStateStopped, true);
       break;
+    case TRAP_TRACE:
+      for (const auto &thread_sp : m_threads) {
+        static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
+      }
+      SetState(StateType::eStateStopped, true);
+      break;
+    case TRAP_EXEC: {
+      Error error = ReinitializeThreads();
+      if (error.Fail()) {
+        SetState(StateType::eStateInvalid);
+        return;
+      }
+
+      // Let our delegate know we have just exec'd.
+      NotifyDidExec();
+
+      SetState(StateType::eStateStopped, true);
+    } break;
     }
   }
 }
@@ -389,11 +407,13 @@
     return Error();
   }
 
+  Error error;
+
   switch (action->state) {
   case eStateRunning: {
     // Run the thread, possibly feeding it the signal.
-    Error error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(),
-                                                     (void *)1, action->signal);
+    error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
+                                               action->signal);
     if (!error.Success())
       return error;
     for (const auto &thread_sp : m_threads) {
@@ -403,7 +423,15 @@
     break;
   }
   case eStateStepping:
-    return Error("Not implemented");
+    // 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_sp : m_threads) {
+      static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping();
+    }
+    SetState(eStateStepping, true);
     break;
 
   case eStateSuspended:
@@ -732,22 +760,11 @@
 
   ResolveProcessArchitecture(m_pid, m_arch);
 
-  /* Initialize threads */
-  struct ptrace_lwpinfo info = {};
-  error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
+  error = ReinitializeThreads();
   if (error.Fail()) {
     SetState(StateType::eStateInvalid);
     return error;
   }
-  while (info.pl_lwpid != 0) {
-    NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
-    thread_sp->SetStoppedBySignal(SIGSTOP);
-    error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
-    if (error.Fail()) {
-      SetState(StateType::eStateInvalid);
-      return error;
-    }
-  }
 
   /* Set process stopped */
   SetState(StateType::eStateStopped);
@@ -850,9 +867,6 @@
 ::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Error &error) {
   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
 
-  // Use a map to keep track of the threads which we have attached/need to
-  // attach.
-  Host::TidMap tids_to_attach;
   if (pid <= 1) {
     error.SetErrorToGenericError();
     error.SetErrorString("Attaching to process 1 is not allowed.");
@@ -874,21 +888,11 @@
   m_pid = pid;
 
   /* Initialize threads */
-  struct ptrace_lwpinfo info = {};
-  error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
+  error = ReinitializeThreads();
   if (error.Fail()) {
     SetState(StateType::eStateInvalid);
     return -1;
   }
-  while (info.pl_lwpid != 0) {
-    NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
-    thread_sp->SetStoppedBySignal(SIGSTOP);
-    error = PtraceWrapper(PT_LWPINFO, pid, &info, sizeof(info));
-    if (error.Fail()) {
-      SetState(StateType::eStateInvalid);
-      return -1;
-    }
-  }
 
   // Let our process instance know the thread has stopped.
   SetState(StateType::eStateStopped);
@@ -989,3 +993,26 @@
 
   return buf;
 }
+
+Error NativeProcessNetBSD::ReinitializeThreads() {
+  // Clear old threads
+  m_threads.clear();
+
+  // Initialize new thread
+  struct ptrace_lwpinfo info = {};
+  Error error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+  if (error.Fail()) {
+    return error;
+  }
+  // Reinitialize from scratch threads and register them in process
+  while (info.pl_lwpid != 0) {
+    NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
+    thread_sp->SetStoppedByExec();
+    error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+    if (error.Fail()) {
+      return error;
+    }
+  }
+
+  return error;
+}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 8463220..ae946a8 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -131,6 +131,8 @@
   void SigchldHandler();
 
   ::pid_t Attach(lldb::pid_t pid, Error &error);
+
+  Error ReinitializeThreads();
 };
 
 } // namespace process_netbsd
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
index 009f82b..1bb6324 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -41,6 +41,22 @@
   return DoWriteGPR(buf);
 }
 
+Error NativeRegisterContextNetBSD::ReadFPR() {
+  void *buf = GetFPRBuffer();
+  if (!buf)
+    return Error("FPR buffer is NULL");
+
+  return DoReadFPR(buf);
+}
+
+Error NativeRegisterContextNetBSD::WriteFPR() {
+  void *buf = GetFPRBuffer();
+  if (!buf)
+    return Error("FPR buffer is NULL");
+
+  return DoWriteFPR(buf);
+}
+
 Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) {
   return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf,
                                             m_thread.GetID());
@@ -51,6 +67,16 @@
                                             m_thread.GetID());
 }
 
+Error NativeRegisterContextNetBSD::DoReadFPR(void *buf) {
+  return NativeProcessNetBSD::PtraceWrapper(PT_GETFPREGS, GetProcessPid(), buf,
+                                            m_thread.GetID());
+}
+
+Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) {
+  return NativeProcessNetBSD::PtraceWrapper(PT_SETFPREGS, GetProcessPid(), buf,
+                                            m_thread.GetID());
+}
+
 NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
   auto process_sp =
       std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
index 9834acb..5ff59bc 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -37,13 +37,24 @@
 protected:
   virtual Error ReadGPR();
   virtual Error WriteGPR();
+
+  virtual Error ReadFPR();
+  virtual Error WriteFPR();
+
   virtual void *GetGPRBuffer() { return nullptr; }
   virtual size_t GetGPRSize() {
     return GetRegisterInfoInterface().GetGPRSize();
   }
+
+  virtual void *GetFPRBuffer() { return nullptr; }
+  virtual size_t GetFPRSize() { return 0; }
+
   virtual Error DoReadGPR(void *buf);
   virtual Error DoWriteGPR(void *buf);
 
+  virtual Error DoReadFPR(void *buf);
+  virtual Error DoWriteFPR(void *buf);
+
   virtual NativeProcessNetBSD &GetProcess();
   virtual ::pid_t GetProcessPid();
 };
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 0dcdcc9..76e64ac 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -154,6 +154,9 @@
   case GPRegSet:
     ReadGPR();
     return 0;
+  case FPRegSet:
+    ReadFPR();
+    return 0;
   default:
     break;
   }
@@ -164,6 +167,9 @@
   case GPRegSet:
     WriteGPR();
     return 0;
+  case FPRegSet:
+    WriteFPR();
+    return 0;
   default:
     break;
   }
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index 3166d96..f6f7d7f 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -48,13 +48,15 @@
 
 protected:
   void *GetGPRBuffer() override { return &m_gpr_x86_64; }
+  void *GetFPRBuffer() override { return &m_fpr_x86_64; }
 
 private:
   // Private member types.
-  enum { GPRegSet };
+  enum { GPRegSet, FPRegSet };
 
   // Private member variables.
   struct reg m_gpr_x86_64;
+  struct fpreg m_fpr_x86_64;
 
   int GetSetForNativeRegNum(int reg_num) const;
 
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index 8493e98..f23621e 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -56,6 +56,18 @@
   m_stop_info.details.signal.signo = SIGTRAP;
 }
 
+void NativeThreadNetBSD::SetStoppedByTrace() {
+  SetStopped();
+  m_stop_info.reason = StopReason::eStopReasonTrace;
+  m_stop_info.details.signal.signo = SIGTRAP;
+}
+
+void NativeThreadNetBSD::SetStoppedByExec() {
+  SetStopped();
+  m_stop_info.reason = StopReason::eStopReasonExec;
+  m_stop_info.details.signal.signo = SIGTRAP;
+}
+
 void NativeThreadNetBSD::SetStopped() {
   const StateType new_state = StateType::eStateStopped;
   m_state = new_state;
@@ -67,6 +79,11 @@
   m_stop_info.reason = StopReason::eStopReasonNone;
 }
 
+void NativeThreadNetBSD::SetStepping() {
+  m_state = StateType::eStateStepping;
+  m_stop_info.reason = StopReason::eStopReasonNone;
+}
+
 std::string NativeThreadNetBSD::GetName() { return std::string(""); }
 
 lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index 94d3830..85fff5d 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -51,8 +51,11 @@
 
   void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
   void SetStoppedByBreakpoint();
+  void SetStoppedByTrace();
+  void SetStoppedByExec();
   void SetStopped();
   void SetRunning();
+  void SetStepping();
 
   // ---------------------------------------------------------------------
   // Member Variables