[Lldb-commits] [lldb] r300548 - Introduce FPR and Debug Registers/NetBSD/amd64 support

Kamil Rytarowski via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 18 05:53:36 PDT 2017


Author: kamil
Date: Tue Apr 18 07:53:35 2017
New Revision: 300548

URL: http://llvm.org/viewvc/llvm-project?rev=300548&view=rev
Log:
Introduce FPR and Debug Registers/NetBSD/amd64 support

Summary:
This code offers Debug Registers (80386) model in LLDB/amd64.

This is initial support and has one issue that will be addressed later,
Debug Register trap (TRAP_DBREG) is registered as (TRAP_TRACE)
for unknown reason.  On the other hand this works good enough to
move on and leave this bug to be squashed later.

Improve the NativeProcessNetBSD::ReinitializeThreads() function,
stop setting inside it SetStoppedByExec(). This fixes incorrect
stop reason on attaching (SetStoppedBySignal(SIGSTOP)).

This commits also has no functional style improvements from
clang-format.

This code also ships with FXSAVE support on NetBSD.

Demo:

```
$ lldb ./watch                                                                                                                                      
(lldb) target create "./watch"
Current executable set to './watch' (x86_64).
(lldb) b main
Breakpoint 1: where = watch`main + 15 at watch.c:8, address = 0x000000000040087f
(lldb) r
Process 1573 launched: './watch' (x86_64)
Process 1573 stopped
* thread #1, stop reason = breakpoint 1.1
    frame #0: 0x000000000040087f watch`main(argc=1, argv=0x00007f7fffa12b88) at watch.c:8
   5    {
   6            int i, j, k;
   7    
-> 8            for (i = 0; i < 3; i++)
   9                    for (j = 0; j < 3; j++)
   10                           for (k = 0; k < 3; k++)
   11                                   printf("Hello world! i=%d j=%d k=%d\n", i, j, k);
(lldb) watch set var i
Watchpoint created: Watchpoint 1: addr = 0x7f7fffa12b4c size = 4 state = enabled type = w
    declare @ '/public/lldb_devel/watch.c:6'
    watchpoint spec = 'i'
    new value: 0
(lldb) c
Process 1573 resuming
Hello world! i=0 j=0 k=0
Hello world! i=0 j=0 k=1
Hello world! i=0 j=0 k=2
Hello world! i=0 j=1 k=0
Hello world! i=0 j=1 k=1
Hello world! i=0 j=1 k=2
Hello world! i=0 j=2 k=0
Hello world! i=0 j=2 k=1
Hello world! i=0 j=2 k=2
Process 1573 stopped
* thread #1, stop reason = trace
    frame #0: 0x00000000004008cc watch`main(argc=1, argv=0x00007f7fffa12b88) at watch.c:8
   5    {
   6            int i, j, k;
   7    
-> 8            for (i = 0; i < 3; i++)
   9                    for (j = 0; j < 3; j++)
   10                           for (k = 0; k < 3; k++)
   11                                   printf("Hello world! i=%d j=%d k=%d\n", i, j, k)
```

FPR (in another program using libm)

```
(lldb) register read --all
General Purpose Registers:
       rax = 0x000000000000001c
       rbx = 0x00007f7fff1d4fe0
       rcx = 0x000000000000000c
       rdx = 0x0000000000000002
       rdi = 0x0000746711d5b018  __sF + 152
       rsi = 0x0000000000000001
       rbp = 0x00007f7fff1d3d80
       rsp = 0x00007f7fff1d3d60
        r8 = 0x00007f7fff1d3470
        r9 = 0x0000000000000000
       r10 = 0x0000000000000001
       r11 = 0x0000000000000202
       r12 = 0x00007f7fff1d3da0
       r13 = 0x00007d8ad2d88500
       r14 = 0x0000000000000002
       r15 = 0x00007f7fffa627e0
       rip = 0x00000000004009e9  fpr`main + 217 at fpr.c:15
    rflags = 0x0000000000000202
        cs = 0x0000000000000047
        fs = 0x0000000000000000
        gs = 0x0000000000000000
        ss = 0x000000000000003f
        ds = 0x000000000000003f
        es = 0x000000000000003f
       eax = 0x0000001c
       ebx = 0xff1d4fe0
       ecx = 0x0000000c
       edx = 0x00000002
       edi = 0x11d5b018
       esi = 0x00000001
       ebp = 0xff1d3d80
       esp = 0xff1d3d60
       r8d = 0xff1d3470
       r9d = 0x00000000
      r10d = 0x00000001
      r11d = 0x00000202
      r12d = 0xff1d3da0
      r13d = 0xd2d88500
      r14d = 0x00000002
      r15d = 0xffa627e0
        ax = 0x001c
        bx = 0x4fe0
        cx = 0x000c
        dx = 0x0002
        di = 0xb018
        si = 0x0001
        bp = 0x3d80
        sp = 0x3d60
       r8w = 0x3470
       r9w = 0x0000
      r10w = 0x0001
      r11w = 0x0202
      r12w = 0x3da0
      r13w = 0x8500
      r14w = 0x0002
      r15w = 0x27e0
        ah = 0x00
        bh = 0x4f
        ch = 0x00
        dh = 0x00
        al = 0x1c
        bl = 0xe0
        cl = 0x0c
        dl = 0x02
       dil = 0x18
       sil = 0x01
       bpl = 0x80
       spl = 0x60
       r8l = 0x70
       r9l = 0x00
      r10l = 0x01
      r11l = 0x02
      r12l = 0xa0
      r13l = 0x00
      r14l = 0x02
      r15l = 0xe0

unknown:
     fctrl = 0x037f
     fstat = 0x0220
      ftag = 0x00
       fop = 0x0000
     fiseg = 0x11e1a52c
     fioff = 0x11e1a52c
     foseg = 0xff1d3d54
     fooff = 0xff1d3d54
     mxcsr = 0x00001fa0
  mxcsrmask = 0x0000ffff
       st0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st1 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st2 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st4 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       st7 = {0xa5 0xdb 0x2d 0xbd 0x93 0xae 0xb9 0xfe 0xfe 0x3f}
       mm0 = 0x3fe9d13800000000
       mm1 = 0x3e0485fcce89c000
       mm2 = 0x3fefd735e0000000
       mm3 = 0x0000000000000000
       mm4 = 0x3fe0000000000000
       mm5 = 0x3fe00000005217f3
       mm6 = 0x0000000000000000
       mm7 = 0x3fefd735e0000000
      xmm0 = {0x00 0x00 0x00 0x00 0x38 0xd1 0xe9 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm1 = {0x00 0xc0 0x89 0xce 0xfc 0x85 0x04 0x3e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm2 = {0x00 0x00 0x00 0xe0 0x35 0xd7 0xef 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm4 = {0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm5 = {0xf3 0x17 0x52 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm7 = {0x00 0x00 0x00 0xe0 0x35 0xd7 0xef 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm8 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
      xmm9 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm10 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm11 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm12 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm13 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm14 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
     xmm15 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
       dr0 = 0x0000000000000000
       dr1 = 0x0000000000000000
       dr2 = 0x0000000000000000
       dr3 = 0x0000000000000000
       dr4 = 0x0000000000000000
       dr5 = 0x0000000000000000
       dr6 = 0x00000000ffff0ff0
       dr7 = 0x0000000000000400
22 registers were unavailable.
```

Sponsored by <The NetBSD Foundation>

Reviewers: labath, emaste, joerg, kettenis

Reviewed By: labath

Subscribers: #lldb

Tags: #lldb

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

Modified:
    lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
    lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
    lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
    lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
    lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
    lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
    lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp Tue Apr 18 07:53:35 2017
@@ -224,36 +224,83 @@ void NativeProcessNetBSD::MonitorSIGTRAP
       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
 
   // Get details on the signal raised.
-  if (siginfo_err.Success()) {
-    switch (info.psi_siginfo.si_code) {
-    case TRAP_BRKPT:
+  if (siginfo_err.Fail()) {
+    return;
+  }
+
+  switch (info.psi_siginfo.si_code) {
+  case TRAP_BRKPT:
+    for (const auto &thread_sp : m_threads) {
+      static_pointer_cast<NativeThreadNetBSD>(thread_sp)
+          ->SetStoppedByBreakpoint();
+      FixupBreakpointPCAsNeeded(
+          *static_pointer_cast<NativeThreadNetBSD>(thread_sp));
+    }
+    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();
+
+    for (const auto &thread_sp : m_threads) {
+      static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec();
+    }
+    SetState(StateType::eStateStopped, true);
+  } break;
+  case TRAP_DBREG: {
+    // If a watchpoint was hit, report it
+    uint32_t wp_index;
+    Error error =
+        static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
+            ->GetRegisterContext()
+            ->GetWatchpointHitIndex(wp_index,
+                                    (uintptr_t)info.psi_siginfo.si_addr);
+    if (error.Fail())
+      LLDB_LOG(log,
+               "received error while checking for watchpoint hits, pid = "
+               "{0}, LWP = {1}, error = {2}",
+               GetID(), info.psi_lwpid, error);
+    if (wp_index != LLDB_INVALID_INDEX32) {
       for (const auto &thread_sp : m_threads) {
         static_pointer_cast<NativeThreadNetBSD>(thread_sp)
-            ->SetStoppedByBreakpoint();
-        FixupBreakpointPCAsNeeded(
-            *static_pointer_cast<NativeThreadNetBSD>(thread_sp));
+            ->SetStoppedByWatchpoint(wp_index);
       }
       SetState(StateType::eStateStopped, true);
       break;
-    case TRAP_TRACE:
+    }
+
+    // If a breakpoint was hit, report it
+    uint32_t bp_index;
+    error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
+                ->GetRegisterContext()
+                ->GetHardwareBreakHitIndex(bp_index,
+                                           (uintptr_t)info.psi_siginfo.si_addr);
+    if (error.Fail())
+      LLDB_LOG(log,
+               "received error while checking for hardware "
+               "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
+               GetID(), info.psi_lwpid, error);
+    if (bp_index != LLDB_INVALID_INDEX32) {
       for (const auto &thread_sp : m_threads) {
-        static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
+        static_pointer_cast<NativeThreadNetBSD>(thread_sp)
+            ->SetStoppedByBreakpoint();
       }
       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;
     }
+  } break;
   }
 }
 
@@ -328,8 +375,8 @@ Error NativeProcessNetBSD::FixupBreakpoi
     return error;
   } else
     LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
-  // First try probing for a breakpoint at a software breakpoint location: PC -
-  // breakpoint size.
+  // First try probing for a breakpoint at a software breakpoint location: PC
+  // - breakpoint size.
   const lldb::addr_t initial_pc_addr =
       context_sp->GetPCfromBreakpointLocation();
   lldb::addr_t breakpoint_addr = initial_pc_addr;
@@ -439,7 +486,7 @@ Error NativeProcessNetBSD::Resume(const
     llvm_unreachable("Unexpected state");
 
   default:
-    return Error("NativeProcessLinux::%s (): unexpected state %s specified "
+    return Error("NativeProcessNetBSD::%s (): unexpected state %s specified "
                  "for pid %" PRIu64 ", tid %" PRIu64,
                  __FUNCTION__, StateAsCString(action->state), GetID(),
                  thread_sp->GetID());
@@ -540,8 +587,8 @@ Error NativeProcessNetBSD::GetMemoryRegi
            "descending memory map entries detected, unexpected");
     prev_base_address = proc_entry_info.GetRange().GetRangeBase();
     UNUSED_IF_ASSERT_DISABLED(prev_base_address);
-    // If the target address comes before this entry, indicate distance to next
-    // region.
+    // If the target address comes before this entry, indicate distance to
+    // next region.
     if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
       range_info.GetRange().SetRangeBase(load_addr);
       range_info.GetRange().SetByteSize(
@@ -561,9 +608,8 @@ Error NativeProcessNetBSD::GetMemoryRegi
   }
   // If we made it here, we didn't find an entry that contained the given
   // address. Return the
-  // load_addr as start and the amount of bytes betwwen load address and the end
-  // of the memory as
-  // size.
+  // load_addr as start and the amount of bytes betwwen load address and the
+  // end of the memory as size.
   range_info.GetRange().SetRangeBase(load_addr);
   range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
   range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@@ -722,8 +768,8 @@ Error NativeProcessNetBSD::LaunchInferio
     LLDB_LOG(log, "waitpid for inferior failed with %s", error);
 
     // Mark the inferior as invalid.
-    // FIXME this could really use a new state - eStateLaunchFailure.  For now,
-    // using eStateInvalid.
+    // FIXME this could really use a new state - eStateLaunchFailure.  For
+    // now, using eStateInvalid.
     SetState(StateType::eStateInvalid);
 
     return error;
@@ -766,6 +812,11 @@ Error NativeProcessNetBSD::LaunchInferio
     return error;
   }
 
+  for (const auto &thread_sp : m_threads) {
+    static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
+        SIGSTOP);
+  }
+
   /* Set process stopped */
   SetState(StateType::eStateStopped);
 
