LLDB mainline
RegisterContextMinidump_ARM64.cpp
Go to the documentation of this file.
1//===-- RegisterContextMinidump_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
10
15
16// C includes
17#include <cassert>
18
19// C++ includes
20
21using namespace lldb;
22using namespace lldb_private;
23using namespace minidump;
24
25#define INV LLDB_INVALID_REGNUM
26#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r))
27
28#define DEF_X(i) \
29 { \
30 "x" #i, nullptr, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
31 {arm64_dwarf::x##i, arm64_dwarf::x##i, INV, INV, reg_x##i}, \
32 nullptr, nullptr, nullptr, \
33 }
34
35#define DEF_W(i) \
36 { \
37 "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
38 {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, \
39 }
40
41#define DEF_X_ARG(i, n) \
42 { \
43 "x" #i, "arg" #n, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
44 {arm64_dwarf::x##i, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, \
45 INV, reg_x##i}, nullptr, nullptr, nullptr, \
46 }
47
48#define DEF_V(i) \
49 { \
50 "v" #i, nullptr, 16, OFFSET(v) + i * 16, eEncodingVector, \
51 eFormatVectorOfUInt8, {arm64_dwarf::v##i, arm64_dwarf::v##i, INV, INV, \
52 reg_v##i}, nullptr, nullptr, nullptr, \
53 }
54
55#define DEF_D(i) \
56 { \
57 "d" #i, nullptr, 8, OFFSET(v) + i * 16, eEncodingVector, \
58 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr, \
59 nullptr, nullptr, \
60 }
61
62#define DEF_S(i) \
63 { \
64 "s" #i, nullptr, 4, OFFSET(v) + i * 16, eEncodingVector, \
65 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr, \
66 nullptr, nullptr, \
67 }
68
69#define DEF_H(i) \
70 { \
71 "h" #i, nullptr, 2, OFFSET(v) + i * 16, eEncodingVector, \
72 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr, \
73 nullptr, nullptr, \
74 }
75
76// Zero based LLDB register numbers for this register context
77enum {
78 // General Purpose Registers
79 reg_x0 = 0,
145 // Floating Point Registers
277};
278
279// Register info definitions for this register context
281 DEF_X_ARG(0, 1),
282 DEF_X_ARG(1, 2),
283 DEF_X_ARG(2, 3),
284 DEF_X_ARG(3, 4),
285 DEF_X_ARG(4, 5),
286 DEF_X_ARG(5, 6),
287 DEF_X_ARG(6, 7),
288 DEF_X_ARG(7, 8),
289 DEF_X(8),
290 DEF_X(9),
291 DEF_X(10),
292 DEF_X(11),
293 DEF_X(12),
294 DEF_X(13),
295 DEF_X(14),
296 DEF_X(15),
297 DEF_X(16),
298 DEF_X(17),
299 DEF_X(18),
300 DEF_X(19),
301 DEF_X(20),
302 DEF_X(21),
303 DEF_X(22),
304 DEF_X(23),
305 DEF_X(24),
306 DEF_X(25),
307 DEF_X(26),
308 DEF_X(27),
309 DEF_X(28),
310 {
311 "fp",
312 "x29",
313 8,
314 OFFSET(x) + 29 * 8,
318 reg_fp},
319 nullptr,
320 nullptr,
321 nullptr,
322 },
323 {
324 "lr",
325 "x30",
326 8,
327 OFFSET(x) + 30 * 8,
331 reg_lr},
332 nullptr,
333 nullptr,
334 nullptr,
335 },
336 {
337 "sp",
338 "x31",
339 8,
340 OFFSET(x) + 31 * 8,
344 reg_sp},
345 nullptr,
346 nullptr,
347 nullptr,
348 },
349 {
350 "pc",
351 nullptr,
352 8,
353 OFFSET(pc),
357 nullptr,
358 nullptr,
359 nullptr,
360 },
361 // w0 - w31
362 DEF_W(0),
363 DEF_W(1),
364 DEF_W(2),
365 DEF_W(3),
366 DEF_W(4),
367 DEF_W(5),
368 DEF_W(6),
369 DEF_W(7),
370 DEF_W(8),
371 DEF_W(9),
372 DEF_W(10),
373 DEF_W(11),
374 DEF_W(12),
375 DEF_W(13),
376 DEF_W(14),
377 DEF_W(15),
378 DEF_W(16),
379 DEF_W(17),
380 DEF_W(18),
381 DEF_W(19),
382 DEF_W(20),
383 DEF_W(21),
384 DEF_W(22),
385 DEF_W(23),
386 DEF_W(24),
387 DEF_W(25),
388 DEF_W(26),
389 DEF_W(27),
390 DEF_W(28),
391 DEF_W(29),
392 DEF_W(30),
393 DEF_W(31),
394 {
395 "cpsr",
396 "psr",
397 4,
398 OFFSET(cpsr),
402 nullptr,
403 nullptr,
404 nullptr,
405 },
406 {
407 "fpsr",
408 nullptr,
409 4,
410 OFFSET(fpsr),
413 {INV, INV, INV, INV, reg_fpsr},
414 nullptr,
415 nullptr,
416 nullptr,
417 },
418 {
419 "fpcr",
420 nullptr,
421 4,
422 OFFSET(fpcr),
425 {INV, INV, INV, INV, reg_fpcr},
426 nullptr,
427 nullptr,
428 nullptr,
429 },
430 // v0 - v31
431 DEF_V(0),
432 DEF_V(1),
433 DEF_V(2),
434 DEF_V(3),
435 DEF_V(4),
436 DEF_V(5),
437 DEF_V(6),
438 DEF_V(7),
439 DEF_V(8),
440 DEF_V(9),
441 DEF_V(10),
442 DEF_V(11),
443 DEF_V(12),
444 DEF_V(13),
445 DEF_V(14),
446 DEF_V(15),
447 DEF_V(16),
448 DEF_V(17),
449 DEF_V(18),
450 DEF_V(19),
451 DEF_V(20),
452 DEF_V(21),
453 DEF_V(22),
454 DEF_V(23),
455 DEF_V(24),
456 DEF_V(25),
457 DEF_V(26),
458 DEF_V(27),
459 DEF_V(28),
460 DEF_V(29),
461 DEF_V(30),
462 DEF_V(31),
463 // d0 - d31
464 DEF_D(0),
465 DEF_D(1),
466 DEF_D(2),
467 DEF_D(3),
468 DEF_D(4),
469 DEF_D(5),
470 DEF_D(6),
471 DEF_D(7),
472 DEF_D(8),
473 DEF_D(9),
474 DEF_D(10),
475 DEF_D(11),
476 DEF_D(12),
477 DEF_D(13),
478 DEF_D(14),
479 DEF_D(15),
480 DEF_D(16),
481 DEF_D(17),
482 DEF_D(18),
483 DEF_D(19),
484 DEF_D(20),
485 DEF_D(21),
486 DEF_D(22),
487 DEF_D(23),
488 DEF_D(24),
489 DEF_D(25),
490 DEF_D(26),
491 DEF_D(27),
492 DEF_D(28),
493 DEF_D(29),
494 DEF_D(30),
495 DEF_D(31),
496 // s0 - s31
497 DEF_S(0),
498 DEF_S(1),
499 DEF_S(2),
500 DEF_S(3),
501 DEF_S(4),
502 DEF_S(5),
503 DEF_S(6),
504 DEF_S(7),
505 DEF_S(8),
506 DEF_S(9),
507 DEF_S(10),
508 DEF_S(11),
509 DEF_S(12),
510 DEF_S(13),
511 DEF_S(14),
512 DEF_S(15),
513 DEF_S(16),
514 DEF_S(17),
515 DEF_S(18),
516 DEF_S(19),
517 DEF_S(20),
518 DEF_S(21),
519 DEF_S(22),
520 DEF_S(23),
521 DEF_S(24),
522 DEF_S(25),
523 DEF_S(26),
524 DEF_S(27),
525 DEF_S(28),
526 DEF_S(29),
527 DEF_S(30),
528 DEF_S(31),
529 // h0 - h31
530 DEF_H(0),
531 DEF_H(1),
532 DEF_H(2),
533 DEF_H(3),
534 DEF_H(4),
535 DEF_H(5),
536 DEF_H(6),
537 DEF_H(7),
538 DEF_H(8),
539 DEF_H(9),
540 DEF_H(10),
541 DEF_H(11),
542 DEF_H(12),
543 DEF_H(13),
544 DEF_H(14),
545 DEF_H(15),
546 DEF_H(16),
547 DEF_H(17),
548 DEF_H(18),
549 DEF_H(19),
550 DEF_H(20),
551 DEF_H(21),
552 DEF_H(22),
553 DEF_H(23),
554 DEF_H(24),
555 DEF_H(25),
556 DEF_H(26),
557 DEF_H(27),
558 DEF_H(28),
559 DEF_H(29),
560 DEF_H(30),
561 DEF_H(31),
562};
563
564constexpr size_t k_num_reg_infos = std::size(g_reg_infos);
565
566// ARM64 general purpose registers.
567const uint32_t g_gpr_regnums[] = {
568 reg_x0,
569 reg_x1,
570 reg_x2,
571 reg_x3,
572 reg_x4,
573 reg_x5,
574 reg_x6,
575 reg_x7,
576 reg_x8,
577 reg_x9,
578 reg_x10,
579 reg_x11,
580 reg_x12,
581 reg_x13,
582 reg_x14,
583 reg_x15,
584 reg_x16,
585 reg_x17,
586 reg_x18,
587 reg_x19,
588 reg_x20,
589 reg_x21,
590 reg_x22,
591 reg_x23,
592 reg_x24,
593 reg_x25,
594 reg_x26,
595 reg_x27,
596 reg_x28,
597 reg_fp,
598 reg_lr,
599 reg_sp,
600 reg_w0,
601 reg_w1,
602 reg_w2,
603 reg_w3,
604 reg_w4,
605 reg_w5,
606 reg_w6,
607 reg_w7,
608 reg_w8,
609 reg_w9,
610 reg_w10,
611 reg_w11,
612 reg_w12,
613 reg_w13,
614 reg_w14,
615 reg_w15,
616 reg_w16,
617 reg_w17,
618 reg_w18,
619 reg_w19,
620 reg_w20,
621 reg_w21,
622 reg_w22,
623 reg_w23,
624 reg_w24,
625 reg_w25,
626 reg_w26,
627 reg_w27,
628 reg_w28,
629 reg_w29,
630 reg_w30,
631 reg_w31,
632 reg_pc,
633 reg_cpsr,
634 LLDB_INVALID_REGNUM // register sets need to end with this flag
635};
636const uint32_t g_fpu_regnums[] = {
637 reg_v0,
638 reg_v1,
639 reg_v2,
640 reg_v3,
641 reg_v4,
642 reg_v5,
643 reg_v6,
644 reg_v7,
645 reg_v8,
646 reg_v9,
647 reg_v10,
648 reg_v11,
649 reg_v12,
650 reg_v13,
651 reg_v14,
652 reg_v15,
653 reg_v16,
654 reg_v17,
655 reg_v18,
656 reg_v19,
657 reg_v20,
658 reg_v21,
659 reg_v22,
660 reg_v23,
661 reg_v24,
662 reg_v25,
663 reg_v26,
664 reg_v27,
665 reg_v28,
666 reg_v29,
667 reg_v30,
668 reg_v31,
669 reg_d0,
670 reg_d1,
671 reg_d2,
672 reg_d3,
673 reg_d4,
674 reg_d5,
675 reg_d6,
676 reg_d7,
677 reg_d8,
678 reg_d9,
679 reg_d10,
680 reg_d11,
681 reg_d12,
682 reg_d13,
683 reg_d14,
684 reg_d15,
685 reg_d16,
686 reg_d17,
687 reg_d18,
688 reg_d19,
689 reg_d20,
690 reg_d21,
691 reg_d22,
692 reg_d23,
693 reg_d24,
694 reg_d25,
695 reg_d26,
696 reg_d27,
697 reg_d28,
698 reg_d29,
699 reg_d30,
700 reg_d31,
701 reg_s0,
702 reg_s1,
703 reg_s2,
704 reg_s3,
705 reg_s4,
706 reg_s5,
707 reg_s6,
708 reg_s7,
709 reg_s8,
710 reg_s9,
711 reg_s10,
712 reg_s11,
713 reg_s12,
714 reg_s13,
715 reg_s14,
716 reg_s15,
717 reg_s16,
718 reg_s17,
719 reg_s18,
720 reg_s19,
721 reg_s20,
722 reg_s21,
723 reg_s22,
724 reg_s23,
725 reg_s24,
726 reg_s25,
727 reg_s26,
728 reg_s27,
729 reg_s28,
730 reg_s29,
731 reg_s30,
732 reg_s31,
733 reg_h0,
734 reg_h1,
735 reg_h2,
736 reg_h3,
737 reg_h4,
738 reg_h5,
739 reg_h6,
740 reg_h7,
741 reg_h8,
742 reg_h9,
743 reg_h10,
744 reg_h11,
745 reg_h12,
746 reg_h13,
747 reg_h14,
748 reg_h15,
749 reg_h16,
750 reg_h17,
751 reg_h18,
752 reg_h19,
753 reg_h20,
754 reg_h21,
755 reg_h22,
756 reg_h23,
757 reg_h24,
758 reg_h25,
759 reg_h26,
760 reg_h27,
761 reg_h28,
762 reg_h29,
763 reg_h30,
764 reg_h31,
765 reg_fpsr,
766 reg_fpcr,
767 LLDB_INVALID_REGNUM // register sets need to end with this flag
768};
769
770// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
771constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;
772constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;
773
775 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
776 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
777};
778
779constexpr size_t k_num_reg_sets = std::size(g_reg_sets);
780
782 lldb_private::Thread &thread, const DataExtractor &data)
783 : RegisterContext(thread, 0) {
784 lldb::offset_t offset = 0;
785 m_regs.context_flags = data.GetU64(&offset);
786 for (unsigned i = 0; i < 32; ++i)
787 m_regs.x[i] = data.GetU64(&offset);
788 m_regs.pc = data.GetU64(&offset);
789 m_regs.cpsr = data.GetU32(&offset);
790 m_regs.fpsr = data.GetU32(&offset);
791 m_regs.fpcr = data.GetU32(&offset);
792 auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
793 if (regs_data)
794 memcpy(m_regs.v, regs_data, sizeof(m_regs.v));
795 static_assert(k_num_regs == k_num_reg_infos);
796}
798
799const RegisterInfo *
801 if (reg < k_num_reg_infos)
802 return &g_reg_infos[reg];
803 return nullptr;
804}
805
809
811 if (set < k_num_reg_sets)
812 return &g_reg_sets[set];
813 return nullptr;
814}
815
817 if (reg < k_num_reg_infos)
818 return g_reg_infos[reg].name;
819 return nullptr;
820}
821
823 RegisterValue &reg_value) {
825 reg_value.SetFromMemoryData(
826 *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
828 return error.Success();
829}
830
832 const RegisterValue &) {
833 return false;
834}
835
837 lldb::RegisterKind kind, uint32_t num) {
838 for (size_t i = 0; i < k_num_regs; ++i) {
839 if (g_reg_infos[i].kinds[kind] == num)
840 return i;
841 }
842 return LLDB_INVALID_REGNUM;
843}
static llvm::raw_ostream & error(Stream &strm)
#define DEF_X_ARG(i, n)
#define OFFSET(r)
constexpr size_t k_num_reg_infos
constexpr size_t k_num_reg_sets
const uint32_t g_gpr_regnums[]
constexpr size_t k_num_fpu_regs
constexpr size_t k_num_gpr_regs
const uint32_t g_fpu_regnums[]
static RegisterInfo g_reg_infos[]
static RegisterSet g_reg_sets[]
An data extractor class.
virtual const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
RegisterContext(Thread &thread, uint32_t concrete_frame_idx)
uint32_t SetFromMemoryData(const RegisterInfo &reg_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
An error handling class.
Definition Status.h:118
RegisterContextMinidump_ARM64(lldb_private::Thread &thread, const DataExtractor &data)
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override
Convert from a given register numbering scheme to the lldb register numbering scheme.
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
A class that represents a running process on the host machine.
uint64_t offset_t
Definition lldb-types.h:85
@ eEncodingUint
unsigned integer
RegisterKind
Register numbering types.
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
Registers are grouped into register sets.