================ @@ -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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits