//===-- NativeRegisterContextDBReg_arm64.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_arm64.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" using namespace lldb_private; uint32_t NativeRegisterContextDBReg_arm64::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) & 0xff) { case 0x01: return 1; case 0x03: return 2; case 0x0f: return 4; case 0xff: return 8; default: return 0; } } std::optional NativeRegisterContextDBReg_arm64::AdjustWatchpoint( const WatchpointDetails &details) { size_t size = details.size; lldb::addr_t addr = details.addr; // Check if size has a valid hardware watchpoint length. if (size != 1 && size != 2 && size != 4 && size != 8) return std::nullopt; // Check 8-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 8-byte aligned addresses as well. if (addr & 0x07) { uint8_t watch_mask = (addr & 0x07) + size; if (watch_mask > 0x08) return std::nullopt; if (watch_mask <= 0x02) size = 2; else if (watch_mask <= 0x04) size = 4; else size = 8; addr = addr & (~0x07); } return WatchpointDetails{size, addr}; } uint32_t NativeRegisterContextDBReg_arm64::MakeBreakControlValue(size_t size) { // PAC (bits 2:1): 0b10 const uint32_t pac_bits = 2 << 1; // 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) size_t encoded_size = ((1 << size) - 1) << 5; // Return encoded hardware breakpoint control value. return m_hw_dbg_enable_bit | pac_bits | encoded_size; } uint32_t NativeRegisterContextDBReg_arm64::MakeWatchControlValue(size_t size, uint32_t watch_flags) { // PAC (bits 2:1): 0b10 const uint32_t pac_bits = 2 << 1; // 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) size_t encoded_size = ((1 << size) - 1) << 5; // Return encoded hardware watchpoint control value. return m_hw_dbg_enable_bit | pac_bits | encoded_size | (watch_flags << 3); }