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