xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1 //===-- NativeRegisterContextWindows_arm64.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(__aarch64__) || defined(_M_ARM64)
10 
11 #include "NativeRegisterContextWindows_arm64.h"
12 #include "NativeThreadWindows.h"
13 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
14 #include "ProcessWindowsLog.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Host/HostThread.h"
17 #include "lldb/Host/windows/HostThreadWindows.h"
18 #include "lldb/Host/windows/windows.h"
19 
20 #include "lldb/Utility/Log.h"
21 #include "lldb/Utility/RegisterValue.h"
22 #include "llvm/ADT/STLExtras.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 #define REG_CONTEXT_SIZE sizeof(::CONTEXT)
28 
29 namespace {
30 static const uint32_t g_gpr_regnums_arm64[] = {
31     gpr_x0_arm64,       gpr_x1_arm64,   gpr_x2_arm64,  gpr_x3_arm64,
32     gpr_x4_arm64,       gpr_x5_arm64,   gpr_x6_arm64,  gpr_x7_arm64,
33     gpr_x8_arm64,       gpr_x9_arm64,   gpr_x10_arm64, gpr_x11_arm64,
34     gpr_x12_arm64,      gpr_x13_arm64,  gpr_x14_arm64, gpr_x15_arm64,
35     gpr_x16_arm64,      gpr_x17_arm64,  gpr_x18_arm64, gpr_x19_arm64,
36     gpr_x20_arm64,      gpr_x21_arm64,  gpr_x22_arm64, gpr_x23_arm64,
37     gpr_x24_arm64,      gpr_x25_arm64,  gpr_x26_arm64, gpr_x27_arm64,
38     gpr_x28_arm64,      gpr_fp_arm64,   gpr_lr_arm64,  gpr_sp_arm64,
39     gpr_pc_arm64,       gpr_cpsr_arm64, gpr_w0_arm64,  gpr_w1_arm64,
40     gpr_w2_arm64,       gpr_w3_arm64,   gpr_w4_arm64,  gpr_w5_arm64,
41     gpr_w6_arm64,       gpr_w7_arm64,   gpr_w8_arm64,  gpr_w9_arm64,
42     gpr_w10_arm64,      gpr_w11_arm64,  gpr_w12_arm64, gpr_w13_arm64,
43     gpr_w14_arm64,      gpr_w15_arm64,  gpr_w16_arm64, gpr_w17_arm64,
44     gpr_w18_arm64,      gpr_w19_arm64,  gpr_w20_arm64, gpr_w21_arm64,
45     gpr_w22_arm64,      gpr_w23_arm64,  gpr_w24_arm64, gpr_w25_arm64,
46     gpr_w26_arm64,      gpr_w27_arm64,  gpr_w28_arm64,
47     LLDB_INVALID_REGNUM // Register set must be terminated with this flag
48 };
49 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) -
50                1) == k_num_gpr_registers_arm64,
51               "g_gpr_regnums_arm64 has wrong number of register infos");
52 
53 static const uint32_t g_fpr_regnums_arm64[] = {
54     fpu_v0_arm64,       fpu_v1_arm64,   fpu_v2_arm64,  fpu_v3_arm64,
55     fpu_v4_arm64,       fpu_v5_arm64,   fpu_v6_arm64,  fpu_v7_arm64,
56     fpu_v8_arm64,       fpu_v9_arm64,   fpu_v10_arm64, fpu_v11_arm64,
57     fpu_v12_arm64,      fpu_v13_arm64,  fpu_v14_arm64, fpu_v15_arm64,
58     fpu_v16_arm64,      fpu_v17_arm64,  fpu_v18_arm64, fpu_v19_arm64,
59     fpu_v20_arm64,      fpu_v21_arm64,  fpu_v22_arm64, fpu_v23_arm64,
60     fpu_v24_arm64,      fpu_v25_arm64,  fpu_v26_arm64, fpu_v27_arm64,
61     fpu_v28_arm64,      fpu_v29_arm64,  fpu_v30_arm64, fpu_v31_arm64,
62     fpu_s0_arm64,       fpu_s1_arm64,   fpu_s2_arm64,  fpu_s3_arm64,
63     fpu_s4_arm64,       fpu_s5_arm64,   fpu_s6_arm64,  fpu_s7_arm64,
64     fpu_s8_arm64,       fpu_s9_arm64,   fpu_s10_arm64, fpu_s11_arm64,
65     fpu_s12_arm64,      fpu_s13_arm64,  fpu_s14_arm64, fpu_s15_arm64,
66     fpu_s16_arm64,      fpu_s17_arm64,  fpu_s18_arm64, fpu_s19_arm64,
67     fpu_s20_arm64,      fpu_s21_arm64,  fpu_s22_arm64, fpu_s23_arm64,
68     fpu_s24_arm64,      fpu_s25_arm64,  fpu_s26_arm64, fpu_s27_arm64,
69     fpu_s28_arm64,      fpu_s29_arm64,  fpu_s30_arm64, fpu_s31_arm64,
70 
71     fpu_d0_arm64,       fpu_d1_arm64,   fpu_d2_arm64,  fpu_d3_arm64,
72     fpu_d4_arm64,       fpu_d5_arm64,   fpu_d6_arm64,  fpu_d7_arm64,
73     fpu_d8_arm64,       fpu_d9_arm64,   fpu_d10_arm64, fpu_d11_arm64,
74     fpu_d12_arm64,      fpu_d13_arm64,  fpu_d14_arm64, fpu_d15_arm64,
75     fpu_d16_arm64,      fpu_d17_arm64,  fpu_d18_arm64, fpu_d19_arm64,
76     fpu_d20_arm64,      fpu_d21_arm64,  fpu_d22_arm64, fpu_d23_arm64,
77     fpu_d24_arm64,      fpu_d25_arm64,  fpu_d26_arm64, fpu_d27_arm64,
78     fpu_d28_arm64,      fpu_d29_arm64,  fpu_d30_arm64, fpu_d31_arm64,
79     fpu_fpsr_arm64,     fpu_fpcr_arm64,
80     LLDB_INVALID_REGNUM // Register set must be terminated with this flag
81 };
82 static_assert(((sizeof g_fpr_regnums_arm64 / sizeof g_fpr_regnums_arm64[0]) -
83                1) == k_num_fpr_registers_arm64,
84               "g_fpu_regnums_arm64 has wrong number of register infos");
85 
86 static const RegisterSet g_reg_sets_arm64[] = {
87     {"General Purpose Registers", "gpr", std::size(g_gpr_regnums_arm64) - 1,
88      g_gpr_regnums_arm64},
89     {"Floating Point Registers", "fpr", std::size(g_fpr_regnums_arm64) - 1,
90      g_fpr_regnums_arm64},
91 };
92 
93 enum { k_num_register_sets = 2 };
94 
95 } // namespace
96 
97 static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)98 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
99   assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
100          "Register setting path assumes this is a 64-bit host");
101   return new RegisterInfoPOSIX_arm64(
102       target_arch, RegisterInfoPOSIX_arm64::eRegsetMaskDefault);
103 }
104 
GetThreadContextHelper(lldb::thread_t thread_handle,PCONTEXT context_ptr,const DWORD control_flag)105 static Status GetThreadContextHelper(lldb::thread_t thread_handle,
106                                      PCONTEXT context_ptr,
107                                      const DWORD control_flag) {
108   Log *log = GetLog(WindowsLog::Registers);
109   Status error;
110 
111   memset(context_ptr, 0, sizeof(::CONTEXT));
112   context_ptr->ContextFlags = control_flag;
113   if (!::GetThreadContext(thread_handle, context_ptr)) {
114     error.SetError(GetLastError(), eErrorTypeWin32);
115     LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__,
116              error);
117     return error;
118   }
119   return Status();
120 }
121 
SetThreadContextHelper(lldb::thread_t thread_handle,PCONTEXT context_ptr)122 static Status SetThreadContextHelper(lldb::thread_t thread_handle,
123                                      PCONTEXT context_ptr) {
124   Log *log = GetLog(WindowsLog::Registers);
125   Status error;
126   // It's assumed that the thread has stopped.
127   if (!::SetThreadContext(thread_handle, context_ptr)) {
128     error.SetError(GetLastError(), eErrorTypeWin32);
129     LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__,
130              error);
131     return error;
132   }
133   return Status();
134 }
135 
136 std::unique_ptr<NativeRegisterContextWindows>
CreateHostNativeRegisterContextWindows(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)137 NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
138     const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
139   // Register context for a native 64-bit application.
140   return std::make_unique<NativeRegisterContextWindows_arm64>(target_arch,
141                                                               native_thread);
142 }
143 
NativeRegisterContextWindows_arm64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)144 NativeRegisterContextWindows_arm64::NativeRegisterContextWindows_arm64(
145     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
146     : NativeRegisterContextWindows(native_thread,
147                                    CreateRegisterInfoInterface(target_arch)) {}
148 
IsGPR(uint32_t reg_index) const149 bool NativeRegisterContextWindows_arm64::IsGPR(uint32_t reg_index) const {
150   return (reg_index >= k_first_gpr_arm64 && reg_index <= k_last_gpr_arm64);
151 }
152 
IsFPR(uint32_t reg_index) const153 bool NativeRegisterContextWindows_arm64::IsFPR(uint32_t reg_index) const {
154   return (reg_index >= k_first_fpr_arm64 && reg_index <= k_last_fpr_arm64);
155 }
156 
GetRegisterSetCount() const157 uint32_t NativeRegisterContextWindows_arm64::GetRegisterSetCount() const {
158   return k_num_register_sets;
159 }
160 
161 const RegisterSet *
GetRegisterSet(uint32_t set_index) const162 NativeRegisterContextWindows_arm64::GetRegisterSet(uint32_t set_index) const {
163   if (set_index >= k_num_register_sets)
164     return nullptr;
165   return &g_reg_sets_arm64[set_index];
166 }
167 
GPRRead(const uint32_t reg,RegisterValue & reg_value)168 Status NativeRegisterContextWindows_arm64::GPRRead(const uint32_t reg,
169                                                    RegisterValue &reg_value) {
170   ::CONTEXT tls_context;
171   DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;
172   Status error =
173       GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
174   if (error.Fail())
175     return error;
176 
177   switch (reg) {
178   case gpr_x0_arm64:
179   case gpr_x1_arm64:
180   case gpr_x2_arm64:
181   case gpr_x3_arm64:
182   case gpr_x4_arm64:
183   case gpr_x5_arm64:
184   case gpr_x6_arm64:
185   case gpr_x7_arm64:
186   case gpr_x8_arm64:
187   case gpr_x9_arm64:
188   case gpr_x10_arm64:
189   case gpr_x11_arm64:
190   case gpr_x12_arm64:
191   case gpr_x13_arm64:
192   case gpr_x14_arm64:
193   case gpr_x15_arm64:
194   case gpr_x16_arm64:
195   case gpr_x17_arm64:
196   case gpr_x18_arm64:
197   case gpr_x19_arm64:
198   case gpr_x20_arm64:
199   case gpr_x21_arm64:
200   case gpr_x22_arm64:
201   case gpr_x23_arm64:
202   case gpr_x24_arm64:
203   case gpr_x25_arm64:
204   case gpr_x26_arm64:
205   case gpr_x27_arm64:
206   case gpr_x28_arm64:
207     reg_value.SetUInt64(tls_context.X[reg - gpr_x0_arm64]);
208     break;
209 
210   case gpr_fp_arm64:
211     reg_value.SetUInt64(tls_context.Fp);
212     break;
213   case gpr_sp_arm64:
214     reg_value.SetUInt64(tls_context.Sp);
215     break;
216   case gpr_lr_arm64:
217     reg_value.SetUInt64(tls_context.Lr);
218     break;
219   case gpr_pc_arm64:
220     reg_value.SetUInt64(tls_context.Pc);
221     break;
222   case gpr_cpsr_arm64:
223     reg_value.SetUInt32(tls_context.Cpsr);
224     break;
225 
226   case gpr_w0_arm64:
227   case gpr_w1_arm64:
228   case gpr_w2_arm64:
229   case gpr_w3_arm64:
230   case gpr_w4_arm64:
231   case gpr_w5_arm64:
232   case gpr_w6_arm64:
233   case gpr_w7_arm64:
234   case gpr_w8_arm64:
235   case gpr_w9_arm64:
236   case gpr_w10_arm64:
237   case gpr_w11_arm64:
238   case gpr_w12_arm64:
239   case gpr_w13_arm64:
240   case gpr_w14_arm64:
241   case gpr_w15_arm64:
242   case gpr_w16_arm64:
243   case gpr_w17_arm64:
244   case gpr_w18_arm64:
245   case gpr_w19_arm64:
246   case gpr_w20_arm64:
247   case gpr_w21_arm64:
248   case gpr_w22_arm64:
249   case gpr_w23_arm64:
250   case gpr_w24_arm64:
251   case gpr_w25_arm64:
252   case gpr_w26_arm64:
253   case gpr_w27_arm64:
254   case gpr_w28_arm64:
255     reg_value.SetUInt32(
256         static_cast<uint32_t>(tls_context.X[reg - gpr_w0_arm64] & 0xffffffff));
257     break;
258   }
259 
260   return error;
261 }
262 
263 Status
GPRWrite(const uint32_t reg,const RegisterValue & reg_value)264 NativeRegisterContextWindows_arm64::GPRWrite(const uint32_t reg,
265                                              const RegisterValue &reg_value) {
266   ::CONTEXT tls_context;
267   DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;
268   auto thread_handle = GetThreadHandle();
269   Status error =
270       GetThreadContextHelper(thread_handle, &tls_context, context_flag);
271   if (error.Fail())
272     return error;
273 
274   switch (reg) {
275   case gpr_x0_arm64:
276   case gpr_x1_arm64:
277   case gpr_x2_arm64:
278   case gpr_x3_arm64:
279   case gpr_x4_arm64:
280   case gpr_x5_arm64:
281   case gpr_x6_arm64:
282   case gpr_x7_arm64:
283   case gpr_x8_arm64:
284   case gpr_x9_arm64:
285   case gpr_x10_arm64:
286   case gpr_x11_arm64:
287   case gpr_x12_arm64:
288   case gpr_x13_arm64:
289   case gpr_x14_arm64:
290   case gpr_x15_arm64:
291   case gpr_x16_arm64:
292   case gpr_x17_arm64:
293   case gpr_x18_arm64:
294   case gpr_x19_arm64:
295   case gpr_x20_arm64:
296   case gpr_x21_arm64:
297   case gpr_x22_arm64:
298   case gpr_x23_arm64:
299   case gpr_x24_arm64:
300   case gpr_x25_arm64:
301   case gpr_x26_arm64:
302   case gpr_x27_arm64:
303   case gpr_x28_arm64:
304     tls_context.X[reg - gpr_x0_arm64] = reg_value.GetAsUInt64();
305     break;
306 
307   case gpr_fp_arm64:
308     tls_context.Fp = reg_value.GetAsUInt64();
309     break;
310   case gpr_sp_arm64:
311     tls_context.Sp = reg_value.GetAsUInt64();
312     break;
313   case gpr_lr_arm64:
314     tls_context.Lr = reg_value.GetAsUInt64();
315     break;
316   case gpr_pc_arm64:
317     tls_context.Pc = reg_value.GetAsUInt64();
318     break;
319   case gpr_cpsr_arm64:
320     tls_context.Cpsr = reg_value.GetAsUInt32();
321     break;
322 
323   case gpr_w0_arm64:
324   case gpr_w1_arm64:
325   case gpr_w2_arm64:
326   case gpr_w3_arm64:
327   case gpr_w4_arm64:
328   case gpr_w5_arm64:
329   case gpr_w6_arm64:
330   case gpr_w7_arm64:
331   case gpr_w8_arm64:
332   case gpr_w9_arm64:
333   case gpr_w10_arm64:
334   case gpr_w11_arm64:
335   case gpr_w12_arm64:
336   case gpr_w13_arm64:
337   case gpr_w14_arm64:
338   case gpr_w15_arm64:
339   case gpr_w16_arm64:
340   case gpr_w17_arm64:
341   case gpr_w18_arm64:
342   case gpr_w19_arm64:
343   case gpr_w20_arm64:
344   case gpr_w21_arm64:
345   case gpr_w22_arm64:
346   case gpr_w23_arm64:
347   case gpr_w24_arm64:
348   case gpr_w25_arm64:
349   case gpr_w26_arm64:
350   case gpr_w27_arm64:
351   case gpr_w28_arm64:
352     tls_context.X[reg - gpr_w0_arm64] = reg_value.GetAsUInt32();
353     break;
354   }
355 
356   return SetThreadContextHelper(thread_handle, &tls_context);
357 }
358 
FPRRead(const uint32_t reg,RegisterValue & reg_value)359 Status NativeRegisterContextWindows_arm64::FPRRead(const uint32_t reg,
360                                                    RegisterValue &reg_value) {
361   ::CONTEXT tls_context;
362   DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
363   Status error =
364       GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
365   if (error.Fail())
366     return error;
367 
368   switch (reg) {
369   case fpu_v0_arm64:
370   case fpu_v1_arm64:
371   case fpu_v2_arm64:
372   case fpu_v3_arm64:
373   case fpu_v4_arm64:
374   case fpu_v5_arm64:
375   case fpu_v6_arm64:
376   case fpu_v7_arm64:
377   case fpu_v8_arm64:
378   case fpu_v9_arm64:
379   case fpu_v10_arm64:
380   case fpu_v11_arm64:
381   case fpu_v12_arm64:
382   case fpu_v13_arm64:
383   case fpu_v14_arm64:
384   case fpu_v15_arm64:
385   case fpu_v16_arm64:
386   case fpu_v17_arm64:
387   case fpu_v18_arm64:
388   case fpu_v19_arm64:
389   case fpu_v20_arm64:
390   case fpu_v21_arm64:
391   case fpu_v22_arm64:
392   case fpu_v23_arm64:
393   case fpu_v24_arm64:
394   case fpu_v25_arm64:
395   case fpu_v26_arm64:
396   case fpu_v27_arm64:
397   case fpu_v28_arm64:
398   case fpu_v29_arm64:
399   case fpu_v30_arm64:
400   case fpu_v31_arm64:
401     reg_value.SetBytes(tls_context.V[reg - fpu_v0_arm64].B, 16,
402                        endian::InlHostByteOrder());
403     break;
404 
405   case fpu_s0_arm64:
406   case fpu_s1_arm64:
407   case fpu_s2_arm64:
408   case fpu_s3_arm64:
409   case fpu_s4_arm64:
410   case fpu_s5_arm64:
411   case fpu_s6_arm64:
412   case fpu_s7_arm64:
413   case fpu_s8_arm64:
414   case fpu_s9_arm64:
415   case fpu_s10_arm64:
416   case fpu_s11_arm64:
417   case fpu_s12_arm64:
418   case fpu_s13_arm64:
419   case fpu_s14_arm64:
420   case fpu_s15_arm64:
421   case fpu_s16_arm64:
422   case fpu_s17_arm64:
423   case fpu_s18_arm64:
424   case fpu_s19_arm64:
425   case fpu_s20_arm64:
426   case fpu_s21_arm64:
427   case fpu_s22_arm64:
428   case fpu_s23_arm64:
429   case fpu_s24_arm64:
430   case fpu_s25_arm64:
431   case fpu_s26_arm64:
432   case fpu_s27_arm64:
433   case fpu_s28_arm64:
434   case fpu_s29_arm64:
435   case fpu_s30_arm64:
436   case fpu_s31_arm64:
437     reg_value.SetFloat(tls_context.V[reg - fpu_s0_arm64].S[0]);
438     break;
439 
440   case fpu_d0_arm64:
441   case fpu_d1_arm64:
442   case fpu_d2_arm64:
443   case fpu_d3_arm64:
444   case fpu_d4_arm64:
445   case fpu_d5_arm64:
446   case fpu_d6_arm64:
447   case fpu_d7_arm64:
448   case fpu_d8_arm64:
449   case fpu_d9_arm64:
450   case fpu_d10_arm64:
451   case fpu_d11_arm64:
452   case fpu_d12_arm64:
453   case fpu_d13_arm64:
454   case fpu_d14_arm64:
455   case fpu_d15_arm64:
456   case fpu_d16_arm64:
457   case fpu_d17_arm64:
458   case fpu_d18_arm64:
459   case fpu_d19_arm64:
460   case fpu_d20_arm64:
461   case fpu_d21_arm64:
462   case fpu_d22_arm64:
463   case fpu_d23_arm64:
464   case fpu_d24_arm64:
465   case fpu_d25_arm64:
466   case fpu_d26_arm64:
467   case fpu_d27_arm64:
468   case fpu_d28_arm64:
469   case fpu_d29_arm64:
470   case fpu_d30_arm64:
471   case fpu_d31_arm64:
472     reg_value.SetDouble(tls_context.V[reg - fpu_d0_arm64].D[0]);
473     break;
474 
475   case fpu_fpsr_arm64:
476     reg_value.SetUInt32(tls_context.Fpsr);
477     break;
478 
479   case fpu_fpcr_arm64:
480     reg_value.SetUInt32(tls_context.Fpcr);
481     break;
482   }
483 
484   return error;
485 }
486 
487 Status
FPRWrite(const uint32_t reg,const RegisterValue & reg_value)488 NativeRegisterContextWindows_arm64::FPRWrite(const uint32_t reg,
489                                              const RegisterValue &reg_value) {
490   ::CONTEXT tls_context;
491   DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
492   auto thread_handle = GetThreadHandle();
493   Status error =
494       GetThreadContextHelper(thread_handle, &tls_context, context_flag);
495   if (error.Fail())
496     return error;
497 
498   switch (reg) {
499   case fpu_v0_arm64:
500   case fpu_v1_arm64:
501   case fpu_v2_arm64:
502   case fpu_v3_arm64:
503   case fpu_v4_arm64:
504   case fpu_v5_arm64:
505   case fpu_v6_arm64:
506   case fpu_v7_arm64:
507   case fpu_v8_arm64:
508   case fpu_v9_arm64:
509   case fpu_v10_arm64:
510   case fpu_v11_arm64:
511   case fpu_v12_arm64:
512   case fpu_v13_arm64:
513   case fpu_v14_arm64:
514   case fpu_v15_arm64:
515   case fpu_v16_arm64:
516   case fpu_v17_arm64:
517   case fpu_v18_arm64:
518   case fpu_v19_arm64:
519   case fpu_v20_arm64:
520   case fpu_v21_arm64:
521   case fpu_v22_arm64:
522   case fpu_v23_arm64:
523   case fpu_v24_arm64:
524   case fpu_v25_arm64:
525   case fpu_v26_arm64:
526   case fpu_v27_arm64:
527   case fpu_v28_arm64:
528   case fpu_v29_arm64:
529   case fpu_v30_arm64:
530   case fpu_v31_arm64:
531     memcpy(tls_context.V[reg - fpu_v0_arm64].B, reg_value.GetBytes(), 16);
532     break;
533 
534   case fpu_s0_arm64:
535   case fpu_s1_arm64:
536   case fpu_s2_arm64:
537   case fpu_s3_arm64:
538   case fpu_s4_arm64:
539   case fpu_s5_arm64:
540   case fpu_s6_arm64:
541   case fpu_s7_arm64:
542   case fpu_s8_arm64:
543   case fpu_s9_arm64:
544   case fpu_s10_arm64:
545   case fpu_s11_arm64:
546   case fpu_s12_arm64:
547   case fpu_s13_arm64:
548   case fpu_s14_arm64:
549   case fpu_s15_arm64:
550   case fpu_s16_arm64:
551   case fpu_s17_arm64:
552   case fpu_s18_arm64:
553   case fpu_s19_arm64:
554   case fpu_s20_arm64:
555   case fpu_s21_arm64:
556   case fpu_s22_arm64:
557   case fpu_s23_arm64:
558   case fpu_s24_arm64:
559   case fpu_s25_arm64:
560   case fpu_s26_arm64:
561   case fpu_s27_arm64:
562   case fpu_s28_arm64:
563   case fpu_s29_arm64:
564   case fpu_s30_arm64:
565   case fpu_s31_arm64:
566     tls_context.V[reg - fpu_s0_arm64].S[0] = reg_value.GetAsFloat();
567     break;
568 
569   case fpu_d0_arm64:
570   case fpu_d1_arm64:
571   case fpu_d2_arm64:
572   case fpu_d3_arm64:
573   case fpu_d4_arm64:
574   case fpu_d5_arm64:
575   case fpu_d6_arm64:
576   case fpu_d7_arm64:
577   case fpu_d8_arm64:
578   case fpu_d9_arm64:
579   case fpu_d10_arm64:
580   case fpu_d11_arm64:
581   case fpu_d12_arm64:
582   case fpu_d13_arm64:
583   case fpu_d14_arm64:
584   case fpu_d15_arm64:
585   case fpu_d16_arm64:
586   case fpu_d17_arm64:
587   case fpu_d18_arm64:
588   case fpu_d19_arm64:
589   case fpu_d20_arm64:
590   case fpu_d21_arm64:
591   case fpu_d22_arm64:
592   case fpu_d23_arm64:
593   case fpu_d24_arm64:
594   case fpu_d25_arm64:
595   case fpu_d26_arm64:
596   case fpu_d27_arm64:
597   case fpu_d28_arm64:
598   case fpu_d29_arm64:
599   case fpu_d30_arm64:
600   case fpu_d31_arm64:
601     tls_context.V[reg - fpu_d0_arm64].D[0] = reg_value.GetAsDouble();
602     break;
603 
604   case fpu_fpsr_arm64:
605     tls_context.Fpsr = reg_value.GetAsUInt32();
606     break;
607 
608   case fpu_fpcr_arm64:
609     tls_context.Fpcr = reg_value.GetAsUInt32();
610     break;
611   }
612 
613   return SetThreadContextHelper(thread_handle, &tls_context);
614 }
615 
616 Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)617 NativeRegisterContextWindows_arm64::ReadRegister(const RegisterInfo *reg_info,
618                                                  RegisterValue &reg_value) {
619   Status error;
620   if (!reg_info) {
621     error.SetErrorString("reg_info NULL");
622     return error;
623   }
624 
625   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
626   if (reg == LLDB_INVALID_REGNUM) {
627     // This is likely an internal register for lldb use only and should not be
628     // directly queried.
629     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
630                                    "register, cannot read directly",
631                                    reg_info->name);
632     return error;
633   }
634 
635   if (IsGPR(reg))
636     return GPRRead(reg, reg_value);
637 
638   if (IsFPR(reg))
639     return FPRRead(reg, reg_value);
640 
641   return Status("unimplemented");
642 }
643 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)644 Status NativeRegisterContextWindows_arm64::WriteRegister(
645     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
646   Status error;
647 
648   if (!reg_info) {
649     error.SetErrorString("reg_info NULL");
650     return error;
651   }
652 
653   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
654   if (reg == LLDB_INVALID_REGNUM) {
655     // This is likely an internal register for lldb use only and should not be
656     // directly written.
657     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
658                                    "register, cannot write directly",
659                                    reg_info->name);
660     return error;
661   }
662 
663   if (IsGPR(reg))
664     return GPRWrite(reg, reg_value);
665 
666   if (IsFPR(reg))
667     return FPRWrite(reg, reg_value);
668 
669   return Status("unimplemented");
670 }
671 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)672 Status NativeRegisterContextWindows_arm64::ReadAllRegisterValues(
673     lldb::WritableDataBufferSP &data_sp) {
674   const size_t data_size = REG_CONTEXT_SIZE;
675   data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
676   ::CONTEXT tls_context;
677   Status error =
678       GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
679   if (error.Fail())
680     return error;
681 
682   uint8_t *dst = data_sp->GetBytes();
683   ::memcpy(dst, &tls_context, data_size);
684   return error;
685 }
686 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)687 Status NativeRegisterContextWindows_arm64::WriteAllRegisterValues(
688     const lldb::DataBufferSP &data_sp) {
689   Status error;
690   const size_t data_size = REG_CONTEXT_SIZE;
691   if (!data_sp) {
692     error.SetErrorStringWithFormat(
693         "NativeRegisterContextWindows_arm64::%s invalid data_sp provided",
694         __FUNCTION__);
695     return error;
696   }
697 
698   if (data_sp->GetByteSize() != data_size) {
699     error.SetErrorStringWithFormatv(
700         "data_sp contained mismatched data size, expected {0}, actual {1}",
701         data_size, data_sp->GetByteSize());
702     return error;
703   }
704 
705   ::CONTEXT tls_context;
706   memcpy(&tls_context, data_sp->GetBytes(), data_size);
707   return SetThreadContextHelper(GetThreadHandle(), &tls_context);
708 }
709 
IsWatchpointHit(uint32_t wp_index,bool & is_hit)710 Status NativeRegisterContextWindows_arm64::IsWatchpointHit(uint32_t wp_index,
711                                                            bool &is_hit) {
712   return Status("unimplemented");
713 }
714 
GetWatchpointHitIndex(uint32_t & wp_index,lldb::addr_t trap_addr)715 Status NativeRegisterContextWindows_arm64::GetWatchpointHitIndex(
716     uint32_t &wp_index, lldb::addr_t trap_addr) {
717   return Status("unimplemented");
718 }
719 
IsWatchpointVacant(uint32_t wp_index,bool & is_vacant)720 Status NativeRegisterContextWindows_arm64::IsWatchpointVacant(uint32_t wp_index,
721                                                               bool &is_vacant) {
722   return Status("unimplemented");
723 }
724 
SetHardwareWatchpointWithIndex(lldb::addr_t addr,size_t size,uint32_t watch_flags,uint32_t wp_index)725 Status NativeRegisterContextWindows_arm64::SetHardwareWatchpointWithIndex(
726     lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
727   return Status("unimplemented");
728 }
729 
ClearHardwareWatchpoint(uint32_t wp_index)730 bool NativeRegisterContextWindows_arm64::ClearHardwareWatchpoint(
731     uint32_t wp_index) {
732   return false;
733 }
734 
ClearAllHardwareWatchpoints()735 Status NativeRegisterContextWindows_arm64::ClearAllHardwareWatchpoints() {
736   return Status("unimplemented");
737 }
738 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags)739 uint32_t NativeRegisterContextWindows_arm64::SetHardwareWatchpoint(
740     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
741   return LLDB_INVALID_INDEX32;
742 }
743 
744 lldb::addr_t
GetWatchpointAddress(uint32_t wp_index)745 NativeRegisterContextWindows_arm64::GetWatchpointAddress(uint32_t wp_index) {
746   return LLDB_INVALID_ADDRESS;
747 }
748 
NumSupportedHardwareWatchpoints()749 uint32_t NativeRegisterContextWindows_arm64::NumSupportedHardwareWatchpoints() {
750   // Not implemented
751   return 0;
752 }
753 
754 #endif // defined(__aarch64__) || defined(_M_ARM64)
755