[Lldb-commits] [lldb] [lldb][Windows] WoA HW Break and Watchpoint support in LLDB (PR #108072)

Omair Javaid via lldb-commits lldb-commits at lists.llvm.org
Wed Oct 9 01:39:46 PDT 2024


https://github.com/omjavaid updated https://github.com/llvm/llvm-project/pull/108072

>From ac61e5a75ce59f7834034494a03b43e81bf02d41 Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid <omair.javaid at linaro.org>
Date: Tue, 10 Sep 2024 18:03:29 +0500
Subject: [PATCH 1/3] WoA hardware breakpoint/watchpoint support

---
 .../Windows/Common/NativeProcessWindows.cpp   | 52 ++++++++---
 .../Common/NativeRegisterContextWindows.cpp   |  3 -
 .../Common/NativeRegisterContextWindows.h     |  6 +-
 .../NativeRegisterContextWindows_WoW64.cpp    |  4 +-
 .../NativeRegisterContextWindows_arm.cpp      |  4 +-
 .../NativeRegisterContextWindows_arm64.cpp    | 86 ++++++++++---------
 .../NativeRegisterContextWindows_arm64.h      | 32 ++-----
 .../NativeRegisterContextWindows_i386.cpp     |  4 +-
 .../NativeRegisterContextWindows_x86_64.cpp   |  4 +-
 .../Windows/Common/NativeThreadWindows.cpp    | 32 +++++++
 10 files changed, 135 insertions(+), 92 deletions(-)

diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 24c9aa6b32659d..87a811123d5de8 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -491,24 +491,47 @@ NativeProcessWindows::OnDebugException(bool first_chance,
     return ExceptionResult::MaskException;
   }
   case DWORD(STATUS_BREAKPOINT):
-  case STATUS_WX86_BREAKPOINT:
-    if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
-      LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
-               record.GetExceptionAddress());
-
-      StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
-
-      if (NativeThreadWindows *stop_thread =
-              GetThreadByID(record.GetThreadID())) {
-        auto &register_context = stop_thread->GetRegisterContext();
+  case STATUS_WX86_BREAKPOINT: {
+    bool breakpoint_hit = false;
+    NativeThreadWindows *stop_thread = GetThreadByID(record.GetThreadID());
+
+    if (stop_thread) {
+      uint32_t hw_id = LLDB_INVALID_INDEX32;
+      auto &reg_ctx = stop_thread->GetRegisterContext();
+      reg_ctx.GetHardwareBreakHitIndex(hw_id, record.GetExceptionAddress());
+      if (hw_id != LLDB_INVALID_INDEX32) {
+        breakpoint_hit = true;
+        LLDB_LOG(log, "Hit hardware breakpoint at address {0:x}.",
+                 record.GetExceptionAddress());
+      } else if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
+        breakpoint_hit = true;
+        LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
+                 record.GetExceptionAddress());
         uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset();
         // The current PC is AFTER the BP opcode, on all architectures.
-        uint64_t pc = register_context.GetPC() - breakpoint_size;
-        register_context.SetPC(pc);
+        uint64_t pc = reg_ctx.GetPC() - breakpoint_size;
+        reg_ctx.SetPC(pc);
       }
 
-      SetState(eStateStopped, true);
-      return ExceptionResult::MaskException;
+      if (breakpoint_hit) {
+        StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
+        SetState(eStateStopped, true);
+        return ExceptionResult::MaskException;
+      } else {
+        const std::vector<ULONG_PTR> &args = record.GetExceptionArguments();
+        if (args.size() >= 2) {
+          reg_ctx.GetWatchpointHitIndex(hw_id, args[1]);
+          if (hw_id != LLDB_INVALID_INDEX32) {
+            addr_t wp_pc = record.GetExceptionAddress();
+            std::string desc =
+                formatv("{0} {1} {2}", args[1], hw_id, wp_pc).str();
+            StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint,
+                       desc);
+            SetState(eStateStopped, true);
+            return ExceptionResult::MaskException;
+          }
+        }
+      }
     }
 
     if (!initial_stop) {
@@ -531,6 +554,7 @@ NativeProcessWindows::OnDebugException(bool first_chance,
       // Hit the initial stop. Continue the application.
       return ExceptionResult::BreakInDebugger;
     }
+  }
 
     [[fallthrough]];
   default:
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
index 9128363eaa577a..95be1183abb759 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
@@ -18,9 +18,6 @@
 using namespace lldb;
 using namespace lldb_private;
 
