[Lldb-commits] [lldb] [lldb][ARM] Port Arm Linux to use NativeRegisterContextDBReg (PR #152284)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 6 03:15:30 PDT 2025
https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/152284
Which is also used by AArch64 and LoongArch.
To do this I had to make some adjustments to NativeRegisterContextDBReg:
* New method AdjustBreakpoint. This is like AdjustWatchpoint, but
only Arm needs to adjust breakpoints. For Arm this method removes the
bottom address bits according to the mode.
* MakeWatchControlValue now takes the address too. Arm uses this to
generate the byte mask.
To test this, I ran the test suite as usual on Arm and found no new
failures, then ran it again with all test programs compiled with
`-mthumb`. This means the binaries will be entirely Thumb code.
Finally I tested it on AArch64, but this is mostly a build test,
as I did not run the entire test suite compiled to AArch32.
Prior to this change, these tests failed with `-mthumb`:
```
Failed Tests (14):
lldb-api :: commands/process/reverse-continue/TestReverseContinue.py
lldb-api :: functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
lldb-api :: functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
lldb-api :: functionalities/reverse-execution/TestReverseContinueBreakpoints.py
lldb-api :: functionalities/reverse-execution/TestReverseContinueWatchpoints.py
lldb-api :: functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py
lldb-api :: functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py
lldb-api :: functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py
lldb-api :: functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py
lldb-api :: functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py
lldb-api :: functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py
lldb-api :: functionalities/thread/jump/TestThreadJump.py
lldb-api :: lang/c/vla/TestVLA.py
lldb-api :: linux/sepdebugsymlink/TestTargetSymbolsSepDebugSymlink.py
```
After this change, no new failures occurred. So I am confident it is
correct.
Looking at those failures, it's a few things:
* Something in the reverse execution wrapper that I can't figure out, but is
likely nothing to do with the real breakpoints.
* The inability to tail call when building thumb code, because the call goes
via. a veneer that might do a mode switch.
* Assumptions about source locations being in specific places.
None of which are massive issues I feel like need fixing before doing this port.
>From 6753d9b62e599dac57d8ba710cedf0640e5b43cd Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 16 Dec 2024 16:02:33 +0000
Subject: [PATCH 1/2] [lldb][ARM] Port Arm Linux to use
NativeRegisterContextDBReg
Which is also used by AArch64 and LoongArch.
To do this I had to make some adjustments to NativeRegisterContextDBReg:
* New method AdjustBreakpoint. This is like AdjustWatchpoint, but
only Arm needs to adjust breakpoints. For Arm this method removes the
bottom address bits according to the mode.
* MakeWatchControlValue now takes the address too. Arm uses this to
generate the byte mask.
To test this, I ran the test suite as usual on Arm and found no new
failures, then ran it again with all test programs compiled with
`-mthumb`. This means the binaries will be entirely Thumb code.
Finally I tested it on AArch64, but this is mostly a build test,
as I did not run the entire test suite compiled to AArch32 mode.
Prior to this change, these tests failed with `-mthumb`:
```
Failed Tests (14):
lldb-api :: commands/process/reverse-continue/TestReverseContinue.py
lldb-api :: functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
lldb-api :: functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
lldb-api :: functionalities/reverse-execution/TestReverseContinueBreakpoints.py
lldb-api :: functionalities/reverse-execution/TestReverseContinueWatchpoints.py
lldb-api :: functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py
lldb-api :: functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py
lldb-api :: functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py
lldb-api :: functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py
lldb-api :: functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py
lldb-api :: functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py
lldb-api :: functionalities/thread/jump/TestThreadJump.py
lldb-api :: lang/c/vla/TestVLA.py
lldb-api :: linux/sepdebugsymlink/TestTargetSymbolsSepDebugSymlink.py
```
After this change, no new failures occured. So I am confident it is
correct.
Looking into those failures, it's a few things:
* Something in the reverse execution wrapper that I can't figure out, but is
likely nothing to do with the real breakpoints.
* The inability to tail call when building thumb code, because the call goes
via. a veneer that might do a mode switch.
* Assumptions about source locations being in speciifc places.
None of which are massive issues I feel like need fixing before doing this port.
---
.../Linux/NativeRegisterContextLinux_arm.cpp | 529 ++----------------
.../Linux/NativeRegisterContextLinux_arm.h | 51 +-
.../Plugins/Process/Utility/CMakeLists.txt | 1 +
.../Utility/NativeRegisterContextDBReg.cpp | 4 +-
.../Utility/NativeRegisterContextDBReg.h | 14 +-
.../NativeRegisterContextDBReg_arm.cpp | 116 ++++
.../Utility/NativeRegisterContextDBReg_arm.h | 46 ++
.../NativeRegisterContextDBReg_arm64.cpp | 7 +-
.../NativeRegisterContextDBReg_arm64.h | 3 +-
.../NativeRegisterContextDBReg_loongarch.cpp | 3 +-
.../NativeRegisterContextDBReg_loongarch.h | 3 +-
11 files changed, 243 insertions(+), 534 deletions(-)
create mode 100644 lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.cpp
create mode 100644 lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index fdafacf410d64..25e91c84ec584 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -76,7 +76,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
::memset(&m_fpr, 0, sizeof(m_fpr));
::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
- ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs));
+ ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
// 16 is just a maximum value, query hardware for actual watchpoint count
m_max_hwp_supported = 16;
@@ -283,484 +283,60 @@ bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const {
return false;
}
-uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareBreakpoints() {
- Log *log = GetLog(POSIXLog::Breakpoints);
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Status error;
-
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return 0;
-
- LLDB_LOG(log, "{0}", m_max_hbp_supported);
- return m_max_hbp_supported;
-}
-
-uint32_t
-NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
- size_t size) {
- Log *log = GetLog(POSIXLog::Breakpoints);
- LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, bp_index = 0;
-
- // Setup address and control values.
- // Use size to get a hint of arm vs thumb modes.
- switch (size) {
- case 2:
- control_value = (0x3 << 5) | 7;
- addr &= ~1;
- break;
- case 4:
- control_value = (0xfu << 5) | 7;
- addr &= ~3;
- break;
- default:
- return LLDB_INVALID_INDEX32;
- }
-
- // Iterate over stored breakpoints and find a free bp_index
- bp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- if ((m_hbr_regs[i].control & 1) == 0) {
- bp_index = i; // Mark last free slot
- } else if (m_hbr_regs[i].address == addr) {
- return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
- }
- }
-
- if (bp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Update breakpoint in local cache
- m_hbr_regs[bp_index].real_addr = addr;
- m_hbr_regs[bp_index].address = addr;
- m_hbr_regs[bp_index].control = control_value;
-
- // PTRACE call to set corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK,
- bp_index);
-
- if (error.Fail()) {
- m_hbr_regs[bp_index].address = 0;
- m_hbr_regs[bp_index].control &= ~1;
-
- return LLDB_INVALID_INDEX32;
- }
-
- return bp_index;
-}
-
-bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) {
- Log *log = GetLog(POSIXLog::Breakpoints);
- LLDB_LOG(log, "hw_idx: {0}", hw_idx);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return false;
-
- if (hw_idx >= m_max_hbp_supported)
- return false;
-
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
- uint32_t tempControl = m_hbr_regs[hw_idx].control;
-
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
-
- // PTRACE call to clear corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK,
- hw_idx);
-
- if (error.Fail()) {
- m_hbr_regs[hw_idx].control = tempControl;
- m_hbr_regs[hw_idx].address = tempAddr;
-
- return false;
- }
-
- return true;
-}
-
-Status NativeRegisterContextLinux_arm::GetHardwareBreakHitIndex(
- uint32_t &bp_index, lldb::addr_t trap_addr) {
- Log *log = GetLog(POSIXLog::Breakpoints);
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- lldb::addr_t break_addr;
-
- for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
- break_addr = m_hbr_regs[bp_index].address;
-
- if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) {
- m_hbr_regs[bp_index].hit_addr = trap_addr;
- return Status();
- }
- }
-
- bp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-Status NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() {
- Log *log = GetLog(POSIXLog::Breakpoints);
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__);
-
- Status error;
-
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return error;
-
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0;
-
- for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- if (m_hbr_regs[i].control & 0x01) {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hbr_regs[i].address;
- tempControl = m_hbr_regs[i].control;
-
- // Clear breakpoints in local cache
- m_hbr_regs[i].control &= ~1;
- m_hbr_regs[i].address = 0;
-
- // Ptrace call to update hardware debug registers
- error =
- WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK, i);
-
- if (error.Fail()) {
- m_hbr_regs[i].control = tempControl;
- m_hbr_regs[i].address = tempAddr;
-
- return error;
- }
- }
- }
-
- return Status();
-}
-
-uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() {
- Log *log = GetLog(POSIXLog::Watchpoints);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return 0;
-
- LLDB_LOG(log, "{0}", m_max_hwp_supported);
- return m_max_hwp_supported;
-}
-
-uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
- watch_flags);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
- lldb::addr_t real_addr = addr;
-
- // Check if we are setting watchpoint other than read/write/access Also
- // update watchpoint flag to match Arm write-read bit configuration.
- switch (watch_flags) {
- case 1:
- watch_flags = 2;
- break;
- case 2:
- watch_flags = 1;
- break;
- case 3:
- break;
- default:
- return LLDB_INVALID_INDEX32;
- }
-
- // Can't watch zero bytes
- // Can't watch more than 4 bytes per WVR/WCR pair
-
- if (size == 0 || size > 4)
- return LLDB_INVALID_INDEX32;
-
- // Check 4-byte alignment for hardware watchpoint target address. Below is a
- // hack to recalculate address and size in order to make sure we can watch
- // non 4-byte aligned addresses as well.
- if (addr & 0x03) {
- uint8_t watch_mask = (addr & 0x03) + size;
-
- if (watch_mask > 0x04)
- return LLDB_INVALID_INDEX32;
- else if (watch_mask <= 0x02)
- size = 2;
- else
- size = 4;
-
- addr = addr & (~0x03);
- }
-
- // We can only watch up to four bytes that follow a 4 byte aligned address
- // per watchpoint register pair, so make sure we can properly encode this.
- addr_word_offset = addr % 4;
- byte_mask = ((1u << size) - 1u) << addr_word_offset;
-
- // Check if we need multiple watchpoint register
- if (byte_mask > 0xfu)
- return LLDB_INVALID_INDEX32;
-
- // Setup control value
- // Make the byte_mask into a valid Byte Address Select mask
- control_value = byte_mask << 5;
-
- // Turn on appropriate watchpoint flags read or write
- control_value |= (watch_flags << 3);
-
- // Enable this watchpoint and make it stop in privileged or user mode;
- control_value |= 7;
-
- // Make sure bits 1:0 are clear in our address
- addr &= ~((lldb::addr_t)3);
-
- // Iterate over stored watchpoints and find a free wp_index
- wp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- if ((m_hwp_regs[i].control & 1) == 0) {
- wp_index = i; // Mark last free slot
- } else if (m_hwp_regs[i].address == addr) {
- return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
- }
- }
-
- if (wp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].real_addr = real_addr;
- m_hwp_regs[wp_index].address = addr;
- m_hwp_regs[wp_index].control = control_value;
-
- // PTRACE call to set corresponding watchpoint register.
- error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH,
- wp_index);
-
- if (error.Fail()) {
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].control &= ~1;
-
- return LLDB_INVALID_INDEX32;
- }
-
- return wp_index;
-}
-
-bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint(
- uint32_t wp_index) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return false;
-
- if (wp_index >= m_max_hwp_supported)
- return false;
-
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
- uint32_t tempControl = m_hwp_regs[wp_index].control;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH,
- wp_index);
-
- if (error.Fail()) {
- m_hwp_regs[wp_index].control = tempControl;
- m_hwp_regs[wp_index].address = tempAddr;
-
- return false;
- }
-
- return true;
-}
-
-Status NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() {
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return error;
-
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0;
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- if (m_hwp_regs[i].control & 0x01) {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hwp_regs[i].address;
- tempControl = m_hwp_regs[i].control;
-
- // Clear watchpoints in local cache
- m_hwp_regs[i].control &= ~1;
- m_hwp_regs[i].address = 0;
-
- // Ptrace call to update hardware debug registers
- error =
- WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH, i);
-
- if (error.Fail()) {
- m_hwp_regs[i].control = tempControl;
- m_hwp_regs[i].address = tempAddr;
-
- return error;
- }
- }
- }
-
- return Status();
-}
-
-uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) {
- case 0x01:
- return 1;
- case 0x03:
- return 2;
- case 0x07:
- return 3;
- case 0x0f:
- return 4;
- default:
- return 0;
- }
-}
-bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
- return true;
- else
- return false;
-}
-
-Status
-NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index,
- lldb::addr_t trap_addr) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
-
- uint32_t watch_size;
- lldb::addr_t watch_addr;
-
- for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
- watch_size = GetWatchpointSize(wp_index);
- watch_addr = m_hwp_regs[wp_index].address;
-
- if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
- trap_addr < watch_addr + watch_size) {
- m_hwp_regs[wp_index].hit_addr = trap_addr;
- return Status();
- }
- }
-
- wp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
-
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].real_addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) {
- Log *log = GetLog(POSIXLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
-
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].hit_addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
- Status error;
-
- if (!m_refresh_hwdebug_info) {
- return Status();
- }
+llvm::Error NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
+ if (!m_refresh_hwdebug_info)
+ return llvm::Error::success();
#ifdef __arm__
unsigned int cap_val;
-
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(),
- nullptr, &cap_val,
- sizeof(unsigned int));
+ Status error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val,
+ sizeof(unsigned int));
if (error.Fail())
- return error;
+ return error.ToError();
m_max_hwp_supported = (cap_val >> 8) & 0xff;
m_max_hbp_supported = cap_val & 0xff;
m_refresh_hwdebug_info = false;
- return error;
+ return error.ToError();
#else // __aarch64__
return arm64::ReadHardwareDebugInfo(m_thread.GetID(), m_max_hwp_supported,
- m_max_hbp_supported);
+ m_max_hbp_supported)
+ .ToError();
#endif // ifdef __arm__
}
-Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(
- NativeRegisterContextDBReg::DREGType hwbType, int hwb_index) {
- Status error;
-
+llvm::Error
+NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(DREGType hwbType) {
#ifdef __arm__
+ uint32_t max_index = m_max_hbp_supported;
+ if (hwbType == eDREGTypeWATCH)
+ max_index = m_max_hwp_supported;
+
+ for (uint32_t idx = 0; idx < max_index; ++idx)
+ if (auto error = WriteHardwareDebugReg(hwbType, idx))
+ return error;
+
+ return llvm::Error::success();
+#else // __aarch64__
+ uint32_t max_supported =
+ (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
+ ? m_max_hwp_supported
+ : m_max_hbp_supported;
+ auto ®s = (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
+ ? m_hwp_regs
+ : m_hbp_regs;
+ return arm64::WriteHardwareDebugRegs(hwbType, m_thread.GetID(), max_supported,
+ regs).ToError();
+#endif // ifdef __arm__
+}
+
+llvm::Error
+NativeRegisterContextLinux_arm::WriteHardwareDebugReg(DREGType hwbType,
+ int hwb_index) {
+ Status error;
lldb::addr_t *addr_buf;
uint32_t *ctrl_buf;
@@ -774,15 +350,18 @@ Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(
sizeof(unsigned int));
if (error.Fail())
- return error;
+ return error.ToError();
error = NativeProcessLinux::PtraceWrapper(
PTRACE_SETHBPREGS, m_thread.GetID(),
(PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf,
sizeof(unsigned int));
+
+ if (error.Fail())
+ return error.ToError();
} else {
- addr_buf = &m_hbr_regs[hwb_index].address;
- ctrl_buf = &m_hbr_regs[hwb_index].control;
+ addr_buf = &m_hbp_regs[hwb_index].address;
+ ctrl_buf = &m_hbp_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(
PTRACE_SETHBPREGS, m_thread.GetID(),
@@ -790,26 +369,18 @@ Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(
sizeof(unsigned int));
if (error.Fail())
- return error;
+ return error.ToError();
error = NativeProcessLinux::PtraceWrapper(
PTRACE_SETHBPREGS, m_thread.GetID(),
(PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf,
sizeof(unsigned int));
+
+ if (error.Fail())
+ return error.ToError();
}
- return error;
-#else // __aarch64__
- uint32_t max_supported =
- (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
- ? m_max_hwp_supported
- : m_max_hbp_supported;
- auto ®s = (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
- ? m_hwp_regs
- : m_hbr_regs;
- return arm64::WriteHardwareDebugRegs(hwbType, m_thread.GetID(), max_supported,
- regs);
-#endif // ifdef __arm__
+ return error.ToError();
}
uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset(
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 3a31d68d7a3c4..6ac19e45f1069 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -12,7 +12,7 @@
#define lldb_NativeRegisterContextLinux_arm_h
#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
-#include "Plugins/Process/Utility/NativeRegisterContextDBReg.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
@@ -21,7 +21,8 @@ namespace process_linux {
class NativeProcessLinux;
-class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux {
+class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux,
+ public NativeRegisterContextDBReg_arm {
public:
NativeRegisterContextLinux_arm(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
@@ -42,39 +43,6 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux {
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- // Hardware breakpoints/watchpoint management functions
-
- uint32_t NumSupportedHardwareBreakpoints() override;
-
- uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
-
- bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
-
- Status ClearAllHardwareBreakpoints() override;
-
- Status GetHardwareBreakHitIndex(uint32_t &bp_index,
- lldb::addr_t trap_addr) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- Status ClearAllHardwareWatchpoints() override;
-
- Status GetWatchpointHitIndex(uint32_t &wp_index,
- lldb::addr_t trap_addr) override;
-
- lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
-
- uint32_t GetWatchpointSize(uint32_t wp_index);
-
- bool WatchpointIsEnabled(uint32_t wp_index);
-
protected:
Status DoReadRegisterValue(uint32_t offset, const char *reg_name,
uint32_t size, RegisterValue &value) override;
@@ -100,23 +68,16 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux {
uint32_t m_gpr_arm[k_num_gpr_registers_arm];
RegisterInfoPOSIX_arm::FPU m_fpr;
- std::array<NativeRegisterContextDBReg::DREG, 16>
- m_hbr_regs; // Arm native linux hardware breakpoints
- std::array<NativeRegisterContextDBReg::DREG, 16>
- m_hwp_regs; // Arm native linux hardware watchpoints
-
- uint32_t m_max_hwp_supported;
- uint32_t m_max_hbp_supported;
bool m_refresh_hwdebug_info;
bool IsGPR(unsigned reg) const;
bool IsFPR(unsigned reg) const;
- Status ReadHardwareDebugInfo();
+ llvm::Error ReadHardwareDebugInfo() override;
- Status WriteHardwareDebugRegs(NativeRegisterContextDBReg::DREGType hwbType,
- int hwb_index);
+ llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
+ llvm::Error WriteHardwareDebugReg(DREGType hwbType, int hwb_index) override;
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index 5d99c22dafe15..b1e326ec064e4 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -13,6 +13,7 @@ add_lldb_library(lldbPluginProcessUtility
MemoryTagManagerAArch64MTE.cpp
NativeProcessSoftwareSingleStep.cpp
NativeRegisterContextDBReg.cpp
+ NativeRegisterContextDBReg_arm.cpp
NativeRegisterContextDBReg_arm64.cpp
NativeRegisterContextDBReg_loongarch.cpp
NativeRegisterContextDBReg_x86.cpp
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.cpp
index 19601b7f35d47..a79adb8858635 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.cpp
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.cpp
@@ -222,7 +222,7 @@ uint32_t NativeRegisterContextDBReg::SetHardwareWatchpoint(
addr = adjusted->addr;
// Check if we are setting watchpoint other than read/write/access Also
- // update watchpoint flag to match AArch64/LoongArch write-read bit
+ // update watchpoint flag to match ARM/AArch64/LoongArch write-read bit
// configuration.
switch (watch_flags) {
case lldb::eWatchpointKindWrite:
@@ -237,7 +237,7 @@ uint32_t NativeRegisterContextDBReg::SetHardwareWatchpoint(
return LLDB_INVALID_INDEX32;
}
- control_value = MakeWatchControlValue(size, watch_flags);
+ control_value = MakeWatchControlValue(addr, size, watch_flags);
// Iterate over stored watchpoints and find a free wp_index
wp_index = LLDB_INVALID_INDEX32;
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
index 9b6ecd382c3f3..97e40ab14eaaf 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
@@ -12,6 +12,7 @@
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
#include <array>
+#include <optional>
// Common utilities for hardware breakpoints and hardware watchpoints on AArch64
// and LoongArch.
@@ -76,17 +77,26 @@ class NativeRegisterContextDBReg
// On AArch64 and Loongarch the hardware breakpoint length size is 4, and the
// target address must 4-byte alignment.
- bool ValidateBreakpoint(size_t size, lldb::addr_t addr) {
+ virtual bool ValidateBreakpoint(size_t size, lldb::addr_t addr) {
return (size == 4) && !(addr & 0x3);
}
+
struct WatchpointDetails {
size_t size;
lldb::addr_t addr;
};
virtual std::optional<WatchpointDetails>
AdjustWatchpoint(const WatchpointDetails &details) = 0;
+
+ using BreakpointDetails = WatchpointDetails;
+ virtual std::optional<BreakpointDetails>
+ AdjustBreakpoint(const BreakpointDetails &details) {
+ return details;
+ }
+
virtual uint32_t MakeBreakControlValue(size_t size) = 0;
- virtual uint32_t MakeWatchControlValue(size_t size, uint32_t watch_flags) = 0;
+ virtual uint32_t MakeWatchControlValue(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) = 0;
virtual uint32_t GetWatchpointSize(uint32_t wp_index) = 0;
virtual llvm::Error ReadHardwareDebugInfo() = 0;
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.cpp
new file mode 100644
index 0000000000000..e3b9a49253d0c
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.cpp
@@ -0,0 +1,116 @@
+//===-- NativeRegisterContextDBReg_arm.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 "NativeRegisterContextDBReg_arm.h"
+
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+
+using namespace lldb_private;
+
+uint32_t NativeRegisterContextDBReg_arm::GetWatchpointSize(uint32_t wp_index) {
+ Log *log = GetLog(LLDBLog::Watchpoints);
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x07:
+ return 3;
+ case 0x0f:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+std::optional<NativeRegisterContextDBReg::BreakpointDetails>
+NativeRegisterContextDBReg_arm::AdjustBreakpoint(
+ const BreakpointDetails &details) {
+ BreakpointDetails bd = details;
+ // Use size to get a hint of arm vs thumb modes.
+ switch (bd.size) {
+ case 2:
+ bd.addr &= ~1;
+ break;
+ case 4:
+ bd.addr &= ~3;
+ break;
+ default:
+ return {};
+ }
+
+ return bd;
+}
+
+std::optional<NativeRegisterContextDBReg::WatchpointDetails>
+NativeRegisterContextDBReg_arm::AdjustWatchpoint(
+ const WatchpointDetails &details) {
+ auto [size, addr] = details;
+
+ if (size == 0 || size > 4)
+ return {};
+
+ // Check 4-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 4-byte aligned addresses as well.
+ if (addr & 0x03) {
+ uint8_t watch_mask = (addr & 0x03) + size;
+ if (watch_mask > 0x04)
+ return {};
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else
+ size = 4;
+
+ addr = addr & (~0x03);
+ }
+
+ return WatchpointDetails{size, addr};
+}
+
+uint32_t NativeRegisterContextDBReg_arm::MakeBreakControlValue(size_t size) {
+ switch (size) {
+ case 2:
+ return (0x3 << 5) | 7;
+ case 4:
+ return (0xfu << 5) | 7;
+ default:
+ // We assume that AdjustBreakpoint would have caught this earlier.
+ llvm_unreachable("Invalid breakpoint size.");
+ }
+}
+
+uint32_t NativeRegisterContextDBReg_arm::MakeWatchControlValue(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ uint32_t addr_word_offset = 0, byte_mask = 0;
+
+ // We can only watch up to four bytes that follow a 4 byte aligned address
+ // per watchpoint register pair, so make sure we can properly encode this.
+ addr_word_offset = addr % 4;
+ byte_mask = ((1u << size) - 1u) << addr_word_offset;
+
+ // Check if we need multiple watchpoint register
+ if (byte_mask > 0xfu)
+ return LLDB_INVALID_INDEX32;
+
+ // Setup control value
+ // Make the byte_mask into a valid Byte Address Select mask
+ uint32_t control_value = byte_mask << 5;
+
+ // Turn on appropriate watchpoint flags read or write
+ control_value |= (watch_flags << 3);
+
+ // Enable this watchpoint and make it stop in privileged or user mode;
+ control_value |= 7;
+
+ return control_value;
+}
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
new file mode 100644
index 0000000000000..0af590d1be002
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
@@ -0,0 +1,46 @@
+//===-- NativeRegisterContextDBReg_arm.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_NativeRegisterContextDBReg_arm_h
+#define lldb_NativeRegisterContextDBReg_arm_h
+
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg.h"
+
+namespace lldb_private {
+
+class NativeRegisterContextDBReg_arm : public NativeRegisterContextDBReg {
+public:
+ NativeRegisterContextDBReg_arm()
+ : NativeRegisterContextDBReg(/*enable_bit=*/0x1U) {}
+
+private:
+ uint32_t GetWatchpointSize(uint32_t wp_index) override;
+
+ std::optional<WatchpointDetails>
+ AdjustWatchpoint(const WatchpointDetails &details) override;
+
+ std::optional<BreakpointDetails>
+ AdjustBreakpoint(const BreakpointDetails &details) override;
+
+ uint32_t MakeBreakControlValue(size_t size) override;
+
+ uint32_t MakeWatchControlValue(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
+
+ bool ValidateBreakpoint(size_t size, lldb::addr_t addr) override {
+ // Break on 4 or 2 byte instructions.
+ return size == 4 || size == 2;
+ }
+
+ virtual llvm::Error WriteHardwareDebugReg(DREGType hwbType,
+ int hwb_index) = 0;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextDBReg_arm_h
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
index f2f772ad615c9..c134d2f5d5ce2 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
@@ -78,9 +78,10 @@ uint32_t NativeRegisterContextDBReg_arm64::MakeBreakControlValue(size_t size) {
return m_hw_dbg_enable_bit | pac_bits | encoded_size;
}
-uint32_t
-NativeRegisterContextDBReg_arm64::MakeWatchControlValue(size_t size,
- uint32_t watch_flags) {
+uint32_t NativeRegisterContextDBReg_arm64::MakeWatchControlValue(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ (void)addr;
+
// PAC (bits 2:1): 0b10
const uint32_t pac_bits = 2 << 1;
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
index 42d6bacf64861..b88efd67ad45a 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
@@ -26,7 +26,8 @@ class NativeRegisterContextDBReg_arm64 : public NativeRegisterContextDBReg {
uint32_t MakeBreakControlValue(size_t size) override;
- uint32_t MakeWatchControlValue(size_t size, uint32_t watch_flags) override;
+ uint32_t MakeWatchControlValue(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.cpp b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.cpp
index b3b5e6b4d4139..e5beca468b74e 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.cpp
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.cpp
@@ -52,7 +52,8 @@ NativeRegisterContextDBReg_loongarch::MakeBreakControlValue(size_t size) {
}
uint32_t NativeRegisterContextDBReg_loongarch::MakeWatchControlValue(
- size_t size, uint32_t watch_flags) {
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ (void)addr;
// Encoding hardware watchpoint control value.
// Size encoded:
// case 1 : 0b11
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.h
index 19c5e4cdea263..6582371cf1a11 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_loongarch.h
@@ -26,7 +26,8 @@ class NativeRegisterContextDBReg_loongarch : public NativeRegisterContextDBReg {
uint32_t MakeBreakControlValue(size_t size) override;
- uint32_t MakeWatchControlValue(size_t size, uint32_t watch_flags) override;
+ uint32_t MakeWatchControlValue(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
};
} // namespace lldb_private
>From abc7017284cf07b80d739a5356b7ff5413838ddf Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Tue, 5 Aug 2025 12:37:48 +0000
Subject: [PATCH 2/2] refactor write registers
---
.../Linux/NativeRegisterContextLinux_arm.cpp | 45 +++++++------------
.../Linux/NativeRegisterContextLinux_arm.h | 4 +-
.../Utility/NativeRegisterContextDBReg_arm.h | 3 --
3 files changed, 18 insertions(+), 34 deletions(-)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 25e91c84ec584..85395f1c15125 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -333,55 +333,40 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(DREGType hwbType) {
#endif // ifdef __arm__
}
+#ifdef __arm__
llvm::Error
NativeRegisterContextLinux_arm::WriteHardwareDebugReg(DREGType hwbType,
int hwb_index) {
Status error;
lldb::addr_t *addr_buf;
uint32_t *ctrl_buf;
+ int addr_idx = (hwb_index << 1) + 1;
+ int ctrl_idx = addr_idx + 1;
if (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH) {
+ addr_idx *= -1;
addr_buf = &m_hwp_regs[hwb_index].address;
+ ctrl_idx *= -1;
ctrl_buf = &m_hwp_regs[hwb_index].control;
-
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_SETHBPREGS, m_thread.GetID(),
- (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 1), addr_buf,
- sizeof(unsigned int));
-
- if (error.Fail())
- return error.ToError();
-
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_SETHBPREGS, m_thread.GetID(),
- (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf,
- sizeof(unsigned int));
-
- if (error.Fail())
- return error.ToError();
} else {
addr_buf = &m_hbp_regs[hwb_index].address;
ctrl_buf = &m_hbp_regs[hwb_index].control;
+ }
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_SETHBPREGS, m_thread.GetID(),
- (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 1), addr_buf,
- sizeof(unsigned int));
-
- if (error.Fail())
- return error.ToError();
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t)addr_idx,
+ addr_buf, sizeof(unsigned int));
- error = NativeProcessLinux::PtraceWrapper(
- PTRACE_SETHBPREGS, m_thread.GetID(),
- (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf,
- sizeof(unsigned int));
+ if (error.Fail())
+ return error.ToError();
- if (error.Fail())
- return error.ToError();
- }
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_SETHBPREGS, m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t)ctrl_idx,
+ ctrl_buf, sizeof(unsigned int));
return error.ToError();
}
+#endif // ifdef __arm__
uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset(
const RegisterInfo *reg_info) const {
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 6ac19e45f1069..cf36859b16ad4 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -77,7 +77,9 @@ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux,
llvm::Error ReadHardwareDebugInfo() override;
llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
- llvm::Error WriteHardwareDebugReg(DREGType hwbType, int hwb_index) override;
+#ifdef __arm__
+ llvm::Error WriteHardwareDebugReg(DREGType hwbType, int hwb_index);
+#endif
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
index 0af590d1be002..92cc6bb654e7e 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm.h
@@ -36,9 +36,6 @@ class NativeRegisterContextDBReg_arm : public NativeRegisterContextDBReg {
// Break on 4 or 2 byte instructions.
return size == 4 || size == 2;
}
-
- virtual llvm::Error WriteHardwareDebugReg(DREGType hwbType,
- int hwb_index) = 0;
};
} // namespace lldb_private
More information about the lldb-commits
mailing list