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/Utility/DataBufferHeap.h" 17 #include "lldb/Utility/Log.h" 18 #include "lldb/Utility/RegisterValue.h" 19 #include "lldb/Utility/Status.h" 20 21 #include "Plugins/Process/Linux/NativeProcessLinux.h" 22 #include "Plugins/Process/Linux/Procfs.h" 23 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 24 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" 25 26 // System includes - They have to be included after framework includes because 27 // they define some macros which collide with variable names in other modules 28 #include <sys/socket.h> 29 // NT_PRSTATUS and NT_FPREGSET definition 30 #include <elf.h> 31 32 #ifndef NT_ARM_SVE 33 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ 34 #endif 35 36 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 37 38 using namespace lldb; 39 using namespace lldb_private; 40 using namespace lldb_private::process_linux; 41 42 std::unique_ptr<NativeRegisterContextLinux> 43 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 44 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { 45 switch (target_arch.GetMachine()) { 46 case llvm::Triple::arm: 47 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 48 native_thread); 49 case llvm::Triple::aarch64: 50 return std::make_unique<NativeRegisterContextLinux_arm64>(target_arch, 51 native_thread); 52 default: 53 llvm_unreachable("have no register context for architecture"); 54 } 55 } 56 57 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( 58 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 59 : NativeRegisterContextRegisterInfo( 60 native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { 61 ::memset(&m_fpr, 0, sizeof(m_fpr)); 62 ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); 63 ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 64 ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); 65 ::memset(&m_sve_header, 0, sizeof(m_sve_header)); 66 67 // 16 is just a maximum value, query hardware for actual watchpoint count 68 m_max_hwp_supported = 16; 69 m_max_hbp_supported = 16; 70 71 m_refresh_hwdebug_info = true; 72 73 m_gpr_is_valid = false; 74 m_fpu_is_valid = false; 75 m_sve_buffer_is_valid = false; 76 m_sve_header_is_valid = false; 77 78 // SVE is not enabled until we query user_sve_header 79 m_sve_state = SVEState::Unknown; 80 } 81 82 RegisterInfoPOSIX_arm64 & 83 NativeRegisterContextLinux_arm64::GetRegisterInfo() const { 84 return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 85 } 86 87 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { 88 return GetRegisterInfo().GetRegisterSetCount(); 89 } 90 91 const RegisterSet * 92 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { 93 return GetRegisterInfo().GetRegisterSet(set_index); 94 } 95 96 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { 97 uint32_t count = 0; 98 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 99 count += GetRegisterSet(set_index)->num_registers; 100 return count; 101 } 102 103 Status 104 NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, 105 RegisterValue ®_value) { 106 Status error; 107 108 if (!reg_info) { 109 error.SetErrorString("reg_info NULL"); 110 return error; 111 } 112 113 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 114 115 if (reg == LLDB_INVALID_REGNUM) 116 return Status("no lldb regnum for %s", reg_info && reg_info->name 117 ? reg_info->name 118 : "<unknown register>"); 119 120 uint8_t *src; 121 uint32_t offset = LLDB_INVALID_INDEX32; 122 uint64_t sve_vg; 123 std::vector<uint8_t> sve_reg_non_live; 124 125 if (IsGPR(reg)) { 126 error = ReadGPR(); 127 if (error.Fail()) 128 return error; 129 130 offset = reg_info->byte_offset; 131 assert(offset < GetGPRSize()); 132 src = (uint8_t *)GetGPRBuffer() + offset; 133 134 } else if (IsFPR(reg)) { 135 if (m_sve_state == SVEState::Disabled) { 136 // SVE is disabled take legacy route for FPU register access 137 error = ReadFPR(); 138 if (error.Fail()) 139 return error; 140 141 offset = CalculateFprOffset(reg_info); 142 assert(offset < GetFPRSize()); 143 src = (uint8_t *)GetFPRBuffer() + offset; 144 } else { 145 // SVE enabled, we will read and cache SVE ptrace data 146 error = ReadAllSVE(); 147 if (error.Fail()) 148 return error; 149 150 // FPSR and FPCR will be located right after Z registers in 151 // SVEState::FPSIMD while in SVEState::Full they will be located at the 152 // end of register data after an alignment correction based on currently 153 // selected vector length. 154 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 155 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 156 sve_reg_num = reg; 157 if (m_sve_state == SVEState::Full) 158 offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 159 else if (m_sve_state == SVEState::FPSIMD) 160 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 161 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 162 sve_reg_num = reg; 163 if (m_sve_state == SVEState::Full) 164 offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 165 else if (m_sve_state == SVEState::FPSIMD) 166 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 167 } else { 168 // Extract SVE Z register value register number for this reg_info 169 if (reg_info->value_regs && 170 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 171 sve_reg_num = reg_info->value_regs[0]; 172 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 173 } 174 175 assert(offset < GetSVEBufferSize()); 176 src = (uint8_t *)GetSVEBuffer() + offset; 177 } 178 } else if (IsSVE(reg)) { 179 180 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 181 return Status("SVE disabled or not supported"); 182 183 if (GetRegisterInfo().IsSVERegVG(reg)) { 184 sve_vg = GetSVERegVG(); 185 src = (uint8_t *)&sve_vg; 186 } else { 187 // SVE enabled, we will read and cache SVE ptrace data 188 error = ReadAllSVE(); 189 if (error.Fail()) 190 return error; 191 192 if (m_sve_state == SVEState::FPSIMD) { 193 // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so 194 // just copy 16 bytes of v register to the start of z register. All 195 // other SVE register will be set to zero. 196 sve_reg_non_live.resize(reg_info->byte_size, 0); 197 src = sve_reg_non_live.data(); 198 199 if (GetRegisterInfo().IsSVEZReg(reg)) { 200 offset = CalculateSVEOffset(reg_info); 201 assert(offset < GetSVEBufferSize()); 202 ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset, 203 16); 204 } 205 } else { 206 offset = CalculateSVEOffset(reg_info); 207 assert(offset < GetSVEBufferSize()); 208 src = (uint8_t *)GetSVEBuffer() + offset; 209 } 210 } 211 } else 212 return Status("failed - register wasn't recognized to be a GPR or an FPR, " 213 "write strategy unknown"); 214 215 reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, 216 eByteOrderLittle, error); 217 218 return error; 219 } 220 221 Status NativeRegisterContextLinux_arm64::WriteRegister( 222 const RegisterInfo *reg_info, const RegisterValue ®_value) { 223 Status error; 224 225 if (!reg_info) 226 return Status("reg_info NULL"); 227 228 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 229 230 if (reg == LLDB_INVALID_REGNUM) 231 return Status("no lldb regnum for %s", reg_info && reg_info->name 232 ? reg_info->name 233 : "<unknown register>"); 234 235 uint8_t *dst; 236 uint32_t offset = LLDB_INVALID_INDEX32; 237 std::vector<uint8_t> sve_reg_non_live; 238 239 if (IsGPR(reg)) { 240 error = ReadGPR(); 241 if (error.Fail()) 242 return error; 243 244 assert(reg_info->byte_offset < GetGPRSize()); 245 dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; 246 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 247 248 return WriteGPR(); 249 } else if (IsFPR(reg)) { 250 if (m_sve_state == SVEState::Disabled) { 251 // SVE is disabled take legacy route for FPU register access 252 error = ReadFPR(); 253 if (error.Fail()) 254 return error; 255 256 offset = CalculateFprOffset(reg_info); 257 assert(offset < GetFPRSize()); 258 dst = (uint8_t *)GetFPRBuffer() + offset; 259 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 260 261 return WriteFPR(); 262 } else { 263 // SVE enabled, we will read and cache SVE ptrace data 264 error = ReadAllSVE(); 265 if (error.Fail()) 266 return error; 267 268 // FPSR and FPCR will be located right after Z registers in 269 // SVEState::FPSIMD while in SVEState::Full they will be located at the 270 // end of register data after an alignment correction based on currently 271 // selected vector length. 272 uint32_t sve_reg_num = LLDB_INVALID_REGNUM; 273 if (reg == GetRegisterInfo().GetRegNumFPSR()) { 274 sve_reg_num = reg; 275 if (m_sve_state == SVEState::Full) 276 offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 277 else if (m_sve_state == SVEState::FPSIMD) 278 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16); 279 } else if (reg == GetRegisterInfo().GetRegNumFPCR()) { 280 sve_reg_num = reg; 281 if (m_sve_state == SVEState::Full) 282 offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl)); 283 else if (m_sve_state == SVEState::FPSIMD) 284 offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4; 285 } else { 286 // Extract SVE Z register value register number for this reg_info 287 if (reg_info->value_regs && 288 reg_info->value_regs[0] != LLDB_INVALID_REGNUM) 289 sve_reg_num = reg_info->value_regs[0]; 290 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num)); 291 } 292 293 assert(offset < GetSVEBufferSize()); 294 dst = (uint8_t *)GetSVEBuffer() + offset; 295 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 296 return WriteAllSVE(); 297 } 298 } else if (IsSVE(reg)) { 299 if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown) 300 return Status("SVE disabled or not supported"); 301 else { 302 if (GetRegisterInfo().IsSVERegVG(reg)) 303 return Status("SVE state change operation not supported"); 304 305 // Target has SVE enabled, we will read and cache SVE ptrace data 306 error = ReadAllSVE(); 307 if (error.Fail()) 308 return error; 309 310 // If target supports SVE but currently in FPSIMD mode. 311 if (m_sve_state == SVEState::FPSIMD) { 312 // Here we will check if writing this SVE register enables 313 // SVEState::Full 314 bool set_sve_state_full = false; 315 const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes(); 316 if (GetRegisterInfo().IsSVEZReg(reg)) { 317 for (uint32_t i = 16; i < reg_info->byte_size; i++) { 318 if (reg_bytes[i]) { 319 set_sve_state_full = true; 320 break; 321 } 322 } 323 } else if (GetRegisterInfo().IsSVEPReg(reg) || 324 reg == GetRegisterInfo().GetRegNumSVEFFR()) { 325 for (uint32_t i = 0; i < reg_info->byte_size; i++) { 326 if (reg_bytes[i]) { 327 set_sve_state_full = true; 328 break; 329 } 330 } 331 } 332 333 if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) { 334 // We are writing a Z register which is zero beyond 16 bytes so copy 335 // first 16 bytes only as SVE payload mirrors legacy fpsimd structure 336 offset = CalculateSVEOffset(reg_info); 337 assert(offset < GetSVEBufferSize()); 338 dst = (uint8_t *)GetSVEBuffer() + offset; 339 ::memcpy(dst, reg_value.GetBytes(), 16); 340 341 return WriteAllSVE(); 342 } else 343 return Status("SVE state change operation not supported"); 344 } else { 345 offset = CalculateSVEOffset(reg_info); 346 assert(offset < GetSVEBufferSize()); 347 dst = (uint8_t *)GetSVEBuffer() + offset; 348 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 349 return WriteAllSVE(); 350 } 351 } 352 } 353 354 return Status("Failed to write register value"); 355 } 356 357 Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( 358 lldb::DataBufferSP &data_sp) { 359 Status error; 360 361 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 362 363 error = ReadGPR(); 364 if (error.Fail()) 365 return error; 366 367 error = ReadFPR(); 368 if (error.Fail()) 369 return error; 370 371 uint8_t *dst = data_sp->GetBytes(); 372 ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); 373 dst += GetGPRSize(); 374 ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); 375 376 return error; 377 } 378 379 Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( 380 const lldb::DataBufferSP &data_sp) { 381 Status error; 382 383 if (!data_sp) { 384 error.SetErrorStringWithFormat( 385 "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", 386 __FUNCTION__); 387 return error; 388 } 389 390 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 391 error.SetErrorStringWithFormat( 392 "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " 393 "data size, expected %" PRIu64 ", actual %" PRIu64, 394 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 395 return error; 396 } 397 398 uint8_t *src = data_sp->GetBytes(); 399 if (src == nullptr) { 400 error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " 401 "DataBuffer::GetBytes() returned a null " 402 "pointer", 403 __FUNCTION__); 404 return error; 405 } 406 ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); 407 408 error = WriteGPR(); 409 if (error.Fail()) 410 return error; 411 412 src += GetRegisterInfoInterface().GetGPRSize(); 413 ::memcpy(GetFPRBuffer(), src, GetFPRSize()); 414 415 error = WriteFPR(); 416 if (error.Fail()) 417 return error; 418 419 return error; 420 } 421 422 bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { 423 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 424 RegisterInfoPOSIX_arm64::GPRegSet) 425 return true; 426 return false; 427 } 428 429 bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { 430 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 431 RegisterInfoPOSIX_arm64::FPRegSet) 432 return true; 433 return false; 434 } 435 436 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { 437 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 438 RegisterInfoPOSIX_arm64::SVERegSet) 439 return true; 440 return false; 441 } 442 443 uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() { 444 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); 445 446 LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 447 448 Status error; 449 450 // Read hardware breakpoint and watchpoint information. 451 error = ReadHardwareDebugInfo(); 452 453 if (error.Fail()) 454 return 0; 455 456 return m_max_hbp_supported; 457 } 458 459 uint32_t 460 NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, 461 size_t size) { 462 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); 463 LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); 464 465 // Read hardware breakpoint and watchpoint information. 466 Status error = ReadHardwareDebugInfo(); 467 468 if (error.Fail()) 469 return LLDB_INVALID_INDEX32; 470 471 uint32_t control_value = 0, bp_index = 0; 472 473 // Check if size has a valid hardware breakpoint length. 474 if (size != 4) 475 return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware 476 // breakpoint 477 478 // Check 4-byte alignment for hardware breakpoint target address. 479 if (addr & 0x03) 480 return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. 481 482 // Setup control value 483 control_value = 0; 484 control_value |= ((1 << size) - 1) << 5; 485 control_value |= (2 << 1) | 1; 486 487 // Iterate over stored breakpoints and find a free bp_index 488 bp_index = LLDB_INVALID_INDEX32; 489 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 490 if ((m_hbr_regs[i].control & 1) == 0) { 491 bp_index = i; // Mark last free slot 492 } else if (m_hbr_regs[i].address == addr) { 493 return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. 494 } 495 } 496 497 if (bp_index == LLDB_INVALID_INDEX32) 498 return LLDB_INVALID_INDEX32; 499 500 // Update breakpoint in local cache 501 m_hbr_regs[bp_index].real_addr = addr; 502 m_hbr_regs[bp_index].address = addr; 503 m_hbr_regs[bp_index].control = control_value; 504 505 // PTRACE call to set corresponding hardware breakpoint register. 506 error = WriteHardwareDebugRegs(eDREGTypeBREAK); 507 508 if (error.Fail()) { 509 m_hbr_regs[bp_index].address = 0; 510 m_hbr_regs[bp_index].control &= ~1; 511 512 return LLDB_INVALID_INDEX32; 513 } 514 515 return bp_index; 516 } 517 518 bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( 519 uint32_t hw_idx) { 520 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); 521 LLDB_LOG(log, "hw_idx: {0}", hw_idx); 522 523 // Read hardware breakpoint and watchpoint information. 524 Status error = ReadHardwareDebugInfo(); 525 526 if (error.Fail()) 527 return false; 528 529 if (hw_idx >= m_max_hbp_supported) 530 return false; 531 532 // Create a backup we can revert to in case of failure. 533 lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; 534 uint32_t tempControl = m_hbr_regs[hw_idx].control; 535 536 m_hbr_regs[hw_idx].control &= ~1; 537 m_hbr_regs[hw_idx].address = 0; 538 539 // PTRACE call to clear corresponding hardware breakpoint register. 540 error = WriteHardwareDebugRegs(eDREGTypeBREAK); 541 542 if (error.Fail()) { 543 m_hbr_regs[hw_idx].control = tempControl; 544 m_hbr_regs[hw_idx].address = tempAddr; 545 546 return false; 547 } 548 549 return true; 550 } 551 552 Status NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex( 553 uint32_t &bp_index, lldb::addr_t trap_addr) { 554 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); 555 556 LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 557 558 lldb::addr_t break_addr; 559 560 for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { 561 break_addr = m_hbr_regs[bp_index].address; 562 563 if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { 564 m_hbr_regs[bp_index].hit_addr = trap_addr; 565 return Status(); 566 } 567 } 568 569 bp_index = LLDB_INVALID_INDEX32; 570 return Status(); 571 } 572 573 Status NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() { 574 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); 575 576 LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 577 578 Status error; 579 580 // Read hardware breakpoint and watchpoint information. 581 error = ReadHardwareDebugInfo(); 582 583 if (error.Fail()) 584 return error; 585 586 lldb::addr_t tempAddr = 0; 587 uint32_t tempControl = 0; 588 589 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 590 if (m_hbr_regs[i].control & 0x01) { 591 // Create a backup we can revert to in case of failure. 592 tempAddr = m_hbr_regs[i].address; 593 tempControl = m_hbr_regs[i].control; 594 595 // Clear watchpoints in local cache 596 m_hbr_regs[i].control &= ~1; 597 m_hbr_regs[i].address = 0; 598 599 // Ptrace call to update hardware debug registers 600 error = WriteHardwareDebugRegs(eDREGTypeBREAK); 601 602 if (error.Fail()) { 603 m_hbr_regs[i].control = tempControl; 604 m_hbr_regs[i].address = tempAddr; 605 606 return error; 607 } 608 } 609 } 610 611 return Status(); 612 } 613 614 uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { 615 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 616 617 // Read hardware breakpoint and watchpoint information. 618 Status error = ReadHardwareDebugInfo(); 619 620 if (error.Fail()) 621 return 0; 622 623 LLDB_LOG(log, "{0}", m_max_hwp_supported); 624 return m_max_hwp_supported; 625 } 626 627 uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( 628 lldb::addr_t addr, size_t size, uint32_t watch_flags) { 629 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 630 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, 631 watch_flags); 632 633 // Read hardware breakpoint and watchpoint information. 634 Status error = ReadHardwareDebugInfo(); 635 636 if (error.Fail()) 637 return LLDB_INVALID_INDEX32; 638 639 uint32_t control_value = 0, wp_index = 0; 640 lldb::addr_t real_addr = addr; 641 642 // Check if we are setting watchpoint other than read/write/access Also 643 // update watchpoint flag to match AArch64 write-read bit configuration. 644 switch (watch_flags) { 645 case 1: 646 watch_flags = 2; 647 break; 648 case 2: 649 watch_flags = 1; 650 break; 651 case 3: 652 break; 653 default: 654 return LLDB_INVALID_INDEX32; 655 } 656 657 // Check if size has a valid hardware watchpoint length. 658 if (size != 1 && size != 2 && size != 4 && size != 8) 659 return LLDB_INVALID_INDEX32; 660 661 // Check 8-byte alignment for hardware watchpoint target address. Below is a 662 // hack to recalculate address and size in order to make sure we can watch 663 // non 8-byte aligned addresses as well. 664 if (addr & 0x07) { 665 uint8_t watch_mask = (addr & 0x07) + size; 666 667 if (watch_mask > 0x08) 668 return LLDB_INVALID_INDEX32; 669 else if (watch_mask <= 0x02) 670 size = 2; 671 else if (watch_mask <= 0x04) 672 size = 4; 673 else 674 size = 8; 675 676 addr = addr & (~0x07); 677 } 678 679 // Setup control value 680 control_value = watch_flags << 3; 681 control_value |= ((1 << size) - 1) << 5; 682 control_value |= (2 << 1) | 1; 683 684 // Iterate over stored watchpoints and find a free wp_index 685 wp_index = LLDB_INVALID_INDEX32; 686 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 687 if ((m_hwp_regs[i].control & 1) == 0) { 688 wp_index = i; // Mark last free slot 689 } else if (m_hwp_regs[i].address == addr) { 690 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. 691 } 692 } 693 694 if (wp_index == LLDB_INVALID_INDEX32) 695 return LLDB_INVALID_INDEX32; 696 697 // Update watchpoint in local cache 698 m_hwp_regs[wp_index].real_addr = real_addr; 699 m_hwp_regs[wp_index].address = addr; 700 m_hwp_regs[wp_index].control = control_value; 701 702 // PTRACE call to set corresponding watchpoint register. 703 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 704 705 if (error.Fail()) { 706 m_hwp_regs[wp_index].address = 0; 707 m_hwp_regs[wp_index].control &= ~1; 708 709 return LLDB_INVALID_INDEX32; 710 } 711 712 return wp_index; 713 } 714 715 bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( 716 uint32_t wp_index) { 717 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 718 LLDB_LOG(log, "wp_index: {0}", wp_index); 719 720 // Read hardware breakpoint and watchpoint information. 721 Status error = ReadHardwareDebugInfo(); 722 723 if (error.Fail()) 724 return false; 725 726 if (wp_index >= m_max_hwp_supported) 727 return false; 728 729 // Create a backup we can revert to in case of failure. 730 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 731 uint32_t tempControl = m_hwp_regs[wp_index].control; 732 733 // Update watchpoint in local cache 734 m_hwp_regs[wp_index].control &= ~1; 735 m_hwp_regs[wp_index].address = 0; 736 737 // Ptrace call to update hardware debug registers 738 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 739 740 if (error.Fail()) { 741 m_hwp_regs[wp_index].control = tempControl; 742 m_hwp_regs[wp_index].address = tempAddr; 743 744 return false; 745 } 746 747 return true; 748 } 749 750 Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { 751 // Read hardware breakpoint and watchpoint information. 752 Status error = ReadHardwareDebugInfo(); 753 754 if (error.Fail()) 755 return error; 756 757 lldb::addr_t tempAddr = 0; 758 uint32_t tempControl = 0; 759 760 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 761 if (m_hwp_regs[i].control & 0x01) { 762 // Create a backup we can revert to in case of failure. 763 tempAddr = m_hwp_regs[i].address; 764 tempControl = m_hwp_regs[i].control; 765 766 // Clear watchpoints in local cache 767 m_hwp_regs[i].control &= ~1; 768 m_hwp_regs[i].address = 0; 769 770 // Ptrace call to update hardware debug registers 771 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 772 773 if (error.Fail()) { 774 m_hwp_regs[i].control = tempControl; 775 m_hwp_regs[i].address = tempAddr; 776 777 return error; 778 } 779 } 780 } 781 782 return Status(); 783 } 784 785 uint32_t 786 NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { 787 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 788 LLDB_LOG(log, "wp_index: {0}", wp_index); 789 790 switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { 791 case 0x01: 792 return 1; 793 case 0x03: 794 return 2; 795 case 0x0f: 796 return 4; 797 case 0xff: 798 return 8; 799 default: 800 return 0; 801 } 802 } 803 bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { 804 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 805 LLDB_LOG(log, "wp_index: {0}", wp_index); 806 807 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 808 return true; 809 else 810 return false; 811 } 812 813 Status NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( 814 uint32_t &wp_index, lldb::addr_t trap_addr) { 815 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 816 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); 817 818 uint32_t watch_size; 819 lldb::addr_t watch_addr; 820 821 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { 822 watch_size = GetWatchpointSize(wp_index); 823 watch_addr = m_hwp_regs[wp_index].address; 824 825 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && 826 trap_addr < watch_addr + watch_size) { 827 m_hwp_regs[wp_index].hit_addr = trap_addr; 828 return Status(); 829 } 830 } 831 832 wp_index = LLDB_INVALID_INDEX32; 833 return Status(); 834 } 835 836 lldb::addr_t 837 NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { 838 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 839 LLDB_LOG(log, "wp_index: {0}", wp_index); 840 841 if (wp_index >= m_max_hwp_supported) 842 return LLDB_INVALID_ADDRESS; 843 844 if (WatchpointIsEnabled(wp_index)) 845 return m_hwp_regs[wp_index].real_addr; 846 else 847 return LLDB_INVALID_ADDRESS; 848 } 849 850 lldb::addr_t 851 NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) { 852 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); 853 LLDB_LOG(log, "wp_index: {0}", wp_index); 854 855 if (wp_index >= m_max_hwp_supported) 856 return LLDB_INVALID_ADDRESS; 857 858 if (WatchpointIsEnabled(wp_index)) 859 return m_hwp_regs[wp_index].hit_addr; 860 else 861 return LLDB_INVALID_ADDRESS; 862 } 863 864 Status NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { 865 if (!m_refresh_hwdebug_info) { 866 return Status(); 867 } 868 869 ::pid_t tid = m_thread.GetID(); 870 871 int regset = NT_ARM_HW_WATCH; 872 struct iovec ioVec; 873 struct user_hwdebug_state dreg_state; 874 Status error; 875 876 ioVec.iov_base = &dreg_state; 877 ioVec.iov_len = sizeof(dreg_state); 878 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 879 &ioVec, ioVec.iov_len); 880 881 if (error.Fail()) 882 return error; 883 884 m_max_hwp_supported = dreg_state.dbg_info & 0xff; 885 886 regset = NT_ARM_HW_BREAK; 887 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, 888 &ioVec, ioVec.iov_len); 889 890 if (error.Fail()) 891 return error; 892 893 m_max_hbp_supported = dreg_state.dbg_info & 0xff; 894 m_refresh_hwdebug_info = false; 895 896 return error; 897 } 898 899 Status NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) { 900 struct iovec ioVec; 901 struct user_hwdebug_state dreg_state; 902 Status error; 903 904 memset(&dreg_state, 0, sizeof(dreg_state)); 905 ioVec.iov_base = &dreg_state; 906 907 if (hwbType == eDREGTypeWATCH) { 908 hwbType = NT_ARM_HW_WATCH; 909 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 910 (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); 911 912 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 913 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 914 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 915 } 916 } else { 917 hwbType = NT_ARM_HW_BREAK; 918 ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + 919 (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); 920 921 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 922 dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; 923 dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; 924 } 925 } 926 927 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), 928 &hwbType, &ioVec, ioVec.iov_len); 929 } 930 931 Status NativeRegisterContextLinux_arm64::ReadGPR() { 932 Status error; 933 934 if (m_gpr_is_valid) 935 return error; 936 937 struct iovec ioVec; 938 ioVec.iov_base = GetGPRBuffer(); 939 ioVec.iov_len = GetGPRSize(); 940 941 error = ReadRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); 942 943 if (error.Success()) 944 m_gpr_is_valid = true; 945 946 return error; 947 } 948 949 Status NativeRegisterContextLinux_arm64::WriteGPR() { 950 Status error = ReadGPR(); 951 if (error.Fail()) 952 return error; 953 954 struct iovec ioVec; 955 ioVec.iov_base = GetGPRBuffer(); 956 ioVec.iov_len = GetGPRSize(); 957 958 m_gpr_is_valid = false; 959 960 return WriteRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); 961 } 962 963 Status NativeRegisterContextLinux_arm64::ReadFPR() { 964 Status error; 965 966 if (m_fpu_is_valid) 967 return error; 968 969 struct iovec ioVec; 970 ioVec.iov_base = GetFPRBuffer(); 971 ioVec.iov_len = GetFPRSize(); 972 973 error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 974 975 if (error.Success()) 976 m_fpu_is_valid = true; 977 978 return error; 979 } 980 981 Status NativeRegisterContextLinux_arm64::WriteFPR() { 982 Status error = ReadFPR(); 983 if (error.Fail()) 984 return error; 985 986 struct iovec ioVec; 987 ioVec.iov_base = GetFPRBuffer(); 988 ioVec.iov_len = GetFPRSize(); 989 990 m_fpu_is_valid = false; 991 992 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); 993 } 994 995 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { 996 m_gpr_is_valid = false; 997 m_fpu_is_valid = false; 998 m_sve_buffer_is_valid = false; 999 m_sve_header_is_valid = false; 1000 1001 // Update SVE registers in case there is change in configuration. 1002 ConfigureRegisterContext(); 1003 } 1004 1005 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { 1006 Status error; 1007 1008 if (m_sve_header_is_valid) 1009 return error; 1010 1011 struct iovec ioVec; 1012 ioVec.iov_base = GetSVEHeader(); 1013 ioVec.iov_len = GetSVEHeaderSize(); 1014 1015 error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 1016 1017 m_sve_header_is_valid = true; 1018 1019 return error; 1020 } 1021 1022 Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { 1023 Status error; 1024 1025 error = ReadSVEHeader(); 1026 if (error.Fail()) 1027 return error; 1028 1029 struct iovec ioVec; 1030 ioVec.iov_base = GetSVEHeader(); 1031 ioVec.iov_len = GetSVEHeaderSize(); 1032 1033 m_sve_buffer_is_valid = false; 1034 m_sve_header_is_valid = false; 1035 m_fpu_is_valid = false; 1036 1037 return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); 1038 } 1039 1040 Status NativeRegisterContextLinux_arm64::ReadAllSVE() { 1041 Status error; 1042 1043 if (m_sve_buffer_is_valid) 1044 return error; 1045 1046 struct iovec ioVec; 1047 ioVec.iov_base = GetSVEBuffer(); 1048 ioVec.iov_len = GetSVEBufferSize(); 1049 1050 error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 1051 1052 if (error.Success()) 1053 m_sve_buffer_is_valid = true; 1054 1055 return error; 1056 } 1057 1058 Status NativeRegisterContextLinux_arm64::WriteAllSVE() { 1059 Status error; 1060 1061 error = ReadAllSVE(); 1062 if (error.Fail()) 1063 return error; 1064 1065 struct iovec ioVec; 1066 1067 ioVec.iov_base = GetSVEBuffer(); 1068 ioVec.iov_len = GetSVEBufferSize(); 1069 1070 m_sve_buffer_is_valid = false; 1071 m_sve_header_is_valid = false; 1072 m_fpu_is_valid = false; 1073 1074 return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE); 1075 } 1076 1077 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { 1078 // Read SVE configuration data and configure register infos. 1079 if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { 1080 Status error = ReadSVEHeader(); 1081 if (!error.Success() && m_sve_state == SVEState::Unknown) { 1082 m_sve_state = SVEState::Disabled; 1083 GetRegisterInfo().ConfigureVectorRegisterInfos( 1084 RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); 1085 } else { 1086 if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) 1087 m_sve_state = SVEState::FPSIMD; 1088 else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) 1089 m_sve_state = SVEState::Full; 1090 1091 uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; 1092 if (sve_vl_valid(m_sve_header.vl)) 1093 vq = sve_vq_from_vl(m_sve_header.vl); 1094 GetRegisterInfo().ConfigureVectorRegisterInfos(vq); 1095 m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); 1096 } 1097 } 1098 } 1099 1100 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( 1101 const RegisterInfo *reg_info) const { 1102 return reg_info->byte_offset - GetGPRSize(); 1103 } 1104 1105 uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( 1106 const RegisterInfo *reg_info) const { 1107 // Start of Z0 data is after GPRs plus 8 bytes of vg register 1108 uint32_t sve_reg_offset = LLDB_INVALID_INDEX32; 1109 if (m_sve_state == SVEState::FPSIMD) { 1110 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 1111 sve_reg_offset = 1112 SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16; 1113 } else if (m_sve_state == SVEState::Full) { 1114 uint32_t sve_z0_offset = GetGPRSize() + 16; 1115 sve_reg_offset = 1116 SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset; 1117 } 1118 return sve_reg_offset; 1119 } 1120 1121 void *NativeRegisterContextLinux_arm64::GetSVEBuffer() { 1122 if (m_sve_state == SVEState::FPSIMD) 1123 return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET; 1124 1125 return m_sve_ptrace_payload.data(); 1126 } 1127 1128 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters( 1129 ExpeditedRegs expType) const { 1130 std::vector<uint32_t> expedited_reg_nums = 1131 NativeRegisterContext::GetExpeditedRegisters(expType); 1132 if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full) 1133 expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG()); 1134 1135 return expedited_reg_nums; 1136 } 1137 1138 #endif // defined (__arm64__) || defined (__aarch64__) 1139