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