LLDB mainline
RegisterContextWindows_x86.cpp
Go to the documentation of this file.
1//===-- RegisterContextWindows_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
9#if defined(__i386__) || defined(_M_IX86)
10
14#include "lldb/Utility/Status.h"
16
17#include "ProcessWindowsLog.h"
20#include "TargetThreadWindows.h"
22
23#include "llvm/ADT/STLExtras.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28#define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase
29#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary
30
31namespace {
32
33// This enum defines the layout of the global RegisterInfo array. This is
34// necessary because lldb register sets are defined in terms of indices into
35// the register array. As such, the order of RegisterInfos defined in global
36// registers array must match the order defined here. When defining the
37// register set layouts, these values can appear in an arbitrary order, and
38// that determines the order that register values are displayed in a dump.
39enum RegisterIndex {
40 eRegisterIndexEax,
41 eRegisterIndexEbx,
42 eRegisterIndexEcx,
43 eRegisterIndexEdx,
44 eRegisterIndexEdi,
45 eRegisterIndexEsi,
46 eRegisterIndexEbp,
47 eRegisterIndexEsp,
48 eRegisterIndexEip,
49 eRegisterIndexEflags
50};
51
52// Array of all register information supported by Windows x86
54 {DEFINE_GPR(eax, nullptr),
57 nullptr,
58 nullptr,
59 nullptr,
60 },
61 {DEFINE_GPR(ebx, nullptr),
64 nullptr,
65 nullptr,
66 nullptr,
67 },
68 {DEFINE_GPR(ecx, nullptr),
71 nullptr,
72 nullptr,
73 nullptr,
74 },
75 {DEFINE_GPR(edx, nullptr),
78 nullptr,
79 nullptr,
80 nullptr,
81 },
82 {DEFINE_GPR(edi, nullptr),
85 nullptr,
86 nullptr,
87 nullptr,
88 },
89 {DEFINE_GPR(esi, nullptr),
92 nullptr,
93 nullptr,
94 nullptr,
95 },
96 {DEFINE_GPR(ebp, "fp"),
99 nullptr,
100 nullptr,
101 nullptr,
102 },
103 {DEFINE_GPR(esp, "sp"),
106 nullptr,
107 nullptr,
108 nullptr,
109 },
110 {DEFINE_GPR(eip, "pc"),
113 nullptr,
114 nullptr,
115 nullptr,
116 },
117 {DEFINE_GPR_BIN(eflags, "flags"),
120 nullptr,
121 nullptr,
122 nullptr,
123 },
124};
125static size_t k_num_register_infos = std::size(g_register_infos);
126
127// Array of lldb register numbers used to define the set of all General Purpose
128// Registers
129uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,
130 eRegisterIndexEcx, eRegisterIndexEdx,
131 eRegisterIndexEdi, eRegisterIndexEsi,
132 eRegisterIndexEbp, eRegisterIndexEsp,
133 eRegisterIndexEip, eRegisterIndexEflags};
134
135RegisterSet g_register_sets[] = {
136 {"General Purpose Registers", "gpr", std::size(g_gpr_reg_indices),
137 g_gpr_reg_indices},
138};
139}
140
141// Constructors and Destructors
142RegisterContextWindows_x86::RegisterContextWindows_x86(
143 Thread &thread, uint32_t concrete_frame_idx)
144 : RegisterContextWindows(thread, concrete_frame_idx) {}
145
146RegisterContextWindows_x86::~RegisterContextWindows_x86() {}
147
148size_t RegisterContextWindows_x86::GetRegisterCount() {
149 return std::size(g_register_infos);
150}
151
152const RegisterInfo *
153RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {
154 if (reg < k_num_register_infos)
155 return &g_register_infos[reg];
156 return NULL;
157}
158
159size_t RegisterContextWindows_x86::GetRegisterSetCount() {
160 return std::size(g_register_sets);
161}
162
163const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {
164 return &g_register_sets[reg_set];
165}
166
167bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
168 RegisterValue &reg_value) {
169 if (!CacheAllRegisterValues())
170 return false;
171
172 if (reg_info == nullptr)
173 return false;
174
175 uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
176 switch (reg) {
177 case lldb_eax_i386:
178 return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);
179 case lldb_ebx_i386:
180 return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);
181 case lldb_ecx_i386:
182 return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);
183 case lldb_edx_i386:
184 return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);
185 case lldb_edi_i386:
186 return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);
187 case lldb_esi_i386:
188 return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);
189 case lldb_ebp_i386:
190 return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);
191 case lldb_esp_i386:
192 return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);
193 case lldb_eip_i386:
194 return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);
195 case lldb_eflags_i386:
196 return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags,
197 reg_value);
198 default:
199 Log *log = GetLog(WindowsLog::Registers);
200 LLDB_LOG(log, "Requested unknown register {0}", reg);
201 break;
202 }
203 return false;
204}
205
206bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,
207 const RegisterValue &reg_value) {
208 // Since we cannot only write a single register value to the inferior, we
209 // need to make sure our cached copy of the register values are fresh.
210 // Otherwise when writing EAX, for example, we may also overwrite some other
211 // register with a stale value.
212 if (!CacheAllRegisterValues())
213 return false;
214
215 Log *log = GetLog(WindowsLog::Registers);
216 uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
217 switch (reg) {
218 case lldb_eax_i386:
219 LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32());
220 m_context.Eax = reg_value.GetAsUInt32();
221 break;
222 case lldb_ebx_i386:
223 LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32());
224 m_context.Ebx = reg_value.GetAsUInt32();
225 break;
226 case lldb_ecx_i386:
227 LLDB_LOG(log, "Write value {0:x} to ECX", reg_value.GetAsUInt32());
228 m_context.Ecx = reg_value.GetAsUInt32();
229 break;
230 case lldb_edx_i386:
231 LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32());
232 m_context.Edx = reg_value.GetAsUInt32();
233 break;
234 case lldb_edi_i386:
235 LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32());
236 m_context.Edi = reg_value.GetAsUInt32();
237 break;
238 case lldb_esi_i386:
239 LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32());
240 m_context.Esi = reg_value.GetAsUInt32();
241 break;
242 case lldb_ebp_i386:
243 LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32());
244 m_context.Ebp = reg_value.GetAsUInt32();
245 break;
246 case lldb_esp_i386:
247 LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32());
248 m_context.Esp = reg_value.GetAsUInt32();
249 break;
250 case lldb_eip_i386:
251 LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32());
252 m_context.Eip = reg_value.GetAsUInt32();
253 break;
254 case lldb_eflags_i386:
255 LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32());
256 m_context.EFlags = reg_value.GetAsUInt32();
257 break;
258 default:
259 LLDB_LOG(log, "Write value {0:x} to unknown register {1}",
260 reg_value.GetAsUInt32(), reg);
261 }
262
263 // Physically update the registers in the target process.
264 return ApplyAllRegisterValues();
265}
266
267bool RegisterContextWindows_x86::ReadRegisterHelper(
268 DWORD flags_required, const char *reg_name, DWORD value,
269 RegisterValue &reg_value) const {
270 Log *log = GetLog(WindowsLog::Registers);
271 if ((m_context.ContextFlags & flags_required) != flags_required) {
272 LLDB_LOG(log, "Thread context doesn't have {0}", reg_name);
273 return false;
274 }
275 LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name);
276 reg_value.SetUInt32(value);
277 return true;
278}
279
280#endif // defined(__i386__) || defined(_M_IX86)
static const uint32_t k_num_register_infos
static const RegisterInfo g_register_infos[]
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:369
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:57
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:60
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:56
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:58
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
Definition: SBAddress.h:15
@ eRegisterKindLLDB
lldb's internal register numbers
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.
Registers are grouped into register sets.