@@ -894,6 +945,11 @@ NativeThreadNetBSDSP NativeProcessNetBSD
     return -1;
   }
 
+  for (const auto &thread_sp : m_threads) {
+    static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
+        SIGSTOP);
+  }
+
   // Let our process instance know the thread has stopped.
   SetState(StateType::eStateStopped);
 
@@ -1007,7 +1063,6 @@ Error NativeProcessNetBSD::ReinitializeT
   // 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;

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp Tue Apr 18 07:53:35 2017
@@ -57,6 +57,22 @@ Error NativeRegisterContextNetBSD::Write
   return DoWriteFPR(buf);
 }
 
+Error NativeRegisterContextNetBSD::ReadDBR() {
+  void *buf = GetDBRBuffer();
+  if (!buf)
+    return Error("DBR buffer is NULL");
+
+  return DoReadDBR(buf);
+}
+
+Error NativeRegisterContextNetBSD::WriteDBR() {
+  void *buf = GetDBRBuffer();
+  if (!buf)
+    return Error("DBR buffer is NULL");
+
+  return DoWriteDBR(buf);
+}
+
 Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) {
   return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf,
                                             m_thread.GetID());
@@ -77,6 +93,16 @@ Error NativeRegisterContextNetBSD::DoWri
                                             m_thread.GetID());
 }
 
