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_hwcap && (*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>(
@@ -82,6 +105,9 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
82
105
::memset (&m_hwp_regs, 0 , sizeof (m_hwp_regs));
83
106
::memset (&m_hbp_regs, 0 , sizeof (m_hbp_regs));
84
107
::memset (&m_sve_header, 0 , sizeof (m_sve_header));
108
+ ::memset (&m_pac_mask, 0 , sizeof (m_pac_mask));
109
+
110
+ m_mte_ctrl_reg = 0 ;
85
111
86
112
// 16 is just a maximum value, query hardware for actual watchpoint count
87
113
m_max_hwp_supported = 16 ;
@@ -93,6 +119,8 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
93
119
m_fpu_is_valid = false ;
94
120
m_sve_buffer_is_valid = false ;
95
121
m_sve_header_is_valid = false ;
122
+ m_pac_mask_is_valid = false ;
123
+ m_mte_ctrl_is_valid = false ;
96
124
97
125
if (GetRegisterInfo ().IsSVEEnabled ())
98
126
m_sve_state = SVEState::Unknown;
@@ -229,6 +257,22 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
229
257
src = (uint8_t *)GetSVEBuffer () + offset;
230
258
}
231
259
}
260
+ } else if (IsPAuth (reg)) {
261
+ error = ReadPAuthMask ();
262
+ if (error.Fail ())
263
+ return error;
264
+
265
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetPAuthOffset ();
266
+ assert (offset < GetPACMaskSize ());
267
+ src = (uint8_t *)GetPACMask () + offset;
268
+ } else if (IsMTE (reg)) {
269
+ error = ReadMTEControl ();
270
+ if (error.Fail ())
271
+ return error;
272
+
273
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetMTEOffset ();
274
+ assert (offset < GetMTEControlSize ());
275
+ src = (uint8_t *)GetMTEControl () + offset;
232
276
} else
233
277
return Status (" failed - register wasn't recognized to be a GPR or an FPR, "
234
278
" write strategy unknown" );
@@ -387,6 +431,17 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
387
431
return WriteAllSVE ();
388
432
}
389
433
}
434
+ } else if (IsMTE (reg)) {
435
+ error = ReadMTEControl ();
436
+ if (error.Fail ())
437
+ return error;
438
+
439
+ offset = reg_info->byte_offset - GetRegisterInfo ().GetMTEOffset ();
440
+ assert (offset < GetMTEControlSize ());
441
+ dst = (uint8_t *)GetMTEControl () + offset;
442
+ ::memcpy (dst, reg_value.GetBytes(), reg_info->byte_size);
443
+
444
+ return WriteMTEControl ();
390
445
}
391
446
392
447
return Status (" Failed to write register value" );
@@ -475,6 +530,14 @@ bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
475
530
return GetRegisterInfo ().IsSVEReg (reg);
476
531
}
477
532
533
+ bool NativeRegisterContextLinux_arm64::IsPAuth (unsigned reg) const {
534
+ return GetRegisterInfo ().IsPAuthReg (reg);
535
+ }
536
+
537
+ bool NativeRegisterContextLinux_arm64::IsMTE (unsigned reg) const {
538
+ return GetRegisterInfo ().IsMTEReg (reg);
539
+ }
540
+
478
541
llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo () {
479
542
if (!m_refresh_hwdebug_info) {
480
543
return llvm::Error::success ();
@@ -616,6 +679,8 @@ void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
616
679
m_fpu_is_valid = false ;
617
680
m_sve_buffer_is_valid = false ;
618
681
m_sve_header_is_valid = false ;
682
+ m_pac_mask_is_valid = false ;
683
+ m_mte_ctrl_is_valid = false ;
619
684
620
685
// Update SVE registers in case there is change in configuration.
621
686
ConfigureRegisterContext ();
@@ -633,7 +698,26 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
633
698
634
699
error = ReadRegisterSet (&ioVec, GetSVEHeaderSize (), NT_ARM_SVE);
635
700
636
- m_sve_header_is_valid = true ;
701
+ if (error.Success ())
702
+ m_sve_header_is_valid = true ;
703
+
704
+ return error;
705
+ }
706
+
707
+ Status NativeRegisterContextLinux_arm64::ReadPAuthMask () {
708
+ Status error;
709
+
710
+ if (m_pac_mask_is_valid)
711
+ return error;
712
+
713
+ struct iovec ioVec;
714
+ ioVec.iov_base = GetPACMask ();
715
+ ioVec.iov_len = GetPACMaskSize ();
716
+
717
+ error = ReadRegisterSet (&ioVec, GetPACMaskSize (), NT_ARM_PAC_MASK);
718
+
719
+ if (error.Success ())
720
+ m_pac_mask_is_valid = true ;
637
721
638
722
return error;
639
723
}
@@ -693,6 +777,40 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
693
777
return WriteRegisterSet (&ioVec, GetSVEBufferSize (), NT_ARM_SVE);
694
778
}
695
779
780
+ Status NativeRegisterContextLinux_arm64::ReadMTEControl () {
781
+ Status error;
782
+
783
+ if (m_mte_ctrl_is_valid)
784
+ return error;
785
+
786
+ struct iovec ioVec;
787
+ ioVec.iov_base = GetMTEControl ();
788
+ ioVec.iov_len = GetMTEControlSize ();
789
+
790
+ error = ReadRegisterSet (&ioVec, GetMTEControlSize (), NT_ARM_TAGGED_ADDR_CTRL);
791
+
792
+ if (error.Success ())
793
+ m_mte_ctrl_is_valid = true ;
794
+
795
+ return error;
796
+ }
797
+
798
+ Status NativeRegisterContextLinux_arm64::WriteMTEControl () {
799
+ Status error;
800
+
801
+ error = ReadMTEControl ();
802
+ if (error.Fail ())
803
+ return error;
804
+
805
+ struct iovec ioVec;
806
+ ioVec.iov_base = GetMTEControl ();
807
+ ioVec.iov_len = GetMTEControlSize ();
808
+
809
+ m_mte_ctrl_is_valid = false ;
810
+
811
+ return WriteRegisterSet (&ioVec, GetMTEControlSize (), NT_ARM_TAGGED_ADDR_CTRL);
812
+ }
813
+
696
814
void NativeRegisterContextLinux_arm64::ConfigureRegisterContext () {
697
815
// ConfigureRegisterContext gets called from InvalidateAllRegisters
698
816
// on every stop and configures SVE vector length.
0 commit comments