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