33
33
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
34
34
#endif
35
35
36
+ #ifndef NT_ARM_PAC_MASK
37
+ #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
38
+ #endif
39
+
40
+ #ifndef NT_ARM_TAGGED_ADDR_CTRL
41
+ #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
42
+ #endif
43
+
44
+ #define HWCAP_PACA (1 << 30 )
45
+ #define HWCAP2_MTE (1 << 18 )
46
+
36
47
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
37
48
38
49
using namespace lldb ;
@@ -62,6 +73,18 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
62
73
.Success ())
63
74
opt_regsets.Set (RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
64
75
76
+ NativeProcessLinux &process = native_thread.GetProcess ();
77
+
78
+ llvm::Optional<uint64_t > auxv_at_hwcap =
79
+ process.GetAuxValue (AuxVector::AUXV_AT_HWCAP);
80
+ if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
81
+ opt_regsets.Set (RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
82
+
83
+ llvm::Optional<uint64_t > auxv_at_hwcap2 =
84
+ process.GetAuxValue (AuxVector::AUXV_AT_HWCAP2);
85
+ if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
86
+ opt_regsets.Set (RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
87
+
65
88
auto register_info_up =
66
89
std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
67
90
return std::make_unique<NativeRegisterContextLinux_arm64>(
@@ -83,6 +106,9 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
83
106
::memset (&m_hwp_regs, 0 , sizeof (m_hwp_regs));
84
107
::memset (&m_hbp_regs, 0 , sizeof (m_hbp_regs));
85
108
::memset (&m_sve_header, 0 , sizeof (m_sve_header));
109
+ ::memset (&m_pac_mask, 0 , sizeof (m_pac_mask));
110
+
111
+ m_mte_ctrl_reg = 0 ;
86
112
87
113
// 16 is just a maximum value, query hardware for actual watchpoint count
88
114
m_max_hwp_supported = 16 ;
@@ -94,6 +120,8 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
94
120
m_fpu_is_valid = false ;
95
121
m_sve_buffer_is_valid = false ;
96
122
m_sve_header_is_valid = false ;
123
+ m_pac_mask_is_valid = false ;
124
+ m_mte_ctrl_is_valid = false ;
97
125
98
126
if (GetRegisterInfo ().IsSVEEnabled ())
99
127
m_sve_state = SVEState::Unknown;
@@ -230,6 +258,22 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
230
258
src = (uint8_t *)GetSVEBuffer () + offset;
231
259
}
232
260
}
261
+ } else if (IsPAuth (reg)) {
262
+ error = ReadPAuthMask ();
263
+ if (error.Fail ())
264
+ return error;
265
+
266
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetPAuthOffset ();
267
+ assert (offset < GetPACMaskSize ());
268
+ src = (uint8_t *)GetPACMask () + offset;
269
+ } else if (IsMTE (reg)) {
270
+ error = ReadMTEControl ();
271
+ if (error.Fail ())
272
+ return error;
273
+
274
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetMTEOffset ();
275
+ assert (offset < GetMTEControlSize ());
276
+ src = (uint8_t *)GetMTEControl () + offset;
233
277
} else
234
278
return Status (" failed - register wasn't recognized to be a GPR or an FPR, "
235
279
" write strategy unknown" );
@@ -388,6 +432,17 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
388
432
return WriteAllSVE ();
389
433
}
390
434
}
435
+ } else if (IsMTE (reg)) {
436
+ error = ReadMTEControl ();
437
+ if (error.Fail ())
438
+ return error;
439
+
440
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetMTEOffset ();
441
+ assert (offset < GetMTEControlSize ());
442
+ dst = (uint8_t *)GetMTEControl () + offset;
443
+ ::memcpy (dst, reg_value.GetBytes(), reg_info->byte_size);
444
+
445
+ return WriteMTEControl ();
391
446
}
392
447
393
448
return Status (" Failed to write register value" );
@@ -476,6 +531,14 @@ bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
476
531
return GetRegisterInfo ().IsSVEReg (reg);
477
532
}
478
533
534
+ bool NativeRegisterContextLinux_arm64::IsPAuth (unsigned reg) const {
535
+ return GetRegisterInfo ().IsPAuthReg (reg);
536
+ }
537
+
538
+ bool NativeRegisterContextLinux_arm64::IsMTE (unsigned reg) const {
539
+ return GetRegisterInfo ().IsMTEReg (reg);
540
+ }
541
+
479
542
llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo () {
480
543
if (!m_refresh_hwdebug_info) {
481
544
return llvm::Error::success ();
@@ -617,6 +680,8 @@ void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
617
680
m_fpu_is_valid = false ;
618
681
m_sve_buffer_is_valid = false ;
619
682
m_sve_header_is_valid = false ;
683
+ m_pac_mask_is_valid = false ;
684
+ m_mte_ctrl_is_valid = false ;
620
685
621
686
// Update SVE registers in case there is change in configuration.
622
687
ConfigureRegisterContext ();
@@ -634,7 +699,26 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
634
699
635
700
error = ReadRegisterSet (&ioVec, GetSVEHeaderSize (), NT_ARM_SVE);
636
701
637
- m_sve_header_is_valid = true ;
702
+ if (error.Success ())
703
+ m_sve_header_is_valid = true ;
704
+
705
+ return error;
706
+ }
707
+
708
+ Status NativeRegisterContextLinux_arm64::ReadPAuthMask () {
709
+ Status error;
710
+
711
+ if (m_pac_mask_is_valid)
712
+ return error;
713
+
714
+ struct iovec ioVec;
715
+ ioVec.iov_base = GetPACMask ();
716
+ ioVec.iov_len = GetPACMaskSize ();
717
+
718
+ error = ReadRegisterSet (&ioVec, GetPACMaskSize (), NT_ARM_PAC_MASK);
719
+
720
+ if (error.Success ())
721
+ m_pac_mask_is_valid = true ;
638
722
639
723
return error;
640
724
}
@@ -694,6 +778,40 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
694
778
return WriteRegisterSet (&ioVec, GetSVEBufferSize (), NT_ARM_SVE);
695
779
}
696
780
781
+ Status NativeRegisterContextLinux_arm64::ReadMTEControl () {
782
+ Status error;
783
+
784
+ if (m_mte_ctrl_is_valid)
785
+ return error;
786
+
787
+ struct iovec ioVec;
788
+ ioVec.iov_base = GetMTEControl ();
789
+ ioVec.iov_len = GetMTEControlSize ();
790
+
791
+ error = ReadRegisterSet (&ioVec, GetMTEControlSize (), NT_ARM_TAGGED_ADDR_CTRL);
792
+
793
+ if (error.Success ())
794
+ m_mte_ctrl_is_valid = true ;
795
+
796
+ return error;
797
+ }
798
+
799
+ Status NativeRegisterContextLinux_arm64::WriteMTEControl () {
800
+ Status error;
801
+
802
+ error = ReadMTEControl ();
803
+ if (error.Fail ())
804
+ return error;
805
+
806
+ struct iovec ioVec;
807
+ ioVec.iov_base = GetMTEControl ();
808
+ ioVec.iov_len = GetMTEControlSize ();
809
+
810
+ m_mte_ctrl_is_valid = false ;
811
+
812
+ return WriteRegisterSet (&ioVec, GetMTEControlSize (), NT_ARM_TAGGED_ADDR_CTRL);
813
+ }
814
+
697
815
void NativeRegisterContextLinux_arm64::ConfigureRegisterContext () {
698
816
// ConfigureRegisterContext gets called from InvalidateAllRegisters
699
817
// on every stop and configures SVE vector length.
0 commit comments