9#if defined(__arm64__) || defined(__aarch64__)
38#define NT_ARM_SVE 0x405
47#define NT_ARM_ZA 0x40c
55#ifndef NT_ARM_PAC_MASK
56#define NT_ARM_PAC_MASK 0x406
59#ifndef NT_ARM_TAGGED_ADDR_CTRL
60#define NT_ARM_TAGGED_ADDR_CTRL 0x409
63#define HWCAP_PACA (1 << 30)
65#define HWCAP2_MTE (1 << 18)
75static std::mutex g_register_flags_mutex;
78std::unique_ptr<NativeRegisterContextLinux>
79NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
82 case llvm::Triple::arm:
83 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
85 case llvm::Triple::aarch64: {
90 ioVec.iov_base = &sve_header;
91 ioVec.iov_len =
sizeof(sve_header);
92 unsigned int regset = NT_ARM_SVE;
96 native_thread.
GetID(), ®set,
97 &ioVec,
sizeof(sve_header))
103 ioVec.iov_len =
sizeof(sve_header);
104 regset = NT_ARM_SSVE;
106 native_thread.
GetID(), ®set,
107 &ioVec,
sizeof(sve_header))
113 ioVec.iov_base = &za_header;
114 ioVec.iov_len =
sizeof(za_header);
117 native_thread.
GetID(), ®set,
118 &ioVec,
sizeof(za_header))
123 std::array<uint8_t, 64> zt_reg;
124 ioVec.iov_base = zt_reg.data();
125 ioVec.iov_len = zt_reg.size();
128 native_thread.
GetID(), ®set,
129 &ioVec, zt_reg.size())
135 std::optional<uint64_t> auxv_at_hwcap =
137 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
140 std::optional<uint64_t> auxv_at_hwcap2 =
142 if (auxv_at_hwcap2 && (*auxv_at_hwcap2 &
HWCAP2_MTE))
147 std::lock_guard<std::mutex> lock(g_register_flags_mutex);
149 g_register_flags.
DetectFields(auxv_at_hwcap.value_or(0),
150 auxv_at_hwcap2.value_or(0));
152 auto register_info_up =
153 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
154 return std::make_unique<NativeRegisterContextLinux_arm64>(
155 target_arch, native_thread, std::move(register_info_up));
158 llvm_unreachable(
"have no register context for architecture");
162llvm::Expected<ArchSpec>
163NativeRegisterContextLinux::DetermineArchitecture(
lldb::tid_t tid) {
164 return DetermineArchitectureViaGPR(
168NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
170 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
172 register_info_up.release()),
175 GetRegisterInfoInterface().GetRegisterInfo(),
176 GetRegisterInfoInterface().GetRegisterCount());
178 ::memset(&m_fpr, 0,
sizeof(m_fpr));
179 ::memset(&m_gpr_arm64, 0,
sizeof(m_gpr_arm64));
180 ::memset(&m_hwp_regs, 0,
sizeof(m_hwp_regs));
181 ::memset(&m_hbp_regs, 0,
sizeof(m_hbp_regs));
182 ::memset(&m_sve_header, 0,
sizeof(m_sve_header));
183 ::memset(&m_pac_mask, 0,
sizeof(m_pac_mask));
184 ::memset(&m_tls_regs, 0,
sizeof(m_tls_regs));
185 ::memset(&m_sme_pseudo_regs, 0,
sizeof(m_sme_pseudo_regs));
186 std::fill(m_zt_reg.begin(), m_zt_reg.end(), 0);
191 m_max_hwp_supported = 16;
192 m_max_hbp_supported = 16;
194 m_refresh_hwdebug_info =
true;
196 m_gpr_is_valid =
false;
197 m_fpu_is_valid =
false;
198 m_sve_buffer_is_valid =
false;
199 m_sve_header_is_valid =
false;
200 m_pac_mask_is_valid =
false;
201 m_mte_ctrl_is_valid =
false;
202 m_tls_is_valid =
false;
203 m_zt_buffer_is_valid =
false;
206 m_tls_size = GetRegisterInfo().IsSSVEPresent() ?
sizeof(m_tls_regs)
207 :
sizeof(m_tls_regs.tpidr_reg);
209 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent())
216NativeRegisterContextLinux_arm64::GetRegisterInfo()
const {
220uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount()
const {
225NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index)
const {
226 return GetRegisterInfo().GetRegisterSet(set_index);
229uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount()
const {
231 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
237NativeRegisterContextLinux_arm64::ReadRegister(
const RegisterInfo *reg_info,
242 error.SetErrorString(
"reg_info NULL");
249 return Status(
"no lldb regnum for %s", reg_info && reg_info->
name
251 :
"<unknown register>");
256 std::vector<uint8_t> sve_reg_non_live;
264 assert(offset < GetGPRSize());
265 src = (uint8_t *)GetGPRBuffer() + offset;
267 }
else if (IsFPR(reg)) {
274 offset = CalculateFprOffset(reg_info);
275 assert(offset < GetFPRSize());
276 src = (uint8_t *)GetFPRBuffer() + offset;
281 error = ReadAllSVE();
290 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
293 offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
295 offset = sve::ptrace_fpsimd_offset + (32 * 16);
296 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
299 offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
301 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
307 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
310 assert(offset < GetSVEBufferSize());
311 src = (uint8_t *)GetSVEBuffer() + offset;
313 }
else if (IsTLS(reg)) {
318 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
319 assert(offset < GetTLSBufferSize());
320 src = (uint8_t *)GetTLSBuffer() + offset;
321 }
else if (IsSVE(reg)) {
323 return Status(
"SVE disabled or not supported");
325 if (GetRegisterInfo().IsSVERegVG(reg)) {
326 sve_vg = GetSVERegVG();
327 src = (uint8_t *)&sve_vg;
330 error = ReadAllSVE();
338 sve_reg_non_live.resize(reg_info->
byte_size, 0);
339 src = sve_reg_non_live.data();
341 if (GetRegisterInfo().IsSVEZReg(reg)) {
342 offset = CalculateSVEOffset(reg_info);
343 assert(offset < GetSVEBufferSize());
344 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
348 offset = CalculateSVEOffset(reg_info);
349 assert(offset < GetSVEBufferSize());
350 src = (uint8_t *)GetSVEBuffer() + offset;
353 }
else if (IsPAuth(reg)) {
354 error = ReadPAuthMask();
358 offset = reg_info->
byte_offset - GetRegisterInfo().GetPAuthOffset();
359 assert(offset < GetPACMaskSize());
360 src = (uint8_t *)GetPACMask() + offset;
361 }
else if (IsMTE(reg)) {
362 error = ReadMTEControl();
366 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
367 assert(offset < GetMTEControlSize());
368 src = (uint8_t *)GetMTEControl() + offset;
369 }
else if (IsSME(reg)) {
370 if (GetRegisterInfo().IsSMERegZA(reg)) {
371 error = ReadZAHeader();
377 if (m_za_header.size ==
sizeof(m_za_header)) {
381 m_za_ptrace_payload.resize(((m_za_header.vl) * (m_za_header.vl)) +
383 std::fill(m_za_ptrace_payload.begin(), m_za_ptrace_payload.end(), 0);
394 src = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
395 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
403 src = (uint8_t *)GetZTBuffer();
405 error = ReadSMESVG();
412 offset = reg_info->
byte_offset - GetRegisterInfo().GetSMEOffset();
413 assert(offset < GetSMEPseudoBufferSize());
414 src = (uint8_t *)GetSMEPseudoBuffer() + offset;
417 return Status(
"failed - register wasn't recognized to be a GPR or an FPR, "
418 "write strategy unknown");
421 eByteOrderLittle,
error);
426Status NativeRegisterContextLinux_arm64::WriteRegister(
431 return Status(
"reg_info NULL");
436 return Status(
"no lldb regnum for %s", reg_info && reg_info->
name
438 :
"<unknown register>");
442 std::vector<uint8_t> sve_reg_non_live;
450 dst = (uint8_t *)GetGPRBuffer() + reg_info->
byte_offset;
454 }
else if (IsFPR(reg)) {
461 offset = CalculateFprOffset(reg_info);
462 assert(offset < GetFPRSize());
463 dst = (uint8_t *)GetFPRBuffer() + offset;
469 error = ReadAllSVE();
478 if (reg == GetRegisterInfo().GetRegNumFPSR()) {
481 offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
483 offset = sve::ptrace_fpsimd_offset + (32 * 16);
484 }
else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
487 offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
489 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
495 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
498 assert(offset < GetSVEBufferSize());
499 dst = (uint8_t *)GetSVEBuffer() + offset;
501 return WriteAllSVE();
503 }
else if (IsSVE(reg)) {
505 return Status(
"SVE disabled or not supported");
508 error = ReadAllSVE();
512 if (GetRegisterInfo().IsSVERegVG(reg)) {
515 if (sve::vl_valid(vg_value * 8)) {
516 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
519 SetSVERegVG(vg_value);
521 error = WriteSVEHeader();
522 if (
error.Success()) {
525 m_za_header_is_valid =
false;
526 ConfigureRegisterContext();
529 if (m_sve_header_is_valid && vg_value == GetSVERegVG())
533 return Status(
"SVE vector length update failed.");
540 bool set_sve_state_full =
false;
541 const uint8_t *reg_bytes = (
const uint8_t *)reg_value.
GetBytes();
542 if (GetRegisterInfo().IsSVEZReg(reg)) {
543 for (uint32_t i = 16; i < reg_info->
byte_size; i++) {
545 set_sve_state_full =
true;
549 }
else if (GetRegisterInfo().IsSVEPReg(reg) ||
550 reg == GetRegisterInfo().GetRegNumSVEFFR()) {
551 for (uint32_t i = 0; i < reg_info->
byte_size; i++) {
553 set_sve_state_full =
true;
559 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
562 offset = CalculateSVEOffset(reg_info);
563 assert(offset < GetSVEBufferSize());
564 dst = (uint8_t *)GetSVEBuffer() + offset;
565 ::memcpy(dst, reg_value.
GetBytes(), 16);
567 return WriteAllSVE();
569 return Status(
"SVE state change operation not supported");
571 offset = CalculateSVEOffset(reg_info);
572 assert(offset < GetSVEBufferSize());
573 dst = (uint8_t *)GetSVEBuffer() + offset;
575 return WriteAllSVE();
578 }
else if (IsMTE(reg)) {
579 error = ReadMTEControl();
583 offset = reg_info->
byte_offset - GetRegisterInfo().GetMTEOffset();
584 assert(offset < GetMTEControlSize());
585 dst = (uint8_t *)GetMTEControl() + offset;
588 return WriteMTEControl();
589 }
else if (IsTLS(reg)) {
594 offset = reg_info->
byte_offset - GetRegisterInfo().GetTLSOffset();
595 assert(offset < GetTLSBufferSize());
596 dst = (uint8_t *)GetTLSBuffer() + offset;
600 }
else if (IsSME(reg)) {
601 if (GetRegisterInfo().IsSMERegZA(reg)) {
608 dst = (uint8_t *)GetZABuffer() + GetZAHeaderSize();
615 }
else if (GetRegisterInfo().IsSMERegZT(reg)) {
620 dst = (uint8_t *)GetZTBuffer();
625 return Status(
"Writing to SVG or SVCR is not supported.");
628 return Status(
"Failed to write register value");
631enum RegisterSetType : uint32_t {
642static uint8_t *AddRegisterSetType(uint8_t *dst,
643 RegisterSetType register_set_type) {
644 *(
reinterpret_cast<uint32_t *
>(dst)) = register_set_type;
645 return dst +
sizeof(uint32_t);
648static uint8_t *AddSavedRegistersData(uint8_t *dst,
void *src,
size_t size) {
649 ::memcpy(dst, src, size);
653static uint8_t *AddSavedRegisters(uint8_t *dst,
654 enum RegisterSetType register_set_type,
655 void *src,
size_t size) {
656 dst = AddRegisterSetType(dst, register_set_type);
657 return AddSavedRegistersData(dst, src, size);
661NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) {
663 cached_size =
sizeof(RegisterSetType) + GetGPRBufferSize();
668 if (GetRegisterInfo().IsZAPresent()) {
669 error = ReadZAHeader();
676 cached_size +=
sizeof(RegisterSetType) + m_za_header.size;
679 m_za_buffer_is_valid =
false;
688 GetRegisterInfo().IsZTPresent() &&
690 m_za_header.size >
sizeof(m_za_header)) {
691 cached_size +=
sizeof(RegisterSetType) + GetZTBufferSize();
701 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) {
704 sizeof(RegisterSetType) +
sizeof(m_sve_state) + GetSVEBufferSize();
705 error = ReadAllSVE();
707 cached_size +=
sizeof(RegisterSetType) + GetFPRSize();
713 if (GetRegisterInfo().IsMTEPresent()) {
714 cached_size +=
sizeof(RegisterSetType) + GetMTEControlSize();
715 error = ReadMTEControl();
721 cached_size +=
sizeof(RegisterSetType) + GetTLSBufferSize();
727Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
739 uint32_t reg_data_byte_size = 0;
740 Status error = CacheAllRegisters(reg_data_byte_size);
745 uint8_t *dst = data_sp->GetBytes();
747 dst = AddSavedRegisters(dst, RegisterSetType::GPR, GetGPRBuffer(),
784 assert(m_za_header.size <= GetZABufferSize());
785 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
789 if (GetRegisterInfo().IsSVEPresent() || GetRegisterInfo().IsSSVEPresent()) {
790 dst = AddRegisterSetType(dst, RegisterSetType::SVE);
791 *(
reinterpret_cast<SVEState *
>(dst)) = m_sve_state;
792 dst +=
sizeof(m_sve_state);
793 dst = AddSavedRegistersData(dst, GetSVEBuffer(), GetSVEBufferSize());
795 dst = AddSavedRegisters(dst, RegisterSetType::FPR, GetFPRBuffer(),
800 assert(m_za_header.size <= GetZABufferSize());
801 dst = AddSavedRegisters(dst, RegisterSetType::SME, GetZABuffer(),
812 GetRegisterInfo().IsZTPresent() &&
814 m_za_header.size >
sizeof(m_za_header))
815 dst = AddSavedRegisters(dst, RegisterSetType::SME2, GetZTBuffer(),
818 if (GetRegisterInfo().IsMTEPresent()) {
819 dst = AddSavedRegisters(dst, RegisterSetType::MTE, GetMTEControl(),
820 GetMTEControlSize());
823 dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(),
829static Status RestoreRegisters(
void *buffer,
const uint8_t **src,
size_t len,
830 bool &is_valid, std::function<
Status()> writer) {
831 ::memcpy(buffer, *src, len);
837Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
852 error.SetErrorStringWithFormat(
853 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
858 const uint8_t *src = data_sp->GetBytes();
859 if (src ==
nullptr) {
860 error.SetErrorStringWithFormat(
"NativeRegisterContextLinux_arm64::%s "
861 "DataBuffer::GetBytes() returned a null "
867 uint64_t reg_data_min_size =
868 GetGPRBufferSize() + GetFPRSize() + 2 * (
sizeof(RegisterSetType));
869 if (data_sp->GetByteSize() < reg_data_min_size) {
870 error.SetErrorStringWithFormat(
871 "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
872 "register data bytes, expected at least %" PRIu64
", actual %" PRIu64,
873 __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
877 const uint8_t *end = src + data_sp->GetByteSize();
879 const RegisterSetType kind =
880 *
reinterpret_cast<const RegisterSetType *
>(src);
881 src +=
sizeof(RegisterSetType);
884 case RegisterSetType::GPR:
885 error = RestoreRegisters(
886 GetGPRBuffer(), &src, GetGPRBufferSize(), m_gpr_is_valid,
887 std::bind(&NativeRegisterContextLinux_arm64::WriteGPR,
this));
889 case RegisterSetType::SVE:
891 m_sve_state =
static_cast<SVEState>(*src);
892 src +=
sizeof(m_sve_state);
896 ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
897 if (!sve::vl_valid(m_sve_header.vl)) {
898 m_sve_header_is_valid =
false;
899 error.SetErrorStringWithFormat(
"NativeRegisterContextLinux_arm64::%s "
900 "Invalid SVE header in data_sp",
904 m_sve_header_is_valid =
true;
905 error = WriteSVEHeader();
912 ConfigureRegisterContext();
915 error = RestoreRegisters(
916 GetSVEBuffer(), &src, GetSVEBufferSize(), m_sve_buffer_is_valid,
917 std::bind(&NativeRegisterContextLinux_arm64::WriteAllSVE,
this));
919 case RegisterSetType::FPR:
920 error = RestoreRegisters(
921 GetFPRBuffer(), &src, GetFPRSize(), m_fpu_is_valid,
922 std::bind(&NativeRegisterContextLinux_arm64::WriteFPR,
this));
924 case RegisterSetType::MTE:
925 error = RestoreRegisters(
926 GetMTEControl(), &src, GetMTEControlSize(), m_mte_ctrl_is_valid,
927 std::bind(&NativeRegisterContextLinux_arm64::WriteMTEControl,
this));
929 case RegisterSetType::TLS:
930 error = RestoreRegisters(
931 GetTLSBuffer(), &src, GetTLSBufferSize(), m_tls_is_valid,
932 std::bind(&NativeRegisterContextLinux_arm64::WriteTLS,
this));
934 case RegisterSetType::SME:
940 ::memcpy(GetZAHeader(), src, GetZAHeaderSize());
944 m_za_ptrace_payload.resize(m_za_header.size);
945 ::memcpy(GetZABuffer(), src, GetZABufferSize());
946 m_za_buffer_is_valid =
true;
954 ConfigureRegisterContext();
959 src += GetZABufferSize();
961 case RegisterSetType::SME2:
965 error = RestoreRegisters(
966 GetZTBuffer(), &src, GetZTBufferSize(), m_zt_buffer_is_valid,
967 std::bind(&NativeRegisterContextLinux_arm64::WriteZT,
this));
978bool NativeRegisterContextLinux_arm64::IsGPR(
unsigned reg)
const {
979 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
985bool NativeRegisterContextLinux_arm64::IsFPR(
unsigned reg)
const {
986 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
992bool NativeRegisterContextLinux_arm64::IsSVE(
unsigned reg)
const {
993 return GetRegisterInfo().IsSVEReg(reg);
996bool NativeRegisterContextLinux_arm64::IsSME(
unsigned reg)
const {
997 return GetRegisterInfo().IsSMEReg(reg);
1000bool NativeRegisterContextLinux_arm64::IsPAuth(
unsigned reg)
const {
1001 return GetRegisterInfo().IsPAuthReg(reg);
1004bool NativeRegisterContextLinux_arm64::IsMTE(
unsigned reg)
const {
1005 return GetRegisterInfo().IsMTEReg(reg);
1008bool NativeRegisterContextLinux_arm64::IsTLS(
unsigned reg)
const {
1009 return GetRegisterInfo().IsTLSReg(reg);
1012llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
1013 if (!m_refresh_hwdebug_info) {
1014 return llvm::Error::success();
1017 ::pid_t tid = m_thread.GetID();
1019 int regset = NT_ARM_HW_WATCH;
1021 struct user_hwdebug_state dreg_state;
1024 ioVec.iov_base = &dreg_state;
1025 ioVec.iov_len =
sizeof(dreg_state);
1027 &ioVec, ioVec.iov_len);
1030 return error.ToError();
1032 m_max_hwp_supported = dreg_state.dbg_info & 0xff;
1034 regset = NT_ARM_HW_BREAK;
1036 &ioVec, ioVec.iov_len);
1039 return error.ToError();
1041 m_max_hbp_supported = dreg_state.dbg_info & 0xff;
1042 m_refresh_hwdebug_info =
false;
1044 return llvm::Error::success();
1048NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
1050 struct user_hwdebug_state dreg_state;
1053 memset(&dreg_state, 0,
sizeof(dreg_state));
1054 ioVec.iov_base = &dreg_state;
1057 case eDREGTypeWATCH:
1058 regset = NT_ARM_HW_WATCH;
1059 ioVec.iov_len =
sizeof(dreg_state.dbg_info) +
sizeof(dreg_state.pad) +
1060 (
sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
1062 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
1063 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
1064 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
1067 case eDREGTypeBREAK:
1068 regset = NT_ARM_HW_BREAK;
1069 ioVec.iov_len =
sizeof(dreg_state.dbg_info) +
sizeof(dreg_state.pad) +
1070 (
sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
1072 for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
1073 dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
1074 dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
1079 return NativeProcessLinux::PtraceWrapper(
PTRACE_SETREGSET, m_thread.GetID(),
1080 ®set, &ioVec, ioVec.iov_len)
1084Status NativeRegisterContextLinux_arm64::ReadGPR() {
1091 ioVec.iov_base = GetGPRBuffer();
1092 ioVec.iov_len = GetGPRBufferSize();
1094 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1096 if (
error.Success())
1097 m_gpr_is_valid =
true;
1102Status NativeRegisterContextLinux_arm64::WriteGPR() {
1108 ioVec.iov_base = GetGPRBuffer();
1109 ioVec.iov_len = GetGPRBufferSize();
1111 m_gpr_is_valid =
false;
1113 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
1116Status NativeRegisterContextLinux_arm64::ReadFPR() {
1123 ioVec.iov_base = GetFPRBuffer();
1124 ioVec.iov_len = GetFPRSize();
1126 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1128 if (
error.Success())
1129 m_fpu_is_valid =
true;
1134Status NativeRegisterContextLinux_arm64::WriteFPR() {
1140 ioVec.iov_base = GetFPRBuffer();
1141 ioVec.iov_len = GetFPRSize();
1143 m_fpu_is_valid =
false;
1145 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
1148void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
1149 m_gpr_is_valid =
false;
1150 m_fpu_is_valid =
false;
1151 m_sve_buffer_is_valid =
false;
1152 m_sve_header_is_valid =
false;
1153 m_za_buffer_is_valid =
false;
1154 m_za_header_is_valid =
false;
1155 m_pac_mask_is_valid =
false;
1156 m_mte_ctrl_is_valid =
false;
1157 m_tls_is_valid =
false;
1158 m_zt_buffer_is_valid =
false;
1161 ConfigureRegisterContext();
1164unsigned NativeRegisterContextLinux_arm64::GetSVERegSet() {
1168Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
1171 if (m_sve_header_is_valid)
1175 ioVec.iov_base = GetSVEHeader();
1176 ioVec.iov_len = GetSVEHeaderSize();
1178 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1180 if (
error.Success())
1181 m_sve_header_is_valid =
true;
1186Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
1189 if (m_pac_mask_is_valid)
1193 ioVec.iov_base = GetPACMask();
1194 ioVec.iov_len = GetPACMaskSize();
1196 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
1198 if (
error.Success())
1199 m_pac_mask_is_valid =
true;
1204Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
1207 error = ReadSVEHeader();
1212 ioVec.iov_base = GetSVEHeader();
1213 ioVec.iov_len = GetSVEHeaderSize();
1215 m_sve_buffer_is_valid =
false;
1216 m_sve_header_is_valid =
false;
1217 m_fpu_is_valid =
false;
1219 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), GetSVERegSet());
1222Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
1224 if (m_sve_buffer_is_valid)
1228 ioVec.iov_base = GetSVEBuffer();
1229 ioVec.iov_len = GetSVEBufferSize();
1231 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1233 if (
error.Success())
1234 m_sve_buffer_is_valid =
true;
1239Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
1242 error = ReadAllSVE();
1248 ioVec.iov_base = GetSVEBuffer();
1249 ioVec.iov_len = GetSVEBufferSize();
1251 m_sve_buffer_is_valid =
false;
1252 m_sve_header_is_valid =
false;
1253 m_fpu_is_valid =
false;
1255 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
1258Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
1270 if (
error.Success() && (m_za_header.size >
sizeof(m_za_header)))
1271 m_sme_pseudo_regs.ctrl_reg |= 2;
1276Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
1279 if (m_mte_ctrl_is_valid)
1283 ioVec.iov_base = GetMTEControl();
1284 ioVec.iov_len = GetMTEControlSize();
1286 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1288 if (
error.Success())
1289 m_mte_ctrl_is_valid =
true;
1294Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
1297 error = ReadMTEControl();
1302 ioVec.iov_base = GetMTEControl();
1303 ioVec.iov_len = GetMTEControlSize();
1305 m_mte_ctrl_is_valid =
false;
1307 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
1310Status NativeRegisterContextLinux_arm64::ReadTLS() {
1317 ioVec.iov_base = GetTLSBuffer();
1318 ioVec.iov_len = GetTLSBufferSize();
1320 error = ReadRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1322 if (
error.Success())
1323 m_tls_is_valid =
true;
1328Status NativeRegisterContextLinux_arm64::WriteTLS() {
1336 ioVec.iov_base = GetTLSBuffer();
1337 ioVec.iov_len = GetTLSBufferSize();
1339 m_tls_is_valid =
false;
1341 return WriteRegisterSet(&ioVec, GetTLSBufferSize(), NT_ARM_TLS);
1344Status NativeRegisterContextLinux_arm64::ReadZAHeader() {
1347 if (m_za_header_is_valid)
1351 ioVec.iov_base = GetZAHeader();
1352 ioVec.iov_len = GetZAHeaderSize();
1354 error = ReadRegisterSet(&ioVec, GetZAHeaderSize(), NT_ARM_ZA);
1356 if (
error.Success())
1357 m_za_header_is_valid =
true;
1362Status NativeRegisterContextLinux_arm64::ReadZA() {
1365 if (m_za_buffer_is_valid)
1369 ioVec.iov_base = GetZABuffer();
1370 ioVec.iov_len = GetZABufferSize();
1372 error = ReadRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1374 if (
error.Success())
1375 m_za_buffer_is_valid =
true;
1380Status NativeRegisterContextLinux_arm64::WriteZA() {
1391 ioVec.iov_base = GetZABuffer();
1392 ioVec.iov_len = GetZABufferSize();
1394 m_za_buffer_is_valid =
false;
1395 m_za_header_is_valid =
false;
1397 m_zt_buffer_is_valid =
false;
1399 return WriteRegisterSet(&ioVec, GetZABufferSize(), NT_ARM_ZA);
1402Status NativeRegisterContextLinux_arm64::ReadZT() {
1405 if (m_zt_buffer_is_valid)
1409 ioVec.iov_base = GetZTBuffer();
1410 ioVec.iov_len = GetZTBufferSize();
1412 error = ReadRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1413 m_zt_buffer_is_valid =
error.Success();
1418Status NativeRegisterContextLinux_arm64::WriteZT() {
1426 ioVec.iov_base = GetZTBuffer();
1427 ioVec.iov_len = GetZTBufferSize();
1429 m_zt_buffer_is_valid =
false;
1432 m_za_buffer_is_valid =
false;
1433 m_za_header_is_valid =
false;
1435 return WriteRegisterSet(&ioVec, GetZTBufferSize(), NT_ARM_ZT);
1438void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
1450 m_sve_header_is_valid =
false;
1451 m_sve_buffer_is_valid =
false;
1456 if (!(
error.Success() && ((m_sve_header.flags & sve::ptrace_regs_mask) ==
1457 sve::ptrace_regs_sve))) {
1459 m_sve_header_is_valid =
false;
1460 m_sve_buffer_is_valid =
false;
1462 error = ReadSVEHeader();
1463 if (
error.Success()) {
1466 if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
1467 sve::ptrace_regs_fpsimd)
1480 if (sve::vl_valid(m_sve_header.vl))
1481 vq = sve::vq_from_vl(m_sve_header.vl);
1483 GetRegisterInfo().ConfigureVectorLengthSVE(vq);
1484 m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve));
1488 if (!m_za_header_is_valid) {
1490 if (
error.Success()) {
1492 if (sve::vl_valid(m_za_header.vl))
1493 vq = sve::vq_from_vl(m_za_header.vl);
1495 GetRegisterInfo().ConfigureVectorLengthZA(vq);
1496 m_za_ptrace_payload.resize(m_za_header.size);
1497 m_za_buffer_is_valid =
false;
1502uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
1507uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
1513 sve_reg_offset = sve::ptrace_fpsimd_offset +
1514 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
1518 uint32_t sve_z0_offset = GetGPRSize() + 16;
1520 sve::SigRegsOffset() + reg_info->
byte_offset - sve_z0_offset;
1522 return sve_reg_offset;
1525Status NativeRegisterContextLinux_arm64::ReadSMESVG() {
1529 if (
error.Success())
1530 m_sme_pseudo_regs.svg_reg = m_za_header.vl / 8;
1535std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
1537 std::vector<uint32_t> expedited_reg_nums =
1538 NativeRegisterContext::GetExpeditedRegisters(expType);
1541 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
1544 if (GetRegisterInfo().IsSSVEPresent())
1545 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSMESVG());
1547 return expedited_reg_nums;
1550llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
1551NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
1552 if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) {
1553 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
1557 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1558 "Unknown AArch64 memory tag type %d", type);
1561lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
1569 if (ReadPAuthMask().Success())
1570 mask |= m_pac_mask.data_mask;
1572 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_HWCAP
Machine dependent hints about processor capabilities.
static size_t GetGPRSizeStatic()
size_t GetRegisterSetCount() const override
@ eVectorQuadwordAArch64SVE
An architecture specification class.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
A subclass of DataBuffer that stores a data buffer on the heap.
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
This class manages the storage and detection of register field information for Arm64 Linux registers.
void DetectFields(uint64_t hwcap, uint64_t hwcap2)
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.
std::optional< uint64_t > GetAuxValue(enum AuxVector::EntryType type)
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
Manages communication with the inferior (debugee) process.
NativeProcessLinux & GetProcess()
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_REGNUM
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.