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