+Error NativeRegisterContextNetBSD::DoReadDBR(void *buf) {
+  return NativeProcessNetBSD::PtraceWrapper(PT_GETDBREGS, GetProcessPid(), buf,
+                                            m_thread.GetID());
+}
+
+Error NativeRegisterContextNetBSD::DoWriteDBR(void *buf) {
+  return NativeProcessNetBSD::PtraceWrapper(PT_SETDBREGS, GetProcessPid(), buf,
+                                            m_thread.GetID());
+}
+
 NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
   auto process_sp =
       std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h Tue Apr 18 07:53:35 2017
@@ -41,6 +41,9 @@ protected:
   virtual Error ReadFPR();
   virtual Error WriteFPR();
 
+  virtual Error ReadDBR();
+  virtual Error WriteDBR();
+
   virtual void *GetGPRBuffer() { return nullptr; }
   virtual size_t GetGPRSize() {
     return GetRegisterInfoInterface().GetGPRSize();
@@ -49,12 +52,18 @@ protected:
   virtual void *GetFPRBuffer() { return nullptr; }
   virtual size_t GetFPRSize() { return 0; }
 
+  virtual void *GetDBRBuffer() { return nullptr; }
+  virtual size_t GetDBRSize() { return 0; }
+
   virtual Error DoReadGPR(void *buf);
   virtual Error DoWriteGPR(void *buf);
 
   virtual Error DoReadFPR(void *buf);
   virtual Error DoWriteFPR(void *buf);
 
+  virtual Error DoReadDBR(void *buf);
+  virtual Error DoWriteDBR(void *buf);
+
   virtual NativeProcessNetBSD &GetProcess();
   virtual ::pid_t GetProcessPid();
 };

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp Tue Apr 18 07:53:35 2017
@@ -19,7 +19,15 @@
 
 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
 
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <x86/cpu.h>
 #include <elf.h>