-NativeRegisterContextWindows::NativeRegisterContextWindows(
-    NativeThreadProtocol &thread, RegisterInfoInterface *reg_info_interface_p)
-    : NativeRegisterContextRegisterInfo(thread, reg_info_interface_p) {}
 
 lldb::thread_t NativeRegisterContextWindows::GetThreadHandle() const {
   auto wthread = static_cast<NativeThreadWindows *>(&m_thread);
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
index 841b8547f3e904..d00595251f41de 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
@@ -17,11 +17,9 @@ namespace lldb_private {
 
 class NativeThreadWindows;
 
-class NativeRegisterContextWindows : public NativeRegisterContextRegisterInfo {
+class NativeRegisterContextWindows
+    : public virtual NativeRegisterContextRegisterInfo {
 public:
-  NativeRegisterContextWindows(
-      NativeThreadProtocol &native_thread,
-      RegisterInfoInterface *reg_info_interface_p);
 
   static std::unique_ptr<NativeRegisterContextWindows>
   CreateHostNativeRegisterContextWindows(const ArchSpec &target_arch,
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
index a9642d1c5e48da..069c327ee2f9a6 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
@@ -88,8 +88,8 @@ static Status SetWoW64ThreadContextHelper(lldb::thread_t thread_handle,
 
 NativeRegisterContextWindows_WoW64::NativeRegisterContextWindows_WoW64(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextWindows(native_thread,
-                                   CreateRegisterInfoInterface(target_arch)) {}
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {}
 
 bool NativeRegisterContextWindows_WoW64::IsGPR(uint32_t reg_index) const {
   return (reg_index >= k_first_gpr_i386 && reg_index < k_first_alias_i386);
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
index 4209fdf3c7109a..fd8a0c05c1b25c 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
@@ -128,8 +128,8 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
 
 NativeRegisterContextWindows_arm::NativeRegisterContextWindows_arm(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextWindows(native_thread,
-                                   CreateRegisterInfoInterface(target_arch)) {}
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {}
 
 bool NativeRegisterContextWindows_arm::IsGPR(uint32_t reg_index) const {
   return (reg_index >= k_first_gpr_arm && reg_index <= k_last_gpr_arm);
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
index 080a9140e36a64..547ddcc4035d46 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
@@ -10,7 +10,6 @@
 
 #include "NativeRegisterContextWindows_arm64.h"
 #include "NativeThreadWindows.h"
-#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 #include "ProcessWindowsLog.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/HostThread.h"
@@ -143,8 +142,14 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
 
 NativeRegisterContextWindows_arm64::NativeRegisterContextWindows_arm64(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextWindows(native_thread,
-                                   CreateRegisterInfoInterface(target_arch)) {}
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {
+  // Currently, there is no API to query the maximum supported hardware
+  // breakpoints and watchpoints on Windows. The values set below are based
+  // on tests conducted on Windows 11 with Snapdragon Elite X hardware.
+  m_max_hwp_supported = 1;
+  m_max_hbp_supported = 6;
+}
 
 bool NativeRegisterContextWindows_arm64::IsGPR(uint32_t reg_index) const {
   return (reg_index >= k_first_gpr_arm64 && reg_index <= k_last_gpr_arm64);
@@ -709,48 +714,49 @@ Status NativeRegisterContextWindows_arm64::WriteAllRegisterValues(
   return SetThreadContextHelper(GetThreadHandle(), &tls_context);
 }
 
-Status NativeRegisterContextWindows_arm64::IsWatchpointHit(uint32_t wp_index,
-                                                           bool &is_hit) {
-  return Status::FromErrorString("unimplemented");
-}
-
-Status NativeRegisterContextWindows_arm64::GetWatchpointHitIndex(
-    uint32_t &wp_index, lldb::addr_t trap_addr) {
-  return Status::FromErrorString("unimplemented");
-}
-
-Status NativeRegisterContextWindows_arm64::IsWatchpointVacant(uint32_t wp_index,
-                                                              bool &is_vacant) {
-  return Status::FromErrorString("unimplemented");
-}
-
-Status NativeRegisterContextWindows_arm64::SetHardwareWatchpointWithIndex(
-    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
-  return Status::FromErrorString("unimplemented");
-}
-
-bool NativeRegisterContextWindows_arm64::ClearHardwareWatchpoint(
-    uint32_t wp_index) {
-  return false;
-}
+llvm::Error NativeRegisterContextWindows_arm64::ReadHardwareDebugInfo() {
+  ::CONTEXT tls_context;
+  Status error = GetThreadContextHelper(GetThreadHandle(), &tls_context,
+                                        CONTEXT_DEBUG_REGISTERS);
+  if (error.Fail())
+    return error.ToError();
 
-Status NativeRegisterContextWindows_arm64::ClearAllHardwareWatchpoints() {
-  return Status::FromErrorString("unimplemented");
-}
+  for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+    m_hwp_regs[i].address = tls_context.Wvr[i];
+    m_hwp_regs[i].control = tls_context.Wcr[i];
+  }
 
-uint32_t NativeRegisterContextWindows_arm64::SetHardwareWatchpoint(
-    lldb::addr_t addr, size_t size, uint32_t watch_flags) {
-  return LLDB_INVALID_INDEX32;
+  for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+    m_hbp_regs[i].address = tls_context.Bvr[i];
+    m_hbp_regs[i].control = tls_context.Bcr[i];
+  }
+  return llvm::Error::success();
 }
 
-lldb::addr_t
-NativeRegisterContextWindows_arm64::GetWatchpointAddress(uint32_t wp_index) {
-  return LLDB_INVALID_ADDRESS;
-}
+llvm::Error
+NativeRegisterContextWindows_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
+  ::CONTEXT tls_context;
+  Status error = GetThreadContextHelper(GetThreadHandle(), &tls_context,
+                                        CONTEXT_DEBUG_REGISTERS);
+  if (error.Fail())
+    return error.ToError();
+
+  switch (hwbType) {
+  case eDREGTypeWATCH:
+    for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+      tls_context.Wvr[i] = m_hwp_regs[i].address;
+      tls_context.Wcr[i] = m_hwp_regs[i].control;
+    }
+    break;
+  case eDREGTypeBREAK:
+    for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+      tls_context.Bvr[i] = m_hbp_regs[i].address;
+      tls_context.Bcr[i] = m_hbp_regs[i].control;
+    }
+    break;
+  }
 
-uint32_t NativeRegisterContextWindows_arm64::NumSupportedHardwareWatchpoints() {
-  // Not implemented
-  return 0;
+  return SetThreadContextHelper(GetThreadHandle(), &tls_context).ToError();
 }
 
 #endif // defined(__aarch64__) || defined(_M_ARM64)
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h
index 88afc1e7b18a2f..e73a6af4cbf805 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h
@@ -10,6 +10,8 @@
 #ifndef liblldb_NativeRegisterContextWindows_arm64_h_
 #define liblldb_NativeRegisterContextWindows_arm64_h_
 
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 #include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
 
 #include "NativeRegisterContextWindows.h"
@@ -18,7 +20,9 @@ namespace lldb_private {
 
 class NativeThreadWindows;
 
-class NativeRegisterContextWindows_arm64 : public NativeRegisterContextWindows {
+class NativeRegisterContextWindows_arm64
+    : public NativeRegisterContextWindows,
+      public NativeRegisterContextDBReg_arm64 {
 public:
   NativeRegisterContextWindows_arm64(const ArchSpec &target_arch,
                                      NativeThreadProtocol &native_thread);
@@ -37,28 +41,6 @@ class NativeRegisterContextWindows_arm64 : public NativeRegisterContextWindows {
 
   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 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;
-
 protected:
   Status GPRRead(const uint32_t reg, RegisterValue &reg_value);
 
@@ -72,6 +54,10 @@ class NativeRegisterContextWindows_arm64 : public NativeRegisterContextWindows {
   bool IsGPR(uint32_t reg_index) const;
 
   bool IsFPR(uint32_t reg_index) const;
+
+  llvm::Error ReadHardwareDebugInfo() override;
+
+  llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
 };
 
 } // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
index 53df9866793946..7c13759df462da 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
@@ -92,8 +92,8 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
 
 NativeRegisterContextWindows_i386::NativeRegisterContextWindows_i386(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextWindows(native_thread,
-                                   CreateRegisterInfoInterface(target_arch)) {}
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {}
 
 bool NativeRegisterContextWindows_i386::IsGPR(uint32_t reg_index) const {
   return (reg_index < k_first_alias_i386);
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
index 4c59273b845aaa..c54c31e48e4e5f 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
@@ -110,8 +110,8 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
 
 NativeRegisterContextWindows_x86_64::NativeRegisterContextWindows_x86_64(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
-    : NativeRegisterContextWindows(native_thread,
-                                   CreateRegisterInfoInterface(target_arch)) {}
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {}
 
 bool NativeRegisterContextWindows_x86_64::IsGPR(uint32_t reg_index) const {
   return (reg_index >= k_first_gpr_x86_64 && reg_index < k_first_alias_x86_64);
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
index 8ad59cd1ece887..cade9c09ffb192 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
@@ -178,9 +178,41 @@ Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
 
 Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
                                                   size_t size) {
+#if defined(__aarch64__) || defined(_M_ARM64)
+  if (m_state == eStateLaunching)
+    return Status();
+
+  Status error = RemoveHardwareBreakpoint(addr);
+  if (error.Fail())
+    return error;
+
+  uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);
+
+  if (bp_index == LLDB_INVALID_INDEX32)
+    return Status::FromErrorString("Setting hardware breakpoint failed.");
+
+  m_hw_breakpoint_index_map.insert({addr, bp_index});
+
+  return Status();
+#else
   return Status::FromErrorString("unimplemented.");
+#endif
 }
 
 Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
+#if defined(__aarch64__) || defined(_M_ARM64)
+  auto bp = m_hw_breakpoint_index_map.find(addr);
+  if (bp == m_hw_breakpoint_index_map.end())
+    return Status();
+
+  uint32_t bp_index = bp->second;
+  if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) {
+    m_hw_breakpoint_index_map.erase(bp);
+    return Status();
+  }
+
+  return Status::FromErrorString("Clearing hardware breakpoint failed.");
+#else
   return Status::FromErrorString("unimplemented.");
+#endif
 }

>From 895f09f6f765eaa28e938ff41f994f2495534139 Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid <omair.javaid at linaro.org>
Date: Wed, 9 Oct 2024 12:29:39 +0500
Subject: [PATCH 2/3] Remove HW breakpoint support

---
 .../Windows/Common/NativeProcessWindows.cpp   | 39 +++++++------------
 .../NativeRegisterContextWindows_arm64.cpp    | 18 ++-------
 .../Windows/Common/NativeThreadWindows.cpp    | 32 ---------------
 3 files changed, 17 insertions(+), 72 deletions(-)

diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 87a811123d5de8..0c65473d3d3f10 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
@@ -491,42 +491,32 @@ NativeProcessWindows::OnDebugException(bool first_chance,
     return ExceptionResult::MaskException;
   }
   case DWORD(STATUS_BREAKPOINT):
-  case STATUS_WX86_BREAKPOINT: {
-    bool breakpoint_hit = false;
-    NativeThreadWindows *stop_thread = GetThreadByID(record.GetThreadID());
+  case STATUS_WX86_BREAKPOINT:
 
-    if (stop_thread) {
-      uint32_t hw_id = LLDB_INVALID_INDEX32;
+    if (NativeThreadWindows *stop_thread =
+            GetThreadByID(record.GetThreadID())) {
       auto &reg_ctx = stop_thread->GetRegisterContext();
-      reg_ctx.GetHardwareBreakHitIndex(hw_id, record.GetExceptionAddress());
-      if (hw_id != LLDB_INVALID_INDEX32) {
-        breakpoint_hit = true;
-        LLDB_LOG(log, "Hit hardware breakpoint at address {0:x}.",
-                 record.GetExceptionAddress());
-      } else if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
-        breakpoint_hit = true;
+      const auto exception_addr = record.GetExceptionAddress();
+      const auto thread_id = record.GetThreadID();
+
+      if (FindSoftwareBreakpoint(exception_addr)) {
         LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
-                 record.GetExceptionAddress());
-        uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset();
-        // The current PC is AFTER the BP opcode, on all architectures.
-        uint64_t pc = reg_ctx.GetPC() - breakpoint_size;
-        reg_ctx.SetPC(pc);
-      }
+                 exception_addr);
 
-      if (breakpoint_hit) {
-        StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
+        reg_ctx.SetPC(reg_ctx.GetPC() - GetSoftwareBreakpointPCOffset());
+        StopThread(thread_id, StopReason::eStopReasonBreakpoint);
         SetState(eStateStopped, true);
         return ExceptionResult::MaskException;
       } else {
         const std::vector<ULONG_PTR> &args = record.GetExceptionArguments();
         if (args.size() >= 2) {
+          uint32_t hw_id = LLDB_INVALID_INDEX32;
           reg_ctx.GetWatchpointHitIndex(hw_id, args[1]);
+
           if (hw_id != LLDB_INVALID_INDEX32) {
-            addr_t wp_pc = record.GetExceptionAddress();
             std::string desc =
-                formatv("{0} {1} {2}", args[1], hw_id, wp_pc).str();
-            StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint,
-                       desc);
+                formatv("{0} {1} {2}", args[1], hw_id, exception_addr).str();
+            StopThread(thread_id, StopReason::eStopReasonWatchpoint, desc);
             SetState(eStateStopped, true);
             return ExceptionResult::MaskException;
           }
@@ -554,7 +544,6 @@ NativeProcessWindows::OnDebugException(bool first_chance,
       // Hit the initial stop. Continue the application.
       return ExceptionResult::BreakInDebugger;
     }
-  }
 
     [[fallthrough]];
   default:
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
index 547ddcc4035d46..fb2997eb37b429 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
@@ -147,8 +147,8 @@ NativeRegisterContextWindows_arm64::NativeRegisterContextWindows_arm64(
   // Currently, there is no API to query the maximum supported hardware
   // breakpoints and watchpoints on Windows. The values set below are based
   // on tests conducted on Windows 11 with Snapdragon Elite X hardware.
-  m_max_hwp_supported = 1;
-  m_max_hbp_supported = 6;
+  m_max_hwp_supported = 2;
+  m_max_hbp_supported = 0;
 }
 
 bool NativeRegisterContextWindows_arm64::IsGPR(uint32_t reg_index) const {
@@ -726,10 +726,6 @@ llvm::Error NativeRegisterContextWindows_arm64::ReadHardwareDebugInfo() {
     m_hwp_regs[i].control = tls_context.Wcr[i];
   }
 
-  for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
-    m_hbp_regs[i].address = tls_context.Bvr[i];
-    m_hbp_regs[i].control = tls_context.Bcr[i];
-  }
   return llvm::Error::success();
 }
 
@@ -741,19 +737,11 @@ NativeRegisterContextWindows_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
   if (error.Fail())
     return error.ToError();
 
-  switch (hwbType) {
-  case eDREGTypeWATCH:
+  if (hwbType == eDREGTypeWATCH) {
     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
       tls_context.Wvr[i] = m_hwp_regs[i].address;
       tls_context.Wcr[i] = m_hwp_regs[i].control;
     }
-    break;
-  case eDREGTypeBREAK:
-    for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
-      tls_context.Bvr[i] = m_hbp_regs[i].address;
-      tls_context.Bcr[i] = m_hbp_regs[i].control;
-    }
-    break;
   }
 
   return SetThreadContextHelper(GetThreadHandle(), &tls_context).ToError();
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
index cade9c09ffb192..8ad59cd1ece887 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
@@ -178,41 +178,9 @@ Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
 
 Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
                                                   size_t size) {
-#if defined(__aarch64__) || defined(_M_ARM64)
-  if (m_state == eStateLaunching)
-    return Status();
-
-  Status error = RemoveHardwareBreakpoint(addr);
-  if (error.Fail())
-    return error;
-
-  uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);
-
-  if (bp_index == LLDB_INVALID_INDEX32)
-    return Status::FromErrorString("Setting hardware breakpoint failed.");
-
-  m_hw_breakpoint_index_map.insert({addr, bp_index});
-
-  return Status();
-#else
   return Status::FromErrorString("unimplemented.");
-#endif
 }
 
 Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
-#if defined(__aarch64__) || defined(_M_ARM64)
-  auto bp = m_hw_breakpoint_index_map.find(addr);
-  if (bp == m_hw_breakpoint_index_map.end())
-    return Status();
-
-  uint32_t bp_index = bp->second;
-  if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) {
-    m_hw_breakpoint_index_map.erase(bp);
-    return Status();
-  }
-
-  return Status::FromErrorString("Clearing hardware breakpoint failed.");
-#else
   return Status::FromErrorString("unimplemented.");
-#endif
 }

>From b5f2913360cc9e0c2a1fc8ce9e7bd526b8418c9e Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid <omair.javaid at linaro.org>
Date: Wed, 9 Oct 2024 13:39:17 +0500
Subject: [PATCH 3/3] Run clang-format and fix issues

---
 .../Process/Windows/Common/NativeRegisterContextWindows.cpp      | 1 -
 .../Process/Windows/Common/NativeRegisterContextWindows.h        | 1 -
 2 files changed, 2 deletions(-)

diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
index 95be1183abb759..effe6df36b5765 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp
@@ -18,7 +18,6 @@
 using namespace lldb;
 using namespace lldb_private;
 
-
 lldb::thread_t NativeRegisterContextWindows::GetThreadHandle() const {
   auto wthread = static_cast<NativeThreadWindows *>(&m_thread);
   return wthread->GetHostThread().GetNativeThread().GetSystemHandle();
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
index d00595251f41de..0f9e37dbd9f527 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
@@ -20,7 +20,6 @@ class NativeThreadWindows;
 class NativeRegisterContextWindows
     : public virtual NativeRegisterContextRegisterInfo {
 public:
-
   static std::unique_ptr<NativeRegisterContextWindows>
   CreateHostNativeRegisterContextWindows(const ArchSpec &target_arch,
                                          NativeThreadProtocol &native_thread);



More information about the lldb-commits mailing list