-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][Windows] WoA HW Watchpoint support in LLDB #108072
Conversation
@llvm/pr-subscribers-lldb Author: Omair Javaid (omjavaid) ChangesThis pull request adds support for hardware breakpoints and watchpoints in LLDB on Windows on ARM. Known Issues:
Testing:
Full diff: https://github.com/llvm/llvm-project/pull/108072.diff 10 Files Affected:
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
index 24c9aa6b32659d..886df987dc84b6 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 ®ister_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 ®_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..66ced71d27d69a 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.h
@@ -17,11 +17,8 @@ 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..1ba89fbf3215bb 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_WoW64.cpp
@@ -88,7 +88,7 @@ static Status SetWoW64ThreadContextHelper(lldb::thread_t thread_handle,
NativeRegisterContextWindows_WoW64::NativeRegisterContextWindows_WoW64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextWindows(native_thread,
+ : NativeRegisterContextRegisterInfo(native_thread,
CreateRegisterInfoInterface(target_arch)) {}
bool NativeRegisterContextWindows_WoW64::IsGPR(uint32_t reg_index) const {
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
index 4209fdf3c7109a..470da1afc8222e 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm.cpp
@@ -128,7 +128,7 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
NativeRegisterContextWindows_arm::NativeRegisterContextWindows_arm(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextWindows(native_thread,
+ : NativeRegisterContextRegisterInfo(native_thread,
CreateRegisterInfoInterface(target_arch)) {}
bool NativeRegisterContextWindows_arm::IsGPR(uint32_t reg_index) const {
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
index 080a9140e36a64..ae09ebffa5508c 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..164d46143df950 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.h
@@ -11,6 +11,8 @@
#define liblldb_NativeRegisterContextWindows_arm64_h_
#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include "NativeRegisterContextWindows.h"
@@ -18,7 +20,8 @@ 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 +40,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 ®_value);
@@ -72,6 +53,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..71e3616d1af9c9 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_i386.cpp
@@ -92,7 +92,7 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
NativeRegisterContextWindows_i386::NativeRegisterContextWindows_i386(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextWindows(native_thread,
+ : NativeRegisterContextRegisterInfo(native_thread,
CreateRegisterInfoInterface(target_arch)) {}
bool NativeRegisterContextWindows_i386::IsGPR(uint32_t reg_index) const {
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..3709390d953d19 100644
--- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
@@ -110,7 +110,7 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
NativeRegisterContextWindows_x86_64::NativeRegisterContextWindows_x86_64(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextWindows(native_thread,
+ : NativeRegisterContextRegisterInfo(native_thread,
CreateRegisterInfoInterface(target_arch)) {}
bool NativeRegisterContextWindows_x86_64::IsGPR(uint32_t reg_index) const {
diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
index 8ad59cd1ece887..cd5cd4541082fb 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
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
1c29d30
to
ac61e5a
Compare
i skimmed the patch, I didn't see anything that concerns me. The fact that we can't query the number of hardware watchpoints/breakpoints means that this code will misbehave on other platforms where the numbers are different - we might have four hardware watchpoints, but you'll be limited to only setting one. The hardware might only have 4 hardware breakpoints, so this code will let you set two additional ones which are ignored. But I don't know what approach would be better here, given what Windows apparently provides. I'll probably need to touch this new code a tiny bit once it's merged, for #105594 but there's no reason for Omair to do anything about that right now, I'm not ready to land my patches yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems ok to me.
If I had to guess, I'd say that the initial stop problem is due to us stopping the process "too early" (i.e., in a state where it's not yet fully initialized and ready to accept debugger commands). Maybe there's a different way to stop the process at the first instruction?
lldb/source/Plugins/Process/Windows/Common/NativeThreadWindows.cpp
Outdated
Show resolved
Hide resolved
lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
Show resolved
Hide resolved
Remind me, does lldb support hardware breakpoints for x86 right now either? From the content of this PR, I assume it does not. (which is fine, I'm just trying to be clear what our starting point is) |
Relates to #80665 |
yes x86_64 windows does not support hardware breakpoints. However it does support hardware watchpoints. |
Yes I think there might be a Windows API launch flag that can let us do early detection of hardware breakpoints and watchpoints. But so far after lots of experimentation I have not been able to find the right set. |
Is it possible this is a bug in Windows itself? Though it seems unlikely given that Visual Studio supports WoA. I'm not sure about merging this until we know more about that part, at least whether it's a bug or not. Perhaps we (Linaro) can get some information from Microsoft on this? |
So further update from my offline (out of LLDB) testing with windows API and setting hardware breakpoints suggest that we might be doing something different on LLDB side during launch or while setting hardware breakpoints/watchpoints that stops us from hitting those exceptions. In simple console based debugger I have played with Windows API and set hardware breakpoints and found a good configuration that works. I will keep debugging this might get to fix it on LLDB side as well. And will talk to our friends at MS at some stage for any clarifications that might be needed. |
@DavidSpickett @labath I have updated this PR and dropped hardware breakpoint support for the unresolved "set hw break on main" issue As x86_64 windows also does not support hardware breakpoints (probably for the same reason). This PR now only implements HW watchpoint support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So is this X86 and ARM64 or just one?
Also this needs a release note, which is a good place to note the limitations as well.
lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
Outdated
Show resolved
Hide resolved
lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
Show resolved
Hide resolved
2b55cfa
to
cf027cf
Compare
lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp
Outdated
Show resolved
Hide resolved
lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_x86_64.cpp
Show resolved
Hide resolved
Please update the PR description to reflect what the current code does, or if you want to leave the notes there, move them into an obvious section that you can cut out if/when this gets merged. |
I have updates the PR description the "Known Issues (Just for documentation):" part will be skipped in the final patch description. |
cf027cf
to
d2f686a
Compare
I want to be 100% sure of the status of this issue:
This is a problem with watchpoints too, right? I can see an argument that says code breakpoints are much more likely to be placed before the initial stop, so watchpoints are still useful even with this limitation and this PR should still be merged. But please open an issue for that, describing the problem and as far as you know. why it might be occurring. It will give us something to "mark as duplicate" :) |
Yes this happens with watchpoints too on both AArch64 and x64 WIndows.
Yes because LLDB requires a running process to set watchpoints however for breakpoints thats not the case. In most cases user sets breakpoint on main and then set watchpoints which masks this problem altogether.
I have create #125054 |
Agreed, this isn't ideal but it is an improvement from the current features. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're hitting limitations in Windows itself, and 1 watchpoint is more useful than zero, so this LGTM.
To preempt a potential discussion: I think this should not be backported to 20. Unless you've got a very good reason for it. We don't have the most comprehensive testing on Windows and we already have a few caveats here. We might encounter more as time goes on and fixes may be complex.
But, by LLDB 21, maybe we will have ironed those out.
Also thanks for tackling this, I know I said once (possibly twice) that I'd do it but kept getting distracted. I know you put a bunch of research time into this too. |
Apparently, these changes break lldb-remote-linux-win buildbot with the following error:
https://lab.llvm.org/buildbot/#/builders/197/builds/1447/steps/8/logs/stdio https://lab.llvm.org/buildbot/#/builders/197/builds/1447 Could you take care of it? |
@dzhidzhoev I am taking a look. Thanks for spotting this. |
This patch fixes LLDB Windows build with MSVC compiler. MSVC deletes the default constructor due to virtual inheritance rules. Explicitly define the default constructor in NativeRegisterContextWindows to ensure constructibility.
This PR adds support for hardware watchpoints in LLDB for AArch64 Windows targets. Windows does not provide an API to query the number of available hardware watchpoints supported by underlying hardware platform. Therefore, current implementation supports only a single hardware watchpoint, which has been verified on Windows 11 using Microsoft SQ2 and Snapdragon Elite X hardware. LLDB test suite ninja check-lldb still fails watchpoint-related tests. However, tests that do not require more than a single watchpoint pass successfully when run individually.
This PR adds support for hardware watchpoints in LLDB for AArch64 Windows targets. Windows does not provide an API to query the number of available hardware watchpoints supported by underlying hardware platform. Therefore, current implementation supports only a single hardware watchpoint, which has been verified on Windows 11 using Microsoft SQ2 and Snapdragon Elite X hardware. LLDB test suite ninja check-lldb still fails watchpoint-related tests. However, tests that do not require more than a single watchpoint pass successfully when run individually.
This PR adds support for hardware watchpoints in LLDB for AArch64 Windows targets. Windows does not provide an API to query the number of available hardware watchpoints supported by underlying hardware platform. Therefore, current implementation supports only a single hardware watchpoint, which has been verified on Windows 11 using Microsoft SQ2 and Snapdragon Elite X hardware. LLDB test suite ninja check-lldb still fails watchpoint-related tests. However, tests that do not require more than a single watchpoint pass successfully when run individually.
This PR adds support for hardware watchpoints in LLDB for AArch64 Windows
targets.
Windows does not provide an API to query the number of available hardware
watchpoints supported by underlying hardware platform. Therefore, current
implementation supports only a single hardware watchpoint, which has been
verified on Windows 11 using Microsoft SQ2 and Snapdragon Elite X hardware.
LLDB test suite ninja check-lldb still fails watchpoint-related tests. However,
tests that do not require more than a single watchpoint pass successfully
when run individually.
Known Issues (Just for documentation):
Number of Supported Hardware Breakpoints/Watchpoints: Windows does not provide the exact number of supported hardware breakpoints or watchpoints. The current implementation guesses this number based on testing how many can be successfully applied on the platform. winnt.h defines ARM64_MAX_WATCHPOINTS = 2 and ARM64_MAX_BREAKPOINTS = 8 however actual number differs.
Initial Stop Behavior: Hardware breakpoints or watchpoints set on the initial stop do not trigger, even though they are correctly written to the Windows context. They only trigger if set after the main program has started. This issue causes the test suite to fail when it attempts to set hardware breakpoints on the main function before running, as these do not get triggered.