================ @@ -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; ---------------- b10902118 wrote:
This is actually unneeded. `addr_word_offset` will always be 0 because there is `addr = addr & (~0x03);` in `NativeRegisterContextDBReg_arm::AdjustWatchpoint`. Previous `NativeRegisterContextLinux_arm::SetHardwareWatchpoint` made this redundancy, which is clearer there. https://github.com/llvm/llvm-project/pull/152284 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits