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 // Array of lldb register numbers used to define the set of all General Purpose Registers
140 uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx,   eRegisterIndexRcx, eRegisterIndexRdx,
141                                 eRegisterIndexRdi, eRegisterIndexRsi,   eRegisterIndexR8,  eRegisterIndexR9,
142                                 eRegisterIndexR10, eRegisterIndexR11,   eRegisterIndexR12, eRegisterIndexR13,
143                                 eRegisterIndexR14, eRegisterIndexR15,   eRegisterIndexRbp, eRegisterIndexRsp,
144                                 eRegisterIndexRip, eRegisterIndexRflags};
145 
146 RegisterSet g_register_sets[] = {
147     {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
148 };
149 }
150 
151 //------------------------------------------------------------------
152 // Constructors and Destructors
153 //------------------------------------------------------------------
154 RegisterContextWindows_x64::RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx)
155     : RegisterContextWindows(thread, concrete_frame_idx)
156 {
157 }
158 
159 RegisterContextWindows_x64::~RegisterContextWindows_x64()
160 {
161 }
162 
163 size_t
164 RegisterContextWindows_x64::GetRegisterCount()
165 {
166     return llvm::array_lengthof(g_register_infos);
167 }
168 
169 const RegisterInfo *
170 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg)
171 {
172     return &g_register_infos[reg];
173 }
174 
175 size_t
176 RegisterContextWindows_x64::GetRegisterSetCount()
177 {
178     return llvm::array_lengthof(g_register_sets);
179 }
180 
181 const RegisterSet *
182 RegisterContextWindows_x64::GetRegisterSet(size_t reg_set)
183 {
184     return &g_register_sets[reg_set];
185 }
186 
187 bool
188 RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
189 {
190     if (!CacheAllRegisterValues())
191         return false;
192 
193     switch (reg_info->kinds[eRegisterKindLLDB])
194     {
195         case lldb_rax_x86_64:
196             reg_value.SetUInt64(m_context.Rax);
197             break;
198         case lldb_rbx_x86_64:
199             reg_value.SetUInt64(m_context.Rbx);
200             break;
201         case lldb_rcx_x86_64:
202             reg_value.SetUInt64(m_context.Rcx);
203             break;
204         case lldb_rdx_x86_64:
205             reg_value.SetUInt64(m_context.Rdx);
206             break;
207         case lldb_rdi_x86_64:
208             reg_value.SetUInt64(m_context.Rdi);
209             break;
210         case lldb_rsi_x86_64:
211             reg_value.SetUInt64(m_context.Rsi);
212             break;
213         case lldb_r8_x86_64:
214             reg_value.SetUInt64(m_context.R8);
215             break;
216         case lldb_r9_x86_64:
217             reg_value.SetUInt64(m_context.R9);
218             break;
219         case lldb_r10_x86_64:
220             reg_value.SetUInt64(m_context.R10);
221             break;
222         case lldb_r11_x86_64:
223             reg_value.SetUInt64(m_context.R11);
224             break;
225         case lldb_r12_x86_64:
226             reg_value.SetUInt64(m_context.R12);
227             break;
228         case lldb_r13_x86_64:
229             reg_value.SetUInt64(m_context.R13);
230             break;
231         case lldb_r14_x86_64:
232             reg_value.SetUInt64(m_context.R14);
233             break;
234         case lldb_r15_x86_64:
235             reg_value.SetUInt64(m_context.R15);
236             break;
237         case lldb_rbp_x86_64:
238             reg_value.SetUInt64(m_context.Rbp);
239             break;
240         case lldb_rsp_x86_64:
241             reg_value.SetUInt64(m_context.Rsp);
242             break;
243         case lldb_rip_x86_64:
244             reg_value.SetUInt64(m_context.Rip);
245             break;
246         case lldb_rflags_x86_64:
247             reg_value.SetUInt64(m_context.EFlags);
248             break;
249     }
250     return true;
251 }
252 
253 bool
254 RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)
255 {
256     // Since we cannot only write a single register value to the inferior, we need to make sure
257     // our cached copy of the register values are fresh.  Otherwise when writing EAX, for example,
258     // we may also overwrite some other register with a stale value.
259     if (!CacheAllRegisterValues())
260         return false;
261 
262     switch (reg_info->kinds[eRegisterKindLLDB])
263     {
264         case lldb_rax_x86_64:
265             m_context.Rax = reg_value.GetAsUInt64();
266             break;
267         case lldb_rbx_x86_64:
268             m_context.Rbx = reg_value.GetAsUInt64();
269             break;
270         case lldb_rcx_x86_64:
271             m_context.Rcx = reg_value.GetAsUInt64();
272             break;
273         case lldb_rdx_x86_64:
274             m_context.Rdx = reg_value.GetAsUInt64();
275             break;
276         case lldb_rdi_x86_64:
277             m_context.Rdi = reg_value.GetAsUInt64();
278             break;
279         case lldb_rsi_x86_64:
280             m_context.Rsi = reg_value.GetAsUInt64();
281             break;
282         case lldb_r8_x86_64:
283             m_context.R8 = reg_value.GetAsUInt64();
284             break;
285         case lldb_r9_x86_64:
286             m_context.R9 = reg_value.GetAsUInt64();
287             break;
288         case lldb_r10_x86_64:
289             m_context.R10 = reg_value.GetAsUInt64();
290             break;
291         case lldb_r11_x86_64:
292             m_context.R11 = reg_value.GetAsUInt64();
293             break;
294         case lldb_r12_x86_64:
295             m_context.R12 = reg_value.GetAsUInt64();
296             break;
297         case lldb_r13_x86_64:
298             m_context.R13 = reg_value.GetAsUInt64();
299             break;
300         case lldb_r14_x86_64:
301             m_context.R14 = reg_value.GetAsUInt64();
302             break;
303         case lldb_r15_x86_64:
304             m_context.R15 = reg_value.GetAsUInt64();
305             break;
306         case lldb_rbp_x86_64:
307             m_context.Rbp = reg_value.GetAsUInt64();
308             break;
309         case lldb_rsp_x86_64:
310             m_context.Rsp = reg_value.GetAsUInt64();
311             break;
312         case lldb_rip_x86_64:
313             m_context.Rip = reg_value.GetAsUInt64();
314             break;
315         case lldb_rflags_x86_64:
316             m_context.EFlags = reg_value.GetAsUInt64();
317             break;
318     }
319 
320     // Physically update the registers in the target process.
321     TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
322     return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
323 }
324