mgorny updated this revision to Diff 299950.
mgorny retitled this revision from "[lldb] Unify x86 watchpoint implementation 
on Linux and NetBSD (and future FreeBSD plugin) [WIP]" to "[lldb] Split out 
NetBSD/x86 watchpoint impl for unification".
mgorny edited the summary of this revision.
mgorny added a comment.
Herald added a subscriber: arichardson.

Updated per comments, made it NetBSD-only for now.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89874/new/

https://reviews.llvm.org/D89874

Files:
  lldb/include/lldb/Host/common/NativeRegisterContext.h
  lldb/source/Host/common/NativeRegisterContext.cpp
  lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
  lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
  lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
  lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
  lldb/source/Plugins/Process/Utility/CMakeLists.txt
  lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
  lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h

Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h
@@ -0,0 +1,48 @@
+//===-- NativeRegisterContextWatchpoint_x86.h -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_NativeRegisterContextWatchpoint_x86_h
+#define lldb_NativeRegisterContextWatchpoint_x86_h
+
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
+
+namespace lldb_private {
+
+class NativeRegisterContextWatchpoint_x86 : public virtual NativeRegisterContextRegisterInfo {
+public:
+  Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+  Status GetWatchpointHitIndex(uint32_t &wp_index,
+                               lldb::addr_t trap_addr) override;
+
+  Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+  Status ClearWatchpointHit(uint32_t wp_index) override;
+
+  Status ClearAllHardwareWatchpoints() override;
+
+  Status 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;
+
+private:
+  const RegisterInfo *GetDR(int num) const;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextWatchpoint_x86_h
Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
@@ -0,0 +1,265 @@
+//===-- NativeRegisterContextWatchpoint_x86.cpp ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeRegisterContextWatchpoint_x86.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+using namespace lldb_private;
+
+// Returns mask/value for status bit of wp_index in DR6
+static inline uint64_t GetStatusBit(uint32_t wp_index) {
+  // DR6: ...BBBB
+  //         3210 <- status bits for bp./wp. i; 1 if hit
+  return 1 << wp_index;
+}
+
+// Returns mask/value for global enable bit of wp_index in DR7
+static inline uint64_t GetEnableBit(uint32_t wp_index) {
+  // DR7: ...GLGLGLGL
+  //         33221100 <- global/local enable for bp./wp.; 1 if enabled
+  // we use global bits because NetBSD kernel does not preserve local
+  // bits reliably; Linux seems fine with either
+  return 1 << (2 * wp_index + 1);
+}
+
+// Returns mask for both enable bits of wp_index in DR7
+static inline uint64_t GetBothEnableBitMask(uint32_t wp_index) {
+  // DR7: ...GLGLGLGL
+  //         33221100 <- global/local enable for bp./wp.; 1 if enabled
+  return 3 << (2 * wp_index + 1);
+}
+
+// Returns value for type bits of wp_index in DR7
+static inline uint64_t GetWatchTypeBits(uint32_t watch_flags, uint32_t wp_index) {
+  // DR7:
+  // bit: 3322222222221111...
+  //      1098765432109876...
+  // val: SSTTSSTTSSTTSSTT...
+  // wp.: 3333222211110000...
+  //
+  // where T - type is 01 for write, 11 for r/w
+  return watch_flags << (16 + 4 * wp_index);
+}
+
+// Returns value for size bits of wp_index in DR7
+static inline uint64_t GetWatchSizeBits(uint32_t size, uint32_t wp_index) {
+  // DR7:
+  // bit: 3322222222221111...
+  //      1098765432109876...
+  // val: SSTTSSTTSSTTSSTT...
+  // wp.: 3333222211110000...
+  //
+  // where S - size is:
+  // 00 for 1 byte
+  // 01 for 2 bytes
+  // 10 for 8 bytes
+  // 11 for 4 bytes
+  return (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
+}
+
+// Returns bitmask for all bits controlling wp_index in DR7
+static inline uint64_t GetWatchControlBitmask(uint32_t wp_index) {
+  // DR7:
+  // bit: 33222222222211111111110000000000
+  //      10987654321098765432109876543210
+  // val: SSTTSSTTSSTTSSTTxxxxxxGLGLGLGLGL
+  // wp.: 3333222211110000xxxxxxEE33221100
+  return GetBothEnableBitMask(wp_index) | (0xF << (16 + 4 * wp_index));
+}
+
+// Bit mask for control bits regarding all watchpoints.
+static constexpr uint64_t watchpoint_all_control_bit_mask = 0xFFFF00FF;
+
+const RegisterInfo *NativeRegisterContextWatchpoint_x86::GetDR(int num) const {
+  assert(num >= 0 && num <= 7);
+  switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+  case llvm::Triple::x86:
+    return GetRegisterInfoAtIndex(lldb_dr0_i386 + num);
+  case llvm::Triple::x86_64:
+    return GetRegisterInfoAtIndex(lldb_dr0_x86_64 + num);
+  default:
+    llvm_unreachable("Unhandled target architecture.");
+  }
+}
+
+Status NativeRegisterContextWatchpoint_x86::IsWatchpointHit(uint32_t wp_index,
+                                                           bool &is_hit) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Status("Watchpoint index out of range");
+
+  RegisterValue dr6;
+  Status error = ReadRegister(GetDR(6), dr6);
+  if (error.Fail())
+    is_hit = false;
+  else
+    is_hit = dr6.GetAsUInt64() & GetStatusBit(wp_index);
+
+  return error;
+}
+
+Status NativeRegisterContextWatchpoint_x86::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;
+    Status 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 Status();
+}
+
+Status NativeRegisterContextWatchpoint_x86::IsWatchpointVacant(uint32_t wp_index,
+                                                              bool &is_vacant) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Status("Watchpoint index out of range");
+
+  RegisterValue dr7;
+  Status error = ReadRegister(GetDR(7), dr7);
+  if (error.Fail())
+    is_vacant = false;
+  else
+    is_vacant = !(dr7.GetAsUInt64() & GetEnableBit(wp_index));
+
+  return error;
+}
+
+Status NativeRegisterContextWatchpoint_x86::SetHardwareWatchpointWithIndex(
+    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
+
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Status("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 == 2)
+    watch_flags = 3;
+
+  if (watch_flags != 1 && watch_flags != 3)
+    return Status("Invalid read/write bits for watchpoint");
+  if (size != 1 && size != 2 && size != 4 && size != 8)
+    return Status("Invalid size for watchpoint");
+
+  bool is_vacant;
+  Status error = IsWatchpointVacant(wp_index, is_vacant);
+  if (error.Fail())
+    return error;
+  if (!is_vacant)
+    return Status("Watchpoint index not vacant");
+
+  RegisterValue dr7, drN;
+  error = ReadRegister(GetDR(7), dr7);
+  if (error.Fail())
+    return error;
+  error = ReadRegister(GetDR(wp_index), drN);
+  if (error.Fail())
+    return error;
+
+  uint64_t control_bits = dr7.GetAsUInt64() & ~GetWatchControlBitmask(wp_index);
+  control_bits |= GetEnableBit(wp_index) | GetWatchTypeBits(watch_flags, wp_index) | GetWatchSizeBits(size, wp_index);
+
+  // Clear dr6 if address or bits changed (i.e. we're not reenabling the same
+  // watchpoint).  This can not be done when clearing watchpoints since
+  // the gdb-remote protocol repeatedly clears and readds watchpoints on all
+  // program threads, effectively clearing pending events on NetBSD.
+  // NB: enable bits in dr7 are always 0 here since we're (re)adding it
+  if (drN.GetAsUInt64() != addr ||
+      (dr7.GetAsUInt64() & GetWatchControlBitmask(wp_index)) != (GetWatchTypeBits(watch_flags, wp_index) | GetWatchSizeBits(size, wp_index))) {
+    ClearWatchpointHit(wp_index);
+
+    // We skip update to drN if neither address nor mode changed.
+    error = WriteRegister(GetDR(wp_index), RegisterValue(addr));
+    if (error.Fail())
+      return error;
+  }
+
+  error = WriteRegister(GetDR(7), RegisterValue(control_bits));
+  if (error.Fail())
+    return error;
+
+  return error;
+}
+
+bool NativeRegisterContextWatchpoint_x86::ClearHardwareWatchpoint(
+    uint32_t wp_index) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return false;
+
+  RegisterValue dr7;
+  Status error = ReadRegister(GetDR(7), dr7);
+  if (error.Fail())
+    return false;
+
+  return WriteRegister(GetDR(7), RegisterValue(dr7.GetAsUInt64() & ~GetBothEnableBitMask(wp_index))).Success();
+}
+
+Status NativeRegisterContextWatchpoint_x86::ClearWatchpointHit(uint32_t wp_index) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return Status("Watchpoint index out of range");
+
+  RegisterValue dr6;
+  Status error = ReadRegister(GetDR(6), dr6);
+  if (error.Fail())
+    return error;
+
+  return WriteRegister(GetDR(6), RegisterValue(dr6.GetAsUInt64() & ~GetStatusBit(wp_index)));
+}
+
+Status NativeRegisterContextWatchpoint_x86::ClearAllHardwareWatchpoints() {
+  RegisterValue dr7;
+  Status error = ReadRegister(GetDR(7), dr7);
+  if (error.Fail())
+    return error;
+  return WriteRegister(GetDR(7), RegisterValue(dr7.GetAsUInt64() & ~watchpoint_all_control_bit_mask));
+}
+
+uint32_t NativeRegisterContextWatchpoint_x86::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;
+    Status 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) {
+      LLDB_LOGF(log, "NativeRegisterContextWatchpoint_x86::%s Error: %s",
+                __FUNCTION__, error.AsCString());
+    }
+  }
+  return LLDB_INVALID_INDEX32;
+}
+
+lldb::addr_t
+NativeRegisterContextWatchpoint_x86::GetWatchpointAddress(uint32_t wp_index) {
+  if (wp_index >= NumSupportedHardwareWatchpoints())
+    return LLDB_INVALID_ADDRESS;
+  RegisterValue drN;
+  if (ReadRegister(GetDR(wp_index), drN).Fail())
+    return LLDB_INVALID_ADDRESS;
+  return drN.GetAsUInt64();
+}
+
+uint32_t NativeRegisterContextWatchpoint_x86::NumSupportedHardwareWatchpoints() {
+  // Available debug address registers: dr0, dr1, dr2, dr3
+  return 4;
+}
Index: lldb/source/Plugins/Process/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -10,6 +10,7 @@
   LinuxSignals.cpp
   MipsLinuxSignals.cpp
   NativeRegisterContextRegisterInfo.cpp
