1 //===-- NativeRegisterContextLinux_arm64.cpp ------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #if defined(__arm64__) || defined(__aarch64__) 10 11 #include "NativeRegisterContextLinux_arm.h" 12 #include "NativeRegisterContextLinux_arm64.h" 13 14 15 #include "lldb/Host/common/NativeProcessProtocol.h" 16 #include "lldb/Host/linux/Ptrace.h" 17 #include "lldb/Utility/DataBufferHeap.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/RegisterValue.h" 20 #include "lldb/Utility/Status.h" 21 22 #include "Plugins/Process/Linux/NativeProcessLinux.h" 23 #include "Plugins/Process/Linux/Procfs.h" 24 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 25 #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h" 26 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 27 28 // System includes - They have to be included after framework includes because 29 // they define some macros which collide with variable names in other modules 30 #include <sys/socket.h> 31 // NT_PRSTATUS and NT_FPREGSET definition 32 #include <elf.h> 33 34 #ifndef NT_ARM_SVE 35 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ 36 #endif 37 38 #ifndef NT_ARM_PAC_MASK 39 #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */ 40 #endif 41 42 #ifndef NT_ARM_TAGGED_ADDR_CTRL 43 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */ 44 #endif 45 46 #define HWCAP_PACA (1 << 30) 47 #define HWCAP2_MTE (1 << 18) 48 49 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 50 51 using namespace lldb; 52 using namespace lldb_private; 53 using namespace lldb_private::process_linux; 54 55 std::unique_ptr<NativeRegisterContextLinux> 56 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 57 const ArchSpec &target_arch, NativeThreadLinux &native_thread) { 58 switch (target_arch.GetMachine()) { 59 case llvm::Triple::arm: 60 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 61 native_thread); 62 case llvm::Triple::aarch64: { 63 // Configure register sets supported by this AArch64 target. 64 // Read SVE header to check for SVE support. 65 struct user_sve_header sve_header; 66 struct iovec ioVec; 67 ioVec.iov_base = &sve_header; 68 ioVec.iov_len = sizeof(sve_header); 69 unsigned int regset = NT_ARM_SVE; 70 71 Flags opt_regsets; 72 if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, 73 native_thread.GetID(), ®set, 74 &ioVec, sizeof(sve_header)) 75 .Success()) 76 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); 77 78 NativeProcessLinux &process = native_thread.GetProcess(); 79 80 llvm::Optional<uint64_t> auxv_at_hwcap = 81 process.GetAuxValue(AuxVector::AUXV_AT_HWCAP); 82 if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA)) 83 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth); 84 85 llvm::Optional<uint64_t> auxv_at_hwcap2 = 86 process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2); 87 if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE)) 88 opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE); 89 90 auto register_info_up = 91 std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets); 92 return std::make_unique<NativeRegisterContextLinux_arm64>( 93 target_arch, native_thread, std::move(register_info_up)); 94 } 95 default: 96 llvm_unreachable("have no register context for architecture"); 97 } 98 } 99 100 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 101 const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 102 std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up) 103 : NativeRegisterContextRegisterInfo(native_thread, 104 register_info_up.release()), 105 NativeRegisterContextLinux(native_thread) { 106 ::memset(&m_fpr, 0, sizeof(m_fpr)); 107 ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 108 ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 109 ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); 110 ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 111 ::memset(&m_pac_mask, 0, sizeof(m_pac_mask)); 112 113 m_mte_ctrl_reg = 0; 114 115 // 16 is just a maximum value, query hardware for actual watchpoint count 116 m_max_hwp_supported = 16; 117 m_max_hbp_supported = 16; 118 119 m_refresh_hwdebug_info = true; 120 121 m_gpr_is_valid = false; 122 m_fpu_is_valid = false; 123 m_sve_buffer_is_valid = false; 124 m_sve_header_is_valid = false; 125 m_pac_mask_is_valid = false; 126 m_mte_ctrl_is_valid = false; 127 128 if (GetRegisterInfo().IsSVEEnabled()) 129 m_sve_state = SVEState::Unknown; 130 else 131 m_sve_state = SVEState::Disabled; 132 } 133 134 RegisterInfoPOSIX_arm64 & 135 NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 136 return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 137 } 138 139 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 140 return GetRegisterInfo().GetRegisterSetCount(); 141 } 142 143 const RegisterSet * 144 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 145 return GetRegisterInfo().GetRegisterSet(set_index); 146 } 147 148 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 149 uint32_t count = 0; 150 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 151 count += GetRegisterSet(set_index)->num_registers; 152 return count; 153 } 154 155 Status 156 NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 157 RegisterValue ®_value) { 158 Status error; 159 160 if (!reg_info) { 161 error.SetErrorString("reg_info NULL"); 162 return error; 163 } 164 165 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 166 167 if (reg == LLDB_INVALID_REGNUM) 168 return Status("no lldb regnum for %s", reg_info && reg_info->name 169 ? reg_info->name 170 : "<unknown register>"); 171 172 uint8_t *src; 173 uint32_t offset = LLDB_INVALID_INDEX32; 174 uint64_t sve_vg; 175 std::vector<uint8_t> sve_reg_non_live; 176 177 if (IsGPR(reg)) { 178 error = ReadGPR(); 179 if (error.Fail()) 180 return error; 181 182 offset = reg_info->byte_offset; 183 assert(offset < GetGPRSize()); 184 src = (uint8_t *)GetGPRBuffer() + offset; 185 186 } else if (IsFPR(reg)) { 187 if (m_sve_state == SVEState::Disabled) { 188 // SVE is disabled take legacy route for FPU register access 189 error = ReadFPR(); 190 if (error.Fail()) 191 return error; 192 193 offset = CalculateFprOffset(reg_info); 194 assert(offset < GetFPRSize()); 195 src = (uint8_t *)GetFPRBuffer() + offset; 196 } else { 197 // SVE enabled, we will read and cache SVE ptrace data 198 error = ReadAllSVE(); 199 if (error.Fail()) 200 return error; 201 202 // FPSR and FPCR will be located right after Z registers in 203 // SVEState::FPSIMD while in SVEState::Full they will be located at the 204 // end of register data after an alignment correction based on currently 205 // selected vector length. 206 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 207 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 208 sve_reg_num = reg; 209 if (m_sve_state == SVEState::Full) 210 offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl)); 211 else if (m_sve_state == SVEState::FPSIMD) 212 offset = sve::ptrace_fpsimd_offset + (32 * 16); 213 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 214 sve_reg_num = reg; 215 if (m_sve_state == SVEState::Full) 216 offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl)); 217 else if (m_sve_state == SVEState::FPSIMD) 218 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4; 219 } else { 220 // Extract SVE Z register value register number for this reg_info 221 if (reg_info->value_regs && 222 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 223 sve_reg_num = reg_info->value_regs[0]; 224 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 225 } 226 227 assert(offset < GetSVEBufferSize()); 228 src = (uint8_t *)GetSVEBuffer() + offset; 229 } 230 } else if (IsSVE(reg)) { 231 232 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 233 return Status("SVE disabled or not supported"); 234 235 if (GetRegisterInfo().IsSVERegVG(reg)) { 236 sve_vg = GetSVERegVG(); 237 src = (uint8_t *)&sve_vg; 238 } else { 239 // SVE enabled, we will read and cache SVE ptrace data 240 error = ReadAllSVE(); 241 if (error.Fail()) 242 return error; 243 244 if (m_sve_state == SVEState::FPSIMD) { 245 // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 246 // just copy 16 bytes of v register to the start of z register. All 247 // other SVE register will be set to zero. 248 sve_reg_non_live.resize(reg_info->byte_size, 0); 249 src = sve_reg_non_live.data(); 250 251 if (GetRegisterInfo().IsSVEZReg(reg)) { 252 offset = CalculateSVEOffset(reg_info); 253 assert(offset < GetSVEBufferSize()); 254 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 255 16); 256 } 257 } else { 258 offset = CalculateSVEOffset(reg_info); 259 assert(offset < GetSVEBufferSize()); 260 src = (uint8_t *)GetSVEBuffer() + offset; 261 } 262 } 263 } else if (IsPAuth(reg)) { 264 error = ReadPAuthMask(); 265 if (error.Fail()) 266 return error; 267 268 offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset(); 269 assert(offset < GetPACMaskSize()); 270 src = (uint8_t *)GetPACMask() + offset; 271 } else if (IsMTE(reg)) { 272 error = ReadMTEControl(); 273 if (error.Fail()) 274 return error; 275 276 offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 277 assert(offset < GetMTEControlSize()); 278 src = (uint8_t *)GetMTEControl() + offset; 279 } else 280 return Status("failed - register wasn't recognized to be a GPR or an FPR, " 281 "write strategy unknown"); 282 283 reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 284 eByteOrderLittle, error); 285 286 return error; 287 } 288 289 Status NativeRegisterContextLinux_arm64::WriteRegister( 290 const RegisterInfo *reg_info, const RegisterValue ®_value) { 291 Status error; 292 293 if (!reg_info) 294 return Status("reg_info NULL"); 295 296 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 297 298 if (reg == LLDB_INVALID_REGNUM) 299 return Status("no lldb regnum for %s", reg_info && reg_info->name 300 ? reg_info->name 301 : "<unknown register>"); 302 303 uint8_t *dst; 304 uint32_t offset = LLDB_INVALID_INDEX32; 305 std::vector<uint8_t> sve_reg_non_live; 306 307 if (IsGPR(reg)) { 308 error = ReadGPR(); 309 if (error.Fail()) 310 return error; 311 312 assert(reg_info->byte_offset < GetGPRSize()); 313 dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 314 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 315 316 return WriteGPR(); 317 } else if (IsFPR(reg)) { 318 if (m_sve_state == SVEState::Disabled) { 319 // SVE is disabled take legacy route for FPU register access 320 error = ReadFPR(); 321 if (error.Fail()) 322 return error; 323 324 offset = CalculateFprOffset(reg_info); 325 assert(offset < GetFPRSize()); 326 dst = (uint8_t *)GetFPRBuffer() + offset; 327 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 328 329 return WriteFPR(); 330 } else { 331 // SVE enabled, we will read and cache SVE ptrace data 332 error = ReadAllSVE(); 333 if (error.Fail()) 334 return error; 335 336 // FPSR and FPCR will be located right after Z registers in 337 // SVEState::FPSIMD while in SVEState::Full they will be located at the 338 // end of register data after an alignment correction based on currently 339 // selected vector length. 340 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 341 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 342 sve_reg_num = reg; 343 if (m_sve_state == SVEState::Full) 344 offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl)); 345 else if (m_sve_state == SVEState::FPSIMD) 346 offset = sve::ptrace_fpsimd_offset + (32 * 16); 347 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 348 sve_reg_num = reg; 349 if (m_sve_state == SVEState::Full) 350 offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl)); 351 else if (m_sve_state == SVEState::FPSIMD) 352 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4; 353 } else { 354 // Extract SVE Z register value register number for this reg_info 355 if (reg_info->value_regs && 356 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 357 sve_reg_num = reg_info->value_regs[0]; 358 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 359 } 360 361 assert(offset < GetSVEBufferSize()); 362 dst = (uint8_t *)GetSVEBuffer() + offset; 363 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 364 return WriteAllSVE(); 365 } 366 } else if (IsSVE(reg)) { 367 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 368 return Status("SVE disabled or not supported"); 369 else { 370 // Target has SVE enabled, we will read and cache SVE ptrace data 371 error = ReadAllSVE(); 372 if (error.Fail()) 373 return error; 374 375 if (GetRegisterInfo().IsSVERegVG(reg)) { 376 uint64_t vg_value = reg_value.GetAsUInt64(); 377 378 if (sve_vl_valid(vg_value * 8)) { 379 if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 380 return error; 381 382 SetSVERegVG(vg_value); 383 384 error = WriteSVEHeader(); 385 if (error.Success()) 386 ConfigureRegisterContext(); 387 388 if (m_sve_header_is_valid && vg_value == GetSVERegVG()) 389 return error; 390 } 391 392 return Status("SVE vector length update failed."); 393 } 394 395 // If target supports SVE but currently in FPSIMD mode. 396 if (m_sve_state == SVEState::FPSIMD) { 397 // Here we will check if writing this SVE register enables 398 // SVEState::Full 399 bool set_sve_state_full = false; 400 const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 401 if (GetRegisterInfo().IsSVEZReg(reg)) { 402 for (uint32_t i = 16; i < reg_info->byte_size; i++) { 403 if (reg_bytes[i]) { 404 set_sve_state_full = true; 405 break; 406 } 407 } 408 } else if (GetRegisterInfo().IsSVEPReg(reg) || 409 reg == GetRegisterInfo().GetRegNumSVEFFR()) { 410 for (uint32_t i = 0; i < reg_info->byte_size; i++) { 411 if (reg_bytes[i]) { 412 set_sve_state_full = true; 413 break; 414 } 415 } 416 } 417 418 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 419 // We are writing a Z register which is zero beyond 16 bytes so copy 420 // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 421 offset = CalculateSVEOffset(reg_info); 422 assert(offset < GetSVEBufferSize()); 423 dst = (uint8_t *)GetSVEBuffer() + offset; 424 ::memcpy(dst, reg_value.GetBytes(), 16); 425 426 return WriteAllSVE(); 427 } else 428 return Status("SVE state change operation not supported"); 429 } else { 430 offset = CalculateSVEOffset(reg_info); 431 assert(offset < GetSVEBufferSize()); 432 dst = (uint8_t *)GetSVEBuffer() + offset; 433 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 434 return WriteAllSVE(); 435 } 436 } 437 } else if (IsMTE(reg)) { 438 error = ReadMTEControl(); 439 if (error.Fail()) 440 return error; 441 442 offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset(); 443 assert(offset < GetMTEControlSize()); 444 dst = (uint8_t *)GetMTEControl() + offset; 445 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 446 447 return WriteMTEControl(); 448 } 449 450 return Status("Failed to write register value"); 451 } 452 453 Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 454 lldb::DataBufferSP &data_sp) { 455 Status error; 456 457 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 458 459 error = ReadGPR(); 460 if (error.Fail()) 461 return error; 462 463 error = ReadFPR(); 464 if (error.Fail()) 465 return error; 466 467 uint8_t *dst = data_sp->GetBytes(); 468 ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 469 dst += GetGPRSize(); 470 ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 471 472 return error; 473 } 474 475 Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 476 const lldb::DataBufferSP &data_sp) { 477 Status error; 478 479 if (!data_sp) { 480 error.SetErrorStringWithFormat( 481 "NativeRegisterContextLinux_arm64::%s invalid data_sp provided", 482 __FUNCTION__); 483 return error; 484 } 485 486 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 487 error.SetErrorStringWithFormat( 488 "NativeRegisterContextLinux_arm64::%s data_sp contained mismatched " 489 "data size, expected %" PRIu64 ", actual %" PRIu64, 490 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 491 return error; 492 } 493 494 uint8_t *src = data_sp->GetBytes(); 495 if (src == nullptr) { 496 error.SetErrorStringWithFormat("NativeRegisterContextLinux_arm64::%s " 497 "DataBuffer::GetBytes() returned a null " 498 "pointer", 499 __FUNCTION__); 500 return error; 501 } 502 ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 503 504 error = WriteGPR(); 505 if (error.Fail()) 506 return error; 507 508 src += GetRegisterInfoInterface().GetGPRSize(); 509 ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 510 511 error = WriteFPR(); 512 if (error.Fail()) 513 return error; 514 515 return error; 516 } 517 518 bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 519 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 520 RegisterInfoPOSIX_arm64::GPRegSet) 521 return true; 522 return false; 523 } 524 525 bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 526 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 527 RegisterInfoPOSIX_arm64::FPRegSet) 528 return true; 529 return false; 530 } 531 532 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 533 return GetRegisterInfo().IsSVEReg(reg); 534 } 535 536 bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const { 537 return GetRegisterInfo().IsPAuthReg(reg); 538 } 539 540 bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const { 541 return GetRegisterInfo().IsMTEReg(reg); 542 } 543 544 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 545 if (!m_refresh_hwdebug_info) { 546 return llvm::Error::success(); 547 } 548 549 ::pid_t tid = m_thread.GetID(); 550 551 int regset = NT_ARM_HW_WATCH; 552 struct iovec ioVec; 553 struct user_hwdebug_state dreg_state; 554 Status error; 555 556 ioVec.iov_base = &dreg_state; 557 ioVec.iov_len = sizeof(dreg_state); 558 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 559 &ioVec, ioVec.iov_len); 560 561 if (error.Fail()) 562 return error.ToError(); 563 564 m_max_hwp_supported = dreg_state.dbg_info & 0xff; 565 566 regset = NT_ARM_HW_BREAK; 567 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 568 &ioVec, ioVec.iov_len); 569 570 if (error.Fail()) 571 return error.ToError(); 572 573 m_max_hbp_supported = dreg_state.dbg_info & 0xff; 574 m_refresh_hwdebug_info = false; 575 576 return llvm::Error::success(); 577 } 578 579 llvm::Error 580 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) { 581 struct iovec ioVec; 582 struct user_hwdebug_state dreg_state; 583 int regset; 584 585 memset(&dreg_state, 0, sizeof(dreg_state)); 586 ioVec.iov_base = &dreg_state; 587 588 switch (hwbType) { 589 case eDREGTypeWATCH: 590 regset = NT_ARM_HW_WATCH; 591 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 592 (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 593 594 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 595 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 596 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 597 } 598 break; 599 case eDREGTypeBREAK: 600 regset = NT_ARM_HW_BREAK; 601 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 602 (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 603 604 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 605 dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address; 606 dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control; 607 } 608 break; 609 } 610 611 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 612 ®set, &ioVec, ioVec.iov_len) 613 .ToError(); 614 } 615 616 Status NativeRegisterContextLinux_arm64::ReadGPR() { 617 Status error; 618 619 if (m_gpr_is_valid) 620 return error; 621 622 struct iovec ioVec; 623 ioVec.iov_base = GetGPRBuffer(); 624 ioVec.iov_len = GetGPRBufferSize(); 625 626 error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 627 628 if (error.Success()) 629 m_gpr_is_valid = true; 630 631 return error; 632 } 633 634 Status NativeRegisterContextLinux_arm64::WriteGPR() { 635 Status error = ReadGPR(); 636 if (error.Fail()) 637 return error; 638 639 struct iovec ioVec; 640 ioVec.iov_base = GetGPRBuffer(); 641 ioVec.iov_len = GetGPRBufferSize(); 642 643 m_gpr_is_valid = false; 644 645 return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS); 646 } 647 648 Status NativeRegisterContextLinux_arm64::ReadFPR() { 649 Status error; 650 651 if (m_fpu_is_valid) 652 return error; 653 654 struct iovec ioVec; 655 ioVec.iov_base = GetFPRBuffer(); 656 ioVec.iov_len = GetFPRSize(); 657 658 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 659 660 if (error.Success()) 661 m_fpu_is_valid = true; 662 663 return error; 664 } 665 666 Status NativeRegisterContextLinux_arm64::WriteFPR() { 667 Status error = ReadFPR(); 668 if (error.Fail()) 669 return error; 670 671 struct iovec ioVec; 672 ioVec.iov_base = GetFPRBuffer(); 673 ioVec.iov_len = GetFPRSize(); 674 675 m_fpu_is_valid = false; 676 677 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 678 } 679 680 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 681 m_gpr_is_valid = false; 682 m_fpu_is_valid = false; 683 m_sve_buffer_is_valid = false; 684 m_sve_header_is_valid = false; 685 m_pac_mask_is_valid = false; 686 m_mte_ctrl_is_valid = false; 687 688 // Update SVE registers in case there is change in configuration. 689 ConfigureRegisterContext(); 690 } 691 692 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 693 Status error; 694 695 if (m_sve_header_is_valid) 696 return error; 697 698 struct iovec ioVec; 699 ioVec.iov_base = GetSVEHeader(); 700 ioVec.iov_len = GetSVEHeaderSize(); 701 702 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 703 704 if (error.Success()) 705 m_sve_header_is_valid = true; 706 707 return error; 708 } 709 710 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() { 711 Status error; 712 713 if (m_pac_mask_is_valid) 714 return error; 715 716 struct iovec ioVec; 717 ioVec.iov_base = GetPACMask(); 718 ioVec.iov_len = GetPACMaskSize(); 719 720 error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK); 721 722 if (error.Success()) 723 m_pac_mask_is_valid = true; 724 725 return error; 726 } 727 728 Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 729 Status error; 730 731 error = ReadSVEHeader(); 732 if (error.Fail()) 733 return error; 734 735 struct iovec ioVec; 736 ioVec.iov_base = GetSVEHeader(); 737 ioVec.iov_len = GetSVEHeaderSize(); 738 739 m_sve_buffer_is_valid = false; 740 m_sve_header_is_valid = false; 741 m_fpu_is_valid = false; 742 743 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 744 } 745 746 Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 747 Status error; 748 749 if (m_sve_buffer_is_valid) 750 return error; 751 752 struct iovec ioVec; 753 ioVec.iov_base = GetSVEBuffer(); 754 ioVec.iov_len = GetSVEBufferSize(); 755 756 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 757 758 if (error.Success()) 759 m_sve_buffer_is_valid = true; 760 761 return error; 762 } 763 764 Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 765 Status error; 766 767 error = ReadAllSVE(); 768 if (error.Fail()) 769 return error; 770 771 struct iovec ioVec; 772 773 ioVec.iov_base = GetSVEBuffer(); 774 ioVec.iov_len = GetSVEBufferSize(); 775 776 m_sve_buffer_is_valid = false; 777 m_sve_header_is_valid = false; 778 m_fpu_is_valid = false; 779 780 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 781 } 782 783 Status NativeRegisterContextLinux_arm64::ReadMTEControl() { 784 Status error; 785 786 if (m_mte_ctrl_is_valid) 787 return error; 788 789 struct iovec ioVec; 790 ioVec.iov_base = GetMTEControl(); 791 ioVec.iov_len = GetMTEControlSize(); 792 793 error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 794 795 if (error.Success()) 796 m_mte_ctrl_is_valid = true; 797 798 return error; 799 } 800 801 Status NativeRegisterContextLinux_arm64::WriteMTEControl() { 802 Status error; 803 804 error = ReadMTEControl(); 805 if (error.Fail()) 806 return error; 807 808 struct iovec ioVec; 809 ioVec.iov_base = GetMTEControl(); 810 ioVec.iov_len = GetMTEControlSize(); 811 812 m_mte_ctrl_is_valid = false; 813 814 return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL); 815 } 816 817 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 818 // ConfigureRegisterContext gets called from InvalidateAllRegisters 819 // on every stop and configures SVE vector length. 820 // If m_sve_state is set to SVEState::Disabled on first stop, code below will 821 // be deemed non operational for the lifetime of current process. 822 if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 823 Status error = ReadSVEHeader(); 824 if (error.Success()) { 825 // If SVE is enabled thread can switch between SVEState::FPSIMD and 826 // SVEState::Full on every stop. 827 if ((m_sve_header.flags & sve::ptrace_regs_mask) == 828 sve::ptrace_regs_fpsimd) 829 m_sve_state = SVEState::FPSIMD; 830 else if ((m_sve_header.flags & sve::ptrace_regs_mask) == 831 sve::ptrace_regs_sve) 832 m_sve_state = SVEState::Full; 833 834 // On every stop we configure SVE vector length by calling 835 // ConfigureVectorLength regardless of current SVEState of this thread. 836 uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 837 if (sve_vl_valid(m_sve_header.vl)) 838 vq = sve::vq_from_vl(m_sve_header.vl); 839 840 GetRegisterInfo().ConfigureVectorLength(vq); 841 m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve)); 842 } 843 } 844 } 845 846 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 847 const RegisterInfo *reg_info) const { 848 return reg_info->byte_offset - GetGPRSize(); 849 } 850 851 uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 852 const RegisterInfo *reg_info) const { 853 // Start of Z0 data is after GPRs plus 8 bytes of vg register 854 uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 855 if (m_sve_state == SVEState::FPSIMD) { 856 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 857 sve_reg_offset = sve::ptrace_fpsimd_offset + 858 (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 859 } else if (m_sve_state == SVEState::Full) { 860 uint32_t sve_z0_offset = GetGPRSize() + 16; 861 sve_reg_offset = 862 sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset; 863 } 864 return sve_reg_offset; 865 } 866 867 void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 868 if (m_sve_state == SVEState::FPSIMD) 869 return m_sve_ptrace_payload.data() + sve::ptrace_fpsimd_offset; 870 871 return m_sve_ptrace_payload.data(); 872 } 873 874 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 875 ExpeditedRegs expType) const { 876 std::vector<uint32_t> expedited_reg_nums = 877 NativeRegisterContext::GetExpeditedRegisters(expType); 878 if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 879 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 880 881 return expedited_reg_nums; 882 } 883 884 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> 885 NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) { 886 if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) { 887 return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(), 888 PTRACE_PEEKMTETAGS, PTRACE_POKEMTETAGS}; 889 } 890 891 return llvm::createStringError(llvm::inconvertibleErrorCode(), 892 "Unknown AArch64 memory tag type %d", type); 893 } 894 895 lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress( 896 lldb::addr_t hit_addr) { 897 // Linux configures user-space virtual addresses with top byte ignored. 898 // We set default value of mask such that top byte is masked out. 899 lldb::addr_t mask = ~((1ULL << 56) - 1); 900 901 // Try to read pointer authentication data_mask register and calculate a 902 // consolidated data address mask after ignoring the top byte. 903 if (ReadPAuthMask().Success()) 904 mask |= m_pac_mask.data_mask; 905 906 return hit_addr & ~mask; 907 ; 908 } 909 910 #endif // defined (__arm64__) || defined (__aarch64__) 911