+#include <err.h>
+#include <stdint.h>
+#include <stdlib.h>
+// clang-format on
 
 using namespace lldb_private;
 using namespace lldb_private::process_netbsd;
@@ -86,6 +94,57 @@ static const RegisterSet g_reg_sets_x86_
 
 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
 
+const int fpu_present = []() -> int {
+  int mib[2];
+  int error;
+  size_t len;
+  int val;
+
+  len = sizeof(val);
+  mib[0] = CTL_MACHDEP;
+  mib[1] = CPU_FPU_PRESENT;
+
+  error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
+  if (error)
+    errx(EXIT_FAILURE, "sysctl");
+
+  return val;
+}();
+
+const int osfxsr = []() -> int {
+  int mib[2];
+  int error;
+  size_t len;
+  int val;
+
+  len = sizeof(val);
+  mib[0] = CTL_MACHDEP;
+  mib[1] = CPU_OSFXSR;
+
+  error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
+  if (error)
+    errx(EXIT_FAILURE, "sysctl");
+
+  return val;
+}();
+
+const int fpu_save = []() -> int {
+  int mib[2];
+  int error;
+  size_t len;
+  int val;
+
+  len = sizeof(val);
+  mib[0] = CTL_MACHDEP;
+  mib[1] = CPU_FPU_SAVE;
+
+  error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
+  if (error)
+    errx(EXIT_FAILURE, "sysctl");
+
+  return val;
+}();
+
 } // namespace
 
 NativeRegisterContextNetBSD *
@@ -114,7 +173,7 @@ NativeRegisterContextNetBSD_x86_64::Nati
     uint32_t concrete_frame_idx)
     : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx,
                                   CreateRegisterInfoInterface(target_arch)),
-      m_gpr_x86_64() {}
+      m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {}
 
 // CONSIDER after local and llgs debugging are merged, register set support can
 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
