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      nullptr,
71      0},
72     {DEFINE_GPR(rbx, nullptr),
73      {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM,
74       LLDB_INVALID_REGNUM, lldb_rbx_x86_64},
75      nullptr,
76      nullptr,
77      nullptr,
78      0},
79     {DEFINE_GPR(rcx, nullptr),
80      {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1,
81       LLDB_INVALID_REGNUM, lldb_rcx_x86_64},
82      nullptr,
83      nullptr,
84      nullptr,
85      0},
86     {DEFINE_GPR(rdx, nullptr),
87      {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2,
88       LLDB_INVALID_REGNUM, lldb_rdx_x86_64},
89      nullptr,
90      nullptr,
91      nullptr,
92      0},
93     {DEFINE_GPR(rdi, nullptr),
94      {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM,
95       LLDB_INVALID_REGNUM, lldb_rdi_x86_64},
96      nullptr,
97      nullptr,
98      nullptr,
99      0},
100     {DEFINE_GPR(rsi, nullptr),
101      {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM,
102       LLDB_INVALID_REGNUM, lldb_rsi_x86_64},
103      nullptr,
104      nullptr,
105      nullptr,
106      0},
107     {DEFINE_GPR(rbp, "fp"),
108      {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
109       LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
110      nullptr,
111      nullptr,
112      nullptr,
113      0},
114     {DEFINE_GPR(rsp, "sp"),
115      {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
116       LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
117      nullptr,
118      nullptr,
119      nullptr,
120      0},
121     {DEFINE_GPR(r8, nullptr),
122      {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3,
123       LLDB_INVALID_REGNUM, lldb_r8_x86_64},
124      nullptr,
125      nullptr,
126      nullptr,
127      0},
128     {DEFINE_GPR(r9, nullptr),
129      {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4,
130       LLDB_INVALID_REGNUM, lldb_r9_x86_64},
131      nullptr,
132      nullptr,
133      nullptr,
134      0},
135     {DEFINE_GPR(r10, nullptr),
136      {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5,
137       LLDB_INVALID_REGNUM, lldb_r10_x86_64},
138      nullptr,
139      nullptr,
140      nullptr,
141      0},
142     {DEFINE_GPR(r11, nullptr),
143      {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6,
144       LLDB_INVALID_REGNUM, lldb_r11_x86_64},
145      nullptr,
146      nullptr,
147      nullptr,
148      0},
149     {DEFINE_GPR(r12, nullptr),
150      {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM,
151       LLDB_INVALID_REGNUM, lldb_r12_x86_64},
152      nullptr,
153      nullptr,
154      nullptr,
155      0},
156     {DEFINE_GPR(r13, nullptr),
157      {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM,
158       LLDB_INVALID_REGNUM, lldb_r13_x86_64},
159      nullptr,
160      nullptr,
161      nullptr,
162      0},
163     {DEFINE_GPR(r14, nullptr),
164      {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM,
165       LLDB_INVALID_REGNUM, lldb_r14_x86_64},
166      nullptr,
167      nullptr,
168      nullptr,
169      0},
170     {DEFINE_GPR(r15, nullptr),
171      {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM,
172       LLDB_INVALID_REGNUM, lldb_r15_x86_64},
173      nullptr,
174      nullptr,
175      nullptr,
176      0},
177     {DEFINE_GPR(rip, "pc"),
178      {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC,
179       LLDB_INVALID_REGNUM, lldb_rip_x86_64},
180      nullptr,
181      nullptr,
182      nullptr,
183      0},
184     {DEFINE_GPR_BIN(eflags, "flags"),
185      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
186       LLDB_INVALID_REGNUM, lldb_rflags_x86_64},
187      nullptr,
188      nullptr,
189      nullptr,
190      0},
191 };
192 
193 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
194 
195 // Array of lldb register numbers used to define the set of all General Purpose
196 // Registers
197 uint32_t g_gpr_reg_indices[] = {
198     eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx,
199     eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi,
200     eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8,
201     eRegisterIndexR9,  eRegisterIndexR10, eRegisterIndexR11,
202     eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
203     eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
204 
205 RegisterSet g_register_sets[] = {
206     {"General Purpose Registers", "gpr",
207      llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
208 };
209 }
210 
211 // Constructors and Destructors
212 RegisterContextWindows_x64::RegisterContextWindows_x64(
213     Thread &thread, uint32_t concrete_frame_idx)
214     : RegisterContextWindows(thread, concrete_frame_idx) {}
215 
216 RegisterContextWindows_x64::~RegisterContextWindows_x64() {}
217 
218 size_t RegisterContextWindows_x64::GetRegisterCount() {
219   return llvm::array_lengthof(g_register_infos);
220 }
221 
222 const RegisterInfo *
223 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) {
224   if (reg < k_num_register_infos)
225     return &g_register_infos[reg];
226   return NULL;
227 }
228 
229 size_t RegisterContextWindows_x64::GetRegisterSetCount() {
230   return llvm::array_lengthof(g_register_sets);
231 }
232 
233 const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) {
234   return &g_register_sets[reg_set];
235 }
236 
237 bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
238                                               RegisterValue &reg_value) {
239   if (!CacheAllRegisterValues())
240     return false;
241 
242   if (reg_info == nullptr)
243     return false;
244 
245   switch (reg_info->kinds[eRegisterKindLLDB]) {
246   case lldb_rax_x86_64:
247     reg_value.SetUInt64(m_context.Rax);
248     break;
249   case lldb_rbx_x86_64:
250     reg_value.SetUInt64(m_context.Rbx);
251     break;
252   case lldb_rcx_x86_64:
253     reg_value.SetUInt64(m_context.Rcx);
254     break;
255   case lldb_rdx_x86_64:
256     reg_value.SetUInt64(m_context.Rdx);
257     break;
258   case lldb_rdi_x86_64:
259     reg_value.SetUInt64(m_context.Rdi);
260     break;
261   case lldb_rsi_x86_64:
262     reg_value.SetUInt64(m_context.Rsi);
263     break;
264   case lldb_r8_x86_64:
265     reg_value.SetUInt64(m_context.R8);
266     break;
267   case lldb_r9_x86_64:
268     reg_value.SetUInt64(m_context.R9);
269     break;
270   case lldb_r10_x86_64:
271     reg_value.SetUInt64(m_context.R10);
272     break;
273   case lldb_r11_x86_64:
274     reg_value.SetUInt64(m_context.R11);
275     break;
276   case lldb_r12_x86_64:
277     reg_value.SetUInt64(m_context.R12);
278     break;
279   case lldb_r13_x86_64:
280     reg_value.SetUInt64(m_context.R13);
281     break;
282   case lldb_r14_x86_64:
283     reg_value.SetUInt64(m_context.R14);
284     break;
285   case lldb_r15_x86_64:
286     reg_value.SetUInt64(m_context.R15);
287     break;
288   case lldb_rbp_x86_64:
289     reg_value.SetUInt64(m_context.Rbp);
290     break;
291   case lldb_rsp_x86_64:
292     reg_value.SetUInt64(m_context.Rsp);
293     break;
294   case lldb_rip_x86_64:
295     reg_value.SetUInt64(m_context.Rip);
296     break;
297   case lldb_rflags_x86_64:
298     reg_value.SetUInt64(m_context.EFlags);
299     break;
300   }
301   return true;
302 }
303 
304 bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
305                                                const RegisterValue &reg_value) {
306   // Since we cannot only write a single register value to the inferior, we
307   // need to make sure our cached copy of the register values are fresh.
308   // Otherwise when writing EAX, for example, we may also overwrite some other
309   // register with a stale value.
310   if (!CacheAllRegisterValues())
311     return false;
312 
313   switch (reg_info->kinds[eRegisterKindLLDB]) {
314   case lldb_rax_x86_64:
315     m_context.Rax = reg_value.GetAsUInt64();
316     break;
317   case lldb_rbx_x86_64:
318     m_context.Rbx = reg_value.GetAsUInt64();
319     break;
320   case lldb_rcx_x86_64:
321     m_context.Rcx = reg_value.GetAsUInt64();
322     break;
323   case lldb_rdx_x86_64:
324     m_context.Rdx = reg_value.GetAsUInt64();
325     break;
326   case lldb_rdi_x86_64:
327     m_context.Rdi = reg_value.GetAsUInt64();
328     break;
329   case lldb_rsi_x86_64:
330     m_context.Rsi = reg_value.GetAsUInt64();
331     break;
332   case lldb_r8_x86_64:
333     m_context.R8 = reg_value.GetAsUInt64();
334     break;
335   case lldb_r9_x86_64:
336     m_context.R9 = reg_value.GetAsUInt64();
337     break;
338   case lldb_r10_x86_64:
339     m_context.R10 = reg_value.GetAsUInt64();
340     break;
341   case lldb_r11_x86_64:
342     m_context.R11 = reg_value.GetAsUInt64();
343     break;
344   case lldb_r12_x86_64:
345     m_context.R12 = reg_value.GetAsUInt64();
346     break;
347   case lldb_r13_x86_64:
348     m_context.R13 = reg_value.GetAsUInt64();
349     break;
350   case lldb_r14_x86_64:
351     m_context.R14 = reg_value.GetAsUInt64();
352     break;
353   case lldb_r15_x86_64:
354     m_context.R15 = reg_value.GetAsUInt64();
355     break;
356   case lldb_rbp_x86_64:
357     m_context.Rbp = reg_value.GetAsUInt64();
358     break;
359   case lldb_rsp_x86_64:
360     m_context.Rsp = reg_value.GetAsUInt64();
361     break;
362   case lldb_rip_x86_64:
363     m_context.Rip = reg_value.GetAsUInt64();
364     break;
365   case lldb_rflags_x86_64:
366     m_context.EFlags = reg_value.GetAsUInt64();
367     break;
368   }
369 
370   // Physically update the registers in the target process.
371   TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
372   return ::SetThreadContext(
373       wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
374 }
375