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