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 // Macro auto defines most stuff eh_frame DWARF
55 // GENERIC GDB LLDB
56 // VALUE REGS INVALIDATE REGS
57 // ============================== =======================
58 // =================== ========================= ===================
59 // ================= ========== ===============
60 {DEFINE_GPR(eax, nullptr),
63 nullptr,
64 nullptr,
65 nullptr,
66 },
67 {DEFINE_GPR(ebx, nullptr),
70 nullptr,
71 nullptr,
72 nullptr,
73 },
74 {DEFINE_GPR(ecx, nullptr),
77 nullptr,
78 nullptr,
79 nullptr,
80 },
81 {DEFINE_GPR(edx, nullptr),
84 nullptr,
85 nullptr,
86 nullptr,
87 },
88 {DEFINE_GPR(edi, nullptr),
91 nullptr,
92 nullptr,
93 nullptr,
94 },
95 {DEFINE_GPR(esi, nullptr),
98 nullptr,
99 nullptr,
100 nullptr,
101 },
102 {DEFINE_GPR(ebp, "fp"),
105 nullptr,
106 nullptr,
107 nullptr,
108 },
109 {DEFINE_GPR(esp, "sp"),
112 nullptr,
113 nullptr,
114 nullptr,
115 },
116 {DEFINE_GPR(eip, "pc"),
119 nullptr,
120 nullptr,
121 nullptr,
122 },
123 {DEFINE_GPR_BIN(eflags, "flags"),
126 nullptr,
127 nullptr,
128 nullptr,
129 },
130};
131static size_t k_num_register_infos = std::size(g_register_infos);
132
133// Array of lldb register numbers used to define the set of all General Purpose
134// Registers
135uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,
136 eRegisterIndexEcx, eRegisterIndexEdx,
137 eRegisterIndexEdi, eRegisterIndexEsi,
138 eRegisterIndexEbp, eRegisterIndexEsp,
139 eRegisterIndexEip, eRegisterIndexEflags};
140
141RegisterSet g_register_sets[] = {
142 {"General Purpose Registers", "gpr", std::size(g_gpr_reg_indices),
143 g_gpr_reg_indices},
144};
145}
146
147// Constructors and Destructors
148RegisterContextWindows_x86::RegisterContextWindows_x86(
149 Thread &thread, uint32_t concrete_frame_idx)
150 : RegisterContextWindows(thread, concrete_frame_idx) {}
151
152RegisterContextWindows_x86::~RegisterContextWindows_x86() {}
153
154size_t RegisterContextWindows_x86::GetRegisterCount() {
155 return std::size(g_register_infos);
156}
157
158const RegisterInfo *
159RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {
160 if (reg < k_num_register_infos)
161 return &g_register_infos[reg];
162 return NULL;
163}
164
165size_t RegisterContextWindows_x86::GetRegisterSetCount() {
166 return std::size(g_register_sets);
167}
168
169const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {
170 return &g_register_sets[reg_set];
171}
172
173bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
174 RegisterValue &reg_value) {
175 if (!CacheAllRegisterValues())
176 return false;
177
178 if (reg_info == nullptr)
179 return false;
180
181 uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
182 switch (reg) {
183 case lldb_eax_i386:
184 return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);
185 case lldb_ebx_i386:
186 return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);
187 case lldb_ecx_i386:
188 return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);
189 case lldb_edx_i386:
190 return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);
191 case lldb_edi_i386:
192 return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);
193 case lldb_esi_i386:
194 return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);
195 case lldb_ebp_i386:
196 return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);
197 case lldb_esp_i386:
198 return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);
199 case lldb_eip_i386:
200 return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);
201 case lldb_eflags_i386:
202 return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags,
203 reg_value);
204 default:
205 Log *log = GetLog(WindowsLog::Registers);
206 LLDB_LOG(log, "Requested unknown register {0}", reg);
207 break;
208 }
209 return false;
210}
211
212bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,
213 const RegisterValue &reg_value) {
214 // Since we cannot only write a single register value to the inferior, we
215 // need to make sure our cached copy of the register values are fresh.
216 // Otherwise when writing EAX, for example, we may also overwrite some other
217 // register with a stale value.
218 if (!CacheAllRegisterValues())
219 return false;
220
221 Log *log = GetLog(WindowsLog::Registers);
222 uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
223 switch (reg) {
224 case lldb_eax_i386:
225 LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32());
226 m_context.Eax = reg_value.GetAsUInt32();
227 break;
228 case lldb_ebx_i386:
229 LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32());
230 m_context.Ebx = reg_value.GetAsUInt32();
231 break;
232 case lldb_ecx_i386:
233 LLDB_LOG(log, "Write value {0:x} to ECX", reg_value.GetAsUInt32());
234 m_context.Ecx = reg_value.GetAsUInt32();
235 break;
236 case lldb_edx_i386:
237 LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32());
238 m_context.Edx = reg_value.GetAsUInt32();
239 break;
240 case lldb_edi_i386:
241 LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32());
242 m_context.Edi = reg_value.GetAsUInt32();
243 break;
244 case lldb_esi_i386:
245 LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32());
246 m_context.Esi = reg_value.GetAsUInt32();
247 break;
248 case lldb_ebp_i386:
249 LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32());
250 m_context.Ebp = reg_value.GetAsUInt32();
251 break;
252 case lldb_esp_i386:
253 LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32());
254 m_context.Esp = reg_value.GetAsUInt32();
255 break;
256 case lldb_eip_i386:
257 LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32());
258 m_context.Eip = reg_value.GetAsUInt32();
259 break;
260 case lldb_eflags_i386:
261 LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32());
262 m_context.EFlags = reg_value.GetAsUInt32();
263 break;
264 default:
265 LLDB_LOG(log, "Write value {0:x} to unknown register {1}",
266 reg_value.GetAsUInt32(), reg);
267 }
268
269 // Physically update the registers in the target process.
270 return ApplyAllRegisterValues();
271}
272
273bool RegisterContextWindows_x86::ReadRegisterHelper(
274 DWORD flags_required, const char *reg_name, DWORD value,
275 RegisterValue &reg_value) const {
276 Log *log = GetLog(WindowsLog::Registers);
277 if ((m_context.ContextFlags & flags_required) != flags_required) {
278 LLDB_LOG(log, "Thread context doesn't have {0}", reg_name);
279 return false;
280 }
281 LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name);
282 reg_value.SetUInt32(value);
283 return true;
284}
285
286#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:342
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.
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
@ 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.