LLDB mainline
NativeRegisterContextWindows_arm64.cpp
Go to the documentation of this file.
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
12#include "NativeThreadWindows.h"
13#include "ProcessWindowsLog.h"
14#include "lldb/Host/HostInfo.h"
17
18#include "lldb/Utility/Log.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/ScopeExit.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
27
28namespace {
29static const uint32_t g_gpr_regnums_arm64[] = {
46 LLDB_INVALID_REGNUM // Register set must be terminated with this flag
47};
48static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) -
50 "g_gpr_regnums_arm64 has wrong number of register infos");
51
52static const uint32_t g_fpr_regnums_arm64[] = {
69
79 LLDB_INVALID_REGNUM // Register set must be terminated with this flag
80};
81static_assert(((sizeof g_fpr_regnums_arm64 / sizeof g_fpr_regnums_arm64[0]) -
83 "g_fpu_regnums_arm64 has wrong number of register infos");
84
85static const RegisterSet g_reg_sets_arm64[] = {
86 {"General Purpose Registers", "gpr", std::size(g_gpr_regnums_arm64) - 1,
88 {"Floating Point Registers", "fpr", std::size(g_fpr_regnums_arm64) - 1,
89 g_fpr_regnums_arm64},
90};
91
92enum { k_num_register_sets = 2 };
93
94} // namespace
95
97CreateRegisterInfoInterface(const ArchSpec &target_arch) {
98 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
99 "Register setting path assumes this is a 64-bit host");
100 return new RegisterInfoPOSIX_arm64(
102}
103
104static Status GetThreadContextLength(DWORD context_flags,
105 DWORD &context_length) {
108
109 if (InitializeContext(nullptr, context_flags, nullptr, &context_length)) {
110 error = Status::FromErrorString("InitializeContext succeeded unexpectedly");
111 LLDB_LOG(log, "{0}", error);
112 return error;
113 }
114
115 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
116 error = Status(GetLastError(), eErrorTypeWin32);
117 LLDB_LOG(log,
118 "InitializeContext failed with unexpected error {0}, expected "
119 "ERROR_INSUFFICIENT_BUFFER",
120 error);
121 return error;
122 }
123
124 return error;
125}
126
127static Status GetThreadContextHelper(lldb::thread_t thread_handle,
128 DWORD context_flags, PCONTEXT &context,
129 DataBufferHeap *context_buffer) {
132 DWORD context_length = 0;
133
134 if (!context_buffer) {
135 error = Status::FromErrorString("context buffer not allocated");
136 LLDB_LOG(log, "{0}", error);
137 return error;
138 }
139
140 error = GetThreadContextLength(context_flags, context_length);
141 if (error.Fail())
142 return error;
143
144 if (context_buffer->SetByteSize(context_length) != context_length) {
145 error = Status::FromErrorString("failed to resize context buffer");
146 LLDB_LOG(log, "{0}", error);
147 return error;
148 }
149
150 if (!InitializeContext(context_buffer->GetBytes(), context_flags, &context,
151 &context_length)) {
152 error = Status(GetLastError(), eErrorTypeWin32);
153 LLDB_LOG(log, "InitializeContext failed with error {0}", error);
154 return error;
155 }
156
157 if (!::GetThreadContext(thread_handle, context)) {
158 error = Status(GetLastError(), eErrorTypeWin32);
159 LLDB_LOG(log, "GetThreadContext failed with error {0}", error);
160 return error;
161 }
162
163 return Status();
164}
165
166static Status SetThreadContextHelper(lldb::thread_t thread_handle,
167 PCONTEXT context) {
170 if (!::SetThreadContext(thread_handle, context)) {
171 error = Status(GetLastError(), eErrorTypeWin32);
172 LLDB_LOG(log, "SetThreadContext failed with error {0}", error);
173 return error;
174 }
175 return error;
176}
177
178std::unique_ptr<NativeRegisterContextWindows>
180 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
181 // Register context for a native 64-bit application.
182 return std::make_unique<NativeRegisterContextWindows_arm64>(target_arch,
183 native_thread);
184}
185
186NativeRegisterContextWindows_arm64::NativeRegisterContextWindows_arm64(
187 const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
189 native_thread, CreateRegisterInfoInterface(target_arch)),
190 m_context(nullptr), m_context_buffer(nullptr) {
191 // Currently, there is no API to query the maximum supported hardware
192 // breakpoints and watchpoints on Windows. The values set below are based
193 // on tests conducted on Windows 11 with Snapdragon Elite X hardware.
194 m_max_hwp_supported = 1;
195}
196
197bool NativeRegisterContextWindows_arm64::IsGPR(uint32_t reg_index) const {
198 return (reg_index >= k_first_gpr_arm64 && reg_index <= k_last_gpr_arm64);
199}
200
201bool NativeRegisterContextWindows_arm64::IsFPR(uint32_t reg_index) const {
202 return (reg_index >= k_first_fpr_arm64 && reg_index <= k_last_fpr_arm64);
203}
204
205uint32_t NativeRegisterContextWindows_arm64::GetRegisterSetCount() const {
206 return k_num_register_sets;
207}
208
209const RegisterSet *
210NativeRegisterContextWindows_arm64::GetRegisterSet(uint32_t set_index) const {
211 if (set_index >= k_num_register_sets)
212 return nullptr;
213 return &g_reg_sets_arm64[set_index];
214}
215
216Status NativeRegisterContextWindows_arm64::GPRRead(const uint32_t reg,
217 RegisterValue &reg_value) {
218 Status error = CacheAllRegisterValues();
219 if (error.Fail())
220 return error;
221
222 switch (reg) {
223 case gpr_x0_arm64:
224 case gpr_x1_arm64:
225 case gpr_x2_arm64:
226 case gpr_x3_arm64:
227 case gpr_x4_arm64:
228 case gpr_x5_arm64:
229 case gpr_x6_arm64:
230 case gpr_x7_arm64:
231 case gpr_x8_arm64:
232 case gpr_x9_arm64:
233 case gpr_x10_arm64:
234 case gpr_x11_arm64:
235 case gpr_x12_arm64:
236 case gpr_x13_arm64:
237 case gpr_x14_arm64:
238 case gpr_x15_arm64:
239 case gpr_x16_arm64:
240 case gpr_x17_arm64:
241 case gpr_x18_arm64:
242 case gpr_x19_arm64:
243 case gpr_x20_arm64:
244 case gpr_x21_arm64:
245 case gpr_x22_arm64:
246 case gpr_x23_arm64:
247 case gpr_x24_arm64:
248 case gpr_x25_arm64:
249 case gpr_x26_arm64:
250 case gpr_x27_arm64:
251 case gpr_x28_arm64:
252 reg_value.SetUInt64(m_context->X[reg - gpr_x0_arm64]);
253 break;
254
255 case gpr_fp_arm64:
256 reg_value.SetUInt64(m_context->Fp);
257 break;
258 case gpr_sp_arm64:
259 reg_value.SetUInt64(m_context->Sp);
260 break;
261 case gpr_lr_arm64:
262 reg_value.SetUInt64(m_context->Lr);
263 break;
264 case gpr_pc_arm64:
265 reg_value.SetUInt64(m_context->Pc);
266 break;
267 case gpr_cpsr_arm64:
268 reg_value.SetUInt32(m_context->Cpsr);
269 break;
270
271 case gpr_w0_arm64:
272 case gpr_w1_arm64:
273 case gpr_w2_arm64:
274 case gpr_w3_arm64:
275 case gpr_w4_arm64:
276 case gpr_w5_arm64:
277 case gpr_w6_arm64:
278 case gpr_w7_arm64:
279 case gpr_w8_arm64:
280 case gpr_w9_arm64:
281 case gpr_w10_arm64:
282 case gpr_w11_arm64:
283 case gpr_w12_arm64:
284 case gpr_w13_arm64:
285 case gpr_w14_arm64:
286 case gpr_w15_arm64:
287 case gpr_w16_arm64:
288 case gpr_w17_arm64:
289 case gpr_w18_arm64:
290 case gpr_w19_arm64:
291 case gpr_w20_arm64:
292 case gpr_w21_arm64:
293 case gpr_w22_arm64:
294 case gpr_w23_arm64:
295 case gpr_w24_arm64:
296 case gpr_w25_arm64:
297 case gpr_w26_arm64:
298 case gpr_w27_arm64:
299 case gpr_w28_arm64:
300 reg_value.SetUInt32(
301 static_cast<uint32_t>(m_context->X[reg - gpr_w0_arm64] & 0xffffffff));
302 break;
303 }
304
305 return error;
306}
307
308Status
309NativeRegisterContextWindows_arm64::GPRWrite(const uint32_t reg,
310 const RegisterValue &reg_value) {
311 auto cleanup = llvm::make_scope_exit([&]() { m_context = nullptr; });
312
313 PCONTEXT context = nullptr;
314 DataBufferHeap context_buffer;
315 DWORD context_flags = CONTEXT_CONTROL | CONTEXT_INTEGER;
316 auto thread_handle = GetThreadHandle();
317
318 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
319 &context_buffer);
320 if (error.Fail())
321 return error;
322
323 switch (reg) {
324 case gpr_x0_arm64:
325 case gpr_x1_arm64:
326 case gpr_x2_arm64:
327 case gpr_x3_arm64:
328 case gpr_x4_arm64:
329 case gpr_x5_arm64:
330 case gpr_x6_arm64:
331 case gpr_x7_arm64:
332 case gpr_x8_arm64:
333 case gpr_x9_arm64:
334 case gpr_x10_arm64:
335 case gpr_x11_arm64:
336 case gpr_x12_arm64:
337 case gpr_x13_arm64:
338 case gpr_x14_arm64:
339 case gpr_x15_arm64:
340 case gpr_x16_arm64:
341 case gpr_x17_arm64:
342 case gpr_x18_arm64:
343 case gpr_x19_arm64:
344 case gpr_x20_arm64:
345 case gpr_x21_arm64:
346 case gpr_x22_arm64:
347 case gpr_x23_arm64:
348 case gpr_x24_arm64:
349 case gpr_x25_arm64:
350 case gpr_x26_arm64:
351 case gpr_x27_arm64:
352 case gpr_x28_arm64:
353 context->X[reg - gpr_x0_arm64] = reg_value.GetAsUInt64();
354 break;
355
356 case gpr_fp_arm64:
357 context->Fp = reg_value.GetAsUInt64();
358 break;
359 case gpr_sp_arm64:
360 context->Sp = reg_value.GetAsUInt64();
361 break;
362 case gpr_lr_arm64:
363 context->Lr = reg_value.GetAsUInt64();
364 break;
365 case gpr_pc_arm64:
366 context->Pc = reg_value.GetAsUInt64();
367 break;
368 case gpr_cpsr_arm64:
369 context->Cpsr = reg_value.GetAsUInt32();
370 break;
371
372 case gpr_w0_arm64:
373 case gpr_w1_arm64:
374 case gpr_w2_arm64:
375 case gpr_w3_arm64:
376 case gpr_w4_arm64:
377 case gpr_w5_arm64:
378 case gpr_w6_arm64:
379 case gpr_w7_arm64:
380 case gpr_w8_arm64:
381 case gpr_w9_arm64:
382 case gpr_w10_arm64:
383 case gpr_w11_arm64:
384 case gpr_w12_arm64:
385 case gpr_w13_arm64:
386 case gpr_w14_arm64:
387 case gpr_w15_arm64:
388 case gpr_w16_arm64:
389 case gpr_w17_arm64:
390 case gpr_w18_arm64:
391 case gpr_w19_arm64:
392 case gpr_w20_arm64:
393 case gpr_w21_arm64:
394 case gpr_w22_arm64:
395 case gpr_w23_arm64:
396 case gpr_w24_arm64:
397 case gpr_w25_arm64:
398 case gpr_w26_arm64:
399 case gpr_w27_arm64:
400 case gpr_w28_arm64:
401 context->X[reg - gpr_w0_arm64] = reg_value.GetAsUInt32();
402 break;
403 }
404
405 return SetThreadContextHelper(thread_handle, context);
406}
407
408Status NativeRegisterContextWindows_arm64::FPRRead(const uint32_t reg,
409 RegisterValue &reg_value) {
410 Status error = CacheAllRegisterValues();
411 if (error.Fail())
412 return error;
413
414 switch (reg) {
415 case fpu_v0_arm64:
416 case fpu_v1_arm64:
417 case fpu_v2_arm64:
418 case fpu_v3_arm64:
419 case fpu_v4_arm64:
420 case fpu_v5_arm64:
421 case fpu_v6_arm64:
422 case fpu_v7_arm64:
423 case fpu_v8_arm64:
424 case fpu_v9_arm64:
425 case fpu_v10_arm64:
426 case fpu_v11_arm64:
427 case fpu_v12_arm64:
428 case fpu_v13_arm64:
429 case fpu_v14_arm64:
430 case fpu_v15_arm64:
431 case fpu_v16_arm64:
432 case fpu_v17_arm64:
433 case fpu_v18_arm64:
434 case fpu_v19_arm64:
435 case fpu_v20_arm64:
436 case fpu_v21_arm64:
437 case fpu_v22_arm64:
438 case fpu_v23_arm64:
439 case fpu_v24_arm64:
440 case fpu_v25_arm64:
441 case fpu_v26_arm64:
442 case fpu_v27_arm64:
443 case fpu_v28_arm64:
444 case fpu_v29_arm64:
445 case fpu_v30_arm64:
446 case fpu_v31_arm64:
447 reg_value.SetBytes(m_context->V[reg - fpu_v0_arm64].B, 16,
449 break;
450
451 case fpu_s0_arm64:
452 case fpu_s1_arm64:
453 case fpu_s2_arm64:
454 case fpu_s3_arm64:
455 case fpu_s4_arm64:
456 case fpu_s5_arm64:
457 case fpu_s6_arm64:
458 case fpu_s7_arm64:
459 case fpu_s8_arm64:
460 case fpu_s9_arm64:
461 case fpu_s10_arm64:
462 case fpu_s11_arm64:
463 case fpu_s12_arm64:
464 case fpu_s13_arm64:
465 case fpu_s14_arm64:
466 case fpu_s15_arm64:
467 case fpu_s16_arm64:
468 case fpu_s17_arm64:
469 case fpu_s18_arm64:
470 case fpu_s19_arm64:
471 case fpu_s20_arm64:
472 case fpu_s21_arm64:
473 case fpu_s22_arm64:
474 case fpu_s23_arm64:
475 case fpu_s24_arm64:
476 case fpu_s25_arm64:
477 case fpu_s26_arm64:
478 case fpu_s27_arm64:
479 case fpu_s28_arm64:
480 case fpu_s29_arm64:
481 case fpu_s30_arm64:
482 case fpu_s31_arm64:
483 reg_value.SetFloat(m_context->V[reg - fpu_s0_arm64].S[0]);
484 break;
485
486 case fpu_d0_arm64:
487 case fpu_d1_arm64:
488 case fpu_d2_arm64:
489 case fpu_d3_arm64:
490 case fpu_d4_arm64:
491 case fpu_d5_arm64:
492 case fpu_d6_arm64:
493 case fpu_d7_arm64:
494 case fpu_d8_arm64:
495 case fpu_d9_arm64:
496 case fpu_d10_arm64:
497 case fpu_d11_arm64:
498 case fpu_d12_arm64:
499 case fpu_d13_arm64:
500 case fpu_d14_arm64:
501 case fpu_d15_arm64:
502 case fpu_d16_arm64:
503 case fpu_d17_arm64:
504 case fpu_d18_arm64:
505 case fpu_d19_arm64:
506 case fpu_d20_arm64:
507 case fpu_d21_arm64:
508 case fpu_d22_arm64:
509 case fpu_d23_arm64:
510 case fpu_d24_arm64:
511 case fpu_d25_arm64:
512 case fpu_d26_arm64:
513 case fpu_d27_arm64:
514 case fpu_d28_arm64:
515 case fpu_d29_arm64:
516 case fpu_d30_arm64:
517 case fpu_d31_arm64:
518 reg_value.SetDouble(m_context->V[reg - fpu_d0_arm64].D[0]);
519 break;
520
521 case fpu_fpsr_arm64:
522 reg_value.SetUInt32(m_context->Fpsr);
523 break;
524
525 case fpu_fpcr_arm64:
526 reg_value.SetUInt32(m_context->Fpcr);
527 break;
528 }
529
530 return error;
531}
532
533Status
534NativeRegisterContextWindows_arm64::FPRWrite(const uint32_t reg,
535 const RegisterValue &reg_value) {
536 auto cleanup = llvm::make_scope_exit([&]() { m_context = nullptr; });
537
538 PCONTEXT context = nullptr;
539 DataBufferHeap context_buffer;
540 DWORD context_flags = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
541 auto thread_handle = GetThreadHandle();
542
543 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
544 &context_buffer);
545 if (error.Fail())
546 return error;
547
548 switch (reg) {
549 case fpu_v0_arm64:
550 case fpu_v1_arm64:
551 case fpu_v2_arm64:
552 case fpu_v3_arm64:
553 case fpu_v4_arm64:
554 case fpu_v5_arm64:
555 case fpu_v6_arm64:
556 case fpu_v7_arm64:
557 case fpu_v8_arm64:
558 case fpu_v9_arm64:
559 case fpu_v10_arm64:
560 case fpu_v11_arm64:
561 case fpu_v12_arm64:
562 case fpu_v13_arm64:
563 case fpu_v14_arm64:
564 case fpu_v15_arm64:
565 case fpu_v16_arm64:
566 case fpu_v17_arm64:
567 case fpu_v18_arm64:
568 case fpu_v19_arm64:
569 case fpu_v20_arm64:
570 case fpu_v21_arm64:
571 case fpu_v22_arm64:
572 case fpu_v23_arm64:
573 case fpu_v24_arm64:
574 case fpu_v25_arm64:
575 case fpu_v26_arm64:
576 case fpu_v27_arm64:
577 case fpu_v28_arm64:
578 case fpu_v29_arm64:
579 case fpu_v30_arm64:
580 case fpu_v31_arm64:
581 memcpy(context->V[reg - fpu_v0_arm64].B, reg_value.GetBytes(), 16);
582 break;
583
584 case fpu_s0_arm64:
585 case fpu_s1_arm64:
586 case fpu_s2_arm64:
587 case fpu_s3_arm64:
588 case fpu_s4_arm64:
589 case fpu_s5_arm64:
590 case fpu_s6_arm64:
591 case fpu_s7_arm64:
592 case fpu_s8_arm64:
593 case fpu_s9_arm64:
594 case fpu_s10_arm64:
595 case fpu_s11_arm64:
596 case fpu_s12_arm64:
597 case fpu_s13_arm64:
598 case fpu_s14_arm64:
599 case fpu_s15_arm64:
600 case fpu_s16_arm64:
601 case fpu_s17_arm64:
602 case fpu_s18_arm64:
603 case fpu_s19_arm64:
604 case fpu_s20_arm64:
605 case fpu_s21_arm64:
606 case fpu_s22_arm64:
607 case fpu_s23_arm64:
608 case fpu_s24_arm64:
609 case fpu_s25_arm64:
610 case fpu_s26_arm64:
611 case fpu_s27_arm64:
612 case fpu_s28_arm64:
613 case fpu_s29_arm64:
614 case fpu_s30_arm64:
615 case fpu_s31_arm64:
616 context->V[reg - fpu_s0_arm64].S[0] = reg_value.GetAsFloat();
617 break;
618
619 case fpu_d0_arm64:
620 case fpu_d1_arm64:
621 case fpu_d2_arm64:
622 case fpu_d3_arm64:
623 case fpu_d4_arm64:
624 case fpu_d5_arm64:
625 case fpu_d6_arm64:
626 case fpu_d7_arm64:
627 case fpu_d8_arm64:
628 case fpu_d9_arm64:
629 case fpu_d10_arm64:
630 case fpu_d11_arm64:
631 case fpu_d12_arm64:
632 case fpu_d13_arm64:
633 case fpu_d14_arm64:
634 case fpu_d15_arm64:
635 case fpu_d16_arm64:
636 case fpu_d17_arm64:
637 case fpu_d18_arm64:
638 case fpu_d19_arm64:
639 case fpu_d20_arm64:
640 case fpu_d21_arm64:
641 case fpu_d22_arm64:
642 case fpu_d23_arm64:
643 case fpu_d24_arm64:
644 case fpu_d25_arm64:
645 case fpu_d26_arm64:
646 case fpu_d27_arm64:
647 case fpu_d28_arm64:
648 case fpu_d29_arm64:
649 case fpu_d30_arm64:
650 case fpu_d31_arm64:
651 context->V[reg - fpu_d0_arm64].D[0] = reg_value.GetAsDouble();
652 break;
653
654 case fpu_fpsr_arm64:
655 context->Fpsr = reg_value.GetAsUInt32();
656 break;
657
658 case fpu_fpcr_arm64:
659 context->Fpcr = reg_value.GetAsUInt32();
660 break;
661 }
662
663 return SetThreadContextHelper(thread_handle, context);
664}
665
666Status
667NativeRegisterContextWindows_arm64::ReadRegister(const RegisterInfo *reg_info,
668 RegisterValue &reg_value) {
670 if (!reg_info) {
671 error = Status::FromErrorString("reg_info NULL");
672 return error;
673 }
674
675 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
676 if (reg == LLDB_INVALID_REGNUM) {
677 // This is likely an internal register for lldb use only and should not be
678 // directly queried.
680 "register \"%s\" is an internal-only lldb "
681 "register, cannot read directly",
682 reg_info->name);
683 return error;
684 }
685
686 if (IsGPR(reg))
687 return GPRRead(reg, reg_value);
688
689 if (IsFPR(reg))
690 return FPRRead(reg, reg_value);
691
692 return Status::FromErrorString("unimplemented");
693}
694
695Status NativeRegisterContextWindows_arm64::WriteRegister(
696 const RegisterInfo *reg_info, const RegisterValue &reg_value) {
698
699 if (!reg_info) {
700 error = Status::FromErrorString("reg_info NULL");
701 return error;
702 }
703
704 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
705 if (reg == LLDB_INVALID_REGNUM) {
706 // This is likely an internal register for lldb use only and should not be
707 // directly written.
709 "register \"%s\" is an internal-only lldb "
710 "register, cannot write directly",
711 reg_info->name);
712 return error;
713 }
714
715 if (IsGPR(reg))
716 return GPRWrite(reg, reg_value);
717
718 if (IsFPR(reg))
719 return FPRWrite(reg, reg_value);
720
721 return Status::FromErrorString("unimplemented");
722}
723
724Status NativeRegisterContextWindows_arm64::ReadAllRegisterValues(
727
728 Status error = CacheAllRegisterValues();
729 if (error.Fail())
730 return error;
731
732 if (!m_context_buffer) {
733 error = Status::FromErrorString("register context buffer is not available");
734 LLDB_LOG(log, "{0}", error);
735 return error;
736 }
737
738 data_sp = std::make_shared<DataBufferHeap>(m_context_buffer->GetBytes(),
739 m_context_buffer->GetByteSize());
740
741 return error;
742}
743
744Status NativeRegisterContextWindows_arm64::WriteAllRegisterValues(
745 const lldb::DataBufferSP &data_sp) {
746 auto cleanup = llvm::make_scope_exit([&]() { m_context = nullptr; });
747
750
751 if (!data_sp) {
752 error = Status::FromErrorString("invalid data_sp");
753 LLDB_LOG(log, "{0}", error);
754 return error;
755 }
756
757 DWORD context_flags = CONTEXT_ALL;
758 DWORD context_length = 0;
759
760 error = GetThreadContextLength(context_flags, context_length);
761 if (error.Fail())
762 return error;
763
764 if (data_sp->GetByteSize() != context_length) {
766 "data_sp contained mismatched data size, expected {0}, actual {1}",
767 context_length, data_sp->GetByteSize());
768 LLDB_LOG(log, "{0}", error);
769 return error;
770 }
771
772 PCONTEXT context = nullptr;
773 DataBufferHeap context_buffer;
774 error = GetThreadContextHelper(GetThreadHandle(), context_flags, context,
775 &context_buffer);
776 if (error.Fail())
777 return error;
778
779 ::memcpy(context_buffer.GetBytes(), data_sp->GetBytes(), context_length);
780
781 return SetThreadContextHelper(GetThreadHandle(), context);
782}
783
784llvm::Error NativeRegisterContextWindows_arm64::ReadHardwareDebugInfo() {
785 Status error = CacheAllRegisterValues();
786 if (error.Fail())
787 return error.ToError();
788
789 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
790 m_hwp_regs[i].address = m_context->Wvr[i];
791 m_hwp_regs[i].control = m_context->Wcr[i];
792 }
793
794 return llvm::Error::success();
795}
796
797llvm::Error
798NativeRegisterContextWindows_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
799 auto cleanup = llvm::make_scope_exit([&]() { m_context = nullptr; });
800
801 PCONTEXT context = nullptr;
802 DataBufferHeap context_buffer;
803 DWORD context_flags = CONTEXT_DEBUG_REGISTERS;
804 auto thread_handle = GetThreadHandle();
805
806 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
807 &context_buffer);
808 if (error.Fail())
809 return error.ToError();
810
811 if (hwbType == eDREGTypeWATCH) {
812 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
813 context->Wvr[i] = m_hwp_regs[i].address;
814 context->Wcr[i] = m_hwp_regs[i].control;
815 }
816 }
817
818 return SetThreadContextHelper(GetThreadHandle(), context).ToError();
819}
820
821void NativeRegisterContextWindows_arm64::InvalidateAllRegisters() {
822 m_context = nullptr;
823 m_context_buffer.reset();
824}
825
826Status NativeRegisterContextWindows_arm64::CacheAllRegisterValues() {
828 DWORD context_flags = CONTEXT_ALL;
829
830 if (m_context && (m_context->ContextFlags & context_flags) == context_flags)
831 return error;
832
833 m_context = nullptr;
834
835 if (!m_context_buffer)
836 m_context_buffer = std::make_shared<DataBufferHeap>();
837
838 error = GetThreadContextHelper(GetThreadHandle(), context_flags, m_context,
839 m_context_buffer.get());
840
841 if (error.Fail())
842 m_context = nullptr;
843
844 return error;
845}
846
847#endif // defined(__aarch64__) || defined(_M_ARM64)
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:364
static const uint32_t g_gpr_regnums_arm64[]
static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets]
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t SetByteSize(lldb::offset_t byte_size)
Set the number of bytes in the data buffer.
static std::unique_ptr< NativeRegisterContextWindows > CreateHostNativeRegisterContextWindows(const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
double GetAsDouble(double fail_value=0.0, bool *success_ptr=nullptr) const
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
float GetAsFloat(float fail_value=0.0f, bool *success_ptr=nullptr) const
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
const void * GetBytes() const
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition Status.h:151
uint8_t * GetBytes()
Get a pointer to the data.
Definition DataBuffer.h:108
#define LLDB_INVALID_REGNUM
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
@ eErrorTypeWin32
Standard Win32 error codes.
pthread_t thread_t
Definition lldb-types.h:58
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.