LLDB mainline
NativeRegisterContextDBReg.cpp
Go to the documentation of this file.
1//===-- NativeRegisterContextDBReg.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
10
12#include "lldb/Utility/Log.h"
14
15using namespace lldb_private;
16
19
20 // Read hardware breakpoint and watchpoint information.
21 llvm::Error error = ReadHardwareDebugInfo();
22
23 if (error) {
24 LLDB_LOG_ERROR(log, std::move(error),
25 "failed to read debug registers: {0}");
26 return 0;
27 }
28
29 LLDB_LOG(log, "{0}", m_max_hbp_supported);
31}
32
34 size_t size) {
36 LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
37
38 // Read hardware breakpoint and watchpoint information.
39 llvm::Error error = ReadHardwareDebugInfo();
40 if (error) {
42 log, std::move(error),
43 "unable to set breakpoint: failed to read debug registers: {0}");
45 }
46
47 if (!ValidateBreakpoint(size, addr))
49
50 uint32_t control_value = MakeBreakControlValue(size);
51 auto details = AdjustBreakpoint({size, addr});
52 size = details.size;
53 addr = details.addr;
54
55 // Iterate over stored breakpoints and find a free bp_index
56 uint32_t bp_index = LLDB_INVALID_INDEX32;
57 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
58 if (!BreakpointIsEnabled(i))
59 bp_index = i; // Mark last free slot
60 else if (m_hbp_regs[i].address == addr)
61 return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
62 }
63
64 if (bp_index == LLDB_INVALID_INDEX32)
66
67 // Update breakpoint in local cache
68 m_hbp_regs[bp_index].real_addr = addr;
69 m_hbp_regs[bp_index].address = addr;
70 m_hbp_regs[bp_index].control = control_value;
71
72 // PTRACE call to set corresponding hardware breakpoint register.
74
75 if (error) {
76 m_hbp_regs[bp_index].address = 0;
77 m_hbp_regs[bp_index].control &= ~m_hw_dbg_enable_bit;
78
80 log, std::move(error),
81 "unable to set breakpoint: failed to write debug registers: {0}");
83 }
84
85 return bp_index;
86}
87
90 LLDB_LOG(log, "hw_idx: {0}", hw_idx);
91
92 // Read hardware breakpoint and watchpoint information.
93 llvm::Error error = ReadHardwareDebugInfo();
94 if (error) {
96 log, std::move(error),
97 "unable to clear breakpoint: failed to read debug registers: {0}");
98 return false;
99 }
100
101 if (hw_idx >= m_max_hbp_supported)
102 return false;
103
104 // Create a backup we can revert to in case of failure.
105 lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
106 uint32_t tempControl = m_hbp_regs[hw_idx].control;
107
108 m_hbp_regs[hw_idx].control &= ~m_hw_dbg_enable_bit;
109 m_hbp_regs[hw_idx].address = 0;
110
111 // PTRACE call to clear corresponding hardware breakpoint register.
113
114 if (error) {
115 m_hbp_regs[hw_idx].control = tempControl;
116 m_hbp_regs[hw_idx].address = tempAddr;
117
119 log, std::move(error),
120 "unable to clear breakpoint: failed to write debug registers: {0}");
121 return false;
122 }
123
124 return true;
125}
126
127Status
129 lldb::addr_t trap_addr) {
131
132 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
133
134 lldb::addr_t break_addr;
135
136 for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
137 break_addr = m_hbp_regs[bp_index].address;
138
139 if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
140 m_hbp_regs[bp_index].hit_addr = trap_addr;
141 return Status();
142 }
143 }
144
145 bp_index = LLDB_INVALID_INDEX32;
146 return Status();
147}
148
151
152 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
153
154 // Read hardware breakpoint and watchpoint information.
155 llvm::Error error = ReadHardwareDebugInfo();
156 if (error)
157 return Status::FromError(std::move(error));
158
159 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
160 if (!BreakpointIsEnabled(i))
161 continue;
162 // Create a backup we can revert to in case of failure.
163 lldb::addr_t tempAddr = m_hbp_regs[i].address;
164 uint32_t tempControl = m_hbp_regs[i].control;
165
166 // Clear watchpoints in local cache
167 m_hbp_regs[i].control &= ~m_hw_dbg_enable_bit;
168 m_hbp_regs[i].address = 0;
169
170 // Ptrace call to update hardware debug registers
172
173 if (error) {
174 m_hbp_regs[i].control = tempControl;
175 m_hbp_regs[i].address = tempAddr;
176
177 return Status::FromError(std::move(error));
178 }
179 }
180
181 return Status();
182}
183
185 return ((m_hbp_regs[bp_index].control & m_hw_dbg_enable_bit) != 0);
186}
187
190 llvm::Error error = ReadHardwareDebugInfo();
191 if (error) {
192 LLDB_LOG_ERROR(log, std::move(error),
193 "failed to read debug registers: {0}");
194 return 0;
195 }
196
197 return m_max_hwp_supported;
198}
199
201 lldb::addr_t addr, size_t size, uint32_t watch_flags) {
203 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
204 watch_flags);
205
206 // Read hardware breakpoint and watchpoint information.
207 llvm::Error error = ReadHardwareDebugInfo();
208 if (error) {
210 log, std::move(error),
211 "unable to set watchpoint: failed to read debug registers: {0}");
213 }
214
215 uint32_t control_value = 0, wp_index = 0;
216 lldb::addr_t real_addr = addr;
217 WatchpointDetails details{size, addr};
218
219 auto adjusted = AdjustWatchpoint(details);
220 if (adjusted == std::nullopt)
222 size = adjusted->size;
223 addr = adjusted->addr;
224
225 // Check if we are setting watchpoint other than read/write/access Also
226 // update watchpoint flag to match ARM/AArch64/LoongArch write-read bit
227 // configuration.
228 switch (watch_flags) {
229 case lldb::eWatchpointKindWrite:
230 watch_flags = 2;
231 break;
232 case lldb::eWatchpointKindRead:
233 watch_flags = 1;
234 break;
235 case (lldb::eWatchpointKindRead | lldb::eWatchpointKindWrite):
236 break;
237 default:
239 }
240
241 control_value = MakeWatchControlValue(size, watch_flags);
242
243 // Iterate over stored watchpoints and find a free wp_index
244 wp_index = LLDB_INVALID_INDEX32;
245 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
246 if (!WatchpointIsEnabled(i))
247 wp_index = i; // Mark last free slot
248 else if (m_hwp_regs[i].address == addr) {
249 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
250 }
251 }
252
253 if (wp_index == LLDB_INVALID_INDEX32)
255
256 // Update watchpoint in local cache
257 m_hwp_regs[wp_index].real_addr = real_addr;
258 m_hwp_regs[wp_index].address = addr;
259 m_hwp_regs[wp_index].control = control_value;
260
261 // PTRACE call to set corresponding watchpoint register.
263
264 if (error) {
265 m_hwp_regs[wp_index].address = 0;
266 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
267
269 log, std::move(error),
270 "unable to set watchpoint: failed to write debug registers: {0}");
272 }
273
274 return wp_index;
275}
276
279 LLDB_LOG(log, "wp_index: {0}", wp_index);
280
281 // Read hardware breakpoint and watchpoint information.
282 llvm::Error error = ReadHardwareDebugInfo();
283 if (error) {
285 log, std::move(error),
286 "unable to set watchpoint: failed to read debug registers: {0}");
287 return false;
288 }
289
290 if (wp_index >= m_max_hwp_supported)
291 return false;
292
293 // Create a backup we can revert to in case of failure.
294 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
295 uint32_t tempControl = m_hwp_regs[wp_index].control;
296
297 // Update watchpoint in local cache
298 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
299 m_hwp_regs[wp_index].address = 0;
300
301 // Ptrace call to update hardware debug registers
303
304 if (error) {
305 m_hwp_regs[wp_index].control = tempControl;
306 m_hwp_regs[wp_index].address = tempAddr;
307
309 log, std::move(error),
310 "unable to clear watchpoint: failed to read debug registers: {0}");
311 return false;
312 }
313
314 return true;
315}
316
318 // Read hardware breakpoint and watchpoint information.
319 llvm::Error error = ReadHardwareDebugInfo();
320 if (error)
321 return Status::FromError(std::move(error));
322
323 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
324 if (!WatchpointIsEnabled(i))
325 continue;
326 // Create a backup we can revert to in case of failure.
327 lldb::addr_t tempAddr = m_hwp_regs[i].address;
328 uint32_t tempControl = m_hwp_regs[i].control;
329
330 // Clear watchpoints in local cache
331 m_hwp_regs[i].control = 0;
332 m_hwp_regs[i].address = 0;
333
334 // Ptrace call to update hardware debug registers
336
337 if (error) {
338 m_hwp_regs[i].control = tempControl;
339 m_hwp_regs[i].address = tempAddr;
340
341 return Status::FromError(std::move(error));
342 }
343 }
344
345 return Status();
346}
347
348Status
350 lldb::addr_t trap_addr) {
352 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
353
354 // Read hardware breakpoint and watchpoint information.
355 llvm::Error error = ReadHardwareDebugInfo();
356 if (error)
357 return Status::FromError(std::move(error));
358
359 // AArch64 need mask off ignored bits from watchpoint trap address.
360 trap_addr = FixWatchpointHitAddress(trap_addr);
361
362 uint32_t watch_size;
363 lldb::addr_t watch_addr;
364
365 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
366 watch_size = GetWatchpointSize(wp_index);
367 watch_addr = m_hwp_regs[wp_index].address;
368
369 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
370 trap_addr < watch_addr + watch_size) {
371 m_hwp_regs[wp_index].hit_addr = trap_addr;
372 return Status();
373 }
374 }
375
376 wp_index = LLDB_INVALID_INDEX32;
377 return Status();
378}
379
382 LLDB_LOG(log, "wp_index: {0}", wp_index);
383 return ((m_hwp_regs[wp_index].control & m_hw_dbg_enable_bit) != 0);
384}
385
389 LLDB_LOG(log, "wp_index: {0}", wp_index);
390
391 if (wp_index >= m_max_hwp_supported)
393
394 if (WatchpointIsEnabled(wp_index))
395 return m_hwp_regs[wp_index].real_addr;
397}
398
402 LLDB_LOG(log, "wp_index: {0}", wp_index);
403
404 if (wp_index >= m_max_hwp_supported)
406
407 if (WatchpointIsEnabled(wp_index))
408 return m_hwp_regs[wp_index].hit_addr;
410}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:369
#define LLDB_LOGF(log,...)
Definition Log.h:376
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
virtual lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr)
bool ClearHardwareWatchpoint(uint32_t hw_index) override
virtual llvm::Error WriteHardwareDebugRegs(DREGType hwbType)=0
virtual bool ValidateBreakpoint(size_t size, lldb::addr_t addr)
Status GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override
virtual llvm::Error ReadHardwareDebugInfo()=0
lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override
virtual uint32_t MakeWatchControlValue(size_t size, uint32_t watch_flags)=0
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override
virtual std::optional< WatchpointDetails > AdjustWatchpoint(const WatchpointDetails &details)=0
virtual uint32_t MakeBreakControlValue(size_t size)=0
virtual uint32_t GetWatchpointSize(uint32_t wp_index)=0
virtual BreakpointDetails AdjustBreakpoint(const BreakpointDetails &details)
uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override
Status GetHardwareBreakHitIndex(uint32_t &bp_index, lldb::addr_t trap_addr) override
lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override
An error handling class.
Definition Status.h:118
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:137
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
uint64_t addr_t
Definition lldb-types.h:80