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