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
11 #include "lldb/Host/windows/HostThreadWindows.h"
12 #include "lldb/Host/windows/windows.h"
13 #include "lldb/Utility/RegisterValue.h"
14 #include "lldb/Utility/Status.h"
15 #include "lldb/lldb-private-types.h"
16
17 #include "ProcessWindowsLog.h"
18 #include "RegisterContextWindows_x86.h"
19 #include "Plugins/Process/Utility/RegisterContext_x86.h"
20 #include "TargetThreadWindows.h"
21 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
22
23 #include "llvm/ADT/STLExtras.h"
24
25 using namespace lldb;
26 using 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
31 namespace {
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.
39 enum 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
53 RegisterInfo g_register_infos[] = {
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),
61 {ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM,
62 LLDB_INVALID_REGNUM, lldb_eax_i386},
63 nullptr,
64 nullptr,
65 nullptr,
66 0u},
67 {DEFINE_GPR(ebx, nullptr),
68 {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM,
69 LLDB_INVALID_REGNUM, lldb_ebx_i386},
70 nullptr,
71 nullptr,
72 nullptr,
73 0u},
74 {DEFINE_GPR(ecx, nullptr),
75 {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM,
76 LLDB_INVALID_REGNUM, lldb_ecx_i386},
77 nullptr,
78 nullptr,
79 nullptr,
80 0u},
81 {DEFINE_GPR(edx, nullptr),
82 {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM,
83 LLDB_INVALID_REGNUM, lldb_edx_i386},
84 nullptr,
85 nullptr,
86 nullptr,
87 0u},
88 {DEFINE_GPR(edi, nullptr),
89 {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM,
90 LLDB_INVALID_REGNUM, lldb_edi_i386},
91 nullptr,
92 nullptr,
93 nullptr,
94 0u},
95 {DEFINE_GPR(esi, nullptr),
96 {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM,
97 LLDB_INVALID_REGNUM, lldb_esi_i386},
98 nullptr,
99 nullptr,
100 nullptr,
101 0u},
102 {DEFINE_GPR(ebp, "fp"),
103 {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP,
104 LLDB_INVALID_REGNUM, lldb_ebp_i386},
105 nullptr,
106 nullptr,
107 nullptr,
108 0u},
109 {DEFINE_GPR(esp, "sp"),
110 {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP,
111 LLDB_INVALID_REGNUM, lldb_esp_i386},
112 nullptr,
113 nullptr,
114 nullptr,
115 0u},
116 {DEFINE_GPR(eip, "pc"),
117 {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC,
118 LLDB_INVALID_REGNUM, lldb_eip_i386},
119 nullptr,
120 nullptr,
121 nullptr,
122 0u},
123 {DEFINE_GPR_BIN(eflags, "flags"),
124 {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS,
125 LLDB_INVALID_REGNUM, lldb_eflags_i386},
126 nullptr,
127 nullptr,
128 nullptr,
129 0u},
130 };
131 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
132
133 // Array of lldb register numbers used to define the set of all General Purpose
134 // Registers
135 uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,
136 eRegisterIndexEcx, eRegisterIndexEdx,
137 eRegisterIndexEdi, eRegisterIndexEsi,
138 eRegisterIndexEbp, eRegisterIndexEsp,
139 eRegisterIndexEip, eRegisterIndexEflags};
140
141 RegisterSet g_register_sets[] = {
142 {"General Purpose Registers", "gpr",
143 llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
144 };
145 }
146
147 // Constructors and Destructors
RegisterContextWindows_x86(Thread & thread,uint32_t concrete_frame_idx)148 RegisterContextWindows_x86::RegisterContextWindows_x86(
149 Thread &thread, uint32_t concrete_frame_idx)
150 : RegisterContextWindows(thread, concrete_frame_idx) {}
151
~RegisterContextWindows_x86()152 RegisterContextWindows_x86::~RegisterContextWindows_x86() {}
153
GetRegisterCount()154 size_t RegisterContextWindows_x86::GetRegisterCount() {
155 return llvm::array_lengthof(g_register_infos);
156 }
157
158 const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)159 RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {
160 if (reg < k_num_register_infos)
161 return &g_register_infos[reg];
162 return NULL;
163 }
164
GetRegisterSetCount()165 size_t RegisterContextWindows_x86::GetRegisterSetCount() {
166 return llvm::array_lengthof(g_register_sets);
167 }
168
GetRegisterSet(size_t reg_set)169 const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {
170 return &g_register_sets[reg_set];
171 }
172
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)173 bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
174 RegisterValue ®_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 = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
206 LLDB_LOG(log, "Requested unknown register {0}", reg);
207 break;
208 }
209 return false;
210 }
211
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)212 bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,
213 const RegisterValue ®_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 = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_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
ReadRegisterHelper(DWORD flags_required,const char * reg_name,DWORD value,RegisterValue & reg_value) const273 bool RegisterContextWindows_x86::ReadRegisterHelper(
274 DWORD flags_required, const char *reg_name, DWORD value,
275 RegisterValue ®_value) const {
276 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_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)
287