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
15using namespace lldb_private;
16
17uint32_t
18NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) {
19 Log *log = GetLog(mask: 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
36std::optional<NativeRegisterContextDBReg::WatchpointDetails>
37NativeRegisterContextDBReg_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: size, .addr: addr};
64}
65
66uint32_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
81uint32_t
82NativeRegisterContextDBReg_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

source code of lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp