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 uint32_t control_value = 0, bp_index = 0;
48
49 if (!ValidateBreakpoint(size, addr))
51
52 control_value = MakeBreakControlValue(size);
53
54 // Iterate over stored breakpoints and find a free bp_index
55 bp_index = LLDB_INVALID_INDEX32;
56 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
57 if (!BreakpointIsEnabled(i))
58 bp_index = i; // Mark last free slot
59 else if (m_hbp_regs[i].address == addr)
60 return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
61 }
62
63 if (bp_index == LLDB_INVALID_INDEX32)
65
66 // Update breakpoint in local cache
67 m_hbp_regs[bp_index].real_addr = addr;
68 m_hbp_regs[bp_index].address = addr;
69 m_hbp_regs[bp_index].control = control_value;
70
71 // PTRACE call to set corresponding hardware breakpoint register.
73
74 if (error) {
75 m_hbp_regs[bp_index].address = 0;
76 m_hbp_regs[bp_index].control &= ~m_hw_dbg_enable_bit;
77
79 log, std::move(error),
80 "unable to set breakpoint: failed to write debug registers: {0}");
82 }
83
84 return bp_index;
85}
86
89 LLDB_LOG(log, "hw_idx: {0}", hw_idx);
90
91 // Read hardware breakpoint and watchpoint information.
92 llvm::Error error = ReadHardwareDebugInfo();
93 if (error) {
95 log, std::move(error),
96 "unable to clear breakpoint: failed to read debug registers: {0}");
97 return false;
98 }
99
100 if (hw_idx >= m_max_hbp_supported)
101 return false;
102
103 // Create a backup we can revert to in case of failure.
104 lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
105 uint32_t tempControl = m_hbp_regs[hw_idx].control;
106
107 m_hbp_regs[hw_idx].control &= ~m_hw_dbg_enable_bit;
108 m_hbp_regs[hw_idx].address = 0;
109
110 // PTRACE call to clear corresponding hardware breakpoint register.
112
113 if (error) {
114 m_hbp_regs[hw_idx].control = tempControl;
115 m_hbp_regs[hw_idx].address = tempAddr;
116
118 log, std::move(error),
119 "unable to clear breakpoint: failed to write debug registers: {0}");
120 return false;
121 }
122
123 return true;
124}
125
126Status
128 lldb::addr_t trap_addr) {
130
131 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
132
133 lldb::addr_t break_addr;
134
135 for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
136 break_addr = m_hbp_regs[bp_index].address;
137
138 if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
139 m_hbp_regs[bp_index].hit_addr = trap_addr;
140 return Status();
141 }
142 }
143
144 bp_index = LLDB_INVALID_INDEX32;
145 return Status();
146}
147
150
151 LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__);
152
153 // Read hardware breakpoint and watchpoint information.
154 llvm::Error error = ReadHardwareDebugInfo();
155 if (error)
156 return Status::FromError(std::move(error));
157
158 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
159 if (!BreakpointIsEnabled(i))
160 continue;
161 // Create a backup we can revert to in case of failure.
162 lldb::addr_t tempAddr = m_hbp_regs[i].address;
163 uint32_t tempControl = m_hbp_regs[i].control;
164
165 // Clear watchpoints in local cache
166 m_hbp_regs[i].control &= ~m_hw_dbg_enable_bit;
167 m_hbp_regs[i].address = 0;
168
169 // Ptrace call to update hardware debug registers
171
172 if (error) {
173 m_hbp_regs[i].control = tempControl;
174 m_hbp_regs[i].address = tempAddr;
175
176 return Status::FromError(std::move(error));
177 }
178 }
179
180 return Status();
181}
182
184 return ((m_hbp_regs[bp_index].control & m_hw_dbg_enable_bit) != 0);
185}
186
189 llvm::Error error = ReadHardwareDebugInfo();
190 if (error) {
191 LLDB_LOG_ERROR(log, std::move(error),
192 "failed to read debug registers: {0}");
193 return 0;
194 }
195
196 return m_max_hwp_supported;
197}
198
200 lldb::addr_t addr, size_t size, uint32_t watch_flags) {
202 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
203 watch_flags);
204
205 // Read hardware breakpoint and watchpoint information.
206 llvm::Error error = ReadHardwareDebugInfo();
207 if (error) {
209 log, std::move(error),
210 "unable to set watchpoint: failed to read debug registers: {0}");
212 }
213
214 uint32_t control_value = 0, wp_index = 0;
215 lldb::addr_t real_addr = addr;
216 WatchpointDetails details{size, addr};
217
218 auto adjusted = AdjustWatchpoint(details);
219 if (adjusted == std::nullopt)
221 size = adjusted->size;
222 addr = adjusted->addr;
223
224 // Check if we are setting watchpoint other than read/write/access Also
225 // update watchpoint flag to match AArch64/LoongArch write-read bit
226 // configuration.
227 switch (watch_flags) {
228 case lldb::eWatchpointKindWrite:
229 watch_flags = 2;
230 break;
231 case lldb::eWatchpointKindRead:
232 watch_flags = 1;
233 break;
234 case (lldb::eWatchpointKindRead | lldb::eWatchpointKindWrite):
235 break;
236 default:
238 }
239
240 control_value = MakeWatchControlValue(size, watch_flags);
241
242 // Iterate over stored watchpoints and find a free wp_index
243 wp_index = LLDB_INVALID_INDEX32;
244 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
245 if (!WatchpointIsEnabled(i))
246 wp_index = i; // Mark last free slot
247 else if (m_hwp_regs[i].address == addr) {
248 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
249 }
250 }
251
252 if (wp_index == LLDB_INVALID_INDEX32)
254
255 // Update watchpoint in local cache
256 m_hwp_regs[wp_index].real_addr = real_addr;
257 m_hwp_regs[wp_index].address = addr;
258 m_hwp_regs[wp_index].control = control_value;
259
260 // PTRACE call to set corresponding watchpoint register.
262
263 if (error) {
264 m_hwp_regs[wp_index].address = 0;
265 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
266
268 log, std::move(error),
269 "unable to set watchpoint: failed to write debug registers: {0}");
271 }
272
273 return wp_index;
274}
275
278 LLDB_LOG(log, "wp_index: {0}", wp_index);
279
280 // Read hardware breakpoint and watchpoint information.
281 llvm::Error error = ReadHardwareDebugInfo();
282 if (error) {
284 log, std::move(error),
285 "unable to set watchpoint: failed to read debug registers: {0}");
287 }
288
289 if (wp_index >= m_max_hwp_supported)
290 return false;
291
292 // Create a backup we can revert to in case of failure.
293 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
294 uint32_t tempControl = m_hwp_regs[wp_index].control;
295
296 // Update watchpoint in local cache
297 m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit;
298 m_hwp_regs[wp_index].address = 0;
299
300 // Ptrace call to update hardware debug registers
302
303 if (error) {
304 m_hwp_regs[wp_index].control = tempControl;
305 m_hwp_regs[wp_index].address = tempAddr;
306
308 log, std::move(error),
309 "unable to clear watchpoint: failed to read debug registers: {0}");
310 return false;
311 }
312
313 return true;
314}
315
317 // Read hardware breakpoint and watchpoint information.
318 llvm::Error error = ReadHardwareDebugInfo();
319 if (error)
320 return Status::FromError(std::move(error));
321
322 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
323 if (!WatchpointIsEnabled(i))
324 continue;
325 // Create a backup we can revert to in case of failure.
326 lldb::addr_t tempAddr = m_hwp_regs[i].address;
327 uint32_t tempControl = m_hwp_regs[i].control;
328
329 // Clear watchpoints in local cache
330 m_hwp_regs[i].control = 0;
331 m_hwp_regs[i].address = 0;
332
333 // Ptrace call to update hardware debug registers
335
336 if (error) {
337 m_hwp_regs[i].control = tempControl;
338 m_hwp_regs[i].address = tempAddr;
339
340 return Status::FromError(std::move(error));
341 }
342 }
343
344 return Status();
345}
346
347Status
349 lldb::addr_t trap_addr) {
351 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
352
353 // Read hardware breakpoint and watchpoint information.
354 llvm::Error error = ReadHardwareDebugInfo();
355 if (error)
356 return Status::FromError(std::move(error));
357
358 // AArch64 need mask off ignored bits from watchpoint trap address.
359 trap_addr = FixWatchpointHitAddress(trap_addr);
360
361 uint32_t watch_size;
362 lldb::addr_t watch_addr;
363
364 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
365 watch_size = GetWatchpointSize(wp_index);
366 watch_addr = m_hwp_regs[wp_index].address;
367
368 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
369 trap_addr < watch_addr + watch_size) {
370 m_hwp_regs[wp_index].hit_addr = trap_addr;
371 return Status();
372 }
373 }
374
375 wp_index = LLDB_INVALID_INDEX32;
376 return Status();
377}
378
381 LLDB_LOG(log, "wp_index: {0}", wp_index);
382 return ((m_hwp_regs[wp_index].control & m_hw_dbg_enable_bit) != 0);
383}
384
388 LLDB_LOG(log, "wp_index: {0}", wp_index);
389
390 if (wp_index >= m_max_hwp_supported)
392
393 if (WatchpointIsEnabled(wp_index))
394 return m_hwp_regs[wp_index].real_addr;
396}
397
401 LLDB_LOG(log, "wp_index: {0}", wp_index);
402
403 if (wp_index >= m_max_hwp_supported)
405
406 if (WatchpointIsEnabled(wp_index))
407 return m_hwp_regs[wp_index].hit_addr;
409}
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
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
bool ValidateBreakpoint(size_t size, lldb::addr_t addr)
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
bool ClearHardwareBreakpoint(uint32_t hw_idx) override
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
Definition: lldb-defines.h:83
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
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