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
77#define HWCAP_PACA (1 << 30)
81#define HWCAP_GCS (1UL << 32)
85#define HWCAP2_MTE (1 << 18)
89#define HWCAP2_FPMR (1UL << 48)
93#define HWCAP2_POE (1ULL << 63)
104static std::mutex g_register_flags_detector_mutex;
107std::unique_ptr<NativeRegisterContextLinux>
110 switch (target_arch.GetMachine()) {
111 case llvm::Triple::arm:
112 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
114 case llvm::Triple::aarch64: {
119 ioVec.iov_base = &sve_header;
120 ioVec.iov_len =
sizeof(sve_header);
121 unsigned int regset = NT_ARM_SVE;
125 native_thread.
GetID(), ®set,
126 &ioVec,
sizeof(sve_header))
132 ioVec.iov_len =
sizeof(sve_header);
133 regset = NT_ARM_SSVE;
135 native_thread.
GetID(), ®set,
136 &ioVec,
sizeof(sve_header))
141 ioVec.iov_base = &za_header;
142 ioVec.iov_len =
sizeof(za_header);
145 native_thread.
GetID(), ®set,
146 &ioVec,
sizeof(za_header))
151 std::array<uint8_t, 64> zt_reg;
152 ioVec.iov_base = zt_reg.data();
153 ioVec.iov_len = zt_reg.size();
156 native_thread.
GetID(), ®set,
157 &ioVec, zt_reg.size())
163 std::optional<uint64_t> auxv_at_hwcap =
165 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
168 std::optional<uint64_t> auxv_at_hwcap2 =
170 if (auxv_at_hwcap2) {
183 std::optional<uint64_t> auxv_at_hwcap3 =
185 std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
187 g_register_flags_detector.
DetectFields(auxv_at_hwcap.value_or(0),
188 auxv_at_hwcap2.value_or(0),
189 auxv_at_hwcap3.value_or(0));
191 auto register_info_up =
192 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
193 return std::make_unique<NativeRegisterContextLinux_arm64>(
194 target_arch, native_thread, std::move(register_info_up));
197 llvm_unreachable(
"have no register context for architecture");
201llvm::Expected<ArchSpec>
203 return DetermineArchitectureViaGPR(
207NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
209 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
211 register_info_up.release()),
214 GetRegisterInfoInterface().GetRegisterInfo(),
215 GetRegisterInfoInterface().GetRegisterCount());
217 ::memset(&m_fpr, 0,
sizeof(m_fpr));
218 ::memset(&m_gpr_arm64, 0,
sizeof(m_gpr_arm64));
219 ::memset(&m_hwp_regs, 0,
sizeof(m_hwp_regs));
220 ::memset(&m_hbp_regs, 0,
sizeof(m_hbp_regs));
221 ::memset(&m_sve_header, 0,
sizeof(m_sve_header));
222 ::memset(&m_pac_mask, 0,
sizeof(m_pac_mask));
223 ::memset(&m_tls_regs, 0,
sizeof(m_tls_regs));
224 ::memset(&m_sme_pseudo_regs, 0,
sizeof(m_sme_pseudo_regs));
225 ::memset(&m_gcs_regs, 0,
sizeof(m_gcs_regs));
226 ::memset(&m_poe_regs, 0,
sizeof(m_poe_regs));
227 std::fill(m_zt_reg.begin(), m_zt_reg.end(), 0);
233 m_max_hwp_supported = 16;
234 m_max_hbp_supported = 16;
236 m_refresh_hwdebug_info =
true;
238 m_gpr_is_valid =
false;
239 m_fpu_is_valid =
false;
240 m_sve_buffer_is_valid =
false;
241 m_sve_header_is_valid =
false;
242 m_pac_mask_is_valid =
false;
243 m_mte_ctrl_is_valid =
false;
244 m_tls_is_valid =
false;
245 m_zt_buffer_is_valid =
false;
246 m_fpmr_is_valid =
false;
247 m_gcs_is_valid =
false;
248 m_poe_is_valid =
false;
251 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
252 : sizeof(m_tls_regs.tpidr_reg);
254 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
261NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
265uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
270NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
271 return GetRegisterInfo().GetRegisterSet(set_index);
274uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
276 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
282NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
295 "no lldb regnum for %s",
296 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
301 std::vector<uint8_t> sve_reg_non_live;
309 assert(offset < GetGPRSize());
310 src = (uint8_t *)GetGPRBuffer() + offset;
312 }
else if (IsFPR(reg)) {
322 offset = CalculateFprOffset(reg_info,
324 assert(offset < GetFPRSize());
325 src = (uint8_t *)GetFPRBuffer() + offset;
330 error = ReadAllSVE();
339 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
345 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
356 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
359 assert(offset < GetSVEBufferSize());
360 src = (uint8_t *)GetSVEBuffer() + offset;
362 }
else if (IsTLS(reg)) {
367 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
368 assert(offset < GetTLSBufferSize());
369 src = (uint8_t *)GetTLSBuffer() + offset;
370 }
else if (IsSVE(reg)) {
374 if (GetRegisterInfo().IsSVERegVG(reg)) {
375 error = ReadSVEHeader();
379 sve_vg = GetSVERegVG();
380 src = (uint8_t *)&sve_vg;
386 if (GetRegisterInfo().IsSVEPReg(reg) ||
387 GetRegisterInfo().IsSVERegFFR(reg)) {
388 std::vector<uint8_t> fake_reg(reg_info->
byte_size, 0);
411 const uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
413 assert(offset < GetFPRSize());
414 src = (uint8_t *)GetFPRBuffer() + offset;
417 std::vector<uint8_t> fake_z(reg_info->
byte_size, 0);
418 std::memcpy(&fake_z[0], src, 16 );
425 error = ReadAllSVE();
433 sve_reg_non_live.resize(reg_info->
byte_size, 0);
434 src = sve_reg_non_live.data();
436 if (GetRegisterInfo().IsSVEZReg(reg)) {
437 offset = CalculateSVEOffset(reg_info);
438 assert(offset < GetSVEBufferSize());
439 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
443 offset = CalculateSVEOffset(reg_info);
444 assert(offset < GetSVEBufferSize());
445 src = (uint8_t *)GetSVEBuffer() + offset;
448 }
else if (IsPAuth(reg)) {
449 error = ReadPAuthMask();
453 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
454 assert(offset < GetPACMaskSize());
455 src = (uint8_t *)GetPACMask() + offset;
456 }
else if (IsMTE(reg)) {
457 error = ReadMTEControl();
461 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
462 assert(offset < GetMTEControlSize());
463 src = (uint8_t *)GetMTEControl() + offset;
464 }
else if (IsSME(reg)) {
465 if (GetRegisterInfo().IsSMERegZA(reg)) {
466 error = ReadZAHeader();
472 if (m_za_header.size ==
sizeof(m_za_header)) {
476 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
478 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
489 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
490 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
498 src = (uint8_t *)GetZTBuffer();
500 error = ReadSMESVG();
507 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
508 assert(offset < GetSMEPseudoBufferSize());
509 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
511 }
else if (IsFPMR(reg)) {
516 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
517 assert(offset < GetFPMRBufferSize());
518 src = (uint8_t *)GetFPMRBuffer() + offset;
519 }
else if (IsGCS(reg)) {
524 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
525 assert(offset < GetGCSBufferSize());
526 src = (uint8_t *)GetGCSBuffer() + offset;
527 }
else if (IsPOE(reg)) {
532 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
533 assert(offset < GetPOEBufferSize());
534 src = (uint8_t *)GetPOEBuffer() + offset;
537 "failed - register wasn't recognized to be a GPR or an FPR, "
538 "write strategy unknown");
546Status NativeRegisterContextLinux_arm64::WriteRegister(
557 "no lldb regnum for %s",
558 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
562 std::vector<uint8_t> sve_reg_non_live;
570 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
574 }
else if (IsFPR(reg)) {
584 offset = CalculateFprOffset(reg_info,
586 assert(offset < GetFPRSize());
587 dst = (uint8_t *)GetFPRBuffer() + offset;
593 error = ReadAllSVE();
602 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
608 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
619 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
622 assert(offset < GetSVEBufferSize());
623 dst = (uint8_t *)GetSVEBuffer() + offset;
625 return WriteAllSVE();
627 }
else if (IsSVE(reg)) {
646 if (GetRegisterInfo().IsSVERegVG(reg) ||
647 GetRegisterInfo().IsSVEPReg(reg) ||
648 GetRegisterInfo().IsSVERegFFR(reg))
650 "Cannot write SVE VG, P or FFR registers while outside of "
662 uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
664 assert(offset < GetFPRSize());
665 dst = (uint8_t *)GetFPRBuffer() + offset;
668 ::memcpy(dst, reg_value.
GetBytes(), 16);
673 error = ReadAllSVE();
677 if (GetRegisterInfo().IsSVERegVG(reg)) {
681 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
684 SetSVERegVG(vg_value);
686 error = WriteSVEHeader();
687 if (
error.Success()) {
690 m_za_header_is_valid =
false;
691 ConfigureRegisterContext();
694 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
705 bool set_sve_state_full =
false;
706 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
707 if (GetRegisterInfo().IsSVEZReg(reg)) {
708 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
710 set_sve_state_full =
true;
714 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
715 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
716 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
718 set_sve_state_full =
true;
724 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
727 offset = CalculateSVEOffset(reg_info);
728 assert(offset < GetSVEBufferSize());
729 dst = (uint8_t *)GetSVEBuffer() + offset;
730 ::memcpy(dst, reg_value.
GetBytes(), 16);
732 return WriteAllSVE();
735 "SVE state change operation not supported");
737 offset = CalculateSVEOffset(reg_info);
738 assert(offset < GetSVEBufferSize());
739 dst = (uint8_t *)GetSVEBuffer() + offset;
741 return WriteAllSVE();
744 }
else if (IsMTE(reg)) {
745 error = ReadMTEControl();
749 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
750 assert(offset < GetMTEControlSize());
751 dst = (uint8_t *)GetMTEControl() + offset;
754 return WriteMTEControl();
755 }
else if (IsTLS(reg)) {
760 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
761 assert(offset < GetTLSBufferSize());
762 dst = (uint8_t *)GetTLSBuffer() + offset;
766 }
else if (IsSME(reg)) {
767 if (GetRegisterInfo().IsSMERegZA(reg)) {
774 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
781 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
786 dst = (uint8_t *)GetZTBuffer();
792 "Writing to SVG or SVCR is not supported.");
793 }
else if (IsFPMR(reg)) {
798 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
799 assert(offset < GetFPMRBufferSize());
800 dst = (uint8_t *)GetFPMRBuffer() + offset;
804 }
else if (IsGCS(reg)) {
809 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
810 assert(offset < GetGCSBufferSize());
811 dst = (uint8_t *)GetGCSBuffer() + offset;
815 }
else if (IsPOE(reg)) {
820 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
821 assert(offset < GetPOEBufferSize());
822 dst = (uint8_t *)GetPOEBuffer() + offset;
831enum RegisterSetType : uint32_t {
846static uint8_t *AddRegisterSetType(uint8_t *dst,
847 RegisterSetType register_set_type) {
848 *(
reinterpret_cast<uint32_t *
>(dst)) = register_set_type;
849 return dst +
sizeof(uint32_t);
852static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
853 ::memcpy(dst, src, size);
857static uint8_t *AddSavedRegisters(uint8_t *dst,
858 enum RegisterSetType register_set_type,
859 void *src,
size_t size) {
860 dst = AddRegisterSetType(dst, register_set_type);
861 return AddSavedRegistersData(dst, src, size);
865NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
867 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
872 if (GetRegisterInfo().IsZAPresent()) {
873 error = ReadZAHeader();
880 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
883 m_za_buffer_is_valid =
false;
892 GetRegisterInfo().IsZTPresent() &&
894 m_za_header.size >
sizeof(m_za_header)) {
895 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
907 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
911 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
912 error = ReadAllSVE();
914 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
920 if (GetRegisterInfo().IsMTEPresent()) {
921 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
922 error = ReadMTEControl();
927 if (GetRegisterInfo().IsFPMRPresent()) {
928 cached_size +=
sizeof(RegisterSetType) + GetFPMRBufferSize();
934 if (GetRegisterInfo().IsGCSPresent()) {
935 cached_size +=
sizeof(RegisterSetType) + GetGCSBufferSize();
941 if (GetRegisterInfo().IsPOEPresent()) {
942 cached_size +=
sizeof(RegisterSetType) + GetPOEBufferSize();
949 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
955Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
967 uint32_t reg_data_byte_size = 0;
968 Status error = CacheAllRegisters(reg_data_byte_size);
973 uint8_t *dst = data_sp->GetBytes();
975 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
1012 assert(m_za_header.size <= GetZABufferSize());
1013 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
1017 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
1019 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
1020 *(
reinterpret_cast<SVEState *
>(dst)) = m_sve_state;
1021 dst +=
sizeof(m_sve_state);
1022 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
1024 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
1029 assert(m_za_header.size <= GetZABufferSize());
1030 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
1041 GetRegisterInfo().IsZTPresent() &&
1043 m_za_header.size >
sizeof(m_za_header))
1044 dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
1047 if (GetRegisterInfo().IsMTEPresent()) {
1048 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
1049 GetMTEControlSize());
1052 if (GetRegisterInfo().IsFPMRPresent()) {
1053 dst = AddSavedRegisters(dst, RegisterSetType::FPMR, GetFPMRBuffer(),
1054 GetFPMRBufferSize());
1057 if (GetRegisterInfo().IsGCSPresent()) {
1058 dst = AddSavedRegisters(dst, RegisterSetType::GCS, GetGCSBuffer(),
1059 GetGCSBufferSize());
1062 if (GetRegisterInfo().IsPOEPresent()) {
1063 dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
1064 GetPOEBufferSize());
1067 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
1068 GetTLSBufferSize());
1073static Status RestoreRegisters(
void *buffer,
const uint8_t **src,
size_t len,
1074 bool &is_valid, std::function<
Status()> writer) {
1075 ::memcpy(buffer, *src, len);
1081Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
1097 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
1102 const uint8_t *src = data_sp->GetBytes();
1103 if (src ==
nullptr) {
1105 "NativeRegisterContextLinux_arm64::%s "
1106 "DataBuffer::GetBytes() returned a null "
1112 uint64_t reg_data_min_size =
1113 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
1114 if (data_sp->GetByteSize() < reg_data_min_size) {
1116 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
1117 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
1118 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
1122 const uint8_t *end = src + data_sp->GetByteSize();
1124 const RegisterSetType kind =
1125 *
reinterpret_cast<const RegisterSetType *
>(src);
1126 src +=
sizeof(RegisterSetType);
1129 case RegisterSetType::GPR:
1130 error = RestoreRegisters(
1131 GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
1132 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
1134 case RegisterSetType::SVE:
1136 m_sve_state =
static_cast<SVEState>(*src);
1137 src +=
sizeof(m_sve_state);
1141 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
1143 m_sve_header_is_valid =
false;
1145 "NativeRegisterContextLinux_arm64::%s "
1146 "Invalid SVE header in data_sp",
1150 m_sve_header_is_valid =
true;
1151 error = WriteSVEHeader();
1158 ConfigureRegisterContext();
1161 error = RestoreRegisters(
1162 GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
1163 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
1165 case RegisterSetType::FPR: {
1166 if (!GetRegisterInfo().IsSVEPresent() &&
1167 GetRegisterInfo().IsSSVEPresent()) {
1180 std::vector<uint8_t> sve_fpsimd_data(data_size);
1185 header->
size = sve_fpsimd_data.size();
1193 ioVec.iov_base = sve_fpsimd_data.data();
1194 ioVec.iov_len = sve_fpsimd_data.size();
1198 error = WriteRegisterSet(&ioVec, sve_fpsimd_data.size(), NT_ARM_SVE);
1201 m_fpu_is_valid =
false;
1202 m_sve_buffer_is_valid =
false;
1203 m_sve_header_is_valid =
false;
1206 ConfigureRegisterContext();
1209 src += GetFPRSize();
1211 error = RestoreRegisters(
1212 GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
1213 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
1217 case RegisterSetType::MTE:
1218 error = RestoreRegisters(
1219 GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
1220 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
1222 case RegisterSetType::TLS:
1223 error = RestoreRegisters(
1224 GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
1225 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
1227 case RegisterSetType::SME:
1233 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
1237 m_za_ptrace_payload.resize(m_za_header.size);
1238 ::memcpy(GetZABuffer(), src, GetZABufferSize());
1239 m_za_buffer_is_valid =
true;
1247 ConfigureRegisterContext();
1252 src += GetZABufferSize();
1254 case RegisterSetType::SME2:
1258 error = RestoreRegisters(
1259 GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
1260 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
1262 case RegisterSetType::FPMR:
1263 error = RestoreRegisters(
1264 GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
1265 std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR,
this));
1267 case RegisterSetType::GCS: {
1272 m_gcs_is_valid =
false;
1277 uint64_t enable_bit = m_gcs_regs.features_enabled & 1UL;
1278 gcs_regs new_gcs_regs = *
reinterpret_cast<const gcs_regs *
>(src);
1279 new_gcs_regs.features_enabled =
1280 (new_gcs_regs.features_enabled & ~1UL) | enable_bit;
1282 const uint8_t *new_gcs_src =
1283 reinterpret_cast<const uint8_t *
>(&new_gcs_regs);
1284 error = RestoreRegisters(
1285 GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), m_gcs_is_valid,
1286 std::bind(&NativeRegisterContextLinux_arm64::WriteGCS,
this));
1287 src += GetGCSBufferSize();
1291 case RegisterSetType::POE:
1292 error = RestoreRegisters(
1293 GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
1294 std::bind(&NativeRegisterContextLinux_arm64::WritePOE,
this));
1305bool NativeRegisterContextLinux_arm64::IsGPR(
unsigned reg)
const {
1306 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
1312bool NativeRegisterContextLinux_arm64::IsFPR(
unsigned reg)
const {
1313 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
1319bool NativeRegisterContextLinux_arm64::IsSVE(
unsigned reg)
const {
1320 return GetRegisterInfo().IsSVEReg(reg);
1323bool NativeRegisterContextLinux_arm64::IsSME(
unsigned reg)
const {
1324 return GetRegisterInfo().IsSMEReg(reg);
1327bool NativeRegisterContextLinux_arm64::IsPAuth(
unsigned reg)
const {
1328 return GetRegisterInfo().IsPAuthReg(reg);
1331bool NativeRegisterContextLinux_arm64::IsMTE(
unsigned reg)
const {
1332 return GetRegisterInfo().IsMTEReg(reg);
1335bool NativeRegisterContextLinux_arm64::IsTLS(
unsigned reg)
const {
1336 return GetRegisterInfo().IsTLSReg(reg);
1339bool NativeRegisterContextLinux_arm64::IsFPMR(
unsigned reg)
const {
1340 return GetRegisterInfo().IsFPMRReg(reg);
1343bool NativeRegisterContextLinux_arm64::IsGCS(
unsigned reg)
const {
1344 return GetRegisterInfo().IsGCSReg(reg);
1347bool NativeRegisterContextLinux_arm64::IsPOE(
unsigned reg)
const {
1348 return GetRegisterInfo().IsPOEReg(reg);
1351llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1352 if (!m_refresh_hwdebug_info) {
1353 return llvm::Error::success();
1356 ::pid_t tid = m_thread.GetID();
1359 m_max_hbp_supported);
1361 return error.ToError();
1363 m_refresh_hwdebug_info =
false;
1365 return llvm::Error::success();
1369NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1370 uint32_t max_supported =
1371 (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
1372 auto ®s = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
1378Status NativeRegisterContextLinux_arm64::ReadGPR() {
1385 ioVec.iov_base = GetGPRBuffer();
1386 ioVec.iov_len = GetGPRBufferSize();
1388 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1390 if (
error.Success())
1391 m_gpr_is_valid =
true;
1396Status NativeRegisterContextLinux_arm64::WriteGPR() {
1402 ioVec.iov_base = GetGPRBuffer();
1403 ioVec.iov_len = GetGPRBufferSize();
1405 m_gpr_is_valid =
false;
1407 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1410Status NativeRegisterContextLinux_arm64::ReadFPR() {
1417 ioVec.iov_base = GetFPRBuffer();
1418 ioVec.iov_len = GetFPRSize();
1420 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1421 if (
error.Success())
1422 m_fpu_is_valid =
true;
1427Status NativeRegisterContextLinux_arm64::WriteFPR() {
1433 ioVec.iov_base = GetFPRBuffer();
1434 ioVec.iov_len = GetFPRSize();
1436 m_fpu_is_valid =
false;
1438 m_sve_buffer_is_valid =
false;
1439 m_sve_header_is_valid =
false;
1441 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1444void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1445 m_gpr_is_valid =
false;
1446 m_fpu_is_valid =
false;
1447 m_sve_buffer_is_valid =
false;
1448 m_sve_header_is_valid =
false;
1449 m_za_buffer_is_valid =
false;
1450 m_za_header_is_valid =
false;
1451 m_pac_mask_is_valid =
false;
1452 m_mte_ctrl_is_valid =
false;
1453 m_tls_is_valid =
false;
1454 m_zt_buffer_is_valid =
false;
1455 m_fpmr_is_valid =
false;
1456 m_gcs_is_valid =
false;
1457 m_poe_is_valid =
false;
1460 ConfigureRegisterContext();
1463unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1464 switch (m_sve_state) {
1473Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1476 if (m_sve_header_is_valid)
1480 ioVec.iov_base = GetSVEHeader();
1481 ioVec.iov_len = GetSVEHeaderSize();
1483 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1485 if (
error.Success())
1486 m_sve_header_is_valid =
true;
1491Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1494 if (m_pac_mask_is_valid)
1498 ioVec.iov_base = GetPACMask();
1499 ioVec.iov_len = GetPACMaskSize();
1501 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
1503 if (
error.Success())
1504 m_pac_mask_is_valid =
true;
1509Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1512 error = ReadSVEHeader();
1517 ioVec.iov_base = GetSVEHeader();
1518 ioVec.iov_len = GetSVEHeaderSize();
1520 m_sve_buffer_is_valid =
false;
1521 m_sve_header_is_valid =
false;
1522 m_fpu_is_valid =
false;
1524 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1527Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1529 if (m_sve_buffer_is_valid)
1533 ioVec.iov_base = GetSVEBuffer();
1534 ioVec.iov_len = GetSVEBufferSize();
1536 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1538 if (
error.Success())
1539 m_sve_buffer_is_valid =
true;
1544Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1547 error = ReadAllSVE();
1553 ioVec.iov_base = GetSVEBuffer();
1554 ioVec.iov_len = GetSVEBufferSize();
1556 m_sve_buffer_is_valid =
false;
1557 m_sve_header_is_valid =
false;
1558 m_fpu_is_valid =
false;
1560 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1563Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1575 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1576 m_sme_pseudo_regs.ctrl_reg |= 2;
1581Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1584 if (m_mte_ctrl_is_valid)
1588 ioVec.iov_base = GetMTEControl();
1589 ioVec.iov_len = GetMTEControlSize();
1591 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1593 if (
error.Success())
1594 m_mte_ctrl_is_valid =
true;
1599Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1602 error = ReadMTEControl();
1607 ioVec.iov_base = GetMTEControl();
1608 ioVec.iov_len = GetMTEControlSize();
1610 m_mte_ctrl_is_valid =
false;
1612 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1615Status NativeRegisterContextLinux_arm64::ReadTLS() {
1622 ioVec.iov_base = GetTLSBuffer();
1623 ioVec.iov_len = GetTLSBufferSize();
1625 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1627 if (
error.Success())
1628 m_tls_is_valid =
true;
1633Status NativeRegisterContextLinux_arm64::WriteTLS() {
1641 ioVec.iov_base = GetTLSBuffer();
1642 ioVec.iov_len = GetTLSBufferSize();
1644 m_tls_is_valid =
false;
1646 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1649Status NativeRegisterContextLinux_arm64::ReadGCS() {
1656 ioVec.iov_base = GetGCSBuffer();
1657 ioVec.iov_len = GetGCSBufferSize();
1659 error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1661 if (
error.Success())
1662 m_gcs_is_valid =
true;
1667Status NativeRegisterContextLinux_arm64::WriteGCS() {
1675 ioVec.iov_base = GetGCSBuffer();
1676 ioVec.iov_len = GetGCSBufferSize();
1678 m_gcs_is_valid =
false;
1680 return WriteRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1683Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1686 if (m_za_header_is_valid)
1690 ioVec.iov_base = GetZAHeader();
1691 ioVec.iov_len = GetZAHeaderSize();
1693 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), NT_ARM_ZA);
1695 if (
error.Success())
1696 m_za_header_is_valid =
true;
1701Status NativeRegisterContextLinux_arm64::ReadZA() {
1704 if (m_za_buffer_is_valid)
1708 ioVec.iov_base = GetZABuffer();
1709 ioVec.iov_len = GetZABufferSize();
1711 error = ReadRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1713 if (
error.Success())
1714 m_za_buffer_is_valid =
true;
1719Status NativeRegisterContextLinux_arm64::WriteZA() {
1730 ioVec.iov_base = GetZABuffer();
1731 ioVec.iov_len = GetZABufferSize();
1733 m_za_buffer_is_valid =
false;
1734 m_za_header_is_valid =
false;
1736 m_zt_buffer_is_valid =
false;
1738 return WriteRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1741Status NativeRegisterContextLinux_arm64::ReadZT() {
1744 if (m_zt_buffer_is_valid)
1748 ioVec.iov_base = GetZTBuffer();
1749 ioVec.iov_len = GetZTBufferSize();
1751 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1752 m_zt_buffer_is_valid =
error.Success();
1757Status NativeRegisterContextLinux_arm64::WriteZT() {
1765 ioVec.iov_base = GetZTBuffer();
1766 ioVec.iov_len = GetZTBufferSize();
1768 m_zt_buffer_is_valid =
false;
1771 m_za_buffer_is_valid =
false;
1772 m_za_header_is_valid =
false;
1774 return WriteRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1777Status NativeRegisterContextLinux_arm64::ReadFPMR() {
1780 if (m_fpmr_is_valid)
1784 ioVec.iov_base = GetFPMRBuffer();
1785 ioVec.iov_len = GetFPMRBufferSize();
1787 error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1789 if (
error.Success())
1790 m_fpmr_is_valid =
true;
1795Status NativeRegisterContextLinux_arm64::WriteFPMR() {
1803 ioVec.iov_base = GetFPMRBuffer();
1804 ioVec.iov_len = GetFPMRBufferSize();
1806 m_fpmr_is_valid =
false;
1808 return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1811Status NativeRegisterContextLinux_arm64::ReadPOE() {
1818 ioVec.iov_base = GetPOEBuffer();
1819 ioVec.iov_len = GetPOEBufferSize();
1821 error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1823 if (
error.Success())
1824 m_poe_is_valid =
true;
1829Status NativeRegisterContextLinux_arm64::WritePOE() {
1837 ioVec.iov_base = GetPOEBuffer();
1838 ioVec.iov_len = GetPOEBufferSize();
1840 m_poe_is_valid =
false;
1842 return WriteRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1845void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1857 m_sve_header_is_valid =
false;
1858 m_sve_buffer_is_valid =
false;
1862 bool has_sme =
error.Success();
1863 bool sme_is_active =
1868 m_sve_header_is_valid =
false;
1869 m_sve_buffer_is_valid =
false;
1871 error = ReadSVEHeader();
1873 bool has_sve =
error.Success();
1874 bool sve_is_active =
1885 else if (sve_is_active)
1887 else if (fp_is_active)
1899 m_sve_header_is_valid =
false;
1900 m_sve_buffer_is_valid =
false;
1901 error = ReadSVEHeader();
1909 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1914 if (!m_za_header_is_valid) {
1916 if (
error.Success()) {
1921 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1922 m_za_ptrace_payload.resize(m_za_header.size);
1923 m_za_buffer_is_valid =
false;
1928uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1929 const RegisterInfo *reg_info,
bool streaming_fpsimd)
const {
1930 uint32_t offset = reg_info->
byte_offset - GetGPRSize();
1931 if (!streaming_fpsimd)
1943 const size_t fpsr_offset = 16 * 32;
1945 if (reg == GetRegisterInfo().GetRegNumFPSR())
1946 offset = fpsr_offset;
1947 else if (reg == GetRegisterInfo().GetRegNumFPCR())
1948 offset = fpsr_offset + 4;
1950 offset = 16 * (reg - GetRegisterInfo().GetRegNumFPV0());
1955uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1962 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1966 uint32_t sve_z0_offset = GetGPRSize() + 16;
1970 return sve_reg_offset;
1973Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1977 if (
error.Success())
1978 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1983std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1985 std::vector<uint32_t> expedited_reg_nums =
1989 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1992 if (GetRegisterInfo().IsSSVEPresent())
1993 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1995 return expedited_reg_nums;
1998llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1999NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
2001 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
2005 return llvm::createStringError(llvm::inconvertibleErrorCode(),
2006 "Unknown AArch64 memory tag type %d", type);
2009lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
2017 if (ReadPAuthMask().
Success())
2018 mask |= m_pac_mask.data_mask;
2020 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()
size_t GetRegisterSetCount() const override
@ eVectorQuadwordAArch64SVE
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.