xref: /llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.cpp (revision ae5836f6b6a8544e6226f5c1ba6b1beacfe01aef)
1*ae5836f6Swanglei //===-- NativeRegisterContextDBReg.cpp ------------------------------------===//
2*ae5836f6Swanglei //
3*ae5836f6Swanglei // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ae5836f6Swanglei // See https://llvm.org/LICENSE.txt for license information.
5*ae5836f6Swanglei // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ae5836f6Swanglei //
7*ae5836f6Swanglei //===----------------------------------------------------------------------===//
8*ae5836f6Swanglei 
9*ae5836f6Swanglei #include "NativeRegisterContextDBReg.h"
10*ae5836f6Swanglei 
11*ae5836f6Swanglei #include "lldb/Utility/LLDBLog.h"
12*ae5836f6Swanglei #include "lldb/Utility/Log.h"
13*ae5836f6Swanglei #include "lldb/Utility/RegisterValue.h"
14*ae5836f6Swanglei 
15*ae5836f6Swanglei using namespace lldb_private;
16*ae5836f6Swanglei 
17*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::NumSupportedHardwareBreakpoints() {
18*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Breakpoints);
19*ae5836f6Swanglei 
20*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
21*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
22*ae5836f6Swanglei 
23*ae5836f6Swanglei   if (error) {
24*ae5836f6Swanglei     LLDB_LOG_ERROR(log, std::move(error),
25*ae5836f6Swanglei                    "failed to read debug registers: {0}");
26*ae5836f6Swanglei     return 0;
27*ae5836f6Swanglei   }
28*ae5836f6Swanglei 
29*ae5836f6Swanglei   LLDB_LOG(log, "{0}", m_max_hbp_supported);
30*ae5836f6Swanglei   return m_max_hbp_supported;
31*ae5836f6Swanglei }
32*ae5836f6Swanglei 
33*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::SetHardwareBreakpoint(lldb::addr_t addr,
34*ae5836f6Swanglei                                                            size_t size) {
35*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Breakpoints);
36*ae5836f6Swanglei   LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
37*ae5836f6Swanglei 
38*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
39*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
40*ae5836f6Swanglei   if (error) {
41*ae5836f6Swanglei     LLDB_LOG_ERROR(
42*ae5836f6Swanglei         log, std::move(error),
43*ae5836f6Swanglei         "unable to set breakpoint: failed to read debug registers: {0}");
44*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
45*ae5836f6Swanglei   }
46*ae5836f6Swanglei 
47*ae5836f6Swanglei   uint32_t control_value = 0, bp_index = 0;
48*ae5836f6Swanglei 
49*ae5836f6Swanglei   if (!ValidateBreakpoint(size, addr))
50*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
51*ae5836f6Swanglei 
52*ae5836f6Swanglei   control_value = MakeBreakControlValue(size);
53*ae5836f6Swanglei 
54*ae5836f6Swanglei   // Iterate over stored breakpoints and find a free bp_index
55*ae5836f6Swanglei   bp_index = LLDB_INVALID_INDEX32;
56*ae5836f6Swanglei   for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
57*ae5836f6Swanglei     if (!BreakpointIsEnabled(i))
58*ae5836f6Swanglei       bp_index = i; // Mark last free slot
59*ae5836f6Swanglei     else if (m_hbp_regs[i].address == addr)
60*ae5836f6Swanglei       return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
61*ae5836f6Swanglei   }
62*ae5836f6Swanglei 
63*ae5836f6Swanglei   if (bp_index == LLDB_INVALID_INDEX32)
64*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
65*ae5836f6Swanglei 
66*ae5836f6Swanglei   // Update breakpoint in local cache
67*ae5836f6Swanglei   m_hbp_regs[bp_index].real_addr = addr;
68*ae5836f6Swanglei   m_hbp_regs[bp_index].address = addr;
69*ae5836f6Swanglei   m_hbp_regs[bp_index].control = control_value;
70*ae5836f6Swanglei 
71*ae5836f6Swanglei   // PTRACE call to set corresponding hardware breakpoint register.
72*ae5836f6Swanglei   error = WriteHardwareDebugRegs(eDREGTypeBREAK);
73*ae5836f6Swanglei 
74*ae5836f6Swanglei   if (error) {
75*ae5836f6Swanglei     m_hbp_regs[bp_index].address = 0;
76*ae5836f6Swanglei     m_hbp_regs[bp_index].control &= ~m_hw_dbg_enable_bit;
77*ae5836f6Swanglei 
78*ae5836f6Swanglei     LLDB_LOG_ERROR(
79*ae5836f6Swanglei         log, std::move(error),
80*ae5836f6Swanglei         "unable to set breakpoint: failed to write debug registers: {0}");
81*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
82*ae5836f6Swanglei   }
83*ae5836f6Swanglei 
84*ae5836f6Swanglei   return bp_index;
85*ae5836f6Swanglei }
86*ae5836f6Swanglei 
87*ae5836f6Swanglei bool NativeRegisterContextDBReg::ClearHardwareBreakpoint(uint32_t hw_idx) {
88*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Breakpoints);
89*ae5836f6Swanglei   LLDB_LOG(log, "hw_idx: {0}", hw_idx);
90*ae5836f6Swanglei 
91*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
92*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
93*ae5836f6Swanglei   if (error) {
94*ae5836f6Swanglei     LLDB_LOG_ERROR(
95*ae5836f6Swanglei         log, std::move(error),
96*ae5836f6Swanglei         "unable to clear breakpoint: failed to read debug registers: {0}");
97*ae5836f6Swanglei     return false;
98*ae5836f6Swanglei   }
99*ae5836f6Swanglei 
100*ae5836f6Swanglei   if (hw_idx >= m_max_hbp_supported)
101*ae5836f6Swanglei     return false;
102*ae5836f6Swanglei 
103*ae5836f6Swanglei   // Create a backup we can revert to in case of failure.
104*ae5836f6Swanglei   lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
105*ae5836f6Swanglei   uint32_t tempControl = m_hbp_regs[hw_idx].control;
106*ae5836f6Swanglei 
107*ae5836f6Swanglei   m_hbp_regs[hw_idx].control &= ~m_hw_dbg_enable_bit;
108*ae5836f6Swanglei   m_hbp_regs[hw_idx].address = 0;
109*ae5836f6Swanglei 
110*ae5836f6Swanglei   // PTRACE call to clear corresponding hardware breakpoint register.
111*ae5836f6Swanglei   error = WriteHardwareDebugRegs(eDREGTypeBREAK);
112*ae5836f6Swanglei 
113*ae5836f6Swanglei   if (error) {
114*ae5836f6Swanglei     m_hbp_regs[hw_idx].control = tempControl;
115*ae5836f6Swanglei     m_hbp_regs[hw_idx].address = tempAddr;
116*ae5836f6Swanglei 
117*ae5836f6Swanglei     LLDB_LOG_ERROR(
118*ae5836f6Swanglei         log, std::move(error),
119*ae5836f6Swanglei         "unable to clear breakpoint: failed to write debug registers: {0}");
120*ae5836f6Swanglei     return false;
121*ae5836f6Swanglei   }
122*ae5836f6Swanglei 
123*ae5836f6Swanglei   return true;
124*ae5836f6Swanglei }
125*ae5836f6Swanglei 
126*ae5836f6Swanglei Status
127*ae5836f6Swanglei NativeRegisterContextDBReg::GetHardwareBreakHitIndex(uint32_t &bp_index,
128*ae5836f6Swanglei                                                      lldb::addr_t trap_addr) {
129*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Breakpoints);
130*ae5836f6Swanglei 
131*ae5836f6Swanglei   LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
132*ae5836f6Swanglei 
133*ae5836f6Swanglei   lldb::addr_t break_addr;
134*ae5836f6Swanglei 
135*ae5836f6Swanglei   for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
136*ae5836f6Swanglei     break_addr = m_hbp_regs[bp_index].address;
137*ae5836f6Swanglei 
138*ae5836f6Swanglei     if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
139*ae5836f6Swanglei       m_hbp_regs[bp_index].hit_addr = trap_addr;
140*ae5836f6Swanglei       return Status();
141*ae5836f6Swanglei     }
142*ae5836f6Swanglei   }
143*ae5836f6Swanglei 
144*ae5836f6Swanglei   bp_index = LLDB_INVALID_INDEX32;
145*ae5836f6Swanglei   return Status();
146*ae5836f6Swanglei }
147*ae5836f6Swanglei 
148*ae5836f6Swanglei Status NativeRegisterContextDBReg::ClearAllHardwareBreakpoints() {
149*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Breakpoints);
150*ae5836f6Swanglei 
151*ae5836f6Swanglei   LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
152*ae5836f6Swanglei 
153*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
154*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
155*ae5836f6Swanglei   if (error)
156*ae5836f6Swanglei     return Status::FromError(std::move(error));
157*ae5836f6Swanglei 
158*ae5836f6Swanglei   for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
159*ae5836f6Swanglei     if (!BreakpointIsEnabled(i))
160*ae5836f6Swanglei       continue;
161*ae5836f6Swanglei     // Create a backup we can revert to in case of failure.
162*ae5836f6Swanglei     lldb::addr_t tempAddr = m_hbp_regs[i].address;
163*ae5836f6Swanglei     uint32_t tempControl = m_hbp_regs[i].control;
164*ae5836f6Swanglei 
165*ae5836f6Swanglei     // Clear watchpoints in local cache
166*ae5836f6Swanglei     m_hbp_regs[i].control &= ~m_hw_dbg_enable_bit;
167*ae5836f6Swanglei     m_hbp_regs[i].address = 0;
168*ae5836f6Swanglei 
169*ae5836f6Swanglei     // Ptrace call to update hardware debug registers
170*ae5836f6Swanglei     error = WriteHardwareDebugRegs(eDREGTypeBREAK);
171*ae5836f6Swanglei 
172*ae5836f6Swanglei     if (error) {
173*ae5836f6Swanglei       m_hbp_regs[i].control = tempControl;
174*ae5836f6Swanglei       m_hbp_regs[i].address = tempAddr;
175*ae5836f6Swanglei 
176*ae5836f6Swanglei       return Status::FromError(std::move(error));
177*ae5836f6Swanglei     }
178*ae5836f6Swanglei   }
179*ae5836f6Swanglei 
180*ae5836f6Swanglei   return Status();
181*ae5836f6Swanglei }
182*ae5836f6Swanglei 
183*ae5836f6Swanglei bool NativeRegisterContextDBReg::BreakpointIsEnabled(uint32_t bp_index) {
184*ae5836f6Swanglei   return ((m_hbp_regs[bp_index].control & m_hw_dbg_enable_bit) != 0);
185*ae5836f6Swanglei }
186*ae5836f6Swanglei 
187*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::NumSupportedHardwareWatchpoints() {
188*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
189*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
190*ae5836f6Swanglei   if (error) {
191*ae5836f6Swanglei     LLDB_LOG_ERROR(log, std::move(error),
192*ae5836f6Swanglei                    "failed to read debug registers: {0}");
193*ae5836f6Swanglei     return 0;
194*ae5836f6Swanglei   }
195*ae5836f6Swanglei 
196*ae5836f6Swanglei   return m_max_hwp_supported;
197*ae5836f6Swanglei }
198*ae5836f6Swanglei 
199*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::SetHardwareWatchpoint(
200*ae5836f6Swanglei     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
201*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
202*ae5836f6Swanglei   LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
203*ae5836f6Swanglei            watch_flags);
204*ae5836f6Swanglei 
205*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
206*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
207*ae5836f6Swanglei   if (error) {
208*ae5836f6Swanglei     LLDB_LOG_ERROR(
209*ae5836f6Swanglei         log, std::move(error),
210*ae5836f6Swanglei         "unable to set watchpoint: failed to read debug registers: {0}");
211*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
212*ae5836f6Swanglei   }
213*ae5836f6Swanglei 
214*ae5836f6Swanglei   uint32_t control_value = 0, wp_index = 0;
215*ae5836f6Swanglei   lldb::addr_t real_addr = addr;
216*ae5836f6Swanglei   WatchpointDetails details{size, addr};
217*ae5836f6Swanglei 
218*ae5836f6Swanglei   auto adjusted = AdjustWatchpoint(details);
219*ae5836f6Swanglei   if (adjusted == std::nullopt)
220*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
221*ae5836f6Swanglei   size = adjusted->size;
222*ae5836f6Swanglei   addr = adjusted->addr;
223*ae5836f6Swanglei 
224*ae5836f6Swanglei   // Check if we are setting watchpoint other than read/write/access Also
225*ae5836f6Swanglei   // update watchpoint flag to match AArch64/LoongArch write-read bit
226*ae5836f6Swanglei   // configuration.
227*ae5836f6Swanglei   switch (watch_flags) {
228*ae5836f6Swanglei   case lldb::eWatchpointKindWrite:
229*ae5836f6Swanglei     watch_flags = 2;
230*ae5836f6Swanglei     break;
231*ae5836f6Swanglei   case lldb::eWatchpointKindRead:
232*ae5836f6Swanglei     watch_flags = 1;
233*ae5836f6Swanglei     break;
234*ae5836f6Swanglei   case (lldb::eWatchpointKindRead | lldb::eWatchpointKindWrite):
235*ae5836f6Swanglei     break;
236*ae5836f6Swanglei   default:
237*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
238*ae5836f6Swanglei   }
239*ae5836f6Swanglei 
240*ae5836f6Swanglei   control_value = MakeWatchControlValue(size, watch_flags);
241*ae5836f6Swanglei 
242*ae5836f6Swanglei   // Iterate over stored watchpoints and find a free wp_index
243*ae5836f6Swanglei   wp_index = LLDB_INVALID_INDEX32;
244*ae5836f6Swanglei   for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
245*ae5836f6Swanglei     if (!WatchpointIsEnabled(i))
246*ae5836f6Swanglei       wp_index = i; // Mark last free slot
247*ae5836f6Swanglei     else if (m_hwp_regs[i].address == addr) {
248*ae5836f6Swanglei       return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
249*ae5836f6Swanglei     }
250*ae5836f6Swanglei   }
251*ae5836f6Swanglei 
252*ae5836f6Swanglei   if (wp_index == LLDB_INVALID_INDEX32)
253*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
254*ae5836f6Swanglei 
255*ae5836f6Swanglei   // Update watchpoint in local cache
256*ae5836f6Swanglei   m_hwp_regs[wp_index].real_addr = real_addr;
257*ae5836f6Swanglei   m_hwp_regs[wp_index].address = addr;
258*ae5836f6Swanglei   m_hwp_regs[wp_index].control = control_value;
259*ae5836f6Swanglei 
260*ae5836f6Swanglei   // PTRACE call to set corresponding watchpoint register.
261*ae5836f6Swanglei   error = WriteHardwareDebugRegs(eDREGTypeWATCH);
262*ae5836f6Swanglei 
263*ae5836f6Swanglei   if (error) {
264*ae5836f6Swanglei     m_hwp_regs[wp_index].address = 0;
265*ae5836f6Swanglei     m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
266*ae5836f6Swanglei 
267*ae5836f6Swanglei     LLDB_LOG_ERROR(
268*ae5836f6Swanglei         log, std::move(error),
269*ae5836f6Swanglei         "unable to set watchpoint: failed to write debug registers: {0}");
270*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
271*ae5836f6Swanglei   }
272*ae5836f6Swanglei 
273*ae5836f6Swanglei   return wp_index;
274*ae5836f6Swanglei }
275*ae5836f6Swanglei 
276*ae5836f6Swanglei bool NativeRegisterContextDBReg::ClearHardwareWatchpoint(uint32_t wp_index) {
277*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
278*ae5836f6Swanglei   LLDB_LOG(log, "wp_index: {0}", wp_index);
279*ae5836f6Swanglei 
280*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
281*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
282*ae5836f6Swanglei   if (error) {
283*ae5836f6Swanglei     LLDB_LOG_ERROR(
284*ae5836f6Swanglei         log, std::move(error),
285*ae5836f6Swanglei         "unable to set watchpoint: failed to read debug registers: {0}");
286*ae5836f6Swanglei     return LLDB_INVALID_INDEX32;
287*ae5836f6Swanglei   }
288*ae5836f6Swanglei 
289*ae5836f6Swanglei   if (wp_index >= m_max_hwp_supported)
290*ae5836f6Swanglei     return false;
291*ae5836f6Swanglei 
292*ae5836f6Swanglei   // Create a backup we can revert to in case of failure.
293*ae5836f6Swanglei   lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
294*ae5836f6Swanglei   uint32_t tempControl = m_hwp_regs[wp_index].control;
295*ae5836f6Swanglei 
296*ae5836f6Swanglei   // Update watchpoint in local cache
297*ae5836f6Swanglei   m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
298*ae5836f6Swanglei   m_hwp_regs[wp_index].address = 0;
299*ae5836f6Swanglei 
300*ae5836f6Swanglei   // Ptrace call to update hardware debug registers
301*ae5836f6Swanglei   error = WriteHardwareDebugRegs(eDREGTypeWATCH);
302*ae5836f6Swanglei 
303*ae5836f6Swanglei   if (error) {
304*ae5836f6Swanglei     m_hwp_regs[wp_index].control = tempControl;
305*ae5836f6Swanglei     m_hwp_regs[wp_index].address = tempAddr;
306*ae5836f6Swanglei 
307*ae5836f6Swanglei     LLDB_LOG_ERROR(
308*ae5836f6Swanglei         log, std::move(error),
309*ae5836f6Swanglei         "unable to clear watchpoint: failed to read debug registers: {0}");
310*ae5836f6Swanglei     return false;
311*ae5836f6Swanglei   }
312*ae5836f6Swanglei 
313*ae5836f6Swanglei   return true;
314*ae5836f6Swanglei }
315*ae5836f6Swanglei 
316*ae5836f6Swanglei Status NativeRegisterContextDBReg::ClearAllHardwareWatchpoints() {
317*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
318*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
319*ae5836f6Swanglei   if (error)
320*ae5836f6Swanglei     return Status::FromError(std::move(error));
321*ae5836f6Swanglei 
322*ae5836f6Swanglei   for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
323*ae5836f6Swanglei     if (!WatchpointIsEnabled(i))
324*ae5836f6Swanglei       continue;
325*ae5836f6Swanglei     // Create a backup we can revert to in case of failure.
326*ae5836f6Swanglei     lldb::addr_t tempAddr = m_hwp_regs[i].address;
327*ae5836f6Swanglei     uint32_t tempControl = m_hwp_regs[i].control;
328*ae5836f6Swanglei 
329*ae5836f6Swanglei     // Clear watchpoints in local cache
330*ae5836f6Swanglei     m_hwp_regs[i].control = 0;
331*ae5836f6Swanglei     m_hwp_regs[i].address = 0;
332*ae5836f6Swanglei 
333*ae5836f6Swanglei     // Ptrace call to update hardware debug registers
334*ae5836f6Swanglei     error = WriteHardwareDebugRegs(eDREGTypeWATCH);
335*ae5836f6Swanglei 
336*ae5836f6Swanglei     if (error) {
337*ae5836f6Swanglei       m_hwp_regs[i].control = tempControl;
338*ae5836f6Swanglei       m_hwp_regs[i].address = tempAddr;
339*ae5836f6Swanglei 
340*ae5836f6Swanglei       return Status::FromError(std::move(error));
341*ae5836f6Swanglei     }
342*ae5836f6Swanglei   }
343*ae5836f6Swanglei 
344*ae5836f6Swanglei   return Status();
345*ae5836f6Swanglei }
346*ae5836f6Swanglei 
347*ae5836f6Swanglei Status
348*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointHitIndex(uint32_t &wp_index,
349*ae5836f6Swanglei                                                   lldb::addr_t trap_addr) {
350*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
351*ae5836f6Swanglei   LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
352*ae5836f6Swanglei 
353*ae5836f6Swanglei   // Read hardware breakpoint and watchpoint information.
354*ae5836f6Swanglei   llvm::Error error = ReadHardwareDebugInfo();
355*ae5836f6Swanglei   if (error)
356*ae5836f6Swanglei     return Status::FromError(std::move(error));
357*ae5836f6Swanglei 
358*ae5836f6Swanglei   // AArch64 need mask off ignored bits from watchpoint trap address.
359*ae5836f6Swanglei   trap_addr = FixWatchpointHitAddress(trap_addr);
360*ae5836f6Swanglei 
361*ae5836f6Swanglei   uint32_t watch_size;
362*ae5836f6Swanglei   lldb::addr_t watch_addr;
363*ae5836f6Swanglei 
364*ae5836f6Swanglei   for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
365*ae5836f6Swanglei     watch_size = GetWatchpointSize(wp_index);
366*ae5836f6Swanglei     watch_addr = m_hwp_regs[wp_index].address;
367*ae5836f6Swanglei 
368*ae5836f6Swanglei     if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
369*ae5836f6Swanglei         trap_addr < watch_addr + watch_size) {
370*ae5836f6Swanglei       m_hwp_regs[wp_index].hit_addr = trap_addr;
371*ae5836f6Swanglei       return Status();
372*ae5836f6Swanglei     }
373*ae5836f6Swanglei   }
374*ae5836f6Swanglei 
375*ae5836f6Swanglei   wp_index = LLDB_INVALID_INDEX32;
376*ae5836f6Swanglei   return Status();
377*ae5836f6Swanglei }
378*ae5836f6Swanglei 
379*ae5836f6Swanglei bool NativeRegisterContextDBReg::WatchpointIsEnabled(uint32_t wp_index) {
380*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
381*ae5836f6Swanglei   LLDB_LOG(log, "wp_index: {0}", wp_index);
382*ae5836f6Swanglei   return ((m_hwp_regs[wp_index].control & m_hw_dbg_enable_bit) != 0);
383*ae5836f6Swanglei }
384*ae5836f6Swanglei 
385*ae5836f6Swanglei lldb::addr_t
386*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointAddress(uint32_t wp_index) {
387*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
388*ae5836f6Swanglei   LLDB_LOG(log, "wp_index: {0}", wp_index);
389*ae5836f6Swanglei 
390*ae5836f6Swanglei   if (wp_index >= m_max_hwp_supported)
391*ae5836f6Swanglei     return LLDB_INVALID_ADDRESS;
392*ae5836f6Swanglei 
393*ae5836f6Swanglei   if (WatchpointIsEnabled(wp_index))
394*ae5836f6Swanglei     return m_hwp_regs[wp_index].real_addr;
395*ae5836f6Swanglei   return LLDB_INVALID_ADDRESS;
396*ae5836f6Swanglei }
397*ae5836f6Swanglei 
398*ae5836f6Swanglei lldb::addr_t
399*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointHitAddress(uint32_t wp_index) {
400*ae5836f6Swanglei   Log *log = GetLog(LLDBLog::Watchpoints);
401*ae5836f6Swanglei   LLDB_LOG(log, "wp_index: {0}", wp_index);
402*ae5836f6Swanglei 
403*ae5836f6Swanglei   if (wp_index >= m_max_hwp_supported)
404*ae5836f6Swanglei     return LLDB_INVALID_ADDRESS;
405*ae5836f6Swanglei 
406*ae5836f6Swanglei   if (WatchpointIsEnabled(wp_index))
407*ae5836f6Swanglei     return m_hwp_regs[wp_index].hit_addr;
408*ae5836f6Swanglei   return LLDB_INVALID_ADDRESS;
409*ae5836f6Swanglei }
410