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;
184 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
185 : sizeof(m_tls_regs.tpidr_reg);
187 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
194NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
198uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
203NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
204 return GetRegisterInfo().GetRegisterSet(set_index);
207uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
209 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
215NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
228 "no lldb regnum for %s",
229 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
234 std::vector<uint8_t> sve_reg_non_live;
236 if (GetRegisterInfo().IsGPR(reg)) {
242 assert(offset < GetGPRSize());
243 src = (uint8_t *)GetGPRBuffer() + offset;
245 }
else if (GetRegisterInfo().IsFPR(reg)) {
255 offset = CalculateFprOffset(reg_info,
257 assert(offset < GetFPRSize());
258 src = (uint8_t *)GetFPRBuffer() + offset;
263 error = ReadAllSVE();
272 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
278 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
289 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
292 assert(offset < GetSVEBufferSize());
293 src = (uint8_t *)GetSVEBuffer() + offset;
295 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
300 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
301 assert(offset < GetTLSBufferSize());
302 src = (uint8_t *)GetTLSBuffer() + offset;
303 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
307 if (GetRegisterInfo().IsSVERegVG(reg)) {
308 error = ReadSVEHeader();
312 sve_vg = GetSVERegVG();
313 src = (uint8_t *)&sve_vg;
319 if (GetRegisterInfo().IsSVEPReg(reg) ||
320 GetRegisterInfo().IsSVERegFFR(reg)) {
321 std::vector<uint8_t> fake_reg(reg_info->
byte_size, 0);
344 const uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
346 assert(offset < GetFPRSize());
347 src = (uint8_t *)GetFPRBuffer() + offset;
350 std::vector<uint8_t> fake_z(reg_info->
byte_size, 0);
351 std::memcpy(&fake_z[0], src, 16 );
358 error = ReadAllSVE();
366 sve_reg_non_live.resize(reg_info->
byte_size, 0);
367 src = sve_reg_non_live.data();
369 if (GetRegisterInfo().IsSVEZReg(reg)) {
370 offset = CalculateSVEOffset(reg_info);
371 assert(offset < GetSVEBufferSize());
372 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
376 offset = CalculateSVEOffset(reg_info);
377 assert(offset < GetSVEBufferSize());
378 src = (uint8_t *)GetSVEBuffer() + offset;
381 }
else if (GetRegisterInfo().IsPAuthReg(reg)) {
382 error = ReadPAuthMask();
386 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
387 assert(offset < GetPACMaskSize());
388 src = (uint8_t *)GetPACMask() + offset;
389 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
390 error = ReadMTEControl();
394 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
395 assert(offset < GetMTEControlSize());
396 src = (uint8_t *)GetMTEControl() + offset;
397 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
398 if (GetRegisterInfo().IsSMERegZA(reg)) {
399 error = ReadZAHeader();
405 if (m_za_header.size ==
sizeof(m_za_header)) {
409 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
411 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
422 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
423 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
431 src = (uint8_t *)GetZTBuffer();
433 error = ReadSMESVG();
440 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
441 assert(offset < GetSMEPseudoBufferSize());
442 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
444 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
449 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
450 assert(offset < GetFPMRBufferSize());
451 src = (uint8_t *)GetFPMRBuffer() + offset;
452 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
457 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
458 assert(offset < GetGCSBufferSize());
459 src = (uint8_t *)GetGCSBuffer() + offset;
460 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
465 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
466 assert(offset < GetPOEBufferSize());
467 src = (uint8_t *)GetPOEBuffer() + offset;
470 "failed - register wasn't recognized to be a GPR or an FPR, "
471 "write strategy unknown");
479Status NativeRegisterContextLinux_arm64::WriteRegister(
490 "no lldb regnum for %s",
491 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
495 std::vector<uint8_t> sve_reg_non_live;
497 if (GetRegisterInfo().IsGPR(reg)) {
503 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
507 }
else if (GetRegisterInfo().IsFPR(reg)) {
517 offset = CalculateFprOffset(reg_info,
519 assert(offset < GetFPRSize());
520 dst = (uint8_t *)GetFPRBuffer() + offset;
526 error = ReadAllSVE();
535 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
541 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
552 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
555 assert(offset < GetSVEBufferSize());
556 dst = (uint8_t *)GetSVEBuffer() + offset;
558 return WriteAllSVE();
560 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
579 if (GetRegisterInfo().IsSVERegVG(reg) ||
580 GetRegisterInfo().IsSVEPReg(reg) ||
581 GetRegisterInfo().IsSVERegFFR(reg))
583 "Cannot write SVE VG, P or FFR registers while outside of "
595 uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
597 assert(offset < GetFPRSize());
598 dst = (uint8_t *)GetFPRBuffer() + offset;
601 ::memcpy(dst, reg_value.
GetBytes(), 16);
606 error = ReadAllSVE();
610 if (GetRegisterInfo().IsSVERegVG(reg)) {
614 if (IsValid(RegisterSetType::SVE_HEADER) && vg_value == GetSVERegVG())
617 SetSVERegVG(vg_value);
619 error = WriteSVEHeader();
620 if (
error.Success()) {
623 Invalidate(RegisterSetType::ZA_HEADER);
624 ConfigureRegisterContext();
627 if (IsValid(RegisterSetType::SVE_HEADER) && vg_value == GetSVERegVG())
638 bool set_sve_state_full =
false;
639 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
640 if (GetRegisterInfo().IsSVEZReg(reg)) {
641 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
643 set_sve_state_full =
true;
647 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
648 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
649 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
651 set_sve_state_full =
true;
657 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
660 offset = CalculateSVEOffset(reg_info);
661 assert(offset < GetSVEBufferSize());
662 dst = (uint8_t *)GetSVEBuffer() + offset;
663 ::memcpy(dst, reg_value.
GetBytes(), 16);
665 return WriteAllSVE();
668 "SVE state change operation not supported");
670 offset = CalculateSVEOffset(reg_info);
671 assert(offset < GetSVEBufferSize());
672 dst = (uint8_t *)GetSVEBuffer() + offset;
674 return WriteAllSVE();
677 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
678 error = ReadMTEControl();
682 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
683 assert(offset < GetMTEControlSize());
684 dst = (uint8_t *)GetMTEControl() + offset;
687 return WriteMTEControl();
688 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
693 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
694 assert(offset < GetTLSBufferSize());
695 dst = (uint8_t *)GetTLSBuffer() + offset;
699 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
700 if (GetRegisterInfo().IsSMERegZA(reg)) {
707 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
714 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
719 dst = (uint8_t *)GetZTBuffer();
725 "Writing to SVG or SVCR is not supported.");
726 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
731 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
732 assert(offset < GetFPMRBufferSize());
733 dst = (uint8_t *)GetFPMRBuffer() + offset;
737 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
742 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
743 assert(offset < GetGCSBufferSize());
744 dst = (uint8_t *)GetGCSBuffer() + offset;
748 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
753 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
754 assert(offset < GetPOEBufferSize());
755 dst = (uint8_t *)GetPOEBuffer() + offset;
764uint8_t *NativeRegisterContextLinux_arm64::AddRegisterSetType(
765 uint8_t *dst, RegisterSetType register_set_type) {
766 std::memcpy(dst, ®ister_set_type,
sizeof(register_set_type));
767 return dst +
sizeof(RegisterSetType);
770static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
771 ::memcpy(dst, src, size);
775uint8_t *NativeRegisterContextLinux_arm64::AddSavedRegisters(
776 uint8_t *dst, RegisterSetType register_set_type,
void *src,
size_t size) {
777 dst = AddRegisterSetType(dst, register_set_type);
778 return AddSavedRegistersData(dst, src, size);
782NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
784 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
789 if (GetRegisterInfo().IsZAPresent()) {
790 error = ReadZAHeader();
797 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
800 Invalidate(RegisterSetType::ZA);
809 GetRegisterInfo().IsZTPresent() &&
811 m_za_header.size >
sizeof(m_za_header)) {
812 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
824 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
828 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
829 error = ReadAllSVE();
831 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
837 if (GetRegisterInfo().IsMTEPresent()) {
838 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
839 error = ReadMTEControl();
844 if (GetRegisterInfo().IsFPMRPresent()) {
845 cached_size +=
sizeof(RegisterSetType) + GetFPMRBufferSize();
851 if (GetRegisterInfo().IsGCSPresent()) {
852 cached_size +=
sizeof(RegisterSetType) + GetGCSBufferSize();
858 if (GetRegisterInfo().IsPOEPresent()) {
859 cached_size +=
sizeof(RegisterSetType) + GetPOEBufferSize();
866 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
872Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
884 uint32_t reg_data_byte_size = 0;
885 Status error = CacheAllRegisters(reg_data_byte_size);
890 uint8_t *dst = data_sp->GetBytes();
892 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
929 assert(m_za_header.size <= GetZABufferSize());
930 dst = AddSavedRegisters(dst, RegisterSetType::ZA, GetZABuffer(),
934 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
936 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
937 std::memcpy(dst, &m_sve_state,
sizeof(m_sve_state));
938 dst +=
sizeof(m_sve_state);
939 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
941 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
946 assert(m_za_header.size <= GetZABufferSize());
947 dst = AddSavedRegisters(dst, RegisterSetType::ZA, GetZABuffer(),
958 GetRegisterInfo().IsZTPresent() &&
960 m_za_header.size >
sizeof(m_za_header))
961 dst = AddSavedRegisters(dst, RegisterSetType::ZT, GetZTBuffer(),
964 if (GetRegisterInfo().IsMTEPresent()) {
965 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
966 GetMTEControlSize());
969 if (GetRegisterInfo().IsFPMRPresent()) {
970 dst = AddSavedRegisters(dst, RegisterSetType::FPMR, GetFPMRBuffer(),
971 GetFPMRBufferSize());
974 if (GetRegisterInfo().IsGCSPresent()) {
975 dst = AddSavedRegisters(dst, RegisterSetType::GCS, GetGCSBuffer(),
979 if (GetRegisterInfo().IsPOEPresent()) {
980 dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
984 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
990Status NativeRegisterContextLinux_arm64::RestoreRegisters(
991 void *buffer,
const uint8_t **src,
size_t len,
992 const NativeRegisterContextLinux_arm64::RegisterSetType set,
993 std::function<
Status()> writer) {
994 ::memcpy(buffer, *src, len);
1000Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
1016 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
1021 const uint8_t *src = data_sp->GetBytes();
1022 if (src ==
nullptr) {
1024 "NativeRegisterContextLinux_arm64::%s "
1025 "DataBuffer::GetBytes() returned a null "
1031 uint64_t reg_data_min_size =
1032 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
1033 if (data_sp->GetByteSize() < reg_data_min_size) {
1035 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
1036 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
1037 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
1041 const uint8_t *end = src + data_sp->GetByteSize();
1043 RegisterSetType kind;
1044 std::memcpy(&kind, src,
sizeof(kind));
1045 src +=
sizeof(RegisterSetType);
1048 case RegisterSetType::GPR:
1049 error = RestoreRegisters(
1050 GetGPRBuffer(), &src, GetGPRBufferSize(), kind,
1051 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
1053 case RegisterSetType::SVE:
1055 std::memcpy(&m_sve_state, src,
sizeof(m_sve_state));
1056 src +=
sizeof(m_sve_state);
1060 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
1062 Invalidate(RegisterSetType::SVE_HEADER);
1064 "NativeRegisterContextLinux_arm64::%s "
1065 "Invalid SVE header in data_sp",
1069 MakeValid(RegisterSetType::SVE_HEADER);
1070 error = WriteSVEHeader();
1077 ConfigureRegisterContext();
1080 error = RestoreRegisters(
1081 GetSVEBuffer(), &src, GetSVEBufferSize(), kind,
1082 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
1084 case RegisterSetType::FPR: {
1085 Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
1087 ConfigureRegisterContext();
1091 if (!GetRegisterInfo().IsSVEPresent() &&
1092 GetRegisterInfo().IsSSVEPresent() &&
1110 std::vector<uint8_t> sve_fpsimd_data(data_size);
1115 header->
size = sve_fpsimd_data.size();
1123 ioVec.iov_base = sve_fpsimd_data.data();
1124 ioVec.iov_len = sve_fpsimd_data.size();
1128 error = WriteRegisterSet(&ioVec, sve_fpsimd_data.size(),
1129 llvm::ELF::NT_ARM_SVE);
1132 src += GetFPRSize();
1134 if (
error.Success()) {
1136 Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
1137 RegisterSetType::SVE);
1140 ConfigureRegisterContext();
1145 error = RestoreRegisters(
1146 GetFPRBuffer(), &src, GetFPRSize(), kind,
1147 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
1151 case RegisterSetType::MTE:
1152 error = RestoreRegisters(
1153 GetMTEControl(), &src, GetMTEControlSize(), kind,
1154 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
1156 case RegisterSetType::TLS:
1157 error = RestoreRegisters(
1158 GetTLSBuffer(), &src, GetTLSBufferSize(), kind,
1159 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
1161 case RegisterSetType::ZA:
1167 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
1171 m_za_ptrace_payload.resize(m_za_header.size);
1172 ::memcpy(GetZABuffer(), src, GetZABufferSize());
1173 MakeValid(RegisterSetType::ZA);
1181 ConfigureRegisterContext();
1186 src += GetZABufferSize();
1188 case RegisterSetType::ZT:
1192 error = RestoreRegisters(
1193 GetZTBuffer(), &src, GetZTBufferSize(), kind,
1194 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
1196 case RegisterSetType::FPMR:
1197 error = RestoreRegisters(
1198 GetFPMRBuffer(), &src, GetFPMRBufferSize(), kind,
1199 std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR,
this));
1201 case RegisterSetType::GCS: {
1206 Invalidate(RegisterSetType::GCS);
1211 uint64_t enable_bit = m_gcs_regs.features_enabled & 1UL;
1212 gcs_regs new_gcs_regs;
1213 std::memcpy(&new_gcs_regs, src,
sizeof(new_gcs_regs));
1214 new_gcs_regs.features_enabled =
1215 (new_gcs_regs.features_enabled & ~1UL) | enable_bit;
1217 const uint8_t *new_gcs_src =
1218 reinterpret_cast<const uint8_t *
>(&new_gcs_regs);
1219 error = RestoreRegisters(
1220 GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), kind,
1221 std::bind(&NativeRegisterContextLinux_arm64::WriteGCS,
this));
1222 src += GetGCSBufferSize();
1226 case RegisterSetType::POE:
1227 error = RestoreRegisters(
1228 GetPOEBuffer(), &src, GetPOEBufferSize(), kind,
1229 std::bind(&NativeRegisterContextLinux_arm64::WritePOE,
this));
1231 case RegisterSetType::PAC:
1232 case RegisterSetType::SVE_HEADER:
1233 case RegisterSetType::ZA_HEADER:
1245llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1246 if (!m_refresh_hwdebug_info) {
1247 return llvm::Error::success();
1250 ::pid_t tid = m_thread.GetID();
1253 m_max_hbp_supported);
1255 return error.ToError();
1257 m_refresh_hwdebug_info =
false;
1259 return llvm::Error::success();
1263NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1264 uint32_t max_supported =
1265 (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
1266 auto ®s = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
1272Status NativeRegisterContextLinux_arm64::ReadGPR() {
1275 if (IsValid(RegisterSetType::GPR))
1279 ioVec.iov_base = GetGPRBuffer();
1280 ioVec.iov_len = GetGPRBufferSize();
1282 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
1284 if (
error.Success())
1285 MakeValid(RegisterSetType::GPR);
1290Status NativeRegisterContextLinux_arm64::WriteGPR() {
1296 ioVec.iov_base = GetGPRBuffer();
1297 ioVec.iov_len = GetGPRBufferSize();
1299 Invalidate(RegisterSetType::GPR);
1301 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), llvm::ELF::NT_PRSTATUS);
1304Status NativeRegisterContextLinux_arm64::ReadFPR() {
1307 if (IsValid(RegisterSetType::FPR))
1311 ioVec.iov_base = GetFPRBuffer();
1312 ioVec.iov_len = GetFPRSize();
1314 error = ReadRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
1315 if (
error.Success())
1316 MakeValid(RegisterSetType::FPR);
1321Status NativeRegisterContextLinux_arm64::WriteFPR() {
1327 ioVec.iov_base = GetFPRBuffer();
1328 ioVec.iov_len = GetFPRSize();
1331 Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
1332 RegisterSetType::SVE);
1334 return WriteRegisterSet(&ioVec, GetFPRSize(), llvm::ELF::NT_FPREGSET);
1337void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1338 m_validity =
static_cast<RegisterSetType
>(0);
1341 ConfigureRegisterContext();
1344unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1345 switch (m_sve_state) {
1348 return llvm::ELF::NT_ARM_SSVE;
1350 return llvm::ELF::NT_ARM_SVE;
1354Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1357 if (IsValid(RegisterSetType::SVE_HEADER))
1361 ioVec.iov_base = GetSVEHeader();
1362 ioVec.iov_len = GetSVEHeaderSize();
1364 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1366 if (
error.Success())
1367 MakeValid(RegisterSetType::SVE_HEADER);
1372Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1375 if (IsValid(RegisterSetType::PAC))
1379 ioVec.iov_base = GetPACMask();
1380 ioVec.iov_len = GetPACMaskSize();
1382 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), llvm::ELF::NT_ARM_PAC_MASK);
1384 if (
error.Success())
1385 MakeValid(RegisterSetType::PAC);
1390Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1393 error = ReadSVEHeader();
1398 ioVec.iov_base = GetSVEHeader();
1399 ioVec.iov_len = GetSVEHeaderSize();
1401 Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
1402 RegisterSetType::SVE);
1404 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1407Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1409 if (IsValid(RegisterSetType::SVE))
1413 ioVec.iov_base = GetSVEBuffer();
1414 ioVec.iov_len = GetSVEBufferSize();
1416 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1418 if (
error.Success())
1419 MakeValid(RegisterSetType::SVE);
1424Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1427 error = ReadAllSVE();
1433 ioVec.iov_base = GetSVEBuffer();
1434 ioVec.iov_len = GetSVEBufferSize();
1436 Invalidate(RegisterSetType::FPR, RegisterSetType::SVE_HEADER,
1437 RegisterSetType::SVE);
1439 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1442Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1454 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1455 m_sme_pseudo_regs.ctrl_reg |= 2;
1460Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1463 if (IsValid(RegisterSetType::MTE))
1467 ioVec.iov_base = GetMTEControl();
1468 ioVec.iov_len = GetMTEControlSize();
1470 error = ReadRegisterSet(&ioVec, GetMTEControlSize(),
1471 llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
1473 if (
error.Success())
1474 MakeValid(RegisterSetType::MTE);
1479Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1482 error = ReadMTEControl();
1487 ioVec.iov_base = GetMTEControl();
1488 ioVec.iov_len = GetMTEControlSize();
1490 Invalidate(RegisterSetType::MTE);
1492 return WriteRegisterSet(&ioVec, GetMTEControlSize(),
1493 llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL);
1496Status NativeRegisterContextLinux_arm64::ReadTLS() {
1499 if (IsValid(RegisterSetType::TLS))
1503 ioVec.iov_base = GetTLSBuffer();
1504 ioVec.iov_len = GetTLSBufferSize();
1506 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
1508 if (
error.Success())
1509 MakeValid(RegisterSetType::TLS);
1514Status NativeRegisterContextLinux_arm64::WriteTLS() {
1522 ioVec.iov_base = GetTLSBuffer();
1523 ioVec.iov_len = GetTLSBufferSize();
1525 Invalidate(RegisterSetType::TLS);
1527 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), llvm::ELF::NT_ARM_TLS);
1530Status NativeRegisterContextLinux_arm64::ReadGCS() {
1533 if (IsValid(RegisterSetType::GCS))
1537 ioVec.iov_base = GetGCSBuffer();
1538 ioVec.iov_len = GetGCSBufferSize();
1540 error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
1542 if (
error.Success())
1543 MakeValid(RegisterSetType::GCS);
1548Status NativeRegisterContextLinux_arm64::WriteGCS() {
1556 ioVec.iov_base = GetGCSBuffer();
1557 ioVec.iov_len = GetGCSBufferSize();
1559 Invalidate(RegisterSetType::GCS);
1561 return WriteRegisterSet(&ioVec, GetGCSBufferSize(), llvm::ELF::NT_ARM_GCS);
1564Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1567 if (IsValid(RegisterSetType::ZA_HEADER))
1571 ioVec.iov_base = GetZAHeader();
1572 ioVec.iov_len = GetZAHeaderSize();
1574 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), llvm::ELF::NT_ARM_ZA);
1576 if (
error.Success())
1577 MakeValid(RegisterSetType::ZA_HEADER);
1582Status NativeRegisterContextLinux_arm64::ReadZA() {
1585 if (IsValid(RegisterSetType::ZA))
1589 ioVec.iov_base = GetZABuffer();
1590 ioVec.iov_len = GetZABufferSize();
1592 error = ReadRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
1594 if (
error.Success())
1595 MakeValid(RegisterSetType::ZA);
1600Status NativeRegisterContextLinux_arm64::WriteZA() {
1611 ioVec.iov_base = GetZABuffer();
1612 ioVec.iov_len = GetZABufferSize();
1614 Invalidate(RegisterSetType::ZA_HEADER, RegisterSetType::ZA,
1616 RegisterSetType::ZT);
1618 return WriteRegisterSet(&ioVec, GetZABufferSize(), llvm::ELF::NT_ARM_ZA);
1621Status NativeRegisterContextLinux_arm64::ReadZT() {
1624 if (IsValid(RegisterSetType::ZT))
1628 ioVec.iov_base = GetZTBuffer();
1629 ioVec.iov_len = GetZTBufferSize();
1631 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
1632 if (
error.Success())
1633 MakeValid(RegisterSetType::ZT);
1638Status NativeRegisterContextLinux_arm64::WriteZT() {
1646 ioVec.iov_base = GetZTBuffer();
1647 ioVec.iov_len = GetZTBufferSize();
1649 Invalidate(RegisterSetType::ZT,
1652 RegisterSetType::ZA_HEADER, RegisterSetType::ZA);
1654 return WriteRegisterSet(&ioVec, GetZTBufferSize(), llvm::ELF::NT_ARM_ZT);
1657Status NativeRegisterContextLinux_arm64::ReadFPMR() {
1660 if (IsValid(RegisterSetType::FPMR))
1664 ioVec.iov_base = GetFPMRBuffer();
1665 ioVec.iov_len = GetFPMRBufferSize();
1667 error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
1669 if (
error.Success())
1670 MakeValid(RegisterSetType::FPMR);
1675Status NativeRegisterContextLinux_arm64::WriteFPMR() {
1683 ioVec.iov_base = GetFPMRBuffer();
1684 ioVec.iov_len = GetFPMRBufferSize();
1686 Invalidate(RegisterSetType::FPMR);
1688 return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), llvm::ELF::NT_ARM_FPMR);
1691Status NativeRegisterContextLinux_arm64::ReadPOE() {
1694 if (IsValid(RegisterSetType::POE))
1698 ioVec.iov_base = GetPOEBuffer();
1699 ioVec.iov_len = GetPOEBufferSize();
1701 error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
1703 if (
error.Success())
1704 MakeValid(RegisterSetType::POE);
1709Status NativeRegisterContextLinux_arm64::WritePOE() {
1717 ioVec.iov_base = GetPOEBuffer();
1718 ioVec.iov_len = GetPOEBufferSize();
1720 Invalidate(RegisterSetType::POE);
1722 return WriteRegisterSet(&ioVec, GetPOEBufferSize(), llvm::ELF::NT_ARM_POE);
1725void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1731 if (!IsValid(RegisterSetType::SVE_HEADER) &&
1738 Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
1742 bool has_sme =
error.Success();
1743 bool sme_is_active =
1748 Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
1750 error = ReadSVEHeader();
1752 bool has_sve =
error.Success();
1753 bool sve_is_active =
1764 else if (sve_is_active)
1766 else if (fp_is_active)
1777 Invalidate(RegisterSetType::SVE_HEADER, RegisterSetType::SVE);
1778 error = ReadSVEHeader();
1786 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1791 if (!IsValid(RegisterSetType::ZA_HEADER)) {
1793 if (
error.Success()) {
1798 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1799 m_za_ptrace_payload.resize(m_za_header.size);
1800 Invalidate(RegisterSetType::ZA);
1805uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1806 const RegisterInfo *reg_info,
bool streaming_fpsimd)
const {
1807 uint32_t offset = reg_info->
byte_offset - GetGPRSize();
1808 if (!streaming_fpsimd)
1820 const size_t fpsr_offset = 16 * 32;
1822 if (reg == GetRegisterInfo().GetRegNumFPSR())
1823 offset = fpsr_offset;
1824 else if (reg == GetRegisterInfo().GetRegNumFPCR())
1825 offset = fpsr_offset + 4;
1827 offset = 16 * (reg - GetRegisterInfo().GetRegNumFPV0());
1832uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1839 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1843 uint32_t sve_z0_offset = GetGPRSize() + 16;
1847 return sve_reg_offset;
1850Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1854 if (
error.Success())
1855 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1860std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1862 std::vector<uint32_t> expedited_reg_nums =
1866 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1869 if (GetRegisterInfo().IsSSVEPresent())
1870 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1872 return expedited_reg_nums;
1875llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1876NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
1878 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
1882 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1883 "Unknown AArch64 memory tag type %d", type);
1886lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
1894 if (ReadPAuthMask().
Success())
1895 mask |= m_pac_mask.data_mask;
1897 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.