1 //===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #if defined (__arm64__) || defined (__aarch64__) 11 12 #include "NativeRegisterContextLinux_arm.h" 13 #include "NativeRegisterContextLinux_arm64.h" 14 15 // C Includes 16 // C++ Includes 17 18 // Other libraries and framework includes 19 #include "lldb/Core/DataBufferHeap.h" 20 #include "lldb/Core/Error.h" 21 #include "lldb/Core/Log.h" 22 #include "lldb/Core/RegisterValue.h" 23 #include "lldb/Host/common/NativeProcessProtocol.h" 24 25 #include "Plugins/Process/Linux/NativeProcessLinux.h" 26 #include "Plugins/Process/Linux/Procfs.h" 27 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" 28 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" 29 30 // System includes - They have to be included after framework includes because they define some 31 // macros which collide with variable names in other modules 32 #include <sys/socket.h> 33 // NT_PRSTATUS and NT_FPREGSET definition 34 #include <elf.h> 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 // ARM64 general purpose registers. 43 static const uint32_t g_gpr_regnums_arm64[] = 44 { 45 gpr_x0_arm64, 46 gpr_x1_arm64, 47 gpr_x2_arm64, 48 gpr_x3_arm64, 49 gpr_x4_arm64, 50 gpr_x5_arm64, 51 gpr_x6_arm64, 52 gpr_x7_arm64, 53 gpr_x8_arm64, 54 gpr_x9_arm64, 55 gpr_x10_arm64, 56 gpr_x11_arm64, 57 gpr_x12_arm64, 58 gpr_x13_arm64, 59 gpr_x14_arm64, 60 gpr_x15_arm64, 61 gpr_x16_arm64, 62 gpr_x17_arm64, 63 gpr_x18_arm64, 64 gpr_x19_arm64, 65 gpr_x20_arm64, 66 gpr_x21_arm64, 67 gpr_x22_arm64, 68 gpr_x23_arm64, 69 gpr_x24_arm64, 70 gpr_x25_arm64, 71 gpr_x26_arm64, 72 gpr_x27_arm64, 73 gpr_x28_arm64, 74 gpr_fp_arm64, 75 gpr_lr_arm64, 76 gpr_sp_arm64, 77 gpr_pc_arm64, 78 gpr_cpsr_arm64, 79 LLDB_INVALID_REGNUM // register sets need to end with this flag 80 }; 81 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 82 "g_gpr_regnums_arm64 has wrong number of register infos"); 83 84 // ARM64 floating point registers. 85 static const uint32_t g_fpu_regnums_arm64[] = 86 { 87 fpu_v0_arm64, 88 fpu_v1_arm64, 89 fpu_v2_arm64, 90 fpu_v3_arm64, 91 fpu_v4_arm64, 92 fpu_v5_arm64, 93 fpu_v6_arm64, 94 fpu_v7_arm64, 95 fpu_v8_arm64, 96 fpu_v9_arm64, 97 fpu_v10_arm64, 98 fpu_v11_arm64, 99 fpu_v12_arm64, 100 fpu_v13_arm64, 101 fpu_v14_arm64, 102 fpu_v15_arm64, 103 fpu_v16_arm64, 104 fpu_v17_arm64, 105 fpu_v18_arm64, 106 fpu_v19_arm64, 107 fpu_v20_arm64, 108 fpu_v21_arm64, 109 fpu_v22_arm64, 110 fpu_v23_arm64, 111 fpu_v24_arm64, 112 fpu_v25_arm64, 113 fpu_v26_arm64, 114 fpu_v27_arm64, 115 fpu_v28_arm64, 116 fpu_v29_arm64, 117 fpu_v30_arm64, 118 fpu_v31_arm64, 119 fpu_fpsr_arm64, 120 fpu_fpcr_arm64, 121 LLDB_INVALID_REGNUM // register sets need to end with this flag 122 }; 123 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 124 "g_fpu_regnums_arm64 has wrong number of register infos"); 125 126 namespace { 127 // Number of register sets provided by this context. 128 enum 129 { 130 k_num_register_sets = 2 131 }; 132 } 133 134 // Register sets for ARM64. 135 static const RegisterSet 136 g_reg_sets_arm64[k_num_register_sets] = 137 { 138 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 139 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 140 }; 141 142 NativeRegisterContextLinux* 143 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, 144 NativeThreadProtocol &native_thread, 145 uint32_t concrete_frame_idx) 146 { 147 Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); 148 switch (target_arch.GetMachine()) 149 { 150 case llvm::Triple::arm: 151 return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); 152 case llvm::Triple::aarch64: 153 return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); 154 default: 155 if (log) 156 log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__, 157 target_arch.GetTriple().getArchName().str().c_str()); 158 return nullptr; 159 } 160 } 161 162 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, 163 NativeThreadProtocol &native_thread, 164 uint32_t concrete_frame_idx) : 165 NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) 166 { 167 switch (target_arch.GetMachine()) 168 { 169 case llvm::Triple::aarch64: 170 m_reg_info.num_registers = k_num_registers_arm64; 171 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 172 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 173 m_reg_info.last_gpr = k_last_gpr_arm64; 174 m_reg_info.first_fpr = k_first_fpr_arm64; 175 m_reg_info.last_fpr = k_last_fpr_arm64; 176 m_reg_info.first_fpr_v = fpu_v0_arm64; 177 m_reg_info.last_fpr_v = fpu_v31_arm64; 178 m_reg_info.gpr_flags = gpr_cpsr_arm64; 179 break; 180 default: 181 assert(false && "Unhandled target architecture."); 182 break; 183 } 184 185 ::memset(&m_fpr, 0, sizeof (m_fpr)); 186 ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); 187 ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); 188 189 // 16 is just a maximum value, query hardware for actual watchpoint count 190 m_max_hwp_supported = 16; 191 m_max_hbp_supported = 16; 192 m_refresh_hwdebug_info = true; 193 } 194 195 uint32_t 196 NativeRegisterContextLinux_arm64::GetRegisterSetCount () const 197 { 198 return k_num_register_sets; 199 } 200 201 const RegisterSet * 202 NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const 203 { 204 if (set_index < k_num_register_sets) 205 return &g_reg_sets_arm64[set_index]; 206 207 return nullptr; 208 } 209 210 uint32_t 211 NativeRegisterContextLinux_arm64::GetUserRegisterCount() const 212 { 213 uint32_t count = 0; 214 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) 215 count += g_reg_sets_arm64[set_index].num_registers; 216 return count; 217 } 218 219 Error 220 NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 221 { 222 Error error; 223 224 if (!reg_info) 225 { 226 error.SetErrorString ("reg_info NULL"); 227 return error; 228 } 229 230 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 231 232 if (IsFPR(reg)) 233 { 234 error = ReadFPR(); 235 if (error.Fail()) 236 return error; 237 } 238 else 239 { 240 uint32_t full_reg = reg; 241 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 242 243 if (is_subreg) 244 { 245 // Read the full aligned 64-bit register. 246 full_reg = reg_info->invalidate_regs[0]; 247 } 248 249 error = ReadRegisterRaw(full_reg, reg_value); 250 251 if (error.Success ()) 252 { 253 // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 254 if (is_subreg && (reg_info->byte_offset & 0x1)) 255 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 256 257 // If our return byte size was greater than the return value reg size, then 258 // use the type specified by reg_info rather than the uint64_t default 259 if (reg_value.GetByteSize() > reg_info->byte_size) 260 reg_value.SetType(reg_info); 261 } 262 return error; 263 } 264 265 // Get pointer to m_fpr variable and set the data from it. 266 uint32_t fpr_offset = CalculateFprOffset(reg_info); 267 assert (fpr_offset < sizeof m_fpr); 268 uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; 269 reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, eByteOrderLittle, error); 270 271 return error; 272 } 273 274 Error 275 NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 276 { 277 if (!reg_info) 278 return Error ("reg_info NULL"); 279 280 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 281 if (reg_index == LLDB_INVALID_REGNUM) 282 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 283 284 if (IsGPR(reg_index)) 285 return WriteRegisterRaw(reg_index, reg_value); 286 287 if (IsFPR(reg_index)) 288 { 289 // Get pointer to m_fpr variable and set the data to it. 290 uint32_t fpr_offset = CalculateFprOffset(reg_info); 291 assert (fpr_offset < sizeof m_fpr); 292 uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; 293 switch (reg_info->byte_size) 294 { 295 case 2: 296 *(uint16_t *)dst = reg_value.GetAsUInt16(); 297 break; 298 case 4: 299 *(uint32_t *)dst = reg_value.GetAsUInt32(); 300 break; 301 case 8: 302 *(uint64_t *)dst = reg_value.GetAsUInt64(); 303 break; 304 default: 305 assert(false && "Unhandled data size."); 306 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 307 } 308 309 Error error = WriteFPR(); 310 if (error.Fail()) 311 return error; 312 313 return Error (); 314 } 315 316 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 317 } 318 319 Error 320 NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 321 { 322 Error error; 323 324 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 325 if (!data_sp) 326 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); 327 328 error = ReadGPR(); 329 if (error.Fail()) 330 return error; 331 332 error = ReadFPR(); 333 if (error.Fail()) 334 return error; 335 336 uint8_t *dst = data_sp->GetBytes (); 337 if (dst == nullptr) 338 { 339 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); 340 return error; 341 } 342 343 ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 344 dst += GetGPRSize(); 345 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 346 347 return error; 348 } 349 350 Error 351 NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 352 { 353 Error error; 354 355 if (!data_sp) 356 { 357 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 358 return error; 359 } 360 361 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 362 { 363 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 364 return error; 365 } 366 367 368 uint8_t *src = data_sp->GetBytes (); 369 if (src == nullptr) 370 { 371 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 372 return error; 373 } 374 ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); 375 376 error = WriteGPR(); 377 if (error.Fail()) 378 return error; 379 380 src += GetRegisterInfoInterface ().GetGPRSize (); 381 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 382 383 error = WriteFPR(); 384 if (error.Fail()) 385 return error; 386 387 return error; 388 } 389 390 bool 391 NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const 392 { 393 return reg <= m_reg_info.last_gpr; // GPR's come first. 394 } 395 396 bool 397 NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const 398 { 399 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 400 } 401 402 uint32_t 403 NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 404 { 405 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 406 407 if (log) 408 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 409 410 Error error; 411 412 // Read hardware breakpoint and watchpoint information. 413 error = ReadHardwareDebugInfo (); 414 415 if (error.Fail()) 416 return LLDB_INVALID_INDEX32; 417 418 uint32_t control_value = 0, bp_index = 0; 419 420 // Check if size has a valid hardware breakpoint length. 421 if (size != 4) 422 return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint 423 424 // Check 4-byte alignment for hardware breakpoint target address. 425 if (addr & 0x03) 426 return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. 427 428 // Setup control value 429 control_value = 0; 430 control_value |= ((1 << size) - 1) << 5; 431 control_value |= (2 << 1) | 1; 432 433 // Iterate over stored hardware breakpoints 434 // Find a free bp_index or update reference count if duplicate. 435 bp_index = LLDB_INVALID_INDEX32; 436 for (uint32_t i = 0; i < m_max_hbp_supported; i++) 437 { 438 if ((m_hbr_regs[i].control & 1) == 0) 439 { 440 bp_index = i; // Mark last free slot 441 } 442 else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 443 { 444 bp_index = i; // Mark duplicate index 445 break; // Stop searching here 446 } 447 } 448 449 if (bp_index == LLDB_INVALID_INDEX32) 450 return LLDB_INVALID_INDEX32; 451 452 // Add new or update existing breakpoint 453 if ((m_hbr_regs[bp_index].control & 1) == 0) 454 { 455 m_hbr_regs[bp_index].address = addr; 456 m_hbr_regs[bp_index].control = control_value; 457 m_hbr_regs[bp_index].refcount = 1; 458 459 // PTRACE call to set corresponding hardware breakpoint register. 460 error = WriteHardwareDebugRegs(eDREGTypeBREAK); 461 462 if (error.Fail()) 463 { 464 m_hbr_regs[bp_index].address = 0; 465 m_hbr_regs[bp_index].control &= ~1; 466 m_hbr_regs[bp_index].refcount = 0; 467 468 return LLDB_INVALID_INDEX32; 469 } 470 } 471 else 472 m_hbr_regs[bp_index].refcount++; 473 474 return bp_index; 475 } 476 477 bool 478 NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) 479 { 480 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 481 482 if (log) 483 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 484 485 Error error; 486 487 // Read hardware breakpoint and watchpoint information. 488 error = ReadHardwareDebugInfo (); 489 490 if (error.Fail()) 491 return false; 492 493 if (hw_idx >= m_max_hbp_supported) 494 return false; 495 496 // Update reference count if multiple references. 497 if (m_hbr_regs[hw_idx].refcount > 1) 498 { 499 m_hbr_regs[hw_idx].refcount--; 500 return true; 501 } 502 else if (m_hbr_regs[hw_idx].refcount == 1) 503 { 504 // Create a backup we can revert to in case of failure. 505 lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; 506 uint32_t tempControl = m_hbr_regs[hw_idx].control; 507 uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; 508 509 m_hbr_regs[hw_idx].control &= ~1; 510 m_hbr_regs[hw_idx].address = 0; 511 m_hbr_regs[hw_idx].refcount = 0; 512 513 // PTRACE call to clear corresponding hardware breakpoint register. 514 WriteHardwareDebugRegs(eDREGTypeBREAK); 515 516 if (error.Fail()) 517 { 518 m_hbr_regs[hw_idx].control = tempControl; 519 m_hbr_regs[hw_idx].address = tempAddr; 520 m_hbr_regs[hw_idx].refcount = tempRefCount; 521 522 return false; 523 } 524 525 return true; 526 } 527 528 return false; 529 } 530 531 uint32_t 532 NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () 533 { 534 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 535 536 if (log) 537 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 538 539 Error error; 540 541 // Read hardware breakpoint and watchpoint information. 542 error = ReadHardwareDebugInfo (); 543 544 if (error.Fail()) 545 return LLDB_INVALID_INDEX32; 546 547 return m_max_hwp_supported; 548 } 549 550 uint32_t 551 NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 552 { 553 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 554 555 if (log) 556 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 557 558 Error error; 559 560 // Read hardware breakpoint and watchpoint information. 561 error = ReadHardwareDebugInfo (); 562 563 if (error.Fail()) 564 return LLDB_INVALID_INDEX32; 565 566 uint32_t control_value = 0, wp_index = 0; 567 568 // Check if we are setting watchpoint other than read/write/access 569 // Also update watchpoint flag to match AArch64 write-read bit configuration. 570 switch (watch_flags) 571 { 572 case 1: 573 watch_flags = 2; 574 break; 575 case 2: 576 watch_flags = 1; 577 break; 578 case 3: 579 break; 580 default: 581 return LLDB_INVALID_INDEX32; 582 } 583 584 // Check if size has a valid hardware watchpoint length. 585 if (size != 1 && size != 2 && size != 4 && size != 8) 586 return LLDB_INVALID_INDEX32; 587 588 // Check 8-byte alignment for hardware watchpoint target address. 589 // TODO: Add support for watching un-aligned addresses 590 if (addr & 0x07) 591 return LLDB_INVALID_INDEX32; 592 593 // Setup control value 594 control_value = watch_flags << 3; 595 control_value |= ((1 << size) - 1) << 5; 596 control_value |= (2 << 1) | 1; 597 598 // Iterate over stored watchpoints 599 // Find a free wp_index or update reference count if duplicate. 600 wp_index = LLDB_INVALID_INDEX32; 601 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 602 { 603 if ((m_hwp_regs[i].control & 1) == 0) 604 { 605 wp_index = i; // Mark last free slot 606 } 607 else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 608 { 609 wp_index = i; // Mark duplicate index 610 break; // Stop searching here 611 } 612 } 613 614 if (wp_index == LLDB_INVALID_INDEX32) 615 return LLDB_INVALID_INDEX32; 616 617 // Add new or update existing watchpoint 618 if ((m_hwp_regs[wp_index].control & 1) == 0) 619 { 620 // Update watchpoint in local cache 621 m_hwp_regs[wp_index].address = addr; 622 m_hwp_regs[wp_index].control = control_value; 623 m_hwp_regs[wp_index].refcount = 1; 624 625 // PTRACE call to set corresponding watchpoint register. 626 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 627 628 if (error.Fail()) 629 { 630 m_hwp_regs[wp_index].address = 0; 631 m_hwp_regs[wp_index].control &= ~1; 632 m_hwp_regs[wp_index].refcount = 0; 633 634 return LLDB_INVALID_INDEX32; 635 } 636 } 637 else 638 m_hwp_regs[wp_index].refcount++; 639 640 return wp_index; 641 } 642 643 bool 644 NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) 645 { 646 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 647 648 if (log) 649 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 650 651 Error error; 652 653 // Read hardware breakpoint and watchpoint information. 654 error = ReadHardwareDebugInfo (); 655 656 if (error.Fail()) 657 return false; 658 659 if (wp_index >= m_max_hwp_supported) 660 return false; 661 662 // Update reference count if multiple references. 663 if (m_hwp_regs[wp_index].refcount > 1) 664 { 665 m_hwp_regs[wp_index].refcount--; 666 return true; 667 } 668 else if (m_hwp_regs[wp_index].refcount == 1) 669 { 670 // Create a backup we can revert to in case of failure. 671 lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 672 uint32_t tempControl = m_hwp_regs[wp_index].control; 673 uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; 674 675 // Update watchpoint in local cache 676 m_hwp_regs[wp_index].control &= ~1; 677 m_hwp_regs[wp_index].address = 0; 678 m_hwp_regs[wp_index].refcount = 0; 679 680 // Ptrace call to update hardware debug registers 681 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 682 683 if (error.Fail()) 684 { 685 m_hwp_regs[wp_index].control = tempControl; 686 m_hwp_regs[wp_index].address = tempAddr; 687 m_hwp_regs[wp_index].refcount = tempRefCount; 688 689 return false; 690 } 691 692 return true; 693 } 694 695 return false; 696 } 697 698 Error 699 NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () 700 { 701 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 702 703 if (log) 704 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 705 706 Error error; 707 708 // Read hardware breakpoint and watchpoint information. 709 error = ReadHardwareDebugInfo (); 710 711 if (error.Fail()) 712 return error; 713 714 lldb::addr_t tempAddr = 0; 715 uint32_t tempControl = 0, tempRefCount = 0; 716 717 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 718 { 719 if (m_hwp_regs[i].control & 0x01) 720 { 721 // Create a backup we can revert to in case of failure. 722 tempAddr = m_hwp_regs[i].address; 723 tempControl = m_hwp_regs[i].control; 724 tempRefCount = m_hwp_regs[i].refcount; 725 726 // Clear watchpoints in local cache 727 m_hwp_regs[i].control &= ~1; 728 m_hwp_regs[i].address = 0; 729 m_hwp_regs[i].refcount = 0; 730 731 // Ptrace call to update hardware debug registers 732 error = WriteHardwareDebugRegs(eDREGTypeWATCH); 733 734 if (error.Fail()) 735 { 736 m_hwp_regs[i].control = tempControl; 737 m_hwp_regs[i].address = tempAddr; 738 m_hwp_regs[i].refcount = tempRefCount; 739 740 return error; 741 } 742 } 743 } 744 745 return Error(); 746 } 747 748 uint32_t 749 NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) 750 { 751 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 752 753 if (log) 754 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 755 switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) 756 { 757 case 0x01: 758 return 1; 759 case 0x03: 760 return 2; 761 case 0x0f: 762 return 4; 763 case 0xff: 764 return 8; 765 default: 766 return 0; 767 } 768 } 769 bool 770 NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) 771 { 772 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 773 774 if (log) 775 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 776 777 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 778 return true; 779 else 780 return false; 781 } 782 783 Error 784 NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 785 { 786 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 787 788 if (log) 789 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 790 791 uint32_t watch_size; 792 lldb::addr_t watch_addr; 793 794 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 795 { 796 watch_size = GetWatchpointSize (wp_index); 797 watch_addr = m_hwp_regs[wp_index].address; 798 799 if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 800 && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 801 { 802 return Error(); 803 } 804 } 805 806 wp_index = LLDB_INVALID_INDEX32; 807 return Error(); 808 } 809 810 lldb::addr_t 811 NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) 812 { 813 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 814 815 if (log) 816 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 817 818 if (wp_index >= m_max_hwp_supported) 819 return LLDB_INVALID_ADDRESS; 820 821 if (WatchpointIsEnabled(wp_index)) 822 return m_hwp_regs[wp_index].address; 823 else 824 return LLDB_INVALID_ADDRESS; 825 } 826 827 Error 828 NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() 829 { 830 if (!m_refresh_hwdebug_info) 831 { 832 return Error(); 833 } 834 835 ::pid_t tid = m_thread.GetID(); 836 837 int regset = NT_ARM_HW_WATCH; 838 struct iovec ioVec; 839 struct user_hwdebug_state dreg_state; 840 Error error; 841 842 ioVec.iov_base = &dreg_state; 843 ioVec.iov_len = sizeof (dreg_state); 844 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); 845 846 if (error.Fail()) 847 return error; 848 849 m_max_hwp_supported = dreg_state.dbg_info & 0xff; 850 851 regset = NT_ARM_HW_BREAK; 852 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); 853 854 if (error.Fail()) 855 return error; 856 857 m_max_hbp_supported = dreg_state.dbg_info & 0xff; 858 m_refresh_hwdebug_info = false; 859 860 return error; 861 } 862 863 Error 864 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) 865 { 866 struct iovec ioVec; 867 struct user_hwdebug_state dreg_state; 868 Error error; 869 870 memset (&dreg_state, 0, sizeof (dreg_state)); 871 ioVec.iov_base = &dreg_state; 872 873 if (hwbType == eDREGTypeWATCH) 874 { 875 hwbType = NT_ARM_HW_WATCH; 876 ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) 877 + (sizeof (dreg_state.dbg_regs [0]) * m_max_hwp_supported); 878 879 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 880 { 881 dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; 882 dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; 883 } 884 } 885 else 886 { 887 hwbType = NT_ARM_HW_BREAK; 888 ioVec.iov_len = sizeof (dreg_state.dbg_info) + sizeof (dreg_state.pad) 889 + (sizeof (dreg_state.dbg_regs [0]) * m_max_hbp_supported); 890 891 for (uint32_t i = 0; i < m_max_hbp_supported; i++) 892 { 893 dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; 894 dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; 895 } 896 } 897 898 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &hwbType, &ioVec, ioVec.iov_len); 899 } 900 901 Error 902 NativeRegisterContextLinux_arm64::DoReadRegisterValue(uint32_t offset, 903 const char* reg_name, 904 uint32_t size, 905 RegisterValue &value) 906 { 907 Error error; 908 if (offset > sizeof(struct user_pt_regs)) 909 { 910 uintptr_t offset = offset - sizeof(struct user_pt_regs); 911 if (offset > sizeof(struct user_fpsimd_state)) 912 { 913 error.SetErrorString("invalid offset value"); 914 return error; 915 } 916 elf_fpregset_t regs; 917 int regset = NT_FPREGSET; 918 struct iovec ioVec; 919 920 ioVec.iov_base = ®s; 921 ioVec.iov_len = sizeof regs; 922 error = NativeProcessLinux::PtraceWrapper( 923 PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); 924 if (error.Success()) 925 { 926 ArchSpec arch; 927 if (m_thread.GetProcess()->GetArchitecture(arch)) 928 value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); 929 else 930 error.SetErrorString("failed to get architecture"); 931 } 932 } 933 else 934 { 935 elf_gregset_t regs; 936 int regset = NT_PRSTATUS; 937 struct iovec ioVec; 938 939 ioVec.iov_base = ®s; 940 ioVec.iov_len = sizeof regs; 941 error = NativeProcessLinux::PtraceWrapper( 942 PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); 943 if (error.Success()) 944 { 945 ArchSpec arch; 946 if (m_thread.GetProcess()->GetArchitecture(arch)) 947 value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, arch.GetByteOrder()); 948 else 949 error.SetErrorString("failed to get architecture"); 950 } 951 } 952 return error; 953 } 954 955 Error 956 NativeRegisterContextLinux_arm64::DoWriteRegisterValue(uint32_t offset, 957 const char* reg_name, 958 const RegisterValue &value) 959 { 960 Error error; 961 ::pid_t tid = m_thread.GetID(); 962 if (offset > sizeof(struct user_pt_regs)) 963 { 964 uintptr_t offset = offset - sizeof(struct user_pt_regs); 965 if (offset > sizeof(struct user_fpsimd_state)) 966 { 967 error.SetErrorString("invalid offset value"); 968 return error; 969 } 970 elf_fpregset_t regs; 971 int regset = NT_FPREGSET; 972 struct iovec ioVec; 973 974 ioVec.iov_base = ®s; 975 ioVec.iov_len = sizeof regs; 976 error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); 977 978 if (error.Success()) 979 { 980 ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 16); 981 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); 982 } 983 } 984 else 985 { 986 elf_gregset_t regs; 987 int regset = NT_PRSTATUS; 988 struct iovec ioVec; 989 990 ioVec.iov_base = ®s; 991 ioVec.iov_len = sizeof regs; 992 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); 993 if (error.Success()) 994 { 995 ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 8); 996 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); 997 } 998 } 999 return error; 1000 } 1001 1002 Error 1003 NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) 1004 { 1005 int regset = NT_PRSTATUS; 1006 struct iovec ioVec; 1007 Error error; 1008 1009 ioVec.iov_base = buf; 1010 ioVec.iov_len = buf_size; 1011 return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1012 } 1013 1014 Error 1015 NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) 1016 { 1017 int regset = NT_PRSTATUS; 1018 struct iovec ioVec; 1019 Error error; 1020 1021 ioVec.iov_base = buf; 1022 ioVec.iov_len = buf_size; 1023 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1024 } 1025 1026 Error 1027 NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) 1028 { 1029 int regset = NT_FPREGSET; 1030 struct iovec ioVec; 1031 Error error; 1032 1033 ioVec.iov_base = buf; 1034 ioVec.iov_len = buf_size; 1035 return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1036 } 1037 1038 Error 1039 NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) 1040 { 1041 int regset = NT_FPREGSET; 1042 struct iovec ioVec; 1043 Error error; 1044 1045 ioVec.iov_base = buf; 1046 ioVec.iov_len = buf_size; 1047 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); 1048 } 1049 1050 uint32_t 1051 NativeRegisterContextLinux_arm64::CalculateFprOffset(const RegisterInfo* reg_info) const 1052 { 1053 return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; 1054 } 1055 1056 #endif // defined (__arm64__) || defined (__aarch64__) 1057