@@ -143,8 +202,18 @@ NativeRegisterContextNetBSD_x86_64::GetR
 
 int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
     int reg_num) const {
-  if (reg_num < lldb_fctrl_x86_64)
+  if (reg_num <= k_last_gpr_x86_64)
     return GPRegSet;
+  else if (reg_num <= k_last_fpr_x86_64)
+    return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1;
+  else if (reg_num <= k_last_avx_x86_64)
+    return -1; // AVX
+  else if (reg_num <= k_last_mpxr_x86_64)
+    return -1; // MPXR
+  else if (reg_num <= k_last_mpxc_x86_64)
+    return -1; // MPXC
+  else if (reg_num <= lldb_dr7_x86_64)
+    return DBRegSet; // DBR
   else
     return -1;
 }
@@ -157,6 +226,9 @@ int NativeRegisterContextNetBSD_x86_64::
   case FPRegSet:
     ReadFPR();
     return 0;
+  case DBRegSet:
+    ReadDBR();
+    return 0;
   default:
     break;
   }
@@ -170,6 +242,9 @@ int NativeRegisterContextNetBSD_x86_64::
   case FPRegSet:
     WriteFPR();
     return 0;
+  case DBRegSet:
+    WriteDBR();
+    return 0;
   default:
     break;
   }
@@ -285,6 +360,87 @@ Error NativeRegisterContextNetBSD_x86_64
   case lldb_es_x86_64:
     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES];
     break;
+  case lldb_fctrl_x86_64:
+    reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw;
+    break;
+  case lldb_fstat_x86_64:
+    reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw;
+    break;
+  case lldb_ftag_x86_64:
+    reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw;
+    break;
+  case lldb_fop_x86_64:
+    reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode;
+    break;
+  case lldb_fiseg_x86_64:
+    reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64;
+    break;
+  case lldb_fioff_x86_64:
+    reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off;
+    break;
+  case lldb_foseg_x86_64:
+    reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64;
+    break;
+  case lldb_fooff_x86_64:
+    reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off;
+    break;
+  case lldb_mxcsr_x86_64:
+    reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr;
+    break;
+  case lldb_mxcsrmask_x86_64:
+    reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask;
+    break;
+  case lldb_st0_x86_64:
+  case lldb_st1_x86_64:
+  case lldb_st2_x86_64:
+  case lldb_st3_x86_64:
+  case lldb_st4_x86_64:
+  case lldb_st5_x86_64:
+  case lldb_st6_x86_64:
+  case lldb_st7_x86_64:
+    reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
+                       reg_info->byte_size, endian::InlHostByteOrder());
+    break;
+  case lldb_mm0_x86_64:
+  case lldb_mm1_x86_64:
+  case lldb_mm2_x86_64:
+  case lldb_mm3_x86_64:
+  case lldb_mm4_x86_64:
+  case lldb_mm5_x86_64:
+  case lldb_mm6_x86_64:
+  case lldb_mm7_x86_64:
+    reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64],
+                       reg_info->byte_size, endian::InlHostByteOrder());
+    break;
+  case lldb_xmm0_x86_64:
+  case lldb_xmm1_x86_64:
+  case lldb_xmm2_x86_64:
+  case lldb_xmm3_x86_64:
+  case lldb_xmm4_x86_64:
+  case lldb_xmm5_x86_64:
+  case lldb_xmm6_x86_64:
+  case lldb_xmm7_x86_64:
+  case lldb_xmm8_x86_64:
+  case lldb_xmm9_x86_64:
+  case lldb_xmm10_x86_64:
+  case lldb_xmm11_x86_64:
+  case lldb_xmm12_x86_64:
+  case lldb_xmm13_x86_64:
+  case lldb_xmm14_x86_64:
+  case lldb_xmm15_x86_64:
+    reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
+                       reg_info->byte_size, endian::InlHostByteOrder());
+    break;
+  case lldb_dr0_x86_64:
+  case lldb_dr1_x86_64:
+  case lldb_dr2_x86_64:
+  case lldb_dr3_x86_64:
+  case lldb_dr4_x86_64:
+  case lldb_dr5_x86_64:
+  case lldb_dr6_x86_64:
+  case lldb_dr7_x86_64:
+    reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64];
+    break;
   }
 
   return error;
@@ -400,6 +556,87 @@ Error NativeRegisterContextNetBSD_x86_64
   case lldb_es_x86_64:
     m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64();
     break;
