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());
218 m_max_hwp_supported = 16;
219 m_max_hbp_supported = 16;
221 m_gpr_is_valid =
false;
222 m_fpu_is_valid =
false;
223 m_sve_buffer_is_valid =
false;
224 m_sve_header_is_valid =
false;
225 m_pac_mask_is_valid =
false;
226 m_mte_ctrl_is_valid =
false;
227 m_tls_is_valid =
false;
228 m_zt_buffer_is_valid =
false;
229 m_fpmr_is_valid =
false;
230 m_gcs_is_valid =
false;
231 m_poe_is_valid =
false;
234 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
235 : sizeof(m_tls_regs.tpidr_reg);
237 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
244NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
248uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
253NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
254 return GetRegisterInfo().GetRegisterSet(set_index);
257uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
259 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
265NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
278 "no lldb regnum for %s",
279 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
284 std::vector<uint8_t> sve_reg_non_live;
286 if (GetRegisterInfo().IsGPR(reg)) {
292 assert(offset < GetGPRSize());
293 src = (uint8_t *)GetGPRBuffer() + offset;
295 }
else if (GetRegisterInfo().IsFPR(reg)) {
305 offset = CalculateFprOffset(reg_info,
307 assert(offset < GetFPRSize());
308 src = (uint8_t *)GetFPRBuffer() + offset;
313 error = ReadAllSVE();
322 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
328 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
339 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
342 assert(offset < GetSVEBufferSize());
343 src = (uint8_t *)GetSVEBuffer() + offset;
345 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
350 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
351 assert(offset < GetTLSBufferSize());
352 src = (uint8_t *)GetTLSBuffer() + offset;
353 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
357 if (GetRegisterInfo().IsSVERegVG(reg)) {
358 error = ReadSVEHeader();
362 sve_vg = GetSVERegVG();
363 src = (uint8_t *)&sve_vg;
369 if (GetRegisterInfo().IsSVEPReg(reg) ||
370 GetRegisterInfo().IsSVERegFFR(reg)) {
371 std::vector<uint8_t> fake_reg(reg_info->
byte_size, 0);
394 const uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
396 assert(offset < GetFPRSize());
397 src = (uint8_t *)GetFPRBuffer() + offset;
400 std::vector<uint8_t> fake_z(reg_info->
byte_size, 0);
401 std::memcpy(&fake_z[0], src, 16 );
408 error = ReadAllSVE();
416 sve_reg_non_live.resize(reg_info->
byte_size, 0);
417 src = sve_reg_non_live.data();
419 if (GetRegisterInfo().IsSVEZReg(reg)) {
420 offset = CalculateSVEOffset(reg_info);
421 assert(offset < GetSVEBufferSize());
422 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
426 offset = CalculateSVEOffset(reg_info);
427 assert(offset < GetSVEBufferSize());
428 src = (uint8_t *)GetSVEBuffer() + offset;
431 }
else if (GetRegisterInfo().IsPAuthReg(reg)) {
432 error = ReadPAuthMask();
436 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
437 assert(offset < GetPACMaskSize());
438 src = (uint8_t *)GetPACMask() + offset;
439 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
440 error = ReadMTEControl();
444 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
445 assert(offset < GetMTEControlSize());
446 src = (uint8_t *)GetMTEControl() + offset;
447 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
448 if (GetRegisterInfo().IsSMERegZA(reg)) {
449 error = ReadZAHeader();
455 if (m_za_header.size ==
sizeof(m_za_header)) {
459 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
461 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
472 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
473 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
481 src = (uint8_t *)GetZTBuffer();
483 error = ReadSMESVG();
490 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
491 assert(offset < GetSMEPseudoBufferSize());
492 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
494 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
499 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
500 assert(offset < GetFPMRBufferSize());
501 src = (uint8_t *)GetFPMRBuffer() + offset;
502 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
507 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
508 assert(offset < GetGCSBufferSize());
509 src = (uint8_t *)GetGCSBuffer() + offset;
510 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
515 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
516 assert(offset < GetPOEBufferSize());
517 src = (uint8_t *)GetPOEBuffer() + offset;
520 "failed - register wasn't recognized to be a GPR or an FPR, "
521 "write strategy unknown");
529Status NativeRegisterContextLinux_arm64::WriteRegister(
540 "no lldb regnum for %s",
541 reg_info && reg_info->
name ? reg_info->
name :
"<unknown register>");
545 std::vector<uint8_t> sve_reg_non_live;
547 if (GetRegisterInfo().IsGPR(reg)) {
553 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
557 }
else if (GetRegisterInfo().IsFPR(reg)) {
567 offset = CalculateFprOffset(reg_info,
569 assert(offset < GetFPRSize());
570 dst = (uint8_t *)GetFPRBuffer() + offset;
576 error = ReadAllSVE();
585 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
591 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
602 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
605 assert(offset < GetSVEBufferSize());
606 dst = (uint8_t *)GetSVEBuffer() + offset;
608 return WriteAllSVE();
610 }
else if (GetRegisterInfo().IsSVEReg(reg)) {
629 if (GetRegisterInfo().IsSVERegVG(reg) ||
630 GetRegisterInfo().IsSVEPReg(reg) ||
631 GetRegisterInfo().IsSVERegFFR(reg))
633 "Cannot write SVE VG, P or FFR registers while outside of "
645 uint32_t z_num = reg - GetRegisterInfo().GetRegNumSVEZ0();
647 assert(offset < GetFPRSize());
648 dst = (uint8_t *)GetFPRBuffer() + offset;
651 ::memcpy(dst, reg_value.
GetBytes(), 16);
656 error = ReadAllSVE();
660 if (GetRegisterInfo().IsSVERegVG(reg)) {
664 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
667 SetSVERegVG(vg_value);
669 error = WriteSVEHeader();
670 if (
error.Success()) {
673 m_za_header_is_valid =
false;
674 ConfigureRegisterContext();
677 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
688 bool set_sve_state_full =
false;
689 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
690 if (GetRegisterInfo().IsSVEZReg(reg)) {
691 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
693 set_sve_state_full =
true;
697 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
698 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
699 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
701 set_sve_state_full =
true;
707 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
710 offset = CalculateSVEOffset(reg_info);
711 assert(offset < GetSVEBufferSize());
712 dst = (uint8_t *)GetSVEBuffer() + offset;
713 ::memcpy(dst, reg_value.
GetBytes(), 16);
715 return WriteAllSVE();
718 "SVE state change operation not supported");
720 offset = CalculateSVEOffset(reg_info);
721 assert(offset < GetSVEBufferSize());
722 dst = (uint8_t *)GetSVEBuffer() + offset;
724 return WriteAllSVE();
727 }
else if (GetRegisterInfo().IsMTEReg(reg)) {
728 error = ReadMTEControl();
732 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
733 assert(offset < GetMTEControlSize());
734 dst = (uint8_t *)GetMTEControl() + offset;
737 return WriteMTEControl();
738 }
else if (GetRegisterInfo().IsTLSReg(reg)) {
743 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
744 assert(offset < GetTLSBufferSize());
745 dst = (uint8_t *)GetTLSBuffer() + offset;
749 }
else if (GetRegisterInfo().IsSMEReg(reg)) {
750 if (GetRegisterInfo().IsSMERegZA(reg)) {
757 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
764 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
769 dst = (uint8_t *)GetZTBuffer();
775 "Writing to SVG or SVCR is not supported.");
776 }
else if (GetRegisterInfo().IsFPMRReg(reg)) {
781 offset = reg_info->
byte_offset - GetRegisterInfo().GetFPMROffset();
782 assert(offset < GetFPMRBufferSize());
783 dst = (uint8_t *)GetFPMRBuffer() + offset;
787 }
else if (GetRegisterInfo().IsGCSReg(reg)) {
792 offset = reg_info->
byte_offset - GetRegisterInfo().GetGCSOffset();
793 assert(offset < GetGCSBufferSize());
794 dst = (uint8_t *)GetGCSBuffer() + offset;
798 }
else if (GetRegisterInfo().IsPOEReg(reg)) {
803 offset = reg_info->
byte_offset - GetRegisterInfo().GetPOEOffset();
804 assert(offset < GetPOEBufferSize());
805 dst = (uint8_t *)GetPOEBuffer() + offset;
814enum RegisterSetType : uint32_t {
829static uint8_t *AddRegisterSetType(uint8_t *dst,
830 RegisterSetType register_set_type) {
831 *(
reinterpret_cast<uint32_t *
>(dst)) = register_set_type;
832 return dst +
sizeof(uint32_t);
835static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
836 ::memcpy(dst, src, size);
840static uint8_t *AddSavedRegisters(uint8_t *dst,
841 enum RegisterSetType register_set_type,
842 void *src,
size_t size) {
843 dst = AddRegisterSetType(dst, register_set_type);
844 return AddSavedRegistersData(dst, src, size);
848NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
850 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
855 if (GetRegisterInfo().IsZAPresent()) {
856 error = ReadZAHeader();
863 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
866 m_za_buffer_is_valid =
false;
875 GetRegisterInfo().IsZTPresent() &&
877 m_za_header.size >
sizeof(m_za_header)) {
878 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
890 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
894 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
895 error = ReadAllSVE();
897 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
903 if (GetRegisterInfo().IsMTEPresent()) {
904 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
905 error = ReadMTEControl();
910 if (GetRegisterInfo().IsFPMRPresent()) {
911 cached_size +=
sizeof(RegisterSetType) + GetFPMRBufferSize();
917 if (GetRegisterInfo().IsGCSPresent()) {
918 cached_size +=
sizeof(RegisterSetType) + GetGCSBufferSize();
924 if (GetRegisterInfo().IsPOEPresent()) {
925 cached_size +=
sizeof(RegisterSetType) + GetPOEBufferSize();
932 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
938Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
950 uint32_t reg_data_byte_size = 0;
951 Status error = CacheAllRegisters(reg_data_byte_size);
956 uint8_t *dst = data_sp->GetBytes();
958 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
995 assert(m_za_header.size <= GetZABufferSize());
996 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
1000 if ((GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) &&
1002 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
1003 *(
reinterpret_cast<SVEState *
>(dst)) = m_sve_state;
1004 dst +=
sizeof(m_sve_state);
1005 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
1007 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
1012 assert(m_za_header.size <= GetZABufferSize());
1013 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
1024 GetRegisterInfo().IsZTPresent() &&
1026 m_za_header.size >
sizeof(m_za_header))
1027 dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
1030 if (GetRegisterInfo().IsMTEPresent()) {
1031 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
1032 GetMTEControlSize());
1035 if (GetRegisterInfo().IsFPMRPresent()) {
1036 dst = AddSavedRegisters(dst, RegisterSetType::FPMR, GetFPMRBuffer(),
1037 GetFPMRBufferSize());
1040 if (GetRegisterInfo().IsGCSPresent()) {
1041 dst = AddSavedRegisters(dst, RegisterSetType::GCS, GetGCSBuffer(),
1042 GetGCSBufferSize());
1045 if (GetRegisterInfo().IsPOEPresent()) {
1046 dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(),
1047 GetPOEBufferSize());
1050 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
1051 GetTLSBufferSize());
1056static Status RestoreRegisters(
void *buffer,
const uint8_t **src,
size_t len,
1057 bool &is_valid, std::function<
Status()> writer) {
1058 ::memcpy(buffer, *src, len);
1064Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
1080 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
1085 const uint8_t *src = data_sp->GetBytes();
1086 if (src ==
nullptr) {
1088 "NativeRegisterContextLinux_arm64::%s "
1089 "DataBuffer::GetBytes() returned a null "
1095 uint64_t reg_data_min_size =
1096 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
1097 if (data_sp->GetByteSize() < reg_data_min_size) {
1099 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
1100 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
1101 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
1105 const uint8_t *end = src + data_sp->GetByteSize();
1107 const RegisterSetType kind =
1108 *
reinterpret_cast<const RegisterSetType *
>(src);
1109 src +=
sizeof(RegisterSetType);
1112 case RegisterSetType::GPR:
1113 error = RestoreRegisters(
1114 GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
1115 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
1117 case RegisterSetType::SVE:
1119 m_sve_state =
static_cast<SVEState>(*src);
1120 src +=
sizeof(m_sve_state);
1124 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
1126 m_sve_header_is_valid =
false;
1128 "NativeRegisterContextLinux_arm64::%s "
1129 "Invalid SVE header in data_sp",
1133 m_sve_header_is_valid =
true;
1134 error = WriteSVEHeader();
1141 ConfigureRegisterContext();
1144 error = RestoreRegisters(
1145 GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
1146 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
1148 case RegisterSetType::FPR: {
1149 m_sve_buffer_is_valid =
false;
1150 m_sve_header_is_valid =
false;
1152 ConfigureRegisterContext();
1156 if (!GetRegisterInfo().IsSVEPresent() &&
1157 GetRegisterInfo().IsSSVEPresent() &&
1175 std::vector<uint8_t> sve_fpsimd_data(data_size);
1180 header->
size = sve_fpsimd_data.size();
1188 ioVec.iov_base = sve_fpsimd_data.data();
1189 ioVec.iov_len = sve_fpsimd_data.size();
1193 error = WriteRegisterSet(&ioVec, sve_fpsimd_data.size(), NT_ARM_SVE);
1196 src += GetFPRSize();
1198 if (
error.Success()) {
1200 m_fpu_is_valid =
false;
1201 m_sve_buffer_is_valid =
false;
1202 m_sve_header_is_valid =
false;
1205 ConfigureRegisterContext();
1210 error = RestoreRegisters(
1211 GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
1212 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
1216 case RegisterSetType::MTE:
1217 error = RestoreRegisters(
1218 GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
1219 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
1221 case RegisterSetType::TLS:
1222 error = RestoreRegisters(
1223 GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
1224 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
1226 case RegisterSetType::SME:
1232 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
1236 m_za_ptrace_payload.resize(m_za_header.size);
1237 ::memcpy(GetZABuffer(), src, GetZABufferSize());
1238 m_za_buffer_is_valid =
true;
1246 ConfigureRegisterContext();
1251 src += GetZABufferSize();
1253 case RegisterSetType::SME2:
1257 error = RestoreRegisters(
1258 GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
1259 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
1261 case RegisterSetType::FPMR:
1262 error = RestoreRegisters(
1263 GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid,
1264 std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR,
this));
1266 case RegisterSetType::GCS: {
1271 m_gcs_is_valid =
false;
1276 uint64_t enable_bit = m_gcs_regs.features_enabled & 1UL;
1277 gcs_regs new_gcs_regs = *
reinterpret_cast<const gcs_regs *
>(src);
1278 new_gcs_regs.features_enabled =
1279 (new_gcs_regs.features_enabled & ~1UL) | enable_bit;
1281 const uint8_t *new_gcs_src =
1282 reinterpret_cast<const uint8_t *
>(&new_gcs_regs);
1283 error = RestoreRegisters(
1284 GetGCSBuffer(), &new_gcs_src, GetGCSBufferSize(), m_gcs_is_valid,
1285 std::bind(&NativeRegisterContextLinux_arm64::WriteGCS,
this));
1286 src += GetGCSBufferSize();
1290 case RegisterSetType::POE:
1291 error = RestoreRegisters(
1292 GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid,
1293 std::bind(&NativeRegisterContextLinux_arm64::WritePOE,
this));
1304llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1305 if (!m_refresh_hwdebug_info) {
1306 return llvm::Error::success();
1309 ::pid_t tid = m_thread.GetID();
1312 m_max_hbp_supported);
1314 return error.ToError();
1316 m_refresh_hwdebug_info =
false;
1318 return llvm::Error::success();
1322NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1323 uint32_t max_supported =
1324 (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
1325 auto ®s = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
1331Status NativeRegisterContextLinux_arm64::ReadGPR() {
1338 ioVec.iov_base = GetGPRBuffer();
1339 ioVec.iov_len = GetGPRBufferSize();
1341 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1343 if (
error.Success())
1344 m_gpr_is_valid =
true;
1349Status NativeRegisterContextLinux_arm64::WriteGPR() {
1355 ioVec.iov_base = GetGPRBuffer();
1356 ioVec.iov_len = GetGPRBufferSize();
1358 m_gpr_is_valid =
false;
1360 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1363Status NativeRegisterContextLinux_arm64::ReadFPR() {
1370 ioVec.iov_base = GetFPRBuffer();
1371 ioVec.iov_len = GetFPRSize();
1373 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1374 if (
error.Success())
1375 m_fpu_is_valid =
true;
1380Status NativeRegisterContextLinux_arm64::WriteFPR() {
1386 ioVec.iov_base = GetFPRBuffer();
1387 ioVec.iov_len = GetFPRSize();
1389 m_fpu_is_valid =
false;
1391 m_sve_buffer_is_valid =
false;
1392 m_sve_header_is_valid =
false;
1394 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1397void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1398 m_gpr_is_valid =
false;
1399 m_fpu_is_valid =
false;
1400 m_sve_buffer_is_valid =
false;
1401 m_sve_header_is_valid =
false;
1402 m_za_buffer_is_valid =
false;
1403 m_za_header_is_valid =
false;
1404 m_pac_mask_is_valid =
false;
1405 m_mte_ctrl_is_valid =
false;
1406 m_tls_is_valid =
false;
1407 m_zt_buffer_is_valid =
false;
1408 m_fpmr_is_valid =
false;
1409 m_gcs_is_valid =
false;
1410 m_poe_is_valid =
false;
1413 ConfigureRegisterContext();
1416unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1417 switch (m_sve_state) {
1426Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1429 if (m_sve_header_is_valid)
1433 ioVec.iov_base = GetSVEHeader();
1434 ioVec.iov_len = GetSVEHeaderSize();
1436 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1438 if (
error.Success())
1439 m_sve_header_is_valid =
true;
1444Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1447 if (m_pac_mask_is_valid)
1451 ioVec.iov_base = GetPACMask();
1452 ioVec.iov_len = GetPACMaskSize();
1454 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
1456 if (
error.Success())
1457 m_pac_mask_is_valid =
true;
1462Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1465 error = ReadSVEHeader();
1470 ioVec.iov_base = GetSVEHeader();
1471 ioVec.iov_len = GetSVEHeaderSize();
1473 m_sve_buffer_is_valid =
false;
1474 m_sve_header_is_valid =
false;
1475 m_fpu_is_valid =
false;
1477 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1480Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1482 if (m_sve_buffer_is_valid)
1486 ioVec.iov_base = GetSVEBuffer();
1487 ioVec.iov_len = GetSVEBufferSize();
1489 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1491 if (
error.Success())
1492 m_sve_buffer_is_valid =
true;
1497Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1500 error = ReadAllSVE();
1506 ioVec.iov_base = GetSVEBuffer();
1507 ioVec.iov_len = GetSVEBufferSize();
1509 m_sve_buffer_is_valid =
false;
1510 m_sve_header_is_valid =
false;
1511 m_fpu_is_valid =
false;
1513 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1516Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1528 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1529 m_sme_pseudo_regs.ctrl_reg |= 2;
1534Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1537 if (m_mte_ctrl_is_valid)
1541 ioVec.iov_base = GetMTEControl();
1542 ioVec.iov_len = GetMTEControlSize();
1544 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1546 if (
error.Success())
1547 m_mte_ctrl_is_valid =
true;
1552Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1555 error = ReadMTEControl();
1560 ioVec.iov_base = GetMTEControl();
1561 ioVec.iov_len = GetMTEControlSize();
1563 m_mte_ctrl_is_valid =
false;
1565 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1568Status NativeRegisterContextLinux_arm64::ReadTLS() {
1575 ioVec.iov_base = GetTLSBuffer();
1576 ioVec.iov_len = GetTLSBufferSize();
1578 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1580 if (
error.Success())
1581 m_tls_is_valid =
true;
1586Status NativeRegisterContextLinux_arm64::WriteTLS() {
1594 ioVec.iov_base = GetTLSBuffer();
1595 ioVec.iov_len = GetTLSBufferSize();
1597 m_tls_is_valid =
false;
1599 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1602Status NativeRegisterContextLinux_arm64::ReadGCS() {
1609 ioVec.iov_base = GetGCSBuffer();
1610 ioVec.iov_len = GetGCSBufferSize();
1612 error = ReadRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1614 if (
error.Success())
1615 m_gcs_is_valid =
true;
1620Status NativeRegisterContextLinux_arm64::WriteGCS() {
1628 ioVec.iov_base = GetGCSBuffer();
1629 ioVec.iov_len = GetGCSBufferSize();
1631 m_gcs_is_valid =
false;
1633 return WriteRegisterSet(&ioVec, GetGCSBufferSize(), NT_ARM_GCS);
1636Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1639 if (m_za_header_is_valid)
1643 ioVec.iov_base = GetZAHeader();
1644 ioVec.iov_len = GetZAHeaderSize();
1646 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), NT_ARM_ZA);
1648 if (
error.Success())
1649 m_za_header_is_valid =
true;
1654Status NativeRegisterContextLinux_arm64::ReadZA() {
1657 if (m_za_buffer_is_valid)
1661 ioVec.iov_base = GetZABuffer();
1662 ioVec.iov_len = GetZABufferSize();
1664 error = ReadRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1666 if (
error.Success())
1667 m_za_buffer_is_valid =
true;
1672Status NativeRegisterContextLinux_arm64::WriteZA() {
1683 ioVec.iov_base = GetZABuffer();
1684 ioVec.iov_len = GetZABufferSize();
1686 m_za_buffer_is_valid =
false;
1687 m_za_header_is_valid =
false;
1689 m_zt_buffer_is_valid =
false;
1691 return WriteRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1694Status NativeRegisterContextLinux_arm64::ReadZT() {
1697 if (m_zt_buffer_is_valid)
1701 ioVec.iov_base = GetZTBuffer();
1702 ioVec.iov_len = GetZTBufferSize();
1704 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1705 m_zt_buffer_is_valid =
error.Success();
1710Status NativeRegisterContextLinux_arm64::WriteZT() {
1718 ioVec.iov_base = GetZTBuffer();
1719 ioVec.iov_len = GetZTBufferSize();
1721 m_zt_buffer_is_valid =
false;
1724 m_za_buffer_is_valid =
false;
1725 m_za_header_is_valid =
false;
1727 return WriteRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1730Status NativeRegisterContextLinux_arm64::ReadFPMR() {
1733 if (m_fpmr_is_valid)
1737 ioVec.iov_base = GetFPMRBuffer();
1738 ioVec.iov_len = GetFPMRBufferSize();
1740 error = ReadRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1742 if (
error.Success())
1743 m_fpmr_is_valid =
true;
1748Status NativeRegisterContextLinux_arm64::WriteFPMR() {
1756 ioVec.iov_base = GetFPMRBuffer();
1757 ioVec.iov_len = GetFPMRBufferSize();
1759 m_fpmr_is_valid =
false;
1761 return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR);
1764Status NativeRegisterContextLinux_arm64::ReadPOE() {
1771 ioVec.iov_base = GetPOEBuffer();
1772 ioVec.iov_len = GetPOEBufferSize();
1774 error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1776 if (
error.Success())
1777 m_poe_is_valid =
true;
1782Status NativeRegisterContextLinux_arm64::WritePOE() {
1790 ioVec.iov_base = GetPOEBuffer();
1791 ioVec.iov_len = GetPOEBufferSize();
1793 m_poe_is_valid =
false;
1795 return WriteRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE);
1798void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1810 m_sve_header_is_valid =
false;
1811 m_sve_buffer_is_valid =
false;
1815 bool has_sme =
error.Success();
1816 bool sme_is_active =
1821 m_sve_header_is_valid =
false;
1822 m_sve_buffer_is_valid =
false;
1824 error = ReadSVEHeader();
1826 bool has_sve =
error.Success();
1827 bool sve_is_active =
1838 else if (sve_is_active)
1840 else if (fp_is_active)
1852 m_sve_header_is_valid =
false;
1853 m_sve_buffer_is_valid =
false;
1854 error = ReadSVEHeader();
1862 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1867 if (!m_za_header_is_valid) {
1869 if (
error.Success()) {
1874 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1875 m_za_ptrace_payload.resize(m_za_header.size);
1876 m_za_buffer_is_valid =
false;
1881uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1882 const RegisterInfo *reg_info,
bool streaming_fpsimd)
const {
1883 uint32_t offset = reg_info->
byte_offset - GetGPRSize();
1884 if (!streaming_fpsimd)
1896 const size_t fpsr_offset = 16 * 32;
1898 if (reg == GetRegisterInfo().GetRegNumFPSR())
1899 offset = fpsr_offset;
1900 else if (reg == GetRegisterInfo().GetRegNumFPCR())
1901 offset = fpsr_offset + 4;
1903 offset = 16 * (reg - GetRegisterInfo().GetRegNumFPV0());
1908uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1915 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1919 uint32_t sve_z0_offset = GetGPRSize() + 16;
1923 return sve_reg_offset;
1926Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1930 if (
error.Success())
1931 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1936std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1938 std::vector<uint32_t> expedited_reg_nums =
1942 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1945 if (GetRegisterInfo().IsSSVEPresent())
1946 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1948 return expedited_reg_nums;
1951llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1952NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
1954 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
1958 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1959 "Unknown AArch64 memory tag type %d", type);
1962lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
1970 if (ReadPAuthMask().
Success())
1971 mask |= m_pac_mask.data_mask;
1973 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.