9#if defined(__arm64__) || defined(__aarch64__)
30#include "llvm/BinaryFormat/ELF.h"
39#define HWCAP_PACA (1 << 30)
43#define HWCAP_GCS (1UL << 32)
47#define HWCAP2_MTE (1 << 18)
51#define HWCAP2_FPMR (1UL << 48)
55#define HWCAP2_POE (1ULL << 63)
66static std::mutex g_register_flags_detector_mutex;
69std::unique_ptr<NativeRegisterContextLinux>
72 switch (target_arch.GetMachine()) {
73 case llvm::Triple::arm:
74 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
76 case llvm::Triple::aarch64: {
81 ioVec.iov_base = &sve_header;
82 ioVec.iov_len =
sizeof(sve_header);
83 unsigned int regset = llvm::ELF::NT_ARM_SVE;
87 native_thread.
GetID(), ®set,
88 &ioVec,
sizeof(sve_header))
94 ioVec.iov_len =
sizeof(sve_header);
95 regset = llvm::ELF::NT_ARM_SSVE;
97 native_thread.
GetID(), ®set,
98 &ioVec,
sizeof(sve_header))
103 ioVec.iov_base = &za_header;
104 ioVec.iov_len =
sizeof(za_header);
105 regset = llvm::ELF::NT_ARM_ZA;
107 native_thread.
GetID(), ®set,
108 &ioVec,
sizeof(za_header))
113 std::array<uint8_t, 64> zt_reg;
114 ioVec.iov_base = zt_reg.data();
115 ioVec.iov_len = zt_reg.size();
116 regset = llvm::ELF::NT_ARM_ZT;
118 native_thread.
GetID(), ®set,
119 &ioVec, zt_reg.size())
125 std::optional<uint64_t> auxv_at_hwcap =
127 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
130 std::optional<uint64_t> auxv_at_hwcap2 =
132 if (auxv_at_hwcap2) {
145 std::optional<uint64_t> auxv_at_hwcap3 =
147 std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
149 g_register_flags_detector.
DetectFields(auxv_at_hwcap.value_or(0),
150 auxv_at_hwcap2.value_or(0),
151 auxv_at_hwcap3.value_or(0));
153 auto register_info_up =
154 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
155 return std::make_unique<NativeRegisterContextLinux_arm64>(
156 target_arch, native_thread, std::move(register_info_up));
159 llvm_unreachable(
"have no register context for architecture");
163llvm::Expected<ArchSpec>
165 return DetermineArchitectureViaGPR(
169NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
171 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
173 register_info_up.release()),
176 GetRegisterInfoInterface().GetRegisterInfo(),
177 GetRegisterInfoInterface().GetRegisterCount());
180 m_max_hwp_supported = 16;
181 m_max_hbp_supported = 16;
183 m_gpr_is_valid =
false;
184 m_fpu_is_valid =
false;
185 m_sve_buffer_is_valid =
false;
186 m_sve_header_is_valid =
false;
187 m_pac_mask_is_valid =
false;
188 m_mte_ctrl_is_valid =
false;
189 m_tls_is_valid =
false;
190 m_zt_buffer_is_valid =
false;
191 m_fpmr_is_valid =
false;
192 m_gcs_is_valid =
false;
193 m_poe_is_valid =
false;
196 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
197 : sizeof(m_tls_regs.tpidr_reg);
199 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
206NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
210uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
215NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
216 return GetRegisterInfo().GetRegisterSet(set_index);
219uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
221 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
227NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
240 "no lldb regnum for %s",
241 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
246 std::vector<uint8_t> sve_reg_non_live;
248 if (GetRegisterInfo().IsGPR(reg)) {
254 assert(offset < GetGPRSize());
255 src = (uint8_t *)GetGPRBuffer() + offset;
257 }
else if (GetRegisterInfo().IsFPR(reg)) {
267 offset = CalculateFprOffset(reg_info,
269 assert(offset < GetFPRSize());
270 src = (uint8_t *)GetFPRBuffer() + offset;
275 error = ReadAllSVE();
284 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
290 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
301 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
304 assert(offset < GetSVEBufferSize());
305 src = (uint8_t *)GetSVEBuffer() + offset;
307 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
312 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
313 assert(offset < GetTLSBufferSize());
314 src = (uint8_t *)GetTLSBuffer() + offset;
315 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
319 if (GetRegisterInfo().IsSVERegVG(reg)) {
320 error = ReadSVEHeader();
324 sve_vg = GetSVERegVG();
325 src = (uint8_t *)&sve_vg;
331 if (GetRegisterInfo().IsSVEPReg(reg) ||
332 GetRegisterInfo().IsSVERegFFR(reg)) {
333 std::vector<uint8_t> fake_reg(reg_info->
byte_size, 0);
356 const uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
358 assert(offset < GetFPRSize());
359 src = (uint8_t *)GetFPRBuffer() + offset;
362 std::vector<uint8_t> fake_z(reg_info->
byte_size, 0);
363 std::memcpy(&fake_z[0], src, 16 );
370 error = ReadAllSVE();
378 sve_reg_non_live.resize(reg_info->
byte_size, 0);
379 src = sve_reg_non_live.data();
381 if (GetRegisterInfo().IsSVEZReg(reg)) {
382 offset = CalculateSVEOffset(reg_info);
383 assert(offset < GetSVEBufferSize());
384 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
388 offset = CalculateSVEOffset(reg_info);
389 assert(offset < GetSVEBufferSize());
390 src = (uint8_t *)GetSVEBuffer() + offset;
393 }
else if (GetRegisterInfo().IsPAuthReg(reg)) {
394 error = ReadPAuthMask();
398 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
399 assert(offset < GetPACMaskSize());
400 src = (uint8_t *)GetPACMask() + offset;
401 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
402 error = ReadMTEControl();
406 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
407 assert(offset < GetMTEControlSize());
408 src = (uint8_t *)GetMTEControl() + offset;
409 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
410 if (GetRegisterInfo().IsSMERegZA(reg)) {
411 error = ReadZAHeader();
417 if (m_za_header.size ==
sizeof(m_za_header)) {
421 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
423 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
434 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
435 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
443 src = (uint8_t *)GetZTBuffer();
445 error = ReadSMESVG();
452 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
453 assert(offset < GetSMEPseudoBufferSize());
454 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
456 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
461 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
462 assert(offset < GetFPMRBufferSize());
463 src = (uint8_t *)GetFPMRBuffer() + offset;
464 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
469 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
470 assert(offset < GetGCSBufferSize());
471 src = (uint8_t *)GetGCSBuffer() + offset;
472 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
477 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
478 assert(offset < GetPOEBufferSize());
479 src = (uint8_t *)GetPOEBuffer() + offset;
482 "failed - register wasn't recognized to be a GPR or an FPR, "
483 "write strategy unknown");
491Status NativeRegisterContextLinux_arm64::WriteRegister(
502 "no lldb regnum for %s",
503 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
507 std::vector<uint8_t> sve_reg_non_live;
509 if (GetRegisterInfo().IsGPR(reg)) {
515 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
519 }
else if (GetRegisterInfo().IsFPR(reg)) {
529 offset = CalculateFprOffset(reg_info,
531 assert(offset < GetFPRSize());
532 dst = (uint8_t *)GetFPRBuffer() + offset;
538 error = ReadAllSVE();
547 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
553 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
564 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
567 assert(offset < GetSVEBufferSize());
568 dst = (uint8_t *)GetSVEBuffer() + offset;
570 return WriteAllSVE();
572 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
591 if (GetRegisterInfo().IsSVERegVG(reg) ||
592 GetRegisterInfo().IsSVEPReg(reg) ||
593 GetRegisterInfo().IsSVERegFFR(reg))
595 "Cannot write SVE VG, P or FFR registers while outside of "
607 uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
609 assert(offset < GetFPRSize());
610 dst = (uint8_t *)GetFPRBuffer() + offset;
613 ::memcpy(dst, reg_value.
GetBytes(), 16);
618 error = ReadAllSVE();
622 if (GetRegisterInfo().IsSVERegVG(reg)) {
626 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
629 SetSVERegVG(vg_value);
631 error = WriteSVEHeader();
632 if (
error.Success()) {
635 m_za_header_is_valid =
false;
636 ConfigureRegisterContext();
639 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
650 bool set_sve_state_full =
false;
651 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
652 if (GetRegisterInfo().IsSVEZReg(reg)) {
653 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
655 set_sve_state_full =
true;
659 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
660 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
661 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
663 set_sve_state_full =
true;
669 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
672 offset = CalculateSVEOffset(reg_info);
673 assert(offset < GetSVEBufferSize());
674 dst = (uint8_t *)GetSVEBuffer() + offset;
675 ::memcpy(dst, reg_value.
GetBytes(), 16);
677 return WriteAllSVE();
680 "SVE state change operation not supported");
682 offset = CalculateSVEOffset(reg_info);
683 assert(offset < GetSVEBufferSize());
684 dst = (uint8_t *)GetSVEBuffer() + offset;
686 return WriteAllSVE();
689 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
690 error = ReadMTEControl();
694 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
695 assert(offset < GetMTEControlSize());
696 dst = (uint8_t *)GetMTEControl() + offset;
699 return WriteMTEControl();
700 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
705 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
706 assert(offset < GetTLSBufferSize());
707 dst = (uint8_t *)GetTLSBuffer() + offset;
711 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
712 if (GetRegisterInfo().IsSMERegZA(reg)) {
719 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
726 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
731 dst = (uint8_t *)GetZTBuffer();
737 "Writing to SVG or SVCR is not supported.");
738 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
743 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
744 assert(offset < GetFPMRBufferSize());
745 dst = (uint8_t *)GetFPMRBuffer() + offset;
749 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
754 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
755 assert(offset < GetGCSBufferSize());
756 dst = (uint8_t *)GetGCSBuffer() + offset;
760 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
765 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
766 assert(offset < GetPOEBufferSize());
767 dst = (uint8_t *)GetPOEBuffer() + offset;
776enum RegisterSetType : uint32_t {
791static uint8_t *AddRegisterSetType(uint8_t *dst,
792 RegisterSetType register_set_type) {
793 *(
reinterpret_cast<uint32_t *
>(dst)) = register_set_type;
794 return dst +
sizeof(uint32_t);
797static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
798 ::memcpy(dst, src, size);
802static uint8_t *AddSavedRegisters(uint8_t *dst,
803 enum RegisterSetType register_set_type,
804 void *src,
size_t size) {
805 dst = AddRegisterSetType(dst, register_set_type);
806 return AddSavedRegistersData(dst, src, size);
810NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
812 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
817 if (GetRegisterInfo().IsZAPresent()) {
818 error = ReadZAHeader();
825 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
828 m_za_buffer_is_valid =
false;
837 GetRegisterInfo().IsZTPresent() &&
839 m_za_header.size >
sizeof(m_za_header)) {
840 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
852 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
856 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
857 error = ReadAllSVE();
859 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
865 if (GetRegisterInfo().IsMTEPresent()) {
866 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
867 error = ReadMTEControl();
872 if (GetRegisterInfo().IsFPMRPresent()) {
873 cached_size +=
sizeof(RegisterSetType) + GetFPMRBufferSize();
879 if (GetRegisterInfo().IsGCSPresent()) {
880 cached_size +=
sizeof(RegisterSetType) + GetGCSBufferSize();
886 if (GetRegisterInfo().IsPOEPresent()) {
887 cached_size +=
sizeof(RegisterSetType) + GetPOEBufferSize();
894 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
900Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
912 uint32_t reg_data_byte_size = 0;
913 Status error = CacheAllRegisters(reg_data_byte_size);
918 uint8_t *dst = data_sp->GetBytes();
920 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
957 assert(m_za_header.size <= GetZABufferSize());
958 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
962 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
964 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
965 *(
reinterpret_cast<SVEState *
>(dst)) = m_sve_state;
966 dst +=
sizeof(m_sve_state);
967 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
969 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
974 assert(m_za_header.size <= GetZABufferSize());
975 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
986 GetRegisterInfo().IsZTPresent() &&
988 m_za_header.size >
sizeof(m_za_header))
989 dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
992 if (GetRegisterInfo().IsMTEPresent()) {
993 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
994 GetMTEControlSize());
997 if (GetRegisterInfo().IsFPMRPresent()) {
998 dst = AddSavedRegisters(dst, RegisterSetType::FPMR, GetFPMRBuffer(),
999 GetFPMRBufferSize());
1002 if (GetRegisterInfo().IsGCSPresent()) {
1003 dst = AddSavedRegisters(dst, RegisterSetType::GCS, GetGCSBuffer(),
1004 GetGCSBufferSize());
1007 if (GetRegisterInfo().IsPOEPresent()) {
1008 dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
1009 GetPOEBufferSize());
1012 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
1013 GetTLSBufferSize());
1018static Status RestoreRegisters(
void *buffer,
const uint8_t **src,
size_t len,
1019 bool &is_valid, std::function<
Status()> writer) {
1020 ::memcpy(buffer, *src, len);
1026Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
1042 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
1047 const uint8_t *src = data_sp->GetBytes();
1048 if (src ==
nullptr) {
1050 "NativeRegisterContextLinux_arm64::%s "
1051 "DataBuffer::GetBytes() returned a null "
1057 uint64_t reg_data_min_size =
1058 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
1059 if (data_sp->GetByteSize() < reg_data_min_size) {
1061 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
1062 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
1063 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
1067 const uint8_t *end = src + data_sp->GetByteSize();
1069 const RegisterSetType kind =
1070 *
reinterpret_cast<const RegisterSetType *
>(src);
1071 src +=
sizeof(RegisterSetType);
1074 case RegisterSetType::GPR:
1075 error = RestoreRegisters(
1076 GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
1077 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
1079 case RegisterSetType::SVE:
1081 m_sve_state =
static_cast<SVEState>(*src);
1082 src +=
sizeof(m_sve_state);
1086 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
1088 m_sve_header_is_valid =
false;
1090 "NativeRegisterContextLinux_arm64::%s "
1091 "Invalid SVE header in data_sp",
1095 m_sve_header_is_valid =
true;
1096 error = WriteSVEHeader();
1103 ConfigureRegisterContext();
1106 error = RestoreRegisters(
1107 GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
1108 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
1110 case RegisterSetType::FPR: {
1111 m_sve_buffer_is_valid =
false;
1112 m_sve_header_is_valid =
false;
1114 ConfigureRegisterContext();
1118 if (!GetRegisterInfo().IsSVEPresent() &&
1119 GetRegisterInfo().IsSSVEPresent() &&
1137 std::vector<uint8_t> sve_fpsimd_data(data_size);
1142 header->
size = sve_fpsimd_data.size();
1150 ioVec.iov_base = sve_fpsimd_data.data();
1151 ioVec.iov_len = sve_fpsimd_data.size();
1155 error = WriteRegisterSet(&ioVec, sve_fpsimd_data.size(),
1156 llvm::ELF::NT_ARM_SVE);
1159 src += GetFPRSize();
1161 if (
error.Success()) {
1163 m_fpu_is_valid =
false;
1164 m_sve_buffer_is_valid =
false;
1165 m_sve_header_is_valid =
false;
1168 ConfigureRegisterContext();
1173 error = RestoreRegisters(
1174 GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
1175 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
1179 case RegisterSetType::MTE:
1180 error = RestoreRegisters(
1181 GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
1182 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
1184 case RegisterSetType::TLS:
1185 error = RestoreRegisters(
1186 GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
1187 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
1189 case RegisterSetType::SME:
1195 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
1199 m_za_ptrace_payload.resize(m_za_header.size);
1200 ::memcpy(GetZABuffer(), src, GetZABufferSize());
1201 m_za_buffer_is_valid =
true;
1209 ConfigureRegisterContext();
1214 src += GetZABufferSize();
1216 case RegisterSetType::SME2:
1220 error = RestoreRegisters(
1221 GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
1222 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
1224 case RegisterSetType::FPMR:
1225 error = RestoreRegisters(
1226 GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
1227 std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR,
this));
1229 case RegisterSetType::GCS: {
1234 m_gcs_is_valid =
false;
1239 uint64_t enable_bit = m_gcs_regs.features_enabled & 1UL;
1240 gcs_regs new_gcs_regs = *
reinterpret_cast<const gcs_regs *
>(src);
1241 new_gcs_regs.features_enabled =
1242 (new_gcs_regs.features_enabled & ~1UL) | enable_bit;
1244 const uint8_t *new_gcs_src =
1245 reinterpret_cast<const uint8_t *
>(&new_gcs_regs);
1246 error = RestoreRegisters(
1247 GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), m_gcs_is_valid,
1248 std::bind(&NativeRegisterContextLinux_arm64::WriteGCS,
this));
1249 src += GetGCSBufferSize();
1253 case RegisterSetType::POE:
1254 error = RestoreRegisters(
1255 GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
1256 std::bind(&NativeRegisterContextLinux_arm64::WritePOE,
this));
1267llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1268 if (!m_refresh_hwdebug_info) {
1269 return llvm::Error::success();
1272 ::pid_t tid = m_thread.GetID();
1275 m_max_hbp_supported);
1277 return error.ToError();
1279 m_refresh_hwdebug_info =
false;
1281 return llvm::Error::success();
1285NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1286 uint32_t max_supported =
1287 (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
1288 auto ®s = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
1294Status NativeRegisterContextLinux_arm64::ReadGPR() {
1301 ioVec.iov_base = GetGPRBuffer();
1302 ioVec.iov_len = GetGPRBufferSize();
1304 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
1306 if (
error.Success())
1307 m_gpr_is_valid =
true;
1312Status NativeRegisterContextLinux_arm64::WriteGPR() {
1318 ioVec.iov_base = GetGPRBuffer();
1319 ioVec.iov_len = GetGPRBufferSize();
1321 m_gpr_is_valid =
false;
1323 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
1326Status NativeRegisterContextLinux_arm64::ReadFPR() {
1333 ioVec.iov_base = GetFPRBuffer();
1334 ioVec.iov_len = GetFPRSize();
1336 error = ReadRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
1337 if (
error.Success())
1338 m_fpu_is_valid =
true;
1343Status NativeRegisterContextLinux_arm64::WriteFPR() {
1349 ioVec.iov_base = GetFPRBuffer();
1350 ioVec.iov_len = GetFPRSize();
1352 m_fpu_is_valid =
false;
1354 m_sve_buffer_is_valid =
false;
1355 m_sve_header_is_valid =
false;
1357 return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
1360void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1361 m_gpr_is_valid =
false;
1362 m_fpu_is_valid =
false;
1363 m_sve_buffer_is_valid =
false;
1364 m_sve_header_is_valid =
false;
1365 m_za_buffer_is_valid =
false;
1366 m_za_header_is_valid =
false;
1367 m_pac_mask_is_valid =
false;
1368 m_mte_ctrl_is_valid =
false;
1369 m_tls_is_valid =
false;
1370 m_zt_buffer_is_valid =
false;
1371 m_fpmr_is_valid =
false;
1372 m_gcs_is_valid =
false;
1373 m_poe_is_valid =
false;
1376 ConfigureRegisterContext();
1379unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1380 switch (m_sve_state) {
1383 return llvm::ELF::NT_ARM_SSVE;
1385 return llvm::ELF::NT_ARM_SVE;
1389Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1392 if (m_sve_header_is_valid)
1396 ioVec.iov_base = GetSVEHeader();
1397 ioVec.iov_len = GetSVEHeaderSize();
1399 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1401 if (
error.Success())
1402 m_sve_header_is_valid =
true;
1407Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1410 if (m_pac_mask_is_valid)
1414 ioVec.iov_base = GetPACMask();
1415 ioVec.iov_len = GetPACMaskSize();
1417 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), llvm::ELF::NT_ARM_PAC_MASK);
1419 if (
error.Success())
1420 m_pac_mask_is_valid =
true;
1425Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1428 error = ReadSVEHeader();
1433 ioVec.iov_base = GetSVEHeader();
1434 ioVec.iov_len = GetSVEHeaderSize();
1436 m_sve_buffer_is_valid =
false;
1437 m_sve_header_is_valid =
false;
1438 m_fpu_is_valid =
false;
1440 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1443Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1445 if (m_sve_buffer_is_valid)
1449 ioVec.iov_base = GetSVEBuffer();
1450 ioVec.iov_len = GetSVEBufferSize();
1452 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1454 if (
error.Success())
1455 m_sve_buffer_is_valid =
true;
1460Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1463 error = ReadAllSVE();
1469 ioVec.iov_base = GetSVEBuffer();
1470 ioVec.iov_len = GetSVEBufferSize();
1472 m_sve_buffer_is_valid =
false;
1473 m_sve_header_is_valid =
false;
1474 m_fpu_is_valid =
false;
1476 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1479Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1491 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1492 m_sme_pseudo_regs.ctrl_reg |= 2;
1497Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1500 if (m_mte_ctrl_is_valid)
1504 ioVec.iov_base = GetMTEControl();
1505 ioVec.iov_len = GetMTEControlSize();
1507 error = ReadRegisterSet(&ioVec, GetMTEControlSize(),
1508 llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
1510 if (
error.Success())
1511 m_mte_ctrl_is_valid =
true;
1516Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1519 error = ReadMTEControl();
1524 ioVec.iov_base = GetMTEControl();
1525 ioVec.iov_len = GetMTEControlSize();
1527 m_mte_ctrl_is_valid =
false;
1529 return WriteRegisterSet(&ioVec, GetMTEControlSize(),
1530 llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
1533Status NativeRegisterContextLinux_arm64::ReadTLS() {
1540 ioVec.iov_base = GetTLSBuffer();
1541 ioVec.iov_len = GetTLSBufferSize();
1543 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
1545 if (
error.Success())
1546 m_tls_is_valid =
true;
1551Status NativeRegisterContextLinux_arm64::WriteTLS() {
1559 ioVec.iov_base = GetTLSBuffer();
1560 ioVec.iov_len = GetTLSBufferSize();
1562 m_tls_is_valid =
false;
1564 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
1567Status NativeRegisterContextLinux_arm64::ReadGCS() {
1574 ioVec.iov_base = GetGCSBuffer();
1575 ioVec.iov_len = GetGCSBufferSize();
1577 error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
1579 if (
error.Success())
1580 m_gcs_is_valid =
true;
1585Status NativeRegisterContextLinux_arm64::WriteGCS() {
1593 ioVec.iov_base = GetGCSBuffer();
1594 ioVec.iov_len = GetGCSBufferSize();
1596 m_gcs_is_valid =
false;
1598 return WriteRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
1601Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1604 if (m_za_header_is_valid)
1608 ioVec.iov_base = GetZAHeader();
1609 ioVec.iov_len = GetZAHeaderSize();
1611 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), llvm::ELF::NT_ARM_ZA);
1613 if (
error.Success())
1614 m_za_header_is_valid =
true;
1619Status NativeRegisterContextLinux_arm64::ReadZA() {
1622 if (m_za_buffer_is_valid)
1626 ioVec.iov_base = GetZABuffer();
1627 ioVec.iov_len = GetZABufferSize();
1629 error = ReadRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
1631 if (
error.Success())
1632 m_za_buffer_is_valid =
true;
1637Status NativeRegisterContextLinux_arm64::WriteZA() {
1648 ioVec.iov_base = GetZABuffer();
1649 ioVec.iov_len = GetZABufferSize();
1651 m_za_buffer_is_valid =
false;
1652 m_za_header_is_valid =
false;
1654 m_zt_buffer_is_valid =
false;
1656 return WriteRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
1659Status NativeRegisterContextLinux_arm64::ReadZT() {
1662 if (m_zt_buffer_is_valid)
1666 ioVec.iov_base = GetZTBuffer();
1667 ioVec.iov_len = GetZTBufferSize();
1669 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
1670 m_zt_buffer_is_valid =
error.Success();
1675Status NativeRegisterContextLinux_arm64::WriteZT() {
1683 ioVec.iov_base = GetZTBuffer();
1684 ioVec.iov_len = GetZTBufferSize();
1686 m_zt_buffer_is_valid =
false;
1689 m_za_buffer_is_valid =
false;
1690 m_za_header_is_valid =
false;
1692 return WriteRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
1695Status NativeRegisterContextLinux_arm64::ReadFPMR() {
1698 if (m_fpmr_is_valid)
1702 ioVec.iov_base = GetFPMRBuffer();
1703 ioVec.iov_len = GetFPMRBufferSize();
1705 error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
1707 if (
error.Success())
1708 m_fpmr_is_valid =
true;
1713Status NativeRegisterContextLinux_arm64::WriteFPMR() {
1721 ioVec.iov_base = GetFPMRBuffer();
1722 ioVec.iov_len = GetFPMRBufferSize();
1724 m_fpmr_is_valid =
false;
1726 return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
1729Status NativeRegisterContextLinux_arm64::ReadPOE() {
1736 ioVec.iov_base = GetPOEBuffer();
1737 ioVec.iov_len = GetPOEBufferSize();
1739 error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
1741 if (
error.Success())
1742 m_poe_is_valid =
true;
1747Status NativeRegisterContextLinux_arm64::WritePOE() {
1755 ioVec.iov_base = GetPOEBuffer();
1756 ioVec.iov_len = GetPOEBufferSize();
1758 m_poe_is_valid =
false;
1760 return WriteRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
1763void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1775 m_sve_header_is_valid =
false;
1776 m_sve_buffer_is_valid =
false;
1780 bool has_sme =
error.Success();
1781 bool sme_is_active =
1786 m_sve_header_is_valid =
false;
1787 m_sve_buffer_is_valid =
false;
1789 error = ReadSVEHeader();
1791 bool has_sve =
error.Success();
1792 bool sve_is_active =
1803 else if (sve_is_active)
1805 else if (fp_is_active)
1817 m_sve_header_is_valid =
false;
1818 m_sve_buffer_is_valid =
false;
1819 error = ReadSVEHeader();
1827 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1832 if (!m_za_header_is_valid) {
1834 if (
error.Success()) {
1839 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1840 m_za_ptrace_payload.resize(m_za_header.size);
1841 m_za_buffer_is_valid =
false;
1846uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1847 const RegisterInfo *reg_info,
bool streaming_fpsimd)
const {
1848 uint32_t offset = reg_info->
byte_offset - GetGPRSize();
1849 if (!streaming_fpsimd)
1861 const size_t fpsr_offset = 16 * 32;
1863 if (reg == GetRegisterInfo().GetRegNumFPSR())
1864 offset = fpsr_offset;
1865 else if (reg == GetRegisterInfo().GetRegNumFPCR())
1866 offset = fpsr_offset + 4;
1868 offset = 16 * (reg - GetRegisterInfo().GetRegNumFPV0());
1873uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1880 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1884 uint32_t sve_z0_offset = GetGPRSize() + 16;
1888 return sve_reg_offset;
1891Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1895 if (
error.Success())
1896 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1901std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1903 std::vector<uint32_t> expedited_reg_nums =
1907 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1910 if (GetRegisterInfo().IsSSVEPresent())
1911 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1913 return expedited_reg_nums;
1916llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1917NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
1919 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
1923 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1924 "Unknown AArch64 memory tag type %d", type);
1927lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
1935 if (ReadPAuthMask().
Success())
1936 mask |= m_pac_mask.data_mask;
1938 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.