1 //===-- NativeRegisterContextDBReg_arm64.cpp ------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "NativeRegisterContextDBReg_arm64.h" 10 11 #include "lldb/Utility/LLDBLog.h" 12 #include "lldb/Utility/Log.h" 13 #include "lldb/Utility/RegisterValue.h" 14 15 using namespace lldb_private; 16 17 uint32_t 18 NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) { 19 Log *log = GetLog(LLDBLog::Watchpoints); 20 LLDB_LOG(log, "wp_index: {0}", wp_index); 21 22 switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { 23 case 0x01: 24 return 1; 25 case 0x03: 26 return 2; 27 case 0x0f: 28 return 4; 29 case 0xff: 30 return 8; 31 default: 32 return 0; 33 } 34 } 35 36 std::optional<NativeRegisterContextDBReg::WatchpointDetails> 37 NativeRegisterContextDBReg_arm64::AdjustWatchpoint( 38 const WatchpointDetails &details) { 39 size_t size = details.size; 40 lldb::addr_t addr = details.addr; 41 // Check if size has a valid hardware watchpoint length. 42 if (size != 1 && size != 2 && size != 4 && size != 8) 43 return std::nullopt; 44 45 // Check 8-byte alignment for hardware watchpoint target address. Below is a 46 // hack to recalculate address and size in order to make sure we can watch 47 // non 8-byte aligned addresses as well. 48 if (addr & 0x07) { 49 uint8_t watch_mask = (addr & 0x07) + size; 50 51 if (watch_mask > 0x08) 52 return std::nullopt; 53 54 if (watch_mask <= 0x02) 55 size = 2; 56 else if (watch_mask <= 0x04) 57 size = 4; 58 else 59 size = 8; 60 61 addr = addr & (~0x07); 62 } 63 return WatchpointDetails{size, addr}; 64 } 65 66 uint32_t NativeRegisterContextDBReg_arm64::MakeBreakControlValue(size_t size) { 67 // PAC (bits 2:1): 0b10 68 const uint32_t pac_bits = 2 << 1; 69 70 // BAS (bits 12:5) hold a bit-mask of addresses to watch 71 // e.g. 0b00000001 means 1 byte at address 72 // 0b00000011 means 2 bytes (addr..addr+1) 73 // ... 74 // 0b11111111 means 8 bytes (addr..addr+7) 75 size_t encoded_size = ((1 << size) - 1) << 5; 76 77 // Return encoded hardware breakpoint control value. 78 return m_hw_dbg_enable_bit | pac_bits | encoded_size; 79 } 80 81 uint32_t 82 NativeRegisterContextDBReg_arm64::MakeWatchControlValue(size_t size, 83 uint32_t watch_flags) { 84 // PAC (bits 2:1): 0b10 85 const uint32_t pac_bits = 2 << 1; 86 87 // BAS (bits 12:5) hold a bit-mask of addresses to watch 88 // e.g. 0b00000001 means 1 byte at address 89 // 0b00000011 means 2 bytes (addr..addr+1) 90 // ... 91 // 0b11111111 means 8 bytes (addr..addr+7) 92 size_t encoded_size = ((1 << size) - 1) << 5; 93 94 // Return encoded hardware watchpoint control value. 95 return m_hw_dbg_enable_bit | pac_bits | encoded_size | (watch_flags << 3); 96 } 97