LLDB  mainline
NativeRegisterContextDBReg_x86.cpp
Go to the documentation of this file.
1 //===-- NativeRegisterContextDBReg_x86.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 #include "lldb/Utility/LLDBLog.h"
12 
14 
15 using namespace lldb_private;
16 
17 // Returns mask/value for status bit of wp_index in DR6
18 static inline uint64_t GetStatusBit(uint32_t wp_index) {
19  // DR6: ...BBBB
20  // 3210 <- status bits for bp./wp. i; 1 if hit
21  return 1 << wp_index;
22 }
23 
24 // Returns mask/value for global enable bit of wp_index in DR7
25 static inline uint64_t GetEnableBit(uint32_t wp_index) {
26  // DR7: ...GLGLGLGL
27  // 33221100 <- global/local enable for bp./wp.; 1 if enabled
28  // we use global bits because NetBSD kernel does not preserve local
29  // bits reliably; Linux seems fine with either
30  return 1 << (2 * wp_index + 1);
31 }
32 
33 // Returns mask for both enable bits of wp_index in DR7
34 static inline uint64_t GetBothEnableBitMask(uint32_t wp_index) {
35  // DR7: ...GLGLGLGL
36  // 33221100 <- global/local enable for bp./wp.; 1 if enabled
37  return 3 << (2 * wp_index + 1);
38 }
39 
40 // Returns value for type bits of wp_index in DR7
41 static inline uint64_t GetWatchTypeBits(uint32_t watch_flags,
42  uint32_t wp_index) {
43  // DR7:
44  // bit: 3322222222221111...
45  // 1098765432109876...
46  // val: SSTTSSTTSSTTSSTT...
47  // wp.: 3333222211110000...
48  //
49  // where T - type is 01 for write, 11 for r/w
50  return watch_flags << (16 + 4 * wp_index);
51 }
52 
53 // Returns value for size bits of wp_index in DR7
54 static inline uint64_t GetWatchSizeBits(uint32_t size, uint32_t wp_index) {
55  // DR7:
56  // bit: 3322222222221111...
57  // 1098765432109876...
58  // val: SSTTSSTTSSTTSSTT...
59  // wp.: 3333222211110000...
60  //
61  // where S - size is:
62  // 00 for 1 byte
63  // 01 for 2 bytes
64  // 10 for 8 bytes
65  // 11 for 4 bytes
66  return (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
67 }
68 
69 // Returns bitmask for all bits controlling wp_index in DR7
70 static inline uint64_t GetWatchControlBitmask(uint32_t wp_index) {
71  // DR7:
72  // bit: 33222222222211111111110000000000
73  // 10987654321098765432109876543210
74  // val: SSTTSSTTSSTTSSTTxxxxxxGLGLGLGLGL
75  // wp.: 3333222211110000xxxxxxEE33221100
76  return GetBothEnableBitMask(wp_index) | (0xF << (16 + 4 * wp_index));
77 }
78 
79 // Bit mask for control bits regarding all watchpoints.
80 static constexpr uint64_t watchpoint_all_control_bit_mask = 0xFFFF00FF;
81 
82 const RegisterInfo *NativeRegisterContextDBReg_x86::GetDR(int num) const {
83  assert(num >= 0 && num <= 7);
84  switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
85  case llvm::Triple::x86:
87  case llvm::Triple::x86_64:
89  default:
90  llvm_unreachable("Unhandled target architecture.");
91  }
92 }
93 
95  bool &is_hit) {
96  if (wp_index >= NumSupportedHardwareWatchpoints())
97  return Status("Watchpoint index out of range");
98 
99  RegisterValue dr6;
100  Status error = ReadRegister(GetDR(6), dr6);
101  if (error.Fail())
102  is_hit = false;
103  else
104  is_hit = dr6.GetAsUInt64() & GetStatusBit(wp_index);
105 
106  return error;
107 }
108 
109 Status
111  lldb::addr_t trap_addr) {
113  for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
114  bool is_hit;
115  Status error = IsWatchpointHit(wp_index, is_hit);
116  if (error.Fail()) {
117  wp_index = LLDB_INVALID_INDEX32;
118  return error;
119  } else if (is_hit) {
120  return error;
121  }
122  }
123  wp_index = LLDB_INVALID_INDEX32;
124  return Status();
125 }
126 
128  bool &is_vacant) {
129  if (wp_index >= NumSupportedHardwareWatchpoints())
130  return Status("Watchpoint index out of range");
131 
132  RegisterValue dr7;
133  Status error = ReadRegister(GetDR(7), dr7);
134  if (error.Fail())
135  is_vacant = false;
136  else
137  is_vacant = !(dr7.GetAsUInt64() & GetEnableBit(wp_index));
138 
139  return error;
140 }
141 
143  lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
144 
145  if (wp_index >= NumSupportedHardwareWatchpoints())
146  return Status("Watchpoint index out of range");
147 
148  // Read only watchpoints aren't supported on x86_64. Fall back to read/write
149  // waitchpoints instead.
150  // TODO: Add logic to detect when a write happens and ignore that watchpoint
151  // hit.
152  if (watch_flags == 2)
153  watch_flags = 3;
154 
155  if (watch_flags != 1 && watch_flags != 3)
156  return Status("Invalid read/write bits for watchpoint");
157  if (size != 1 && size != 2 && size != 4 && size != 8)
158  return Status("Invalid size for watchpoint");
159 
160  bool is_vacant;
161  Status error = IsWatchpointVacant(wp_index, is_vacant);
162  if (error.Fail())
163  return error;
164  if (!is_vacant)
165  return Status("Watchpoint index not vacant");
166 
167  RegisterValue dr7, drN;
168  error = ReadRegister(GetDR(7), dr7);
169  if (error.Fail())
170  return error;
171  error = ReadRegister(GetDR(wp_index), drN);
172  if (error.Fail())
173  return error;
174 
175  uint64_t control_bits = dr7.GetAsUInt64() & ~GetWatchControlBitmask(wp_index);
176  control_bits |= GetEnableBit(wp_index) |
177  GetWatchTypeBits(watch_flags, wp_index) |
178  GetWatchSizeBits(size, wp_index);
179 
180  // Clear dr6 if address or bits changed (i.e. we're not reenabling the same
181  // watchpoint). This can not be done when clearing watchpoints since
182  // the gdb-remote protocol repeatedly clears and readds watchpoints on all
183  // program threads, effectively clearing pending events on NetBSD.
184  // NB: enable bits in dr7 are always 0 here since we're (re)adding it
185  if (drN.GetAsUInt64() != addr ||
186  (dr7.GetAsUInt64() & GetWatchControlBitmask(wp_index)) !=
187  (GetWatchTypeBits(watch_flags, wp_index) |
188  GetWatchSizeBits(size, wp_index))) {
189  ClearWatchpointHit(wp_index);
190 
191  // We skip update to drN if neither address nor mode changed.
192  error = WriteRegister(GetDR(wp_index), RegisterValue(addr));
193  if (error.Fail())
194  return error;
195  }
196 
197  error = WriteRegister(GetDR(7), RegisterValue(control_bits));
198  if (error.Fail())
199  return error;
200 
201  return error;
202 }
203 
205  uint32_t wp_index) {
206  if (wp_index >= NumSupportedHardwareWatchpoints())
207  return false;
208 
209  RegisterValue dr7;
210  Status error = ReadRegister(GetDR(7), dr7);
211  if (error.Fail())
212  return false;
213 
214  return WriteRegister(GetDR(7), RegisterValue(dr7.GetAsUInt64() &
215  ~GetBothEnableBitMask(wp_index)))
216  .Success();
217 }
218 
220  if (wp_index >= NumSupportedHardwareWatchpoints())
221  return Status("Watchpoint index out of range");
222 
223  RegisterValue dr6;
224  Status error = ReadRegister(GetDR(6), dr6);
225  if (error.Fail())
226  return error;
227 
228  return WriteRegister(
229  GetDR(6), RegisterValue(dr6.GetAsUInt64() & ~GetStatusBit(wp_index)));
230 }
231 
233  RegisterValue dr7;
234  Status error = ReadRegister(GetDR(7), dr7);
235  if (error.Fail())
236  return error;
237  return WriteRegister(
238  GetDR(7),
240 }
241 
243  lldb::addr_t addr, size_t size, uint32_t watch_flags) {
245  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
246  for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
247  bool is_vacant;
248  Status error = IsWatchpointVacant(wp_index, is_vacant);
249  if (is_vacant) {
250  error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
251  if (error.Success())
252  return wp_index;
253  }
254  if (error.Fail() && log) {
255  LLDB_LOGF(log, "NativeRegisterContextDBReg_x86::%s Error: %s",
256  __FUNCTION__, error.AsCString());
257  }
258  }
259  return LLDB_INVALID_INDEX32;
260 }
261 
264  if (wp_index >= NumSupportedHardwareWatchpoints())
265  return LLDB_INVALID_ADDRESS;
266  RegisterValue drN;
267  if (ReadRegister(GetDR(wp_index), drN).Fail())
268  return LLDB_INVALID_ADDRESS;
269  return drN.GetAsUInt64();
270 }
271 
273  // Available debug address registers: dr0, dr1, dr2, dr3
274  return 4;
275 }
GetWatchTypeBits
static uint64_t GetWatchTypeBits(uint32_t watch_flags, uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:41
lldb_private::NativeRegisterContextDBReg_x86::GetWatchpointAddress
lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override
Definition: NativeRegisterContextDBReg_x86.cpp:263
lldb_private::NativeRegisterContext::ReadRegister
virtual Status ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
lldb_private::RegisterValue
Definition: RegisterValue.h:28
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:343
RegisterValue.h
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
GetBothEnableBitMask
static uint64_t GetBothEnableBitMask(uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:34
lldb_private::RegisterValue::GetAsUInt64
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:563
GetStatusBit
static uint64_t GetStatusBit(uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:18
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::Status::Success
bool Success() const
Test for success condition.
Definition: Status.cpp:287
lldb_private::NativeRegisterContextDBReg_x86::SetHardwareWatchpoint
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override
Definition: NativeRegisterContextDBReg_x86.cpp:242
lldb_private::NativeRegisterContextRegisterInfo::GetRegisterInfoInterface
const RegisterInfoInterface & GetRegisterInfoInterface() const
Definition: NativeRegisterContextRegisterInfo.cpp:40
lldb_private::NativeRegisterContextDBReg_x86::SetHardwareWatchpointWithIndex
Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:142
lldb_private::lldb_dr0_i386
@ lldb_dr0_i386
Definition: lldb-x86-register-enums.h:117
lldb_private::LLDBLog::Watchpoints
@ Watchpoints
lldb_private::NativeRegisterContextDBReg_x86::IsWatchpointHit
Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override
Definition: NativeRegisterContextDBReg_x86.cpp:94
GetEnableBit
static uint64_t GetEnableBit(uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:25
lldb_private::Status
Definition: Status.h:44
lldb_private::NativeRegisterContextDBReg_x86::IsWatchpointVacant
Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override
Definition: NativeRegisterContextDBReg_x86.cpp:127
uint32_t
lldb_private::NativeRegisterContextDBReg_x86::ClearWatchpointHit
Status ClearWatchpointHit(uint32_t wp_index) override
Definition: NativeRegisterContextDBReg_x86.cpp:219
lldb-x86-register-enums.h
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::NativeRegisterContextDBReg_x86::GetWatchpointHitIndex
Status GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override
Definition: NativeRegisterContextDBReg_x86.cpp:110
lldb_private::NativeRegisterContextDBReg_x86::ClearAllHardwareWatchpoints
Status ClearAllHardwareWatchpoints() override
Definition: NativeRegisterContextDBReg_x86.cpp:232
lldb_private::NativeRegisterContextDBReg_x86::NumSupportedHardwareWatchpoints
uint32_t NumSupportedHardwareWatchpoints() override
Definition: NativeRegisterContextDBReg_x86.cpp:272
watchpoint_all_control_bit_mask
static constexpr uint64_t watchpoint_all_control_bit_mask
Definition: NativeRegisterContextDBReg_x86.cpp:80
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::NativeRegisterContextDBReg_x86::ClearHardwareWatchpoint
bool ClearHardwareWatchpoint(uint32_t wp_index) override
Definition: NativeRegisterContextDBReg_x86.cpp:204
GetWatchSizeBits
static uint64_t GetWatchSizeBits(uint32_t size, uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:54
lldb_private::lldb_dr0_x86_64
@ lldb_dr0_x86_64
Definition: lldb-x86-register-enums.h:303
arm64_dwarf::x2
@ x2
Definition: ARM64_DWARF_Registers.h:19
LLDB_INVALID_INDEX32
#define LLDB_INVALID_INDEX32
Definition: lldb-defines.h:75
lldb_private::Log
Definition: Log.h:115
lldb_private::NativeRegisterContext::WriteRegister
virtual Status WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)=0
GetWatchControlBitmask
static uint64_t GetWatchControlBitmask(uint32_t wp_index)
Definition: NativeRegisterContextDBReg_x86.cpp:70
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
lldb_private::NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex
const RegisterInfo * GetRegisterInfoAtIndex(uint32_t reg_index) const override
Definition: NativeRegisterContextRegisterInfo.cpp:31
LLDBLog.h
lldb_private::NativeRegisterContextDBReg_x86::GetDR
const RegisterInfo * GetDR(int num) const
Definition: NativeRegisterContextDBReg_x86.cpp:82
NativeRegisterContextDBReg_x86.h