+  case lldb_fctrl_x86_64:
+    m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16();
+    break;
+  case lldb_fstat_x86_64:
+    m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16();
+    break;
+  case lldb_ftag_x86_64:
+    m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8();
+    break;
+  case lldb_fop_x86_64:
+    m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16();
+    break;
+  case lldb_fiseg_x86_64:
+    m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64();
+    break;
+  case lldb_fioff_x86_64:
+    m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32();
+    break;
+  case lldb_foseg_x86_64:
+    m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64();
+    break;
+  case lldb_fooff_x86_64:
+    m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32();
+    break;
+  case lldb_mxcsr_x86_64:
+    m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32();
+    break;
+  case lldb_mxcsrmask_x86_64:
+    m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32();
+    break;
+  case lldb_st0_x86_64:
+  case lldb_st1_x86_64:
+  case lldb_st2_x86_64:
+  case lldb_st3_x86_64:
+  case lldb_st4_x86_64:
+  case lldb_st5_x86_64:
+  case lldb_st6_x86_64:
+  case lldb_st7_x86_64:
+    ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
+             reg_value.GetBytes(), reg_value.GetByteSize());
+    break;
+  case lldb_mm0_x86_64:
+  case lldb_mm1_x86_64:
+  case lldb_mm2_x86_64:
+  case lldb_mm3_x86_64:
+  case lldb_mm4_x86_64:
+  case lldb_mm5_x86_64:
+  case lldb_mm6_x86_64:
+  case lldb_mm7_x86_64:
+    ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64],
+             reg_value.GetBytes(), reg_value.GetByteSize());
+    break;
+  case lldb_xmm0_x86_64:
+  case lldb_xmm1_x86_64:
+  case lldb_xmm2_x86_64:
+  case lldb_xmm3_x86_64:
+  case lldb_xmm4_x86_64:
+  case lldb_xmm5_x86_64:
+  case lldb_xmm6_x86_64:
+  case lldb_xmm7_x86_64:
+  case lldb_xmm8_x86_64:
+  case lldb_xmm9_x86_64:
+  case lldb_xmm10_x86_64:
+  case lldb_xmm11_x86_64:
+  case lldb_xmm12_x86_64:
+  case lldb_xmm13_x86_64:
+  case lldb_xmm14_x86_64:
+  case lldb_xmm15_x86_64:
+    ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
+             reg_value.GetBytes(), reg_value.GetByteSize());
+    break;
+  case lldb_dr0_x86_64:
+  case lldb_dr1_x86_64:
+  case lldb_dr2_x86_64:
+  case lldb_dr3_x86_64:
+  case lldb_dr4_x86_64:
+  case lldb_dr5_x86_64:
+  case lldb_dr6_x86_64:
+  case lldb_dr7_x86_64:
+    m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64();
+    break;
   }
 
   if (WriteRegisterSet(set) != 0)
@@ -480,4 +717,223 @@ Error NativeRegisterContextNetBSD_x86_64
   return error;
 }
 