+  NativeRegisterContextWatchpoint_x86.cpp
   NetBSDSignals.cpp
   RegisterContextDarwin_arm.cpp
   RegisterContextDarwin_arm64.cpp
Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -20,6 +20,7 @@
 
 #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
 #include "Plugins/Process/Utility/RegisterContext_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
 
 #if defined(PT_GETXSTATE) && defined(PT_SETXSTATE)
@@ -31,7 +32,7 @@
 
 class NativeProcessNetBSD;
 
-class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD {
+class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD, public NativeRegisterContextWatchpoint_x86 {
 public:
   NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch,
                                      NativeThreadProtocol &native_thread);
@@ -49,30 +50,6 @@
 
   Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 
-  Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
-
-  Status GetWatchpointHitIndex(uint32_t &wp_index,
-                               lldb::addr_t trap_addr) override;
-
-  Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
-
-  bool ClearHardwareWatchpoint(uint32_t wp_index) override;
-
-  Status ClearWatchpointHit(uint32_t wp_index) override;
-
-  Status ClearAllHardwareWatchpoints() override;
-
-  Status 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;
-
   Status
   CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override;
 
Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -254,7 +254,7 @@
 
 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextNetBSD(native_thread,
+    : NativeRegisterContextRegisterInfo(native_thread,
                                   CreateRegisterInfoInterface(target_arch)),
       m_gpr(), m_fpr(), m_dbr() {}
 
@@ -1125,235 +1125,6 @@
   }
 }
 
