[Lldb-commits] [lldb] [LLDB][Process/Utility] Introduce NativeRegisterContextDBReg class (PR #118043)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Fri Dec 6 02:42:39 PST 2024
================
@@ -272,199 +57,27 @@ uint32_t NativeRegisterContextDBReg_arm64::SetHardwareWatchpoint(
addr = addr & (~0x07);
}
-
- // Setup control value
- control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
- control_value |= watch_flags << 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 (!WatchpointIsEnabled(i))
- 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(eDREGTypeWATCH);
-
- if (error) {
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].control &= ~g_enable_bit;
-
- LLDB_LOG_ERROR(
- log, std::move(error),
- "unable to set watchpoint: failed to write debug registers: {0}");
- return LLDB_INVALID_INDEX32;
- }
-
- return wp_index;
-}
-
-bool NativeRegisterContextDBReg_arm64::ClearHardwareWatchpoint(
- uint32_t wp_index) {
- Log *log = GetLog(LLDBLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- // Read hardware breakpoint and watchpoint information.
- llvm::Error error = ReadHardwareDebugInfo();
- if (error) {
- LLDB_LOG_ERROR(
- log, std::move(error),
- "unable to clear watchpoint: failed to read debug registers: {0}");
- 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 &= ~g_enable_bit;
- m_hwp_regs[wp_index].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error) {
- m_hwp_regs[wp_index].control = tempControl;
- m_hwp_regs[wp_index].address = tempAddr;
-
- LLDB_LOG_ERROR(
- log, std::move(error),
- "unable to clear watchpoint: failed to write debug registers: {0}");
- return false;
- }
-
return true;
}
-Status NativeRegisterContextDBReg_arm64::ClearAllHardwareWatchpoints() {
- // Read hardware breakpoint and watchpoint information.
- llvm::Error error = ReadHardwareDebugInfo();
- if (error)
- return Status::FromError(std::move(error));
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- if (WatchpointIsEnabled(i)) {
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hwp_regs[i].address;
- uint32_t tempControl = m_hwp_regs[i].control;
-
- // Clear watchpoints in local cache
- m_hwp_regs[i].control &= ~g_enable_bit;
- m_hwp_regs[i].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error) {
- m_hwp_regs[i].control = tempControl;
- m_hwp_regs[i].address = tempAddr;
-
- return Status::FromError(std::move(error));
- }
- }
- }
-
- return Status();
-}
-
uint32_t
-NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) {
- Log *log = GetLog(LLDBLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
+NativeRegisterContextDBReg_arm64::MakeControlValue(size_t size,
+ uint32_t *watch_flags) {
+ // PAC (bits 2:1): 0b10
+ uint32_t pac_bits = (2 << 1);
- switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
- case 0x01:
- return 1;
- case 0x03:
- return 2;
- case 0x0f:
- return 4;
- case 0xff:
- return 8;
- default:
- return 0;
- }
-}
-
-bool NativeRegisterContextDBReg_arm64::WatchpointIsEnabled(uint32_t wp_index) {
- Log *log = GetLog(LLDBLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if ((m_hwp_regs[wp_index].control & g_enable_bit) != 0)
- return true;
- else
- return false;
-}
-
-Status NativeRegisterContextDBReg_arm64::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
- Log *log = GetLog(LLDBLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
-
- // Read hardware breakpoint and watchpoint information.
- llvm::Error error = ReadHardwareDebugInfo();
- if (error)
- return Status::FromError(std::move(error));
-
- // Mask off ignored bits from watchpoint trap address.
- trap_addr = FixWatchpointHitAddress(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
-NativeRegisterContextDBReg_arm64::GetWatchpointAddress(uint32_t wp_index) {
- Log *log = GetLog(LLDBLog::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;
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-NativeRegisterContextDBReg_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
- Log *log = GetLog(LLDBLog::Watchpoints);
- LLDB_LOG(log, "wp_index: {0}", wp_index);
+ // BAS (bits 12:5) hold a bit-mask of addresses to watch
+ // e.g. 0b00000001 means 1 byte at address
+ // 0b00000011 means 2 bytes (addr..addr+1)
+ // ...
+ // 0b11111111 means 8 bytes (addr..addr+7)
+ auto EncodingSizeBits = [](size_t size) { return ((1 << size) - 1) << 5; };
----------------
DavidSpickett wrote:
We can avoid the overhead of a lambda (or making the compiler remove the overhead) by doing:
```
size_t encoded_size = ((1 << size) - 1) << 5;
```
https://github.com/llvm/llvm-project/pull/118043
More information about the lldb-commits
mailing list