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 #define DEFINE_FPU_XMM(reg)                                                    \
28   #reg, NULL, 16, 0, eEncodingUint, eFormatVectorOfUInt64,                     \
29   {dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM,            \
30    LLDB_INVALID_REGNUM, lldb_##reg##_x86_64},                                  \
31   nullptr, nullptr, nullptr, 0
32 
33 namespace {
34 
35 // This enum defines the layout of the global RegisterInfo array.  This is
36 // necessary because lldb register sets are defined in terms of indices into
37 // the register array. As such, the order of RegisterInfos defined in global
38 // registers array must match the order defined here. When defining the
39 // register set layouts, these values can appear in an arbitrary order, and
40 // that determines the order that register values are displayed in a dump.
41 enum RegisterIndex {
42   eRegisterIndexRax,
43   eRegisterIndexRbx,
44   eRegisterIndexRcx,
45   eRegisterIndexRdx,
46   eRegisterIndexRdi,
47   eRegisterIndexRsi,
48   eRegisterIndexRbp,
49   eRegisterIndexRsp,
50   eRegisterIndexR8,
51   eRegisterIndexR9,
52   eRegisterIndexR10,
53   eRegisterIndexR11,
54   eRegisterIndexR12,
55   eRegisterIndexR13,
56   eRegisterIndexR14,
57   eRegisterIndexR15,
58   eRegisterIndexRip,
59   eRegisterIndexRflags,
60 
61   eRegisterIndexXmm0,
62   eRegisterIndexXmm1,
63   eRegisterIndexXmm2,
64   eRegisterIndexXmm3,
65   eRegisterIndexXmm4,
66   eRegisterIndexXmm5,
67   eRegisterIndexXmm6,
68   eRegisterIndexXmm7,
69   eRegisterIndexXmm8,
70   eRegisterIndexXmm9,
71   eRegisterIndexXmm10,
72   eRegisterIndexXmm11,
73   eRegisterIndexXmm12,
74   eRegisterIndexXmm13,
75   eRegisterIndexXmm14,
76   eRegisterIndexXmm15
77 };
78 
79 // Array of all register information supported by Windows x86
80 RegisterInfo g_register_infos[] = {
81     //  Macro auto defines most stuff     eh_frame                  DWARF
82     //  GENERIC
83     //  GDB                  LLDB                  VALUE REGS    INVALIDATE REGS
84     //  ================================  =========================
85     //  ======================  =========================
86     //  ===================  =================     ==========    ===============
87     {DEFINE_GPR(rax, nullptr),
88      {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM,
89       LLDB_INVALID_REGNUM, lldb_rax_x86_64},
90      nullptr,
91      nullptr,
92      nullptr,
93      0},
94     {DEFINE_GPR(rbx, nullptr),
95      {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM,
96       LLDB_INVALID_REGNUM, lldb_rbx_x86_64},
97      nullptr,
98      nullptr,
99      nullptr,
100      0},
101     {DEFINE_GPR(rcx, nullptr),
102      {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1,
103       LLDB_INVALID_REGNUM, lldb_rcx_x86_64},
104      nullptr,
105      nullptr,
106      nullptr,
107      0},
108     {DEFINE_GPR(rdx, nullptr),
109      {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2,
110       LLDB_INVALID_REGNUM, lldb_rdx_x86_64},
111      nullptr,
112      nullptr,
113      nullptr,
114      0},
115     {DEFINE_GPR(rdi, nullptr),
116      {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM,
117       LLDB_INVALID_REGNUM, lldb_rdi_x86_64},
118      nullptr,
119      nullptr,
120      nullptr,
121      0},
122     {DEFINE_GPR(rsi, nullptr),
123      {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM,
124       LLDB_INVALID_REGNUM, lldb_rsi_x86_64},
125      nullptr,
126      nullptr,
127      nullptr,
128      0},
129     {DEFINE_GPR(rbp, "fp"),
130      {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
131       LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
132      nullptr,
133      nullptr,
134      nullptr,
135      0},
136     {DEFINE_GPR(rsp, "sp"),
137      {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
138       LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
139      nullptr,
140      nullptr,
141      nullptr,
142      0},
143     {DEFINE_GPR(r8, nullptr),
144      {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3,
145       LLDB_INVALID_REGNUM, lldb_r8_x86_64},
146      nullptr,
147      nullptr,
148      nullptr,
149      0},
150     {DEFINE_GPR(r9, nullptr),
151      {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4,
152       LLDB_INVALID_REGNUM, lldb_r9_x86_64},
153      nullptr,
154      nullptr,
155      nullptr,
156      0},
157     {DEFINE_GPR(r10, nullptr),
158      {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM,
159       LLDB_INVALID_REGNUM, lldb_r10_x86_64},
160      nullptr,
161      nullptr,
162      nullptr,
163      0},
164     {DEFINE_GPR(r11, nullptr),
165      {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM,
166       LLDB_INVALID_REGNUM, lldb_r11_x86_64},
167      nullptr,
168      nullptr,
169      nullptr,
170      0},
171     {DEFINE_GPR(r12, nullptr),
172      {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM,
173       LLDB_INVALID_REGNUM, lldb_r12_x86_64},
174      nullptr,
175      nullptr,
176      nullptr,
177      0},
178     {DEFINE_GPR(r13, nullptr),
179      {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM,
180       LLDB_INVALID_REGNUM, lldb_r13_x86_64},
181      nullptr,
182      nullptr,
183      nullptr,
184      0},
185     {DEFINE_GPR(r14, nullptr),
186      {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM,
187       LLDB_INVALID_REGNUM, lldb_r14_x86_64},
188      nullptr,
189      nullptr,
190      nullptr,
191      0},
192     {DEFINE_GPR(r15, nullptr),
193      {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM,
194       LLDB_INVALID_REGNUM, lldb_r15_x86_64},
195      nullptr,
196      nullptr,
197      nullptr,
198      0},
199     {DEFINE_GPR(rip, "pc"),
200      {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC,
201       LLDB_INVALID_REGNUM, lldb_rip_x86_64},
202      nullptr,
203      nullptr,
204      nullptr,
205      0},
206     {DEFINE_GPR_BIN(eflags, "flags"),
207      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
208       LLDB_INVALID_REGNUM, lldb_rflags_x86_64},
209      nullptr,
210      nullptr,
211      nullptr,
212      0},
213     {DEFINE_FPU_XMM(xmm0)},
214     {DEFINE_FPU_XMM(xmm1)},
215     {DEFINE_FPU_XMM(xmm2)},
216     {DEFINE_FPU_XMM(xmm3)},
217     {DEFINE_FPU_XMM(xmm4)},
218     {DEFINE_FPU_XMM(xmm5)},
219     {DEFINE_FPU_XMM(xmm6)},
220     {DEFINE_FPU_XMM(xmm7)},
221     {DEFINE_FPU_XMM(xmm8)},
222     {DEFINE_FPU_XMM(xmm9)},
223     {DEFINE_FPU_XMM(xmm10)},
224     {DEFINE_FPU_XMM(xmm11)},
225     {DEFINE_FPU_XMM(xmm12)},
226     {DEFINE_FPU_XMM(xmm13)},
227     {DEFINE_FPU_XMM(xmm14)},
228     {DEFINE_FPU_XMM(xmm15)}
229 };
230 
231 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
232 
233 // Array of lldb register numbers used to define the set of all General Purpose
234 // Registers
235 uint32_t g_gpr_reg_indices[] = {
236     eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx,
237     eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi,
238     eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8,
239     eRegisterIndexR9,  eRegisterIndexR10, eRegisterIndexR11,
240     eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
241     eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
242 
243 uint32_t g_fpu_reg_indices[] = {
244     eRegisterIndexXmm0,  eRegisterIndexXmm1,  eRegisterIndexXmm2,
245     eRegisterIndexXmm3,  eRegisterIndexXmm4,  eRegisterIndexXmm5,
246     eRegisterIndexXmm6,  eRegisterIndexXmm7,  eRegisterIndexXmm8,
247     eRegisterIndexXmm9,  eRegisterIndexXmm10, eRegisterIndexXmm11,
248     eRegisterIndexXmm12, eRegisterIndexXmm13, eRegisterIndexXmm14,
249     eRegisterIndexXmm15
250 };
251 
252 RegisterSet g_register_sets[] = {
253     {"General Purpose Registers", "gpr",
254      llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
255     {"Floating Point Registers", "fpu",
256      llvm::array_lengthof(g_fpu_reg_indices), g_fpu_reg_indices}};
257 }
258 
259 // Constructors and Destructors
260 RegisterContextWindows_x64::RegisterContextWindows_x64(
261     Thread &thread, uint32_t concrete_frame_idx)
262     : RegisterContextWindows(thread, concrete_frame_idx) {}
263 
264 RegisterContextWindows_x64::~RegisterContextWindows_x64() {}
265 
266 size_t RegisterContextWindows_x64::GetRegisterCount() {
267   return llvm::array_lengthof(g_register_infos);
268 }
269 
270 const RegisterInfo *
271 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) {
272   if (reg < k_num_register_infos)
273     return &g_register_infos[reg];
274   return NULL;
275 }
276 
277 size_t RegisterContextWindows_x64::GetRegisterSetCount() {
278   return llvm::array_lengthof(g_register_sets);
279 }
280 
281 const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) {
282   return &g_register_sets[reg_set];
283 }
284 
285 bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
286                                               RegisterValue &reg_value) {
287   if (!CacheAllRegisterValues())
288     return false;
289 
290   if (reg_info == nullptr)
291     return false;
292 
293   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
294 
295   switch (reg) {
296   case lldb_rax_x86_64:
297     reg_value.SetUInt64(m_context.Rax);
298     break;
299   case lldb_rbx_x86_64:
300     reg_value.SetUInt64(m_context.Rbx);
301     break;
302   case lldb_rcx_x86_64:
303     reg_value.SetUInt64(m_context.Rcx);
304     break;
305   case lldb_rdx_x86_64:
306     reg_value.SetUInt64(m_context.Rdx);
307     break;
308   case lldb_rdi_x86_64:
309     reg_value.SetUInt64(m_context.Rdi);
310     break;
311   case lldb_rsi_x86_64:
312     reg_value.SetUInt64(m_context.Rsi);
313     break;
314   case lldb_r8_x86_64:
315     reg_value.SetUInt64(m_context.R8);
316     break;
317   case lldb_r9_x86_64:
318     reg_value.SetUInt64(m_context.R9);
319     break;
320   case lldb_r10_x86_64:
321     reg_value.SetUInt64(m_context.R10);
322     break;
323   case lldb_r11_x86_64:
324     reg_value.SetUInt64(m_context.R11);
325     break;
326   case lldb_r12_x86_64:
327     reg_value.SetUInt64(m_context.R12);
328     break;
329   case lldb_r13_x86_64:
330     reg_value.SetUInt64(m_context.R13);
331     break;
332   case lldb_r14_x86_64:
333     reg_value.SetUInt64(m_context.R14);
334     break;
335   case lldb_r15_x86_64:
336     reg_value.SetUInt64(m_context.R15);
337     break;
338   case lldb_rbp_x86_64:
339     reg_value.SetUInt64(m_context.Rbp);
340     break;
341   case lldb_rsp_x86_64:
342     reg_value.SetUInt64(m_context.Rsp);
343     break;
344   case lldb_rip_x86_64:
345     reg_value.SetUInt64(m_context.Rip);
346     break;
347   case lldb_rflags_x86_64:
348     reg_value.SetUInt64(m_context.EFlags);
349     break;
350   case lldb_xmm0_x86_64:
351     reg_value.SetBytes(&m_context.Xmm0,
352                        reg_info->byte_size, endian::InlHostByteOrder());
353     break;
354   case lldb_xmm1_x86_64:
355     reg_value.SetBytes(&m_context.Xmm1,
356                        reg_info->byte_size, endian::InlHostByteOrder());
357     break;
358   case lldb_xmm2_x86_64:
359     reg_value.SetBytes(&m_context.Xmm2,
360                        reg_info->byte_size, endian::InlHostByteOrder());
361     break;
362   case lldb_xmm3_x86_64:
363     reg_value.SetBytes(&m_context.Xmm3,
364                        reg_info->byte_size, endian::InlHostByteOrder());
365     break;
366   case lldb_xmm4_x86_64:
367     reg_value.SetBytes(&m_context.Xmm4,
368                        reg_info->byte_size, endian::InlHostByteOrder());
369     break;
370   case lldb_xmm5_x86_64:
371     reg_value.SetBytes(&m_context.Xmm5,
372                        reg_info->byte_size, endian::InlHostByteOrder());
373     break;
374   case lldb_xmm6_x86_64:
375     reg_value.SetBytes(&m_context.Xmm6,
376                        reg_info->byte_size, endian::InlHostByteOrder());
377     break;
378   case lldb_xmm7_x86_64:
379     reg_value.SetBytes(&m_context.Xmm7,
380                        reg_info->byte_size, endian::InlHostByteOrder());
381     break;
382   case lldb_xmm8_x86_64:
383     reg_value.SetBytes(&m_context.Xmm8,
384                        reg_info->byte_size, endian::InlHostByteOrder());
385     break;
386   case lldb_xmm9_x86_64:
387     reg_value.SetBytes(&m_context.Xmm9,
388                        reg_info->byte_size, endian::InlHostByteOrder());
389     break;
390   case lldb_xmm10_x86_64:
391     reg_value.SetBytes(&m_context.Xmm10,
392                        reg_info->byte_size, endian::InlHostByteOrder());
393     break;
394   case lldb_xmm11_x86_64:
395     reg_value.SetBytes(&m_context.Xmm11,
396                        reg_info->byte_size, endian::InlHostByteOrder());
397     break;
398   case lldb_xmm12_x86_64:
399     reg_value.SetBytes(&m_context.Xmm12,
400                        reg_info->byte_size, endian::InlHostByteOrder());
401     break;
402   case lldb_xmm13_x86_64:
403     reg_value.SetBytes(&m_context.Xmm13,
404                        reg_info->byte_size, endian::InlHostByteOrder());
405     break;
406   case lldb_xmm14_x86_64:
407     reg_value.SetBytes(&m_context.Xmm14,
408                        reg_info->byte_size, endian::InlHostByteOrder());
409     break;
410   case lldb_xmm15_x86_64:
411     reg_value.SetBytes(&m_context.Xmm15,
412                        reg_info->byte_size, endian::InlHostByteOrder());
413     break;
414   }
415   return true;
416 }
417 
418 bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
419                                                const RegisterValue &reg_value) {
420   // Since we cannot only write a single register value to the inferior, we
421   // need to make sure our cached copy of the register values are fresh.
422   // Otherwise when writing EAX, for example, we may also overwrite some other
423   // register with a stale value.
424   if (!CacheAllRegisterValues())
425     return false;
426 
427   switch (reg_info->kinds[eRegisterKindLLDB]) {
428   case lldb_rax_x86_64:
429     m_context.Rax = reg_value.GetAsUInt64();
430     break;
431   case lldb_rbx_x86_64:
432     m_context.Rbx = reg_value.GetAsUInt64();
433     break;
434   case lldb_rcx_x86_64:
435     m_context.Rcx = reg_value.GetAsUInt64();
436     break;
437   case lldb_rdx_x86_64:
438     m_context.Rdx = reg_value.GetAsUInt64();
439     break;
440   case lldb_rdi_x86_64:
441     m_context.Rdi = reg_value.GetAsUInt64();
442     break;
443   case lldb_rsi_x86_64:
444     m_context.Rsi = reg_value.GetAsUInt64();
445     break;
446   case lldb_r8_x86_64:
447     m_context.R8 = reg_value.GetAsUInt64();
448     break;
449   case lldb_r9_x86_64:
450     m_context.R9 = reg_value.GetAsUInt64();
451     break;
452   case lldb_r10_x86_64:
453     m_context.R10 = reg_value.GetAsUInt64();
454     break;
455   case lldb_r11_x86_64:
456     m_context.R11 = reg_value.GetAsUInt64();
457     break;
458   case lldb_r12_x86_64:
459     m_context.R12 = reg_value.GetAsUInt64();
460     break;
461   case lldb_r13_x86_64:
462     m_context.R13 = reg_value.GetAsUInt64();
463     break;
464   case lldb_r14_x86_64:
465     m_context.R14 = reg_value.GetAsUInt64();
466     break;
467   case lldb_r15_x86_64:
468     m_context.R15 = reg_value.GetAsUInt64();
469     break;
470   case lldb_rbp_x86_64:
471     m_context.Rbp = reg_value.GetAsUInt64();
472     break;
473   case lldb_rsp_x86_64:
474     m_context.Rsp = reg_value.GetAsUInt64();
475     break;
476   case lldb_rip_x86_64:
477     m_context.Rip = reg_value.GetAsUInt64();
478     break;
479   case lldb_rflags_x86_64:
480     m_context.EFlags = reg_value.GetAsUInt64();
481     break;
482   case lldb_xmm0_x86_64:
483     memcpy(&m_context.Xmm0, reg_value.GetBytes(), 16);
484     break;
485   case lldb_xmm1_x86_64:
486     memcpy(&m_context.Xmm1, reg_value.GetBytes(), 16);
487     break;
488   case lldb_xmm2_x86_64:
489     memcpy(&m_context.Xmm2, reg_value.GetBytes(), 16);
490     break;
491   case lldb_xmm3_x86_64:
492     memcpy(&m_context.Xmm3, reg_value.GetBytes(), 16);
493     break;
494   case lldb_xmm4_x86_64:
495     memcpy(&m_context.Xmm4, reg_value.GetBytes(), 16);
496     break;
497   case lldb_xmm5_x86_64:
498     memcpy(&m_context.Xmm5, reg_value.GetBytes(), 16);
499     break;
500   case lldb_xmm6_x86_64:
501     memcpy(&m_context.Xmm6, reg_value.GetBytes(), 16);
502     break;
503   case lldb_xmm7_x86_64:
504     memcpy(&m_context.Xmm7, reg_value.GetBytes(), 16);
505     break;
506   case lldb_xmm8_x86_64:
507     memcpy(&m_context.Xmm8, reg_value.GetBytes(), 16);
508     break;
509   case lldb_xmm9_x86_64:
510     memcpy(&m_context.Xmm9, reg_value.GetBytes(), 16);
511     break;
512   case lldb_xmm10_x86_64:
513     memcpy(&m_context.Xmm10, reg_value.GetBytes(), 16);
514     break;
515   case lldb_xmm11_x86_64:
516     memcpy(&m_context.Xmm11, reg_value.GetBytes(), 16);
517     break;
518   case lldb_xmm12_x86_64:
519     memcpy(&m_context.Xmm12, reg_value.GetBytes(), 16);
520     break;
521   case lldb_xmm13_x86_64:
522     memcpy(&m_context.Xmm13, reg_value.GetBytes(), 16);
523     break;
524   case lldb_xmm14_x86_64:
525     memcpy(&m_context.Xmm14, reg_value.GetBytes(), 16);
526     break;
527   case lldb_xmm15_x86_64:
528     memcpy(&m_context.Xmm15, reg_value.GetBytes(), 16);
529     break;
530   }
531 
532   // Physically update the registers in the target process.
533   TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
534   return ::SetThreadContext(
535       wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
536 }
537