-Status NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
-                                                           bool &is_hit) {
-  if (wp_index >= NumSupportedHardwareWatchpoints())
-    return Status("Watchpoint index out of range");
-
-  RegisterValue reg_value;
-  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(6));
-  Status 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;
-}
-
-Status 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;
-    Status 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 Status();
-}
-
-Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
-                                                              bool &is_vacant) {
-  if (wp_index >= NumSupportedHardwareWatchpoints())
-    return Status("Watchpoint index out of range");
-
-  RegisterValue reg_value;
-  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(7));
-  Status 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 + 1)));
-
-  return error;
-}
-
-Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
-    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
-
-  if (wp_index >= NumSupportedHardwareWatchpoints())
-    return Status("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 Status("Invalid read/write bits for watchpoint");
-
-  if (size != 1 && size != 2 && size != 4 && size != 8)
-    return Status("Invalid size for watchpoint");
-
-  bool is_vacant;
-  Status error = IsWatchpointVacant(wp_index, is_vacant);
-  if (error.Fail())
-    return error;
-  if (!is_vacant)
-    return Status("Watchpoint index not vacant");
-
-  const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7));
-  RegisterValue dr7_value;
-  error = ReadRegister(reg_info_dr7, dr7_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 + 1);
-
-  // 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 = dr7_value.GetAsUInt64() & ~bit_mask;
-
-  control_bits |= enable_bit | rw_bits | size_bits;
-
-  const RegisterInfo *const reg_info_drN =
-      GetRegisterInfoAtIndex(GetDR(wp_index));
-  RegisterValue drN_value;
-  error = ReadRegister(reg_info_drN, drN_value);
-  if (error.Fail())
-    return error;
-
-  // clear dr6 if address or bits changed (i.e. we're not reenabling the same
-  // watchpoint)
-  if (drN_value.GetAsUInt64() != addr ||
-      (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
-    ClearWatchpointHit(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;
-
-  // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
-  // or 6-7 of the debug control register (DR7)
-  const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7));
-  RegisterValue reg_value;
-  Status error = ReadRegister(reg_info_dr7, reg_value);
-  if (error.Fail())
-    return false;
-  uint64_t bit_mask = 0x3 << (2 * wp_index);
-  uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
-
-  return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
-}
-
-Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
-  if (wp_index >= NumSupportedHardwareWatchpoints())
-    return Status("Watchpoint index out of range");
-
-  // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
-  // the debug status register (DR6)
-  const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6));
-  RegisterValue reg_value;
-  Status error = ReadRegister(reg_info_dr6, reg_value);
-  if (error.Fail())
-    return error;
-
-  uint64_t bit_mask = 1 << wp_index;
-  uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
-  return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
-}
-
-Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
-  RegisterValue reg_value;
-
-  // clear bits {0-4} of the debug status register (DR6)
-  const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6));
-  Status 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(GetDR(7));
-  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;
-    Status 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) {
-      LLDB_LOGF(log, "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(GetDR(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;
-}
-
 Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
     NativeRegisterContextNetBSD &source) {
   auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -18,11 +18,8 @@
 
 class NativeProcessNetBSD;
 
-class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
+class NativeRegisterContextNetBSD : public virtual NativeRegisterContextRegisterInfo {
 public:
-  NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread,
-                              RegisterInfoInterface *reg_info_interface_p);
-
   // This function is implemented in the NativeRegisterContextNetBSD_*
   // subclasses to create a new instance of the host specific
   // NativeRegisterContextNetBSD. The implementations can't collide as only one
@@ -34,8 +31,6 @@
   virtual Status
   CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0;
 
-  virtual Status ClearWatchpointHit(uint32_t wp_index) = 0;
-
 protected:
   Status DoRegisterSet(int req, void *buf);
   virtual NativeProcessNetBSD &GetProcess();
Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -20,12 +20,6 @@
 #include <sys/ptrace.h>
 // clang-format on
 
-NativeRegisterContextNetBSD::NativeRegisterContextNetBSD(
-    NativeThreadProtocol &native_thread,
-    RegisterInfoInterface *reg_info_interface_p)
-    : NativeRegisterContextRegisterInfo(native_thread,
-                                        reg_info_interface_p) {}
-
 Status NativeRegisterContextNetBSD::DoRegisterSet(int ptrace_req, void *buf) {
   return NativeProcessNetBSD::PtraceWrapper(ptrace_req, GetProcessPid(), buf,
                                             m_thread.GetID());
Index: lldb/source/Host/common/NativeRegisterContext.cpp
===================================================================
--- lldb/source/Host/common/NativeRegisterContext.cpp
+++ lldb/source/Host/common/NativeRegisterContext.cpp
@@ -266,6 +266,10 @@
   return false;
 }
 
+Status NativeRegisterContext::ClearWatchpointHit(uint32_t hw_index) {
+  return Status("not implemented");
+}
+
 Status NativeRegisterContext::ClearAllHardwareWatchpoints() {
   return Status("not implemented");
 }
Index: lldb/include/lldb/Host/common/NativeRegisterContext.h
===================================================================
--- lldb/include/lldb/Host/common/NativeRegisterContext.h
+++ lldb/include/lldb/Host/common/NativeRegisterContext.h
@@ -75,6 +75,8 @@
 
   virtual bool ClearHardwareWatchpoint(uint32_t hw_index);
 
+  virtual Status ClearWatchpointHit(uint32_t hw_index);
+
   virtual Status ClearAllHardwareWatchpoints();
 
   virtual Status IsWatchpointHit(uint32_t wp_index, bool &is_hit);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to