LLDB mainline
RegisterContextWindows.cpp
Go to the documentation of this file.
1//===-- RegisterContextWindows.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
12#include "lldb/Utility/Status.h"
14
15#include "ProcessWindowsLog.h"
17#include "TargetThreadWindows.h"
18
19#include "llvm/ADT/STLExtras.h"
20#include "lldb/Target/Target.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25const DWORD kWinContextFlags = CONTEXT_ALL;
26
27// Constructors and Destructors
29 uint32_t concrete_frame_idx)
30 : RegisterContext(thread, concrete_frame_idx), m_context(),
31 m_context_stale(true) {}
32
34
36 m_context_stale = true;
37}
38
41
43 return false;
44
45 data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
46 memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
47
48 return true;
49}
50
52 const lldb::DataBufferSP &data_sp) {
53 assert(data_sp->GetByteSize() >= sizeof(m_context));
54 memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));
55
57}
58
60 lldb::RegisterKind kind, uint32_t num) {
61 const uint32_t num_regs = GetRegisterCount();
62
63 assert(kind < kNumRegisterKinds);
64 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
65 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
66
67 if (reg_info->kinds[kind] == num)
68 return reg_idx;
69 }
70
72}
73
74bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }
75
77 lldb::addr_t address,
78 uint32_t size, bool read,
79 bool write) {
81 return false;
82
83 switch (size) {
84 case 1:
85 case 2:
86 case 4:
87#if defined(_WIN64)
88 case 8:
89#endif
90 break;
91 default:
92 return false;
93 }
94
96 return false;
97
98#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)
99 unsigned shift = 2 * slot;
100 m_context.Dr7 |= 1ULL << shift;
101
102 (&m_context.Dr0)[slot] = address;
103
104 shift = 18 + 4 * slot;
105 m_context.Dr7 &= ~(3ULL << shift);
106 m_context.Dr7 |= (size == 8 ? 2ULL : size - 1) << shift;
107
108 shift = 16 + 4 * slot;
109 m_context.Dr7 &= ~(3ULL << shift);
110 m_context.Dr7 |= (read ? 3ULL : (write ? 1ULL : 0)) << shift;
111
112 return ApplyAllRegisterValues();
113
114#else
116 LLDB_LOG(log, "hardware breakpoints not currently supported on this arch");
117 return false;
118#endif
119}
120
123 return false;
124
126 return false;
127
128#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)
129 unsigned shift = 2 * slot;
130 m_context.Dr7 &= ~(1ULL << shift);
131
132 return ApplyAllRegisterValues();
133#else
134 return false;
135#endif
136}
137
141
142#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)
143 for (unsigned i = 0UL; i < NUM_HARDWARE_BREAKPOINT_SLOTS; i++)
144 if (m_context.Dr6 & (1ULL << i))
145 return i;
146#endif
147
149}
150
153 if (!m_context_stale)
154 return true;
155
156 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
157 memset(&m_context, 0, sizeof(m_context));
158 m_context.ContextFlags = kWinContextFlags;
159 if (::SuspendThread(
161 (DWORD)-1) {
162 return false;
163 }
164 if (!::GetThreadContext(
166 &m_context)) {
167 LLDB_LOG(
168 log,
169 "GetThreadContext failed with error {0} while caching register values.",
170 ::GetLastError());
171 return false;
172 }
173 if (::ResumeThread(
175 (DWORD)-1) {
176 return false;
177 }
178 LLDB_LOG(log, "successfully updated the register values.");
179 m_context_stale = false;
180 return true;
181}
182
184 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
185 return ::SetThreadContext(
187}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:342
const DWORD kWinContextFlags
A subclass of DataBuffer that stores a data buffer on the heap.
HostNativeThread & GetNativeThread()
Definition: HostThread.cpp:32
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override
bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override
static constexpr unsigned NUM_HARDWARE_BREAKPOINT_SLOTS
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override
Convert from a given register numbering scheme to the lldb register numbering scheme.
bool HardwareSingleStep(bool enable) override
bool AddHardwareBreakpoint(uint32_t slot, lldb::addr_t address, uint32_t size, bool read, bool write)
RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx)
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
virtual size_t GetRegisterCount()=0
#define LLDB_INVALID_INDEX32
Definition: lldb-defines.h:83
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:314
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
Definition: lldb-forward.h:328
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:329
uint64_t addr_t
Definition: lldb-types.h:79
RegisterKind
Register numbering types.
@ kNumRegisterKinds
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.