1 //===-- NativeRegisterContextLinux_arm.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(__arm__) || defined(__arm64__) || defined(__aarch64__) 10 11 #include "NativeRegisterContextLinux_arm.h" 12 13 #include "Plugins/Process/Linux/NativeProcessLinux.h" 14 #include "Plugins/Process/Linux/Procfs.h" 15 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 16 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" 17 #include "lldb/Utility/DataBufferHeap.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/RegisterValue.h" 20 #include "lldb/Utility/Status.h" 21 22 #include <elf.h> 23 #include <sys/socket.h> 24 25 #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr)) 26 27 #ifndef PTRACE_GETVFPREGS 28 #define PTRACE_GETVFPREGS 27 29 #define PTRACE_SETVFPREGS 28 30 #endif 31 #ifndef PTRACE_GETHBPREGS 32 #define PTRACE_GETHBPREGS 29 33 #define PTRACE_SETHBPREGS 30 34 #endif 35 #if !defined(PTRACE_TYPE_ARG3) 36 #define PTRACE_TYPE_ARG3 void * 37 #endif 38 #if !defined(PTRACE_TYPE_ARG4) 39 #define PTRACE_TYPE_ARG4 void * 40 #endif 41 42 using namespace lldb; 43 using namespace lldb_private; 44 using namespace lldb_private::process_linux; 45 46 #if defined(__arm__) 47 48 std::unique_ptr<NativeRegisterContextLinux> 49 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 50 const ArchSpec &target_arch, NativeThreadLinux &native_thread) { 51 return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, 52 native_thread); 53 } 54 55 #endif // defined(__arm__) 56 57 NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( 58 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 59 : NativeRegisterContextRegisterInfo(native_thread, 60 new RegisterInfoPOSIX_arm(target_arch)), 61 NativeRegisterContextLinux(native_thread) { 62 assert(target_arch.GetMachine() == llvm::Triple::arm); 63 64 ::memset(&m_fpr, 0, sizeof(m_fpr)); 65 ::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm)); 66 ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); 67 ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); 68 69 // 16 is just a maximum value, query hardware for actual watchpoint count 70 m_max_hwp_supported = 16; 71 m_max_hbp_supported = 16; 72 m_refresh_hwdebug_info = true; 73 } 74 75 RegisterInfoPOSIX_arm &NativeRegisterContextLinux_arm::GetRegisterInfo() const { 76 return static_cast<RegisterInfoPOSIX_arm &>(*m_register_info_interface_up); 77 } 78 79 uint32_t NativeRegisterContextLinux_arm::GetRegisterSetCount() const { 80 return GetRegisterInfo().GetRegisterSetCount(); 81 } 82 83 uint32_t NativeRegisterContextLinux_arm::GetUserRegisterCount() const { 84 uint32_t count = 0; 85 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 86 count += GetRegisterSet(set_index)->num_registers; 87 return count; 88 } 89 90 const RegisterSet * 91 NativeRegisterContextLinux_arm::GetRegisterSet(uint32_t set_index) const { 92 return GetRegisterInfo().GetRegisterSet(set_index); 93 } 94 95 Status 96 NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info, 97 RegisterValue ®_value) { 98 Status error; 99 100 if (!reg_info) { 101 error.SetErrorString("reg_info NULL"); 102 return error; 103 } 104 105 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 106 107 if (IsFPR(reg)) { 108 error = ReadFPR(); 109 if (error.Fail()) 110 return error; 111 } else { 112 uint32_t full_reg = reg; 113 bool is_subreg = reg_info->invalidate_regs && 114 (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 115 116 if (is_subreg) { 117 // Read the full aligned 64-bit register. 118 full_reg = reg_info->invalidate_regs[0]; 119 } 120 121 error = ReadRegisterRaw(full_reg, reg_value); 122 123 if (error.Success()) { 124 // If our read was not aligned (for ah,bh,ch,dh), shift our returned 125 // value one byte to the right. 126 if (is_subreg && (reg_info->byte_offset & 0x1)) 127 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 128 129 // If our return byte size was greater than the return value reg size, 130 // then use the type specified by reg_info rather than the uint64_t 131 // default 132 if (reg_value.GetByteSize() > reg_info->byte_size) 133 reg_value.SetType(reg_info); 134 } 135 return error; 136 } 137 138 // Get pointer to m_fpr variable and set the data from it. 139 uint32_t fpr_offset = CalculateFprOffset(reg_info); 140 assert(fpr_offset < sizeof m_fpr); 141 uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; 142 switch (reg_info->byte_size) { 143 case 2: 144 reg_value.SetUInt16(*(uint16_t *)src); 145 break; 146 case 4: 147 reg_value.SetUInt32(*(uint32_t *)src); 148 break; 149 case 8: 150 reg_value.SetUInt64(*(uint64_t *)src); 151 break; 152 case 16: 153 reg_value.SetBytes(src, 16, GetByteOrder()); 154 break; 155 default: 156 assert(false && "Unhandled data size."); 157 error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, 158 reg_info->byte_size); 159 break; 160 } 161 162 return error; 163 } 164 165 Status 166 NativeRegisterContextLinux_arm::WriteRegister(const RegisterInfo *reg_info, 167 const RegisterValue ®_value) { 168 if (!reg_info) 169 return Status("reg_info NULL"); 170 171 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 172 if (reg_index == LLDB_INVALID_REGNUM) 173 return Status("no lldb regnum for %s", reg_info && reg_info->name 174 ? reg_info->name 175 : "<unknown register>"); 176 177 if (IsGPR(reg_index)) 178 return WriteRegisterRaw(reg_index, reg_value); 179 180 if (IsFPR(reg_index)) { 181 // Get pointer to m_fpr variable and set the data to it. 182 uint32_t fpr_offset = CalculateFprOffset(reg_info); 183 assert(fpr_offset < sizeof m_fpr); 184 uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; 185 ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); 186 187 return WriteFPR(); 188 } 189 190 return Status("failed - register wasn't recognized to be a GPR or an FPR, " 191 "write strategy unknown"); 192 } 193 194 Status NativeRegisterContextLinux_arm::ReadAllRegisterValues( 195 lldb::WritableDataBufferSP &data_sp) { 196 Status error; 197 198 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 199 error = ReadGPR(); 200 if (error.Fail()) 201 return error; 202 203 error = ReadFPR(); 204 if (error.Fail()) 205 return error; 206 207 uint8_t *dst = data_sp->GetBytes(); 208 ::memcpy(dst, &m_gpr_arm, GetGPRSize()); 209 dst += GetGPRSize(); 210 ::memcpy(dst, &m_fpr, sizeof(m_fpr)); 211 212 return error; 213 } 214 215 Status NativeRegisterContextLinux_arm::WriteAllRegisterValues( 216 const lldb::DataBufferSP &data_sp) { 217 Status error; 218 219 if (!data_sp) { 220 error.SetErrorStringWithFormat( 221 "NativeRegisterContextLinux_arm::%s invalid data_sp provided", 222 __FUNCTION__); 223 return error; 224 } 225 226 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 227 error.SetErrorStringWithFormat( 228 "NativeRegisterContextLinux_arm::%s data_sp contained mismatched " 229 "data size, expected %" PRIu64 ", actual %" PRIu64, 230 __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize()); 231 return error; 232 } 233 234 const uint8_t *src = data_sp->GetBytes(); 235 if (src == nullptr) { 236 error.SetErrorStringWithFormat("NativeRegisterContextLinux_arm::%s " 237 "DataBuffer::GetBytes() returned a null " 238 "pointer", 239 __FUNCTION__); 240 return error; 241 } 242 ::memcpy(&m_gpr_arm, src, GetRegisterInfoInterface().GetGPRSize()); 243 244 error = WriteGPR(); 245 if (error.Fail()) 246 return error; 247 248 src += GetRegisterInfoInterface().GetGPRSize(); 249 ::memcpy(&m_fpr, src, sizeof(m_fpr)); 250 251 error = WriteFPR(); 252 if (error.Fail()) 253 return error; 254 255 return error; 256 } 257 258 bool NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const { 259 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 260 RegisterInfoPOSIX_arm::GPRegSet) 261 return true; 262 return false; 263 } 264 265 bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const { 266 if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == 267 RegisterInfoPOSIX_arm::FPRegSet) 268 return true; 269 return false; 270 } 271 272 uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareBreakpoints() { 273 Log *log = GetLog(POSIXLog::Breakpoints); 274 275 LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 276 277 Status error; 278 279 // Read hardware breakpoint and watchpoint information. 280 error = ReadHardwareDebugInfo(); 281 282 if (error.Fail()) 283 return 0; 284 285 LLDB_LOG(log, "{0}", m_max_hbp_supported); 286 return m_max_hbp_supported; 287 } 288 289 uint32_t 290 NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, 291 size_t size) { 292 Log *log = GetLog(POSIXLog::Breakpoints); 293 LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); 294 295 // Read hardware breakpoint and watchpoint information. 296 Status error = ReadHardwareDebugInfo(); 297 298 if (error.Fail()) 299 return LLDB_INVALID_INDEX32; 300 301 uint32_t control_value = 0, bp_index = 0; 302 303 // Setup address and control values. 304 // Use size to get a hint of arm vs thumb modes. 305 switch (size) { 306 case 2: 307 control_value = (0x3 << 5) | 7; 308 addr &= ~1; 309 break; 310 case 4: 311 control_value = (0xfu << 5) | 7; 312 addr &= ~3; 313 break; 314 default: 315 return LLDB_INVALID_INDEX32; 316 } 317 318 // Iterate over stored breakpoints and find a free bp_index 319 bp_index = LLDB_INVALID_INDEX32; 320 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 321 if ((m_hbr_regs[i].control & 1) == 0) { 322 bp_index = i; // Mark last free slot 323 } else if (m_hbr_regs[i].address == addr) { 324 return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. 325 } 326 } 327 328 if (bp_index == LLDB_INVALID_INDEX32) 329 return LLDB_INVALID_INDEX32; 330 331 // Update breakpoint in local cache 332 m_hbr_regs[bp_index].real_addr = addr; 333 m_hbr_regs[bp_index].address = addr; 334 m_hbr_regs[bp_index].control = control_value; 335 336 // PTRACE call to set corresponding hardware breakpoint register. 337 error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); 338 339 if (error.Fail()) { 340 m_hbr_regs[bp_index].address = 0; 341 m_hbr_regs[bp_index].control &= ~1; 342 343 return LLDB_INVALID_INDEX32; 344 } 345 346 return bp_index; 347 } 348 349 bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) { 350 Log *log = GetLog(POSIXLog::Breakpoints); 351 LLDB_LOG(log, "hw_idx: {0}", hw_idx); 352 353 // Read hardware breakpoint and watchpoint information. 354 Status error = ReadHardwareDebugInfo(); 355 356 if (error.Fail()) 357 return false; 358 359 if (hw_idx >= m_max_hbp_supported) 360 return false; 361 362 // Create a backup we can revert to in case of failure. 363 lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; 364 uint32_t tempControl = m_hbr_regs[hw_idx].control; 365 366 m_hbr_regs[hw_idx].control &= ~1; 367 m_hbr_regs[hw_idx].address = 0; 368 369 // PTRACE call to clear corresponding hardware breakpoint register. 370 error = WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); 371 372 if (error.Fail()) { 373 m_hbr_regs[hw_idx].control = tempControl; 374 m_hbr_regs[hw_idx].address = tempAddr; 375 376 return false; 377 } 378 379 return true; 380 } 381 382 Status NativeRegisterContextLinux_arm::GetHardwareBreakHitIndex( 383 uint32_t &bp_index, lldb::addr_t trap_addr) { 384 Log *log = GetLog(POSIXLog::Breakpoints); 385 386 LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 387 388 lldb::addr_t break_addr; 389 390 for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { 391 break_addr = m_hbr_regs[bp_index].address; 392 393 if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { 394 m_hbr_regs[bp_index].hit_addr = trap_addr; 395 return Status(); 396 } 397 } 398 399 bp_index = LLDB_INVALID_INDEX32; 400 return Status(); 401 } 402 403 Status NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() { 404 Log *log = GetLog(POSIXLog::Breakpoints); 405 406 LLDB_LOGF(log, "NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 407 408 Status error; 409 410 // Read hardware breakpoint and watchpoint information. 411 error = ReadHardwareDebugInfo(); 412 413 if (error.Fail()) 414 return error; 415 416 lldb::addr_t tempAddr = 0; 417 uint32_t tempControl = 0; 418 419 for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 420 if (m_hbr_regs[i].control & 0x01) { 421 // Create a backup we can revert to in case of failure. 422 tempAddr = m_hbr_regs[i].address; 423 tempControl = m_hbr_regs[i].control; 424 425 // Clear breakpoints in local cache 426 m_hbr_regs[i].control &= ~1; 427 m_hbr_regs[i].address = 0; 428 429 // Ptrace call to update hardware debug registers 430 error = WriteHardwareDebugRegs(eDREGTypeBREAK, i); 431 432 if (error.Fail()) { 433 m_hbr_regs[i].control = tempControl; 434 m_hbr_regs[i].address = tempAddr; 435 436 return error; 437 } 438 } 439 } 440 441 return Status(); 442 } 443 444 uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { 445 Log *log = GetLog(POSIXLog::Watchpoints); 446 447 // Read hardware breakpoint and watchpoint information. 448 Status error = ReadHardwareDebugInfo(); 449 450 if (error.Fail()) 451 return 0; 452 453 LLDB_LOG(log, "{0}", m_max_hwp_supported); 454 return m_max_hwp_supported; 455 } 456 457 uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint( 458 lldb::addr_t addr, size_t size, uint32_t watch_flags) { 459 Log *log = GetLog(POSIXLog::Watchpoints); 460 LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, 461 watch_flags); 462 463 // Read hardware breakpoint and watchpoint information. 464 Status error = ReadHardwareDebugInfo(); 465 466 if (error.Fail()) 467 return LLDB_INVALID_INDEX32; 468 469 uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; 470 lldb::addr_t real_addr = addr; 471 472 // Check if we are setting watchpoint other than read/write/access Also 473 // update watchpoint flag to match Arm write-read bit configuration. 474 switch (watch_flags) { 475 case 1: 476 watch_flags = 2; 477 break; 478 case 2: 479 watch_flags = 1; 480 break; 481 case 3: 482 break; 483 default: 484 return LLDB_INVALID_INDEX32; 485 } 486 487 // Can't watch zero bytes 488 // Can't watch more than 4 bytes per WVR/WCR pair 489 490 if (size == 0 || size > 4) 491 return LLDB_INVALID_INDEX32; 492 493 // Check 4-byte alignment for hardware watchpoint target address. Below is a 494 // hack to recalculate address and size in order to make sure we can watch 495 // non 4-byte aligned addresses as well. 496 if (addr & 0x03) { 497 uint8_t watch_mask = (addr & 0x03) + size; 498 499 if (watch_mask > 0x04) 500 return LLDB_INVALID_INDEX32; 501 else if (watch_mask <= 0x02) 502 size = 2; 503 else if (watch_mask <= 0x04) 504 size = 4; 505 506 addr = addr & (~0x03); 507 } 508 509 // We can only watch up to four bytes that follow a 4 byte aligned address 510 // per watchpoint register pair, so make sure we can properly encode this. 511 addr_word_offset = addr % 4; 512 byte_mask = ((1u << size) - 1u) << addr_word_offset; 513 514 // Check if we need multiple watchpoint register 515 if (byte_mask > 0xfu) 516 return LLDB_INVALID_INDEX32; 517 518 // Setup control value 519 // Make the byte_mask into a valid Byte Address Select mask 520 control_value = byte_mask << 5; 521 522 // Turn on appropriate watchpoint flags read or write 523 control_value |= (watch_flags << 3); 524 525 // Enable this watchpoint and make it stop in privileged or user mode; 526 control_value |= 7; 527 528 // Make sure bits 1:0 are clear in our address 529 addr &= ~((lldb::addr_t)3); 530 531 // Iterate over stored watchpoints and find a free wp_index 532 wp_index = LLDB_INVALID_INDEX32; 533 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 534 if ((m_hwp_regs[i].control & 1) == 0) { 535 wp_index = i; // Mark last free slot 536 } else if (m_hwp_regs[i].address == addr) { 537 return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. 538 } 539 } 540 541 if (wp_index == LLDB_INVALID_INDEX32) 542 return LLDB_INVALID_INDEX32; 543 544 // Update watchpoint in local cache 545 m_hwp_regs[wp_index].real_addr = real_addr; 546 m_hwp_regs[wp_index].address = addr; 547 m_hwp_regs[wp_index].control = control_value; 548 549 // PTRACE call to set corresponding watchpoint register. 550 error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 551 552 if (error.Fail()) { 553 m_hwp_regs[wp_index].address = 0; 554 m_hwp_regs[wp_index].control &= ~1; 555 556 return LLDB_INVALID_INDEX32; 557 } 558 559 return wp_index; 560 } 561 562 bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint( 563 uint32_t wp_index) { 564 Log *log = GetLog(POSIXLog::Watchpoints); 565 LLDB_LOG(log, "wp_index: {0}", wp_index); 566 567 // Read hardware breakpoint and watchpoint information. 568 Status error = ReadHardwareDebugInfo(); 569 570 if (error.Fail()) 571 return false; 572 573 if (wp_index >= m_max_hwp_supported) 574 return false; 575 576 // Create a backup we can revert to in case of failure. 577 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 578 uint32_t tempControl = m_hwp_regs[wp_index].control; 579 580 // Update watchpoint in local cache 581 m_hwp_regs[wp_index].control &= ~1; 582 m_hwp_regs[wp_index].address = 0; 583 584 // Ptrace call to update hardware debug registers 585 error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 586 587 if (error.Fail()) { 588 m_hwp_regs[wp_index].control = tempControl; 589 m_hwp_regs[wp_index].address = tempAddr; 590 591 return false; 592 } 593 594 return true; 595 } 596 597 Status NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() { 598 // Read hardware breakpoint and watchpoint information. 599 Status error = ReadHardwareDebugInfo(); 600 601 if (error.Fail()) 602 return error; 603 604 lldb::addr_t tempAddr = 0; 605 uint32_t tempControl = 0; 606 607 for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 608 if (m_hwp_regs[i].control & 0x01) { 609 // Create a backup we can revert to in case of failure. 610 tempAddr = m_hwp_regs[i].address; 611 tempControl = m_hwp_regs[i].control; 612 613 // Clear watchpoints in local cache 614 m_hwp_regs[i].control &= ~1; 615 m_hwp_regs[i].address = 0; 616 617 // Ptrace call to update hardware debug registers 618 error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); 619 620 if (error.Fail()) { 621 m_hwp_regs[i].control = tempControl; 622 m_hwp_regs[i].address = tempAddr; 623 624 return error; 625 } 626 } 627 } 628 629 return Status(); 630 } 631 632 uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) { 633 Log *log = GetLog(POSIXLog::Watchpoints); 634 LLDB_LOG(log, "wp_index: {0}", wp_index); 635 636 switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) { 637 case 0x01: 638 return 1; 639 case 0x03: 640 return 2; 641 case 0x07: 642 return 3; 643 case 0x0f: 644 return 4; 645 default: 646 return 0; 647 } 648 } 649 bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) { 650 Log *log = GetLog(POSIXLog::Watchpoints); 651 LLDB_LOG(log, "wp_index: {0}", wp_index); 652 653 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 654 return true; 655 else 656 return false; 657 } 658 659 Status 660 NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, 661 lldb::addr_t trap_addr) { 662 Log *log = GetLog(POSIXLog::Watchpoints); 663 LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); 664 665 uint32_t watch_size; 666 lldb::addr_t watch_addr; 667 668 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { 669 watch_size = GetWatchpointSize(wp_index); 670 watch_addr = m_hwp_regs[wp_index].address; 671 672 if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && 673 trap_addr < watch_addr + watch_size) { 674 m_hwp_regs[wp_index].hit_addr = trap_addr; 675 return Status(); 676 } 677 } 678 679 wp_index = LLDB_INVALID_INDEX32; 680 return Status(); 681 } 682 683 lldb::addr_t 684 NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) { 685 Log *log = GetLog(POSIXLog::Watchpoints); 686 LLDB_LOG(log, "wp_index: {0}", wp_index); 687 688 if (wp_index >= m_max_hwp_supported) 689 return LLDB_INVALID_ADDRESS; 690 691 if (WatchpointIsEnabled(wp_index)) 692 return m_hwp_regs[wp_index].real_addr; 693 else 694 return LLDB_INVALID_ADDRESS; 695 } 696 697 lldb::addr_t 698 NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) { 699 Log *log = GetLog(POSIXLog::Watchpoints); 700 LLDB_LOG(log, "wp_index: {0}", wp_index); 701 702 if (wp_index >= m_max_hwp_supported) 703 return LLDB_INVALID_ADDRESS; 704 705 if (WatchpointIsEnabled(wp_index)) 706 return m_hwp_regs[wp_index].hit_addr; 707 else 708 return LLDB_INVALID_ADDRESS; 709 } 710 711 Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() { 712 Status error; 713 714 if (!m_refresh_hwdebug_info) { 715 return Status(); 716 } 717 718 unsigned int cap_val; 719 720 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), 721 nullptr, &cap_val, 722 sizeof(unsigned int)); 723 724 if (error.Fail()) 725 return error; 726 727 m_max_hwp_supported = (cap_val >> 8) & 0xff; 728 m_max_hbp_supported = cap_val & 0xff; 729 m_refresh_hwdebug_info = false; 730 731 return error; 732 } 733 734 Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, 735 int hwb_index) { 736 Status error; 737 738 lldb::addr_t *addr_buf; 739 uint32_t *ctrl_buf; 740 741 if (hwbType == eDREGTypeWATCH) { 742 addr_buf = &m_hwp_regs[hwb_index].address; 743 ctrl_buf = &m_hwp_regs[hwb_index].control; 744 745 error = NativeProcessLinux::PtraceWrapper( 746 PTRACE_SETHBPREGS, m_thread.GetID(), 747 (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 1), addr_buf, 748 sizeof(unsigned int)); 749 750 if (error.Fail()) 751 return error; 752 753 error = NativeProcessLinux::PtraceWrapper( 754 PTRACE_SETHBPREGS, m_thread.GetID(), 755 (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf, 756 sizeof(unsigned int)); 757 } else { 758 addr_buf = &m_hbr_regs[hwb_index].address; 759 ctrl_buf = &m_hbr_regs[hwb_index].control; 760 761 error = NativeProcessLinux::PtraceWrapper( 762 PTRACE_SETHBPREGS, m_thread.GetID(), 763 (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 1), addr_buf, 764 sizeof(unsigned int)); 765 766 if (error.Fail()) 767 return error; 768 769 error = NativeProcessLinux::PtraceWrapper( 770 PTRACE_SETHBPREGS, m_thread.GetID(), 771 (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf, 772 sizeof(unsigned int)); 773 } 774 775 return error; 776 } 777 778 uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset( 779 const RegisterInfo *reg_info) const { 780 return reg_info->byte_offset - GetGPRSize(); 781 } 782 783 Status NativeRegisterContextLinux_arm::DoReadRegisterValue( 784 uint32_t offset, const char *reg_name, uint32_t size, 785 RegisterValue &value) { 786 // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android 787 // devices (always return "Bad address"). To avoid using PTRACE_PEEKUSER we 788 // read out the full GPR register set instead. This approach is about 4 times 789 // slower but the performance overhead is negligible in comparison to 790 // processing time in lldb-server. 791 assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); 792 if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) 793 return Status("Register isn't fit into the size of the GPR area"); 794 795 Status error = ReadGPR(); 796 if (error.Fail()) 797 return error; 798 799 value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]); 800 return Status(); 801 } 802 803 Status NativeRegisterContextLinux_arm::DoWriteRegisterValue( 804 uint32_t offset, const char *reg_name, const RegisterValue &value) { 805 // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android 806 // devices (always return "Bad address"). To avoid using PTRACE_POKEUSER we 807 // read out the full GPR register set, modify the requested register and 808 // write it back. This approach is about 4 times slower but the performance 809 // overhead is negligible in comparison to processing time in lldb-server. 810 assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); 811 if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) 812 return Status("Register isn't fit into the size of the GPR area"); 813 814 Status error = ReadGPR(); 815 if (error.Fail()) 816 return error; 817 818 uint32_t reg_value = value.GetAsUInt32(); 819 // As precaution for an undefined behavior encountered while setting PC we 820 // will clear thumb bit of new PC if we are already in thumb mode; that is 821 // CPSR thumb mode bit is set. 822 if (offset / sizeof(uint32_t) == gpr_pc_arm) { 823 // Check if we are already in thumb mode and thumb bit of current PC is 824 // read out to be zero and thumb bit of next PC is read out to be one. 825 if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && !(m_gpr_arm[gpr_pc_arm] & 0x01) && 826 (value.GetAsUInt32() & 0x01)) { 827 reg_value &= (~1ull); 828 } 829 } 830 831 m_gpr_arm[offset / sizeof(uint32_t)] = reg_value; 832 return WriteGPR(); 833 } 834 835 Status NativeRegisterContextLinux_arm::ReadGPR() { 836 #ifdef __arm__ 837 return NativeRegisterContextLinux::ReadGPR(); 838 #else // __aarch64__ 839 struct iovec ioVec; 840 ioVec.iov_base = GetGPRBuffer(); 841 ioVec.iov_len = GetGPRSize(); 842 843 return ReadRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); 844 #endif // __arm__ 845 } 846 847 Status NativeRegisterContextLinux_arm::WriteGPR() { 848 #ifdef __arm__ 849 return NativeRegisterContextLinux::WriteGPR(); 850 #else // __aarch64__ 851 struct iovec ioVec; 852 ioVec.iov_base = GetGPRBuffer(); 853 ioVec.iov_len = GetGPRSize(); 854 855 return WriteRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); 856 #endif // __arm__ 857 } 858 859 Status NativeRegisterContextLinux_arm::ReadFPR() { 860 #ifdef __arm__ 861 return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, m_thread.GetID(), 862 nullptr, GetFPRBuffer(), 863 GetFPRSize()); 864 #else // __aarch64__ 865 struct iovec ioVec; 866 ioVec.iov_base = GetFPRBuffer(); 867 ioVec.iov_len = GetFPRSize(); 868 869 return ReadRegisterSet(&ioVec, GetFPRSize(), NT_ARM_VFP); 870 #endif // __arm__ 871 } 872 873 Status NativeRegisterContextLinux_arm::WriteFPR() { 874 #ifdef __arm__ 875 return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, m_thread.GetID(), 876 nullptr, GetFPRBuffer(), 877 GetFPRSize()); 878 #else // __aarch64__ 879 struct iovec ioVec; 880 ioVec.iov_base = GetFPRBuffer(); 881 ioVec.iov_len = GetFPRSize(); 882 883 return WriteRegisterSet(&ioVec, GetFPRSize(), NT_ARM_VFP); 884 #endif // __arm__ 885 } 886 887 #endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 888