+Error NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
+                                                          bool &is_hit) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Error("Watchpoint index out of range");
+
+  RegisterValue reg_value;
+  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+  Error error = ReadRegister(reg_info, reg_value);
+  if (error.Fail()) {
+    is_hit = false;
+    return error;
+  }
+
+  uint64_t status_bits = reg_value.GetAsUInt64();
+
+  is_hit = status_bits & (1 << wp_index);
+
+  return error;
+}
+
+Error NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex(
+    uint32_t &wp_index, lldb::addr_t trap_addr) {
+  uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+  for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
+    bool is_hit;
+    Error error = IsWatchpointHit(wp_index, is_hit);
+    if (error.Fail()) {
+      wp_index = LLDB_INVALID_INDEX32;
+      return error;
+    } else if (is_hit) {
+      return error;
+    }
+  }
+  wp_index = LLDB_INVALID_INDEX32;
+  return Error();
+}
+
+Error NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
+                                                             bool &is_vacant) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Error("Watchpoint index out of range");
+
+  RegisterValue reg_value;
+  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+  Error error = ReadRegister(reg_info, reg_value);
+  if (error.Fail()) {
+    is_vacant = false;
+    return error;
+  }
+
+  uint64_t control_bits = reg_value.GetAsUInt64();
+
+  is_vacant = !(control_bits & (1 << (2 * wp_index)));
+
+  return error;
+}
+
+Error NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Error("Watchpoint index out of range");
+
+  // Read only watchpoints aren't supported on x86_64. Fall back to read/write
+  // waitchpoints instead.
+  // TODO: Add logic to detect when a write happens and ignore that watchpoint
+  // hit.
+  if (watch_flags == 0x2)
+    watch_flags = 0x3;
+
+  if (watch_flags != 0x1 && watch_flags != 0x3)
+    return Error("Invalid read/write bits for watchpoint");
+
+  if (size != 1 && size != 2 && size != 4 && size != 8)
+    return Error("Invalid size for watchpoint");
+
+  bool is_vacant;
+  Error error = IsWatchpointVacant(wp_index, is_vacant);
+  if (error.Fail())
+    return error;
+  if (!is_vacant)
+    return Error("Watchpoint index not vacant");
+
+  RegisterValue reg_value;
+  const RegisterInfo *const reg_info_dr7 =
+      GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+  error = ReadRegister(reg_info_dr7, reg_value);
+  if (error.Fail())
+    return error;
+
+  // for watchpoints 0, 1, 2, or 3, respectively,
+  // set bits 1, 3, 5, or 7
+  uint64_t enable_bit = 1 << (2 * wp_index);
+
+  // set bits 16-17, 20-21, 24-25, or 28-29
+  // with 0b01 for write, and 0b11 for read/write
+  uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
+
+  // set bits 18-19, 22-23, 26-27, or 30-31
+  // with 0b00, 0b01, 0b10, or 0b11
+  // for 1, 2, 8 (if supported), or 4 bytes, respectively
+  uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
+
+  uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
+
+  uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+
+  control_bits |= enable_bit | rw_bits | size_bits;
+
+  const RegisterInfo *const reg_info_drN =
+      GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
+  error = WriteRegister(reg_info_drN, RegisterValue(addr));
+  if (error.Fail())
+    return error;
+
+  error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
+  if (error.Fail())
+    return error;
+
+  error.Clear();
+  return error;
+}
+
+bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
+    uint32_t wp_index) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return false;
+
+  RegisterValue reg_value;
+
+  // for watchpoints 0, 1, 2, or 3, respectively,
+  // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
+  const RegisterInfo *const reg_info_dr6 =
+      GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+  Error error = ReadRegister(reg_info_dr6, reg_value);
+  if (error.Fail())
+    return false;
+  uint64_t bit_mask = 1 << wp_index;
+  uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+  error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
+  if (error.Fail())
+    return false;
+
+  // for watchpoints 0, 1, 2, or 3, respectively,
+  // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
+  // of the debug control register (DR7)
+  const RegisterInfo *const reg_info_dr7 =
+      GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+  error = ReadRegister(reg_info_dr7, reg_value);
+  if (error.Fail())
+    return false;
+  bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
+  uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+  return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+}
+
+Error NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
+  RegisterValue reg_value;
+
+  // clear bits {0-4} of the debug status register (DR6)
+  const RegisterInfo *const reg_info_dr6 =
+      GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+  Error error = ReadRegister(reg_info_dr6, reg_value);
+  if (error.Fail())
+    return error;
+  uint64_t bit_mask = 0xF;
+  uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
+  error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
+  if (error.Fail())
+    return error;
+
+  // clear bits {0-7,16-31} of the debug control register (DR7)
+  const RegisterInfo *const reg_info_dr7 =
+      GetRegisterInfoAtIndex(lldb_dr7_x86_64);
+  error = ReadRegister(reg_info_dr7, reg_value);
+  if (error.Fail())
+    return error;
+  bit_mask = 0xFF | (0xFFFF << 16);
+  uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+  return WriteRegister(reg_info_dr7, RegisterValue(control_bits));
+}
+
+uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+  for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
+    bool is_vacant;
+    Error error = IsWatchpointVacant(wp_index, is_vacant);
+    if (is_vacant) {
+      error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
+      if (error.Success())
+        return wp_index;
+    }
+    if (error.Fail() && log) {
+      log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s",
+                  __FUNCTION__, error.AsCString());
+    }
+  }
+  return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return LLDB_INVALID_ADDRESS;
+  RegisterValue reg_value;
+  const RegisterInfo *const reg_info_drN =
+      GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
+  if (ReadRegister(reg_info_drN, reg_value).Fail())
+    return LLDB_INVALID_ADDRESS;
+  return reg_value.GetAsUInt64();
+}
+
+uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
+  // Available debug address registers: dr0, dr1, dr2, dr3
+  return 4;
+}
+
 #endif // defined(__x86_64__)

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h Tue Apr 18 07:53:35 2017
@@ -46,17 +46,40 @@ public:
 
   Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 
+  Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+  Error GetWatchpointHitIndex(uint32_t &wp_index,
+                              lldb::addr_t trap_addr) override;
+
+  Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+  Error ClearAllHardwareWatchpoints() override;
+
+  Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
+                                       uint32_t watch_flags, uint32_t wp_index);
+
+  uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+                                 uint32_t watch_flags) override;
+
+  lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+  uint32_t NumSupportedHardwareWatchpoints() override;
+
 protected:
   void *GetGPRBuffer() override { return &m_gpr_x86_64; }
   void *GetFPRBuffer() override { return &m_fpr_x86_64; }
+  void *GetDBRBuffer() override { return &m_dbr_x86_64; }
 
 private:
   // Private member types.
-  enum { GPRegSet, FPRegSet };
+  enum { GPRegSet, FPRegSet, DBRegSet };
 
   // Private member variables.
   struct reg m_gpr_x86_64;
   struct fpreg m_fpr_x86_64;
+  struct dbreg m_dbr_x86_64;
 
   int GetSetForNativeRegNum(int reg_num) const;
 

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp Tue Apr 18 07:53:35 2017
@@ -16,6 +16,9 @@
 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/State.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include <sstream>
 
 using namespace lldb;
 using namespace lldb_private;
@@ -68,6 +71,23 @@ void NativeThreadNetBSD::SetStoppedByExe
   m_stop_info.details.signal.signo = SIGTRAP;
 }
 
+void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
+  SetStopped();
+
+  lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
+
+  std::ostringstream ostr;
+  ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
+  ostr << wp_index;
+
+  ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
+
+  m_stop_description = ostr.str();
+
+  m_stop_info.reason = StopReason::eStopReasonWatchpoint;
+  m_stop_info.details.signal.signo = SIGTRAP;
+}
+
 void NativeThreadNetBSD::SetStopped() {
   const StateType new_state = StateType::eStateStopped;
   m_state = new_state;
@@ -142,18 +162,61 @@ NativeRegisterContextSP NativeThreadNetB
 
 Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
                                         uint32_t watch_flags, bool hardware) {
-  return Error("Unimplemented");
+  if (!hardware)
+    return Error("not implemented");
+  if (m_state == eStateLaunching)
+    return Error();
+  Error error = RemoveWatchpoint(addr);
+  if (error.Fail())
+    return error;
+  NativeRegisterContextSP reg_ctx = GetRegisterContext();
+  uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
+  if (wp_index == LLDB_INVALID_INDEX32)
+    return Error("Setting hardware watchpoint failed.");
+  m_watchpoint_index_map.insert({addr, wp_index});
+  return Error();
 }
 
 Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
-  return Error("Unimplemented");
+  auto wp = m_watchpoint_index_map.find(addr);
+  if (wp == m_watchpoint_index_map.end())
+    return Error();
+  uint32_t wp_index = wp->second;
+  m_watchpoint_index_map.erase(wp);
+  if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
+    return Error();
+  return Error("Clearing hardware watchpoint failed.");
 }
 
 Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
                                                 size_t size) {
-  return Error("Unimplemented");
+  if (m_state == eStateLaunching)
+    return Error();
+
+  Error error = RemoveHardwareBreakpoint(addr);
+  if (error.Fail())
+    return error;
+
+  NativeRegisterContextSP reg_ctx = GetRegisterContext();
+  uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
+
+  if (bp_index == LLDB_INVALID_INDEX32)
+    return Error("Setting hardware breakpoint failed.");
+
+  m_hw_break_index_map.insert({addr, bp_index});
+  return Error();
 }
 
 Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
-  return Error("Unimplemented");
+  auto bp = m_hw_break_index_map.find(addr);
+  if (bp == m_hw_break_index_map.end())
+    return Error();
+
+  uint32_t bp_index = bp->second;
+  if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
+    m_hw_break_index_map.erase(bp);
+    return Error();
+  }
+
+  return Error("Clearing hardware breakpoint failed.");
 }

Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h (original)
+++ lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h Tue Apr 18 07:53:35 2017
@@ -12,6 +12,9 @@
 
 #include "lldb/Host/common/NativeThreadProtocol.h"
 
+#include <map>
+#include <string>
+
 namespace lldb_private {
 namespace process_netbsd {
 
@@ -53,6 +56,7 @@ private:
   void SetStoppedByBreakpoint();
   void SetStoppedByTrace();
   void SetStoppedByExec();
+  void SetStoppedByWatchpoint(uint32_t wp_index);
   void SetStopped();
   void SetRunning();
   void SetStepping();
@@ -64,6 +68,9 @@ private:
   ThreadStopInfo m_stop_info;
   NativeRegisterContextSP m_reg_context_sp;
   std::string m_stop_description;
+  using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
+  WatchpointIndexMap m_watchpoint_index_map;
+  WatchpointIndexMap m_hw_break_index_map;
 };
 
 typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP;

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h?rev=300548&r1=300547&r2=300548&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h Tue Apr 18 07:53:35 2017
@@ -148,7 +148,7 @@
         DR_OFFSET(i), eEncodingUint, eFormatHex,                               \
                   {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
                    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
-                   LLDB_INVALID_REGNUM },                                      \
+                   lldb_##reg##i##_x86_64 },                                   \
                    nullptr, nullptr, nullptr, 0                                \
   }
 




More information about the lldb-commits mailing list