1 //===-- RegisterContextWindows_x64.cpp --------------------------*- C++ -*-===//
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 #include "lldb/Host/windows/HostThreadWindows.h"
10 #include "lldb/Host/windows/windows.h"
11 #include "lldb/Utility/RegisterValue.h"
12 #include "lldb/Utility/Status.h"
13 #include "lldb/lldb-private-types.h"
14 
15 #include "RegisterContextWindows_x64.h"
16 #include "Plugins/Process/Utility/RegisterContext_x86.h"
17 #include "TargetThreadWindows.h"
18 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
19 
20 #include "llvm/ADT/STLExtras.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 #define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase
26 #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary
27 
28 namespace {
29 
30 // This enum defines the layout of the global RegisterInfo array.  This is
31 // necessary because lldb register sets are defined in terms of indices into
32 // the register array. As such, the order of RegisterInfos defined in global
33 // registers array must match the order defined here. When defining the
34 // register set layouts, these values can appear in an arbitrary order, and
35 // that determines the order that register values are displayed in a dump.
36 enum RegisterIndex {
37   eRegisterIndexRax,
38   eRegisterIndexRbx,
39   eRegisterIndexRcx,
40   eRegisterIndexRdx,
41   eRegisterIndexRdi,
42   eRegisterIndexRsi,
43   eRegisterIndexRbp,
44   eRegisterIndexRsp,
45   eRegisterIndexR8,
46   eRegisterIndexR9,
47   eRegisterIndexR10,
48   eRegisterIndexR11,
49   eRegisterIndexR12,
50   eRegisterIndexR13,
51   eRegisterIndexR14,
52   eRegisterIndexR15,
53   eRegisterIndexRip,
54   eRegisterIndexRflags
55 };
56 
57 // Array of all register information supported by Windows x86
58 RegisterInfo g_register_infos[] = {
59     //  Macro auto defines most stuff     eh_frame                  DWARF
60     //  GENERIC
61     //  GDB                  LLDB                  VALUE REGS    INVALIDATE REGS
62     //  ================================  =========================
63     //  ======================  =========================
64     //  ===================  =================     ==========    ===============
65     {DEFINE_GPR(rax, nullptr),
66      {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM,
67       LLDB_INVALID_REGNUM, lldb_rax_x86_64},
68      nullptr,
69      nullptr},
70     {DEFINE_GPR(rbx, nullptr),
71      {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM,
72       LLDB_INVALID_REGNUM, lldb_rbx_x86_64},
73      nullptr,
74      nullptr},
75     {DEFINE_GPR(rcx, nullptr),
76      {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1,
77       LLDB_INVALID_REGNUM, lldb_rcx_x86_64},
78      nullptr,
79      nullptr},
80     {DEFINE_GPR(rdx, nullptr),
81      {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2,
82       LLDB_INVALID_REGNUM, lldb_rdx_x86_64},
83      nullptr,
84      nullptr},
85     {DEFINE_GPR(rdi, nullptr),
86      {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM,
87       LLDB_INVALID_REGNUM, lldb_rdi_x86_64},
88      nullptr,
89      nullptr},
90     {DEFINE_GPR(rsi, nullptr),
91      {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM,
92       LLDB_INVALID_REGNUM, lldb_rsi_x86_64},
93      nullptr,
94      nullptr},
95     {DEFINE_GPR(rbp, "fp"),
96      {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
97       LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
98      nullptr,
99      nullptr},
100     {DEFINE_GPR(rsp, "sp"),
101      {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
102       LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
103      nullptr,
104      nullptr},
105     {DEFINE_GPR(r8, nullptr),
106      {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3,
107       LLDB_INVALID_REGNUM, lldb_r8_x86_64},
108      nullptr,
109      nullptr},
110     {DEFINE_GPR(r9, nullptr),
111      {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4,
112       LLDB_INVALID_REGNUM, lldb_r9_x86_64},
113      nullptr,
114      nullptr},
115     {DEFINE_GPR(r10, nullptr),
116      {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5,
117       LLDB_INVALID_REGNUM, lldb_r10_x86_64},
118      nullptr,
119      nullptr},
120     {DEFINE_GPR(r11, nullptr),
121      {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6,
122       LLDB_INVALID_REGNUM, lldb_r11_x86_64},
123      nullptr,
124      nullptr},
125     {DEFINE_GPR(r12, nullptr),
126      {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM,
127       LLDB_INVALID_REGNUM, lldb_r12_x86_64},
128      nullptr,
129      nullptr},
130     {DEFINE_GPR(r13, nullptr),
131      {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM,
132       LLDB_INVALID_REGNUM, lldb_r13_x86_64},
133      nullptr,
134      nullptr},
135     {DEFINE_GPR(r14, nullptr),
136      {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM,
137       LLDB_INVALID_REGNUM, lldb_r14_x86_64},
138      nullptr,
139      nullptr},
140     {DEFINE_GPR(r15, nullptr),
141      {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM,
142       LLDB_INVALID_REGNUM, lldb_r15_x86_64},
143      nullptr,
144      nullptr},
145     {DEFINE_GPR(rip, "pc"),
146      {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC,
147       LLDB_INVALID_REGNUM, lldb_rip_x86_64},
148      nullptr,
149      nullptr},
150     {DEFINE_GPR_BIN(eflags, "flags"),
151      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
152       LLDB_INVALID_REGNUM, lldb_rflags_x86_64},
153      nullptr,
154      nullptr},
155 };
156 
157 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
158 
159 // Array of lldb register numbers used to define the set of all General Purpose
160 // Registers
161 uint32_t g_gpr_reg_indices[] = {
162     eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx,
163     eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi,
164     eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8,
165     eRegisterIndexR9,  eRegisterIndexR10, eRegisterIndexR11,
166     eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
167     eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
168 
169 RegisterSet g_register_sets[] = {
170     {"General Purpose Registers", "gpr",
171      llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
172 };
173 }
174 
175 // Constructors and Destructors
176 RegisterContextWindows_x64::RegisterContextWindows_x64(
177     Thread &thread, uint32_t concrete_frame_idx)
178     : RegisterContextWindows(thread, concrete_frame_idx) {}
179 
180 RegisterContextWindows_x64::~RegisterContextWindows_x64() {}
181 
182 size_t RegisterContextWindows_x64::GetRegisterCount() {
183   return llvm::array_lengthof(g_register_infos);
184 }
185 
186 const RegisterInfo *
187 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) {
188   if (reg < k_num_register_infos)
189     return &g_register_infos[reg];
190   return NULL;
191 }
192 
193 size_t RegisterContextWindows_x64::GetRegisterSetCount() {
194   return llvm::array_lengthof(g_register_sets);
195 }
196 
197 const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) {
198   return &g_register_sets[reg_set];
199 }
200 
201 bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
202                                               RegisterValue &reg_value) {
203   if (!CacheAllRegisterValues())
204     return false;
205 
206   if (reg_info == nullptr)
207     return false;
208 
209   switch (reg_info->kinds[eRegisterKindLLDB]) {
210   case lldb_rax_x86_64:
211     reg_value.SetUInt64(m_context.Rax);
212     break;
213   case lldb_rbx_x86_64:
214     reg_value.SetUInt64(m_context.Rbx);
215     break;
216   case lldb_rcx_x86_64:
217     reg_value.SetUInt64(m_context.Rcx);
218     break;
219   case lldb_rdx_x86_64:
220     reg_value.SetUInt64(m_context.Rdx);
221     break;
222   case lldb_rdi_x86_64:
223     reg_value.SetUInt64(m_context.Rdi);
224     break;
225   case lldb_rsi_x86_64:
226     reg_value.SetUInt64(m_context.Rsi);
227     break;
228   case lldb_r8_x86_64:
229     reg_value.SetUInt64(m_context.R8);
230     break;
231   case lldb_r9_x86_64:
232     reg_value.SetUInt64(m_context.R9);
233     break;
234   case lldb_r10_x86_64:
235     reg_value.SetUInt64(m_context.R10);
236     break;
237   case lldb_r11_x86_64:
238     reg_value.SetUInt64(m_context.R11);
239     break;
240   case lldb_r12_x86_64:
241     reg_value.SetUInt64(m_context.R12);
242     break;
243   case lldb_r13_x86_64:
244     reg_value.SetUInt64(m_context.R13);
245     break;
246   case lldb_r14_x86_64:
247     reg_value.SetUInt64(m_context.R14);
248     break;
249   case lldb_r15_x86_64:
250     reg_value.SetUInt64(m_context.R15);
251     break;
252   case lldb_rbp_x86_64:
253     reg_value.SetUInt64(m_context.Rbp);
254     break;
255   case lldb_rsp_x86_64:
256     reg_value.SetUInt64(m_context.Rsp);
257     break;
258   case lldb_rip_x86_64:
259     reg_value.SetUInt64(m_context.Rip);
260     break;
261   case lldb_rflags_x86_64:
262     reg_value.SetUInt64(m_context.EFlags);
263     break;
264   }
265   return true;
266 }
267 
268 bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
269                                                const RegisterValue &reg_value) {
270   // Since we cannot only write a single register value to the inferior, we
271   // need to make sure our cached copy of the register values are fresh.
272   // Otherwise when writing EAX, for example, we may also overwrite some other
273   // register with a stale value.
274   if (!CacheAllRegisterValues())
275     return false;
276 
277   switch (reg_info->kinds[eRegisterKindLLDB]) {
278   case lldb_rax_x86_64:
279     m_context.Rax = reg_value.GetAsUInt64();
280     break;
281   case lldb_rbx_x86_64:
282     m_context.Rbx = reg_value.GetAsUInt64();
283     break;
284   case lldb_rcx_x86_64:
285     m_context.Rcx = reg_value.GetAsUInt64();
286     break;
287   case lldb_rdx_x86_64:
288     m_context.Rdx = reg_value.GetAsUInt64();
289     break;
290   case lldb_rdi_x86_64:
291     m_context.Rdi = reg_value.GetAsUInt64();
292     break;
293   case lldb_rsi_x86_64:
294     m_context.Rsi = reg_value.GetAsUInt64();
295     break;
296   case lldb_r8_x86_64:
297     m_context.R8 = reg_value.GetAsUInt64();
298     break;
299   case lldb_r9_x86_64:
300     m_context.R9 = reg_value.GetAsUInt64();
301     break;
302   case lldb_r10_x86_64:
303     m_context.R10 = reg_value.GetAsUInt64();
304     break;
305   case lldb_r11_x86_64:
306     m_context.R11 = reg_value.GetAsUInt64();
307     break;
308   case lldb_r12_x86_64:
309     m_context.R12 = reg_value.GetAsUInt64();
310     break;
311   case lldb_r13_x86_64:
312     m_context.R13 = reg_value.GetAsUInt64();
313     break;
314   case lldb_r14_x86_64:
315     m_context.R14 = reg_value.GetAsUInt64();
316     break;
317   case lldb_r15_x86_64:
318     m_context.R15 = reg_value.GetAsUInt64();
319     break;
320   case lldb_rbp_x86_64:
321     m_context.Rbp = reg_value.GetAsUInt64();
322     break;
323   case lldb_rsp_x86_64:
324     m_context.Rsp = reg_value.GetAsUInt64();
325     break;
326   case lldb_rip_x86_64:
327     m_context.Rip = reg_value.GetAsUInt64();
328     break;
329   case lldb_rflags_x86_64:
330     m_context.EFlags = reg_value.GetAsUInt64();
331     break;
332   }
333 
334   // Physically update the registers in the target process.
335   TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
336   return ::SetThreadContext(
337       wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
338 }
339