9#if defined(__arm64__) || defined(__aarch64__)
39#define NT_ARM_SVE 0x405
48#define NT_ARM_ZA 0x40c
56#ifndef NT_ARM_PAC_MASK
57#define NT_ARM_PAC_MASK 0x406
60#ifndef NT_ARM_TAGGED_ADDR_CTRL
61#define NT_ARM_TAGGED_ADDR_CTRL 0x409
65#define NT_ARM_FPMR 0x40e
69#define NT_ARM_POE 0x40f
73#define NT_ARM_GCS 0x410
76#define HWCAP_PACA (1 << 30)
78#define HWCAP_GCS (1UL << 32)
80#define HWCAP2_MTE (1 << 18)
82#define HWCAP2_FPMR (1UL << 48)
84#define HWCAP2_POE (1ULL << 63)
94static std::mutex g_register_flags_detector_mutex;
97std::unique_ptr<NativeRegisterContextLinux>
100 switch (target_arch.GetMachine()) {
101 case llvm::Triple::arm:
102 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
104 case llvm::Triple::aarch64: {
109 ioVec.iov_base = &sve_header;
110 ioVec.iov_len =
sizeof(sve_header);
111 unsigned int regset = NT_ARM_SVE;
115 native_thread.
GetID(), ®set,
116 &ioVec,
sizeof(sve_header))
122 ioVec.iov_len =
sizeof(sve_header);
123 regset = NT_ARM_SSVE;
125 native_thread.
GetID(), ®set,
126 &ioVec,
sizeof(sve_header))
132 ioVec.iov_base = &za_header;
133 ioVec.iov_len =
sizeof(za_header);
136 native_thread.
GetID(), ®set,
137 &ioVec,
sizeof(za_header))
142 std::array<uint8_t, 64> zt_reg;
143 ioVec.iov_base = zt_reg.data();
144 ioVec.iov_len = zt_reg.size();
147 native_thread.
GetID(), ®set,
148 &ioVec, zt_reg.size())
154 std::optional<uint64_t> auxv_at_hwcap =
156 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
159 std::optional<uint64_t> auxv_at_hwcap2 =
161 if (auxv_at_hwcap2) {
174 std::optional<uint64_t> auxv_at_hwcap3 =
176 std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
178 g_register_flags_detector.
DetectFields(auxv_at_hwcap.value_or(0),
179 auxv_at_hwcap2.value_or(0),
180 auxv_at_hwcap3.value_or(0));
182 auto register_info_up =
183 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
184 return std::make_unique<NativeRegisterContextLinux_arm64>(
185 target_arch, native_thread, std::move(register_info_up));
188 llvm_unreachable(
"have no register context for architecture");
192llvm::Expected<ArchSpec>
194 return DetermineArchitectureViaGPR(
198NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
200 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
202 register_info_up.release()),
205 GetRegisterInfoInterface().GetRegisterInfo(),
206 GetRegisterInfoInterface().GetRegisterCount());
208 ::memset(&m_fpr, 0,
sizeof(m_fpr));
209 ::memset(&m_gpr_arm64, 0,
sizeof(m_gpr_arm64));
210 ::memset(&m_hwp_regs, 0,
sizeof(m_hwp_regs));
211 ::memset(&m_hbp_regs, 0,
sizeof(m_hbp_regs));
212 ::memset(&m_sve_header, 0,
sizeof(m_sve_header));
213 ::memset(&m_pac_mask, 0,
sizeof(m_pac_mask));
214 ::memset(&m_tls_regs, 0,
sizeof(m_tls_regs));
215 ::memset(&m_sme_pseudo_regs, 0,
sizeof(m_sme_pseudo_regs));
216 ::memset(&m_gcs_regs, 0,
sizeof(m_gcs_regs));
217 ::memset(&m_poe_regs, 0,
sizeof(m_poe_regs));
218 std::fill(m_zt_reg.begin(), m_zt_reg.end(), 0);
224 m_max_hwp_supported = 16;
225 m_max_hbp_supported = 16;
227 m_refresh_hwdebug_info =
true;
229 m_gpr_is_valid =
false;
230 m_fpu_is_valid =
false;
231 m_sve_buffer_is_valid =
false;
232 m_sve_header_is_valid =
false;
233 m_pac_mask_is_valid =
false;
234 m_mte_ctrl_is_valid =
false;
235 m_tls_is_valid =
false;
236 m_zt_buffer_is_valid =
false;
237 m_fpmr_is_valid =
false;
238 m_gcs_is_valid =
false;
239 m_poe_is_valid =
false;
242 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
243 : sizeof(m_tls_regs.tpidr_reg);
245 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
252NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
256uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
261NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
262 return GetRegisterInfo().GetRegisterSet(set_index);
265uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
267 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
273NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
286 "no lldb regnum for %s",
287 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
292 std::vector<uint8_t> sve_reg_non_live;
300 assert(offset < GetGPRSize());
301 src = (uint8_t *)GetGPRBuffer() + offset;
303 }
else if (IsFPR(reg)) {
310 offset = CalculateFprOffset(reg_info);
311 assert(offset < GetFPRSize());
312 src = (uint8_t *)GetFPRBuffer() + offset;
317 error = ReadAllSVE();
326 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
332 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
343 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
346 assert(offset < GetSVEBufferSize());
347 src = (uint8_t *)GetSVEBuffer() + offset;
349 }
else if (IsTLS(reg)) {
354 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
355 assert(offset < GetTLSBufferSize());
356 src = (uint8_t *)GetTLSBuffer() + offset;
357 }
else if (IsSVE(reg)) {
361 if (GetRegisterInfo().IsSVERegVG(reg)) {
362 sve_vg = GetSVERegVG();
363 src = (uint8_t *)&sve_vg;
366 error = ReadAllSVE();
374 sve_reg_non_live.resize(reg_info->
byte_size, 0);
375 src = sve_reg_non_live.data();
377 if (GetRegisterInfo().IsSVEZReg(reg)) {
378 offset = CalculateSVEOffset(reg_info);
379 assert(offset < GetSVEBufferSize());
380 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
384 offset = CalculateSVEOffset(reg_info);
385 assert(offset < GetSVEBufferSize());
386 src = (uint8_t *)GetSVEBuffer() + offset;
389 }
else if (IsPAuth(reg)) {
390 error = ReadPAuthMask();
394 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
395 assert(offset < GetPACMaskSize());
396 src = (uint8_t *)GetPACMask() + offset;
397 }
else if (IsMTE(reg)) {
398 error = ReadMTEControl();
402 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
403 assert(offset < GetMTEControlSize());
404 src = (uint8_t *)GetMTEControl() + offset;
405 }
else if (IsSME(reg)) {
406 if (GetRegisterInfo().IsSMERegZA(reg)) {
407 error = ReadZAHeader();
413 if (m_za_header.size ==
sizeof(m_za_header)) {
417 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
419 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
430 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
431 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
439 src = (uint8_t *)GetZTBuffer();
441 error = ReadSMESVG();
448 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
449 assert(offset < GetSMEPseudoBufferSize());
450 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
452 }
else if (IsFPMR(reg)) {
457 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
458 assert(offset < GetFPMRBufferSize());
459 src = (uint8_t *)GetFPMRBuffer() + offset;
460 }
else if (IsGCS(reg)) {
465 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
466 assert(offset < GetGCSBufferSize());
467 src = (uint8_t *)GetGCSBuffer() + offset;
468 }
else if (IsPOE(reg)) {
473 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
474 assert(offset < GetPOEBufferSize());
475 src = (uint8_t *)GetPOEBuffer() + offset;
478 "failed - register wasn't recognized to be a GPR or an FPR, "
479 "write strategy unknown");
487Status NativeRegisterContextLinux_arm64::WriteRegister(
498 "no lldb regnum for %s",
499 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
503 std::vector<uint8_t> sve_reg_non_live;
511 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
515 }
else if (IsFPR(reg)) {
522 offset = CalculateFprOffset(reg_info);
523 assert(offset < GetFPRSize());
524 dst = (uint8_t *)GetFPRBuffer() + offset;
530 error = ReadAllSVE();
539 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
545 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
556 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
559 assert(offset < GetSVEBufferSize());
560 dst = (uint8_t *)GetSVEBuffer() + offset;
562 return WriteAllSVE();
564 }
else if (IsSVE(reg)) {
569 error = ReadAllSVE();
573 if (GetRegisterInfo().IsSVERegVG(reg)) {
577 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
580 SetSVERegVG(vg_value);
582 error = WriteSVEHeader();
583 if (
error.Success()) {
586 m_za_header_is_valid =
false;
587 ConfigureRegisterContext();
590 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
601 bool set_sve_state_full =
false;
602 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
603 if (GetRegisterInfo().IsSVEZReg(reg)) {
604 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
606 set_sve_state_full =
true;
610 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
611 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
612 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
614 set_sve_state_full =
true;
620 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
623 offset = CalculateSVEOffset(reg_info);
624 assert(offset < GetSVEBufferSize());
625 dst = (uint8_t *)GetSVEBuffer() + offset;
626 ::memcpy(dst, reg_value.
GetBytes(), 16);
628 return WriteAllSVE();
631 "SVE state change operation not supported");
633 offset = CalculateSVEOffset(reg_info);
634 assert(offset < GetSVEBufferSize());
635 dst = (uint8_t *)GetSVEBuffer() + offset;
637 return WriteAllSVE();
640 }
else if (IsMTE(reg)) {
641 error = ReadMTEControl();
645 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
646 assert(offset < GetMTEControlSize());
647 dst = (uint8_t *)GetMTEControl() + offset;
650 return WriteMTEControl();
651 }
else if (IsTLS(reg)) {
656 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
657 assert(offset < GetTLSBufferSize());
658 dst = (uint8_t *)GetTLSBuffer() + offset;
662 }
else if (IsSME(reg)) {
663 if (GetRegisterInfo().IsSMERegZA(reg)) {
670 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
677 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
682 dst = (uint8_t *)GetZTBuffer();
688 "Writing to SVG or SVCR is not supported.");
689 }
else if (IsFPMR(reg)) {
694 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
695 assert(offset < GetFPMRBufferSize());
696 dst = (uint8_t *)GetFPMRBuffer() + offset;
700 }
else if (IsGCS(reg)) {
705 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
706 assert(offset < GetGCSBufferSize());
707 dst = (uint8_t *)GetGCSBuffer() + offset;
711 }
else if (IsPOE(reg)) {
716 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
717 assert(offset < GetPOEBufferSize());
718 dst = (uint8_t *)GetPOEBuffer() + offset;
727enum RegisterSetType : uint32_t {
741static uint8_t *AddRegisterSetType(uint8_t *dst,
742 RegisterSetType register_set_type) {
743 *(
reinterpret_cast<uint32_t *
>(dst)) = register_set_type;
744 return dst +
sizeof(uint32_t);
747static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
748 ::memcpy(dst, src, size);
752static uint8_t *AddSavedRegisters(uint8_t *dst,
753 enum RegisterSetType register_set_type,
754 void *src,
size_t size) {
755 dst = AddRegisterSetType(dst, register_set_type);
756 return AddSavedRegistersData(dst, src, size);
760NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
762 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
767 if (GetRegisterInfo().IsZAPresent()) {
768 error = ReadZAHeader();
775 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
778 m_za_buffer_is_valid =
false;
787 GetRegisterInfo().IsZTPresent() &&
789 m_za_header.size >
sizeof(m_za_header)) {
790 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
800 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) {
803 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
804 error = ReadAllSVE();
806 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
812 if (GetRegisterInfo().IsMTEPresent()) {
813 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
814 error = ReadMTEControl();
819 if (GetRegisterInfo().IsFPMRPresent()) {
820 cached_size +=
sizeof(RegisterSetType) + GetFPMRBufferSize();
826 if (GetRegisterInfo().IsGCSPresent()) {
827 cached_size +=
sizeof(RegisterSetType) + GetGCSBufferSize();
833 if (GetRegisterInfo().IsPOEPresent()) {
834 cached_size +=
sizeof(RegisterSetType) + GetPOEBufferSize();
841 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
847Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
859 uint32_t reg_data_byte_size = 0;
860 Status error = CacheAllRegisters(reg_data_byte_size);
865 uint8_t *dst = data_sp->GetBytes();
867 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
904 assert(m_za_header.size <= GetZABufferSize());
905 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
909 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) {
910 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
911 *(
reinterpret_cast<SVEState *
>(dst)) = m_sve_state;
912 dst +=
sizeof(m_sve_state);
913 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
915 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
920 assert(m_za_header.size <= GetZABufferSize());
921 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
932 GetRegisterInfo().IsZTPresent() &&
934 m_za_header.size >
sizeof(m_za_header))
935 dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
938 if (GetRegisterInfo().IsMTEPresent()) {
939 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
940 GetMTEControlSize());
943 if (GetRegisterInfo().IsFPMRPresent()) {
944 dst = AddSavedRegisters(dst, RegisterSetType::FPMR, GetFPMRBuffer(),
945 GetFPMRBufferSize());
948 if (GetRegisterInfo().IsGCSPresent()) {
949 dst = AddSavedRegisters(dst, RegisterSetType::GCS, GetGCSBuffer(),
953 if (GetRegisterInfo().IsPOEPresent()) {
954 dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
958 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
964static Status RestoreRegisters(
void *buffer,
const uint8_t **src,
size_t len,
965 bool &is_valid, std::function<
Status()> writer) {
966 ::memcpy(buffer, *src, len);
972Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
988 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
993 const uint8_t *src = data_sp->GetBytes();
994 if (src ==
nullptr) {
996 "NativeRegisterContextLinux_arm64::%s "
997 "DataBuffer::GetBytes() returned a null "
1003 uint64_t reg_data_min_size =
1004 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
1005 if (data_sp->GetByteSize() < reg_data_min_size) {
1007 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
1008 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
1009 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
1013 const uint8_t *end = src + data_sp->GetByteSize();
1015 const RegisterSetType kind =
1016 *
reinterpret_cast<const RegisterSetType *
>(src);
1017 src +=
sizeof(RegisterSetType);
1020 case RegisterSetType::GPR:
1021 error = RestoreRegisters(
1022 GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
1023 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
1025 case RegisterSetType::SVE:
1027 m_sve_state =
static_cast<SVEState>(*src);
1028 src +=
sizeof(m_sve_state);
1032 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
1034 m_sve_header_is_valid =
false;
1036 "NativeRegisterContextLinux_arm64::%s "
1037 "Invalid SVE header in data_sp",
1041 m_sve_header_is_valid =
true;
1042 error = WriteSVEHeader();
1049 ConfigureRegisterContext();
1052 error = RestoreRegisters(
1053 GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
1054 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
1056 case RegisterSetType::FPR:
1057 error = RestoreRegisters(
1058 GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
1059 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
1061 case RegisterSetType::MTE:
1062 error = RestoreRegisters(
1063 GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
1064 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
1066 case RegisterSetType::TLS:
1067 error = RestoreRegisters(
1068 GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
1069 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
1071 case RegisterSetType::SME:
1077 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
1081 m_za_ptrace_payload.resize(m_za_header.size);
1082 ::memcpy(GetZABuffer(), src, GetZABufferSize());
1083 m_za_buffer_is_valid =
true;
1091 ConfigureRegisterContext();
1096 src += GetZABufferSize();
1098 case RegisterSetType::SME2:
1102 error = RestoreRegisters(
1103 GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
1104 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
1106 case RegisterSetType::FPMR:
1107 error = RestoreRegisters(
1108 GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
1109 std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR,
this));
1111 case RegisterSetType::GCS: {
1116 m_gcs_is_valid =
false;
1121 uint64_t enable_bit = m_gcs_regs.features_enabled & 1UL;
1122 gcs_regs new_gcs_regs = *
reinterpret_cast<const gcs_regs *
>(src);
1123 new_gcs_regs.features_enabled =
1124 (new_gcs_regs.features_enabled & ~1UL) | enable_bit;
1126 const uint8_t *new_gcs_src =
1127 reinterpret_cast<const uint8_t *
>(&new_gcs_regs);
1128 error = RestoreRegisters(
1129 GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), m_gcs_is_valid,
1130 std::bind(&NativeRegisterContextLinux_arm64::WriteGCS,
this));
1131 src += GetGCSBufferSize();
1135 case RegisterSetType::POE:
1136 error = RestoreRegisters(
1137 GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
1138 std::bind(&NativeRegisterContextLinux_arm64::WritePOE,
this));
1149bool NativeRegisterContextLinux_arm64::IsGPR(
unsigned reg)
const {
1150 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
1156bool NativeRegisterContextLinux_arm64::IsFPR(
unsigned reg)
const {
1157 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
1163bool NativeRegisterContextLinux_arm64::IsSVE(
unsigned reg)
const {
1164 return GetRegisterInfo().IsSVEReg(reg);
1167bool NativeRegisterContextLinux_arm64::IsSME(
unsigned reg)
const {
1168 return GetRegisterInfo().IsSMEReg(reg);
1171bool NativeRegisterContextLinux_arm64::IsPAuth(
unsigned reg)
const {
1172 return GetRegisterInfo().IsPAuthReg(reg);
1175bool NativeRegisterContextLinux_arm64::IsMTE(
unsigned reg)
const {
1176 return GetRegisterInfo().IsMTEReg(reg);
1179bool NativeRegisterContextLinux_arm64::IsTLS(
unsigned reg)
const {
1180 return GetRegisterInfo().IsTLSReg(reg);
1183bool NativeRegisterContextLinux_arm64::IsFPMR(
unsigned reg)
const {
1184 return GetRegisterInfo().IsFPMRReg(reg);
1187bool NativeRegisterContextLinux_arm64::IsGCS(
unsigned reg)
const {
1188 return GetRegisterInfo().IsGCSReg(reg);
1191bool NativeRegisterContextLinux_arm64::IsPOE(
unsigned reg)
const {
1192 return GetRegisterInfo().IsPOEReg(reg);
1195llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1196 if (!m_refresh_hwdebug_info) {
1197 return llvm::Error::success();
1200 ::pid_t tid = m_thread.GetID();
1203 m_max_hbp_supported);
1205 return error.ToError();
1207 m_refresh_hwdebug_info =
false;
1209 return llvm::Error::success();
1213NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1214 uint32_t max_supported =
1215 (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
1216 auto ®s = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
1222Status NativeRegisterContextLinux_arm64::ReadGPR() {
1229 ioVec.iov_base = GetGPRBuffer();
1230 ioVec.iov_len = GetGPRBufferSize();
1232 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1234 if (
error.Success())
1235 m_gpr_is_valid =
true;
1240Status NativeRegisterContextLinux_arm64::WriteGPR() {
1246 ioVec.iov_base = GetGPRBuffer();
1247 ioVec.iov_len = GetGPRBufferSize();
1249 m_gpr_is_valid =
false;
1251 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1254Status NativeRegisterContextLinux_arm64::ReadFPR() {
1261 ioVec.iov_base = GetFPRBuffer();
1262 ioVec.iov_len = GetFPRSize();
1264 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1266 if (
error.Success())
1267 m_fpu_is_valid =
true;
1272Status NativeRegisterContextLinux_arm64::WriteFPR() {
1278 ioVec.iov_base = GetFPRBuffer();
1279 ioVec.iov_len = GetFPRSize();
1281 m_fpu_is_valid =
false;
1283 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1286void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1287 m_gpr_is_valid =
false;
1288 m_fpu_is_valid =
false;
1289 m_sve_buffer_is_valid =
false;
1290 m_sve_header_is_valid =
false;
1291 m_za_buffer_is_valid =
false;
1292 m_za_header_is_valid =
false;
1293 m_pac_mask_is_valid =
false;
1294 m_mte_ctrl_is_valid =
false;
1295 m_tls_is_valid =
false;
1296 m_zt_buffer_is_valid =
false;
1297 m_fpmr_is_valid =
false;
1298 m_gcs_is_valid =
false;
1299 m_poe_is_valid =
false;
1302 ConfigureRegisterContext();
1305unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1309Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1312 if (m_sve_header_is_valid)
1316 ioVec.iov_base = GetSVEHeader();
1317 ioVec.iov_len = GetSVEHeaderSize();
1319 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1321 if (
error.Success())
1322 m_sve_header_is_valid =
true;
1327Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1330 if (m_pac_mask_is_valid)
1334 ioVec.iov_base = GetPACMask();
1335 ioVec.iov_len = GetPACMaskSize();
1337 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
1339 if (
error.Success())
1340 m_pac_mask_is_valid =
true;
1345Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1348 error = ReadSVEHeader();
1353 ioVec.iov_base = GetSVEHeader();
1354 ioVec.iov_len = GetSVEHeaderSize();
1356 m_sve_buffer_is_valid =
false;
1357 m_sve_header_is_valid =
false;
1358 m_fpu_is_valid =
false;
1360 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1363Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1365 if (m_sve_buffer_is_valid)
1369 ioVec.iov_base = GetSVEBuffer();
1370 ioVec.iov_len = GetSVEBufferSize();
1372 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1374 if (
error.Success())
1375 m_sve_buffer_is_valid =
true;
1380Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1383 error = ReadAllSVE();
1389 ioVec.iov_base = GetSVEBuffer();
1390 ioVec.iov_len = GetSVEBufferSize();
1392 m_sve_buffer_is_valid =
false;
1393 m_sve_header_is_valid =
false;
1394 m_fpu_is_valid =
false;
1396 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1399Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1411 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1412 m_sme_pseudo_regs.ctrl_reg |= 2;
1417Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1420 if (m_mte_ctrl_is_valid)
1424 ioVec.iov_base = GetMTEControl();
1425 ioVec.iov_len = GetMTEControlSize();
1427 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1429 if (
error.Success())
1430 m_mte_ctrl_is_valid =
true;
1435Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1438 error = ReadMTEControl();
1443 ioVec.iov_base = GetMTEControl();
1444 ioVec.iov_len = GetMTEControlSize();
1446 m_mte_ctrl_is_valid =
false;
1448 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1451Status NativeRegisterContextLinux_arm64::ReadTLS() {
1458 ioVec.iov_base = GetTLSBuffer();
1459 ioVec.iov_len = GetTLSBufferSize();
1461 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1463 if (
error.Success())
1464 m_tls_is_valid =
true;
1469Status NativeRegisterContextLinux_arm64::WriteTLS() {
1477 ioVec.iov_base = GetTLSBuffer();
1478 ioVec.iov_len = GetTLSBufferSize();
1480 m_tls_is_valid =
false;
1482 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1485Status NativeRegisterContextLinux_arm64::ReadGCS() {
1492 ioVec.iov_base = GetGCSBuffer();
1493 ioVec.iov_len = GetGCSBufferSize();
1495 error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1497 if (
error.Success())
1498 m_gcs_is_valid =
true;
1503Status NativeRegisterContextLinux_arm64::WriteGCS() {
1511 ioVec.iov_base = GetGCSBuffer();
1512 ioVec.iov_len = GetGCSBufferSize();
1514 m_gcs_is_valid =
false;
1516 return WriteRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1519Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1522 if (m_za_header_is_valid)
1526 ioVec.iov_base = GetZAHeader();
1527 ioVec.iov_len = GetZAHeaderSize();
1529 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), NT_ARM_ZA);
1531 if (
error.Success())
1532 m_za_header_is_valid =
true;
1537Status NativeRegisterContextLinux_arm64::ReadZA() {
1540 if (m_za_buffer_is_valid)
1544 ioVec.iov_base = GetZABuffer();
1545 ioVec.iov_len = GetZABufferSize();
1547 error = ReadRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1549 if (
error.Success())
1550 m_za_buffer_is_valid =
true;
1555Status NativeRegisterContextLinux_arm64::WriteZA() {
1566 ioVec.iov_base = GetZABuffer();
1567 ioVec.iov_len = GetZABufferSize();
1569 m_za_buffer_is_valid =
false;
1570 m_za_header_is_valid =
false;
1572 m_zt_buffer_is_valid =
false;
1574 return WriteRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1577Status NativeRegisterContextLinux_arm64::ReadZT() {
1580 if (m_zt_buffer_is_valid)
1584 ioVec.iov_base = GetZTBuffer();
1585 ioVec.iov_len = GetZTBufferSize();
1587 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1588 m_zt_buffer_is_valid =
error.Success();
1593Status NativeRegisterContextLinux_arm64::WriteZT() {
1601 ioVec.iov_base = GetZTBuffer();
1602 ioVec.iov_len = GetZTBufferSize();
1604 m_zt_buffer_is_valid =
false;
1607 m_za_buffer_is_valid =
false;
1608 m_za_header_is_valid =
false;
1610 return WriteRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1613Status NativeRegisterContextLinux_arm64::ReadFPMR() {
1616 if (m_fpmr_is_valid)
1620 ioVec.iov_base = GetFPMRBuffer();
1621 ioVec.iov_len = GetFPMRBufferSize();
1623 error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1625 if (
error.Success())
1626 m_fpmr_is_valid =
true;
1631Status NativeRegisterContextLinux_arm64::WriteFPMR() {
1639 ioVec.iov_base = GetFPMRBuffer();
1640 ioVec.iov_len = GetFPMRBufferSize();
1642 m_fpmr_is_valid =
false;
1644 return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1647Status NativeRegisterContextLinux_arm64::ReadPOE() {
1654 ioVec.iov_base = GetPOEBuffer();
1655 ioVec.iov_len = GetPOEBufferSize();
1657 error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1659 if (
error.Success())
1660 m_poe_is_valid =
true;
1665Status NativeRegisterContextLinux_arm64::WritePOE() {
1673 ioVec.iov_base = GetPOEBuffer();
1674 ioVec.iov_len = GetPOEBufferSize();
1676 m_poe_is_valid =
false;
1678 return WriteRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1681void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1693 m_sve_header_is_valid =
false;
1694 m_sve_buffer_is_valid =
false;
1702 m_sve_header_is_valid =
false;
1703 m_sve_buffer_is_valid =
false;
1705 error = ReadSVEHeader();
1706 if (
error.Success()) {
1726 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1731 if (!m_za_header_is_valid) {
1733 if (
error.Success()) {
1738 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1739 m_za_ptrace_payload.resize(m_za_header.size);
1740 m_za_buffer_is_valid =
false;
1745uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1750uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1757 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1761 uint32_t sve_z0_offset = GetGPRSize() + 16;
1765 return sve_reg_offset;
1768Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1772 if (
error.Success())
1773 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1778std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1780 std::vector<uint32_t> expedited_reg_nums =
1784 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1787 if (GetRegisterInfo().IsSSVEPresent())
1788 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1790 return expedited_reg_nums;
1793llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1794NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
1796 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
1800 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1801 "Unknown AArch64 memory tag type %d", type);
1804lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
1812 if (ReadPAuthMask().
Success())
1813 mask |= m_pac_mask.data_mask;
1815 return hit_addr & ~mask;
static llvm::raw_ostream & error(Stream &strm)
#define PTRACE_PEEKMTETAGS
#define PTRACE_POKEMTETAGS
@ AUXV_AT_HWCAP2
Extension of AT_HWCAP.
@ AUXV_AT_HWCAP3
Extension of AT_HWCAP.
@ AUXV_AT_HWCAP
Machine dependent hints about processor capabilities.
static size_t GetGPRSizeStatic()
@ eVectorQuadwordAArch64SVE
size_t GetRegisterSetCount() const override
This class manages the storage and detection of register field information.
void DetectFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
For the registers listed in this class, detect which fields are present.
void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs)
Add the field information of any registers named in this class, to the relevant RegisterInfo instance...
bool HasDetected() const
Returns true if field detection has been run at least once.
A subclass of DataBuffer that stores a data buffer on the heap.
std::optional< uint64_t > GetAuxValue(enum AuxVector::EntryType type)
virtual std::vector< uint32_t > GetExpeditedRegisters(ExpeditedRegs expType) const
lldb::tid_t GetID() const
uint32_t SetFromMemoryData(const RegisterInfo ®_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
const void * GetBytes() const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
Manages communication with the inferior (debugee) process.
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
}
static std::unique_ptr< NativeRegisterContextLinux > CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, NativeThreadLinux &native_thread)
static llvm::Expected< ArchSpec > DetermineArchitecture(lldb::tid_t tid)
NativeProcessLinux & GetProcess()
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_REGNUM
Status WriteHardwareDebugRegs(int hwbType, ::pid_t tid, uint32_t max_supported, const std::array< NativeRegisterContextDBReg::DREG, 16 > ®s)
Status ReadHardwareDebugInfo(::pid_t tid, uint32_t &max_hwp_supported, uint32_t &max_hbp_supported)
uint16_t vq_from_vl(uint16_t vl)
const uint32_t ptrace_fpsimd_offset
uint32_t PTraceFPSROffset(uint16_t vq)
uint32_t PTraceFPCROffset(uint16_t vq)
const uint16_t ptrace_regs_mask
user_sve_header user_za_header
const uint16_t ptrace_regs_sve
uint16_t vl_valid(uint16_t vl)
const uint16_t ptrace_regs_fpsimd
uint32_t PTraceSize(uint16_t vq, uint16_t flags)
A class that represents a running process on the host machine.
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 * value_regs
List of registers (terminated with LLDB_INVALID_REGNUM).
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.
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.
size_t num_registers
The number of registers in REGISTERS array below.