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 #include "NativeRegisterContextLinux_arm64.h" 11 12 #include "lldb/lldb-private-forward.h" 13 #include "lldb/Core/DataBufferHeap.h" 14 #include "lldb/Core/Error.h" 15 #include "lldb/Core/StreamString.h" 16 #include "lldb/Core/RegisterValue.h" 17 #include "lldb/Host/common/NativeProcessProtocol.h" 18 #include "lldb/Host/common/NativeThreadProtocol.h" 19 #include "Plugins/Process/Linux/NativeProcessLinux.h" 20 #include "lldb/Core/Log.h" 21 22 #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) 23 24 using namespace lldb; 25 using namespace lldb_private; 26 using namespace lldb_private::process_linux; 27 28 // ARM64 general purpose registers. 29 static const uint32_t g_gpr_regnums_arm64[] = 30 { 31 gpr_x0_arm64, 32 gpr_x1_arm64, 33 gpr_x2_arm64, 34 gpr_x3_arm64, 35 gpr_x4_arm64, 36 gpr_x5_arm64, 37 gpr_x6_arm64, 38 gpr_x7_arm64, 39 gpr_x8_arm64, 40 gpr_x9_arm64, 41 gpr_x10_arm64, 42 gpr_x11_arm64, 43 gpr_x12_arm64, 44 gpr_x13_arm64, 45 gpr_x14_arm64, 46 gpr_x15_arm64, 47 gpr_x16_arm64, 48 gpr_x17_arm64, 49 gpr_x18_arm64, 50 gpr_x19_arm64, 51 gpr_x20_arm64, 52 gpr_x21_arm64, 53 gpr_x22_arm64, 54 gpr_x23_arm64, 55 gpr_x24_arm64, 56 gpr_x25_arm64, 57 gpr_x26_arm64, 58 gpr_x27_arm64, 59 gpr_x28_arm64, 60 gpr_fp_arm64, 61 gpr_lr_arm64, 62 gpr_sp_arm64, 63 gpr_pc_arm64, 64 gpr_cpsr_arm64, 65 LLDB_INVALID_REGNUM // register sets need to end with this flag 66 }; 67 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 68 "g_gpr_regnums_arm64 has wrong number of register infos"); 69 70 // ARM64 floating point registers. 71 static const uint32_t g_fpu_regnums_arm64[] = 72 { 73 fpu_v0_arm64, 74 fpu_v1_arm64, 75 fpu_v2_arm64, 76 fpu_v3_arm64, 77 fpu_v4_arm64, 78 fpu_v5_arm64, 79 fpu_v6_arm64, 80 fpu_v7_arm64, 81 fpu_v8_arm64, 82 fpu_v9_arm64, 83 fpu_v10_arm64, 84 fpu_v11_arm64, 85 fpu_v12_arm64, 86 fpu_v13_arm64, 87 fpu_v14_arm64, 88 fpu_v15_arm64, 89 fpu_v16_arm64, 90 fpu_v17_arm64, 91 fpu_v18_arm64, 92 fpu_v19_arm64, 93 fpu_v20_arm64, 94 fpu_v21_arm64, 95 fpu_v22_arm64, 96 fpu_v23_arm64, 97 fpu_v24_arm64, 98 fpu_v25_arm64, 99 fpu_v26_arm64, 100 fpu_v27_arm64, 101 fpu_v28_arm64, 102 fpu_v29_arm64, 103 fpu_v30_arm64, 104 fpu_v31_arm64, 105 fpu_fpsr_arm64, 106 fpu_fpcr_arm64, 107 LLDB_INVALID_REGNUM // register sets need to end with this flag 108 }; 109 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 110 "g_fpu_regnums_arm64 has wrong number of register infos"); 111 112 namespace { 113 // Number of register sets provided by this context. 114 enum 115 { 116 k_num_register_sets = 2 117 }; 118 } 119 120 // Register sets for ARM64. 121 static const RegisterSet 122 g_reg_sets_arm64[k_num_register_sets] = 123 { 124 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 125 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 126 }; 127 128 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 ( 129 NativeThreadProtocol &native_thread, 130 uint32_t concrete_frame_idx, 131 RegisterInfoInterface *reg_info_interface_p) : 132 NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) 133 { 134 switch (reg_info_interface_p->m_target_arch.GetMachine()) 135 { 136 case llvm::Triple::aarch64: 137 m_reg_info.num_registers = k_num_registers_arm64; 138 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 139 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 140 m_reg_info.last_gpr = k_last_gpr_arm64; 141 m_reg_info.first_fpr = k_first_fpr_arm64; 142 m_reg_info.last_fpr = k_last_fpr_arm64; 143 m_reg_info.first_fpr_v = fpu_v0_arm64; 144 m_reg_info.last_fpr_v = fpu_v31_arm64; 145 m_reg_info.gpr_flags = gpr_cpsr_arm64; 146 break; 147 default: 148 assert(false && "Unhandled target architecture."); 149 break; 150 } 151 152 ::memset(&m_fpr, 0, sizeof (m_fpr)); 153 ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); 154 ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); 155 156 // 16 is just a maximum value, query hardware for actual watchpoint count 157 m_max_hwp_supported = 16; 158 m_max_hbp_supported = 16; 159 m_refresh_hwdebug_info = true; 160 } 161 162 uint32_t 163 NativeRegisterContextLinux_arm64::GetRegisterSetCount () const 164 { 165 return k_num_register_sets; 166 } 167 168 const RegisterSet * 169 NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const 170 { 171 if (set_index < k_num_register_sets) 172 return &g_reg_sets_arm64[set_index]; 173 174 return nullptr; 175 } 176 177 Error 178 NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 179 { 180 Error error; 181 182 if (!reg_info) 183 { 184 error.SetErrorString ("reg_info NULL"); 185 return error; 186 } 187 188 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 189 190 if (IsFPR(reg)) 191 { 192 if (!ReadFPR()) 193 { 194 error.SetErrorString ("failed to read floating point register"); 195 return error; 196 } 197 } 198 else 199 { 200 uint32_t full_reg = reg; 201 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 202 203 if (is_subreg) 204 { 205 // Read the full aligned 64-bit register. 206 full_reg = reg_info->invalidate_regs[0]; 207 } 208 209 error = ReadRegisterRaw(full_reg, reg_value); 210 211 if (error.Success ()) 212 { 213 // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 214 if (is_subreg && (reg_info->byte_offset & 0x1)) 215 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 216 217 // If our return byte size was greater than the return value reg size, then 218 // use the type specified by reg_info rather than the uint64_t default 219 if (reg_value.GetByteSize() > reg_info->byte_size) 220 reg_value.SetType(reg_info); 221 } 222 return error; 223 } 224 225 // Get pointer to m_fpr variable and set the data from it. 226 assert (reg_info->byte_offset < sizeof m_fpr); 227 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 228 switch (reg_info->byte_size) 229 { 230 case 2: 231 reg_value.SetUInt16(*(uint16_t *)src); 232 break; 233 case 4: 234 reg_value.SetUInt32(*(uint32_t *)src); 235 break; 236 case 8: 237 reg_value.SetUInt64(*(uint64_t *)src); 238 break; 239 default: 240 assert(false && "Unhandled data size."); 241 error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 242 break; 243 } 244 245 return error; 246 } 247 248 Error 249 NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 250 { 251 if (!reg_info) 252 return Error ("reg_info NULL"); 253 254 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 255 if (reg_index == LLDB_INVALID_REGNUM) 256 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 257 258 if (IsGPR(reg_index)) 259 return WriteRegisterRaw(reg_index, reg_value); 260 261 if (IsFPR(reg_index)) 262 { 263 // Get pointer to m_fpr variable and set the data to it. 264 assert (reg_info->byte_offset < sizeof(m_fpr)); 265 uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 266 switch (reg_info->byte_size) 267 { 268 case 2: 269 *(uint16_t *)dst = reg_value.GetAsUInt16(); 270 break; 271 case 4: 272 *(uint32_t *)dst = reg_value.GetAsUInt32(); 273 break; 274 case 8: 275 *(uint64_t *)dst = reg_value.GetAsUInt64(); 276 break; 277 default: 278 assert(false && "Unhandled data size."); 279 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 280 } 281 282 if (!WriteFPR()) 283 { 284 return Error ("NativeRegisterContextLinux_arm64::WriteRegister: WriteFPR failed"); 285 } 286 287 return Error (); 288 } 289 290 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 291 } 292 293 Error 294 NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 295 { 296 Error error; 297 298 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 299 if (!data_sp) 300 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); 301 302 if (!ReadGPR ()) 303 { 304 error.SetErrorString ("ReadGPR() failed"); 305 return error; 306 } 307 308 if (!ReadFPR ()) 309 { 310 error.SetErrorString ("ReadFPR() failed"); 311 return error; 312 } 313 314 uint8_t *dst = data_sp->GetBytes (); 315 if (dst == nullptr) 316 { 317 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); 318 return error; 319 } 320 321 ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 322 dst += GetGPRSize(); 323 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 324 325 return error; 326 } 327 328 Error 329 NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 330 { 331 Error error; 332 333 if (!data_sp) 334 { 335 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 336 return error; 337 } 338 339 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 340 { 341 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 342 return error; 343 } 344 345 346 uint8_t *src = data_sp->GetBytes (); 347 if (src == nullptr) 348 { 349 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 350 return error; 351 } 352 ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); 353 354 if (!WriteGPR ()) 355 { 356 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); 357 return error; 358 } 359 360 src += GetRegisterInfoInterface ().GetGPRSize (); 361 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 362 363 if (!WriteFPR ()) 364 { 365 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); 366 return error; 367 } 368 369 return error; 370 } 371 372 Error 373 NativeRegisterContextLinux_arm64::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) 374 { 375 Error error; 376 377 uint32_t reg_to_write = reg_index; 378 RegisterValue value_to_write = reg_value; 379 380 // Check if this is a subregister of a full register. 381 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); 382 if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 383 { 384 RegisterValue full_value; 385 uint32_t full_reg = reg_info->invalidate_regs[0]; 386 const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 387 388 // Read the full register. 389 error = ReadRegister(full_reg_info, full_value); 390 if (error.Fail ()) 391 return error; 392 393 lldb::ByteOrder byte_order = GetByteOrder(); 394 uint8_t dst[RegisterValue::kMaxRegisterByteSize]; 395 396 // Get the bytes for the full register. 397 const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 398 dst, 399 sizeof(dst), 400 byte_order, 401 error); 402 if (error.Success() && dest_size) 403 { 404 uint8_t src[RegisterValue::kMaxRegisterByteSize]; 405 406 // Get the bytes for the source data. 407 const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 408 if (error.Success() && src_size && (src_size < dest_size)) 409 { 410 // Copy the src bytes to the destination. 411 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 412 // Set this full register as the value to write. 413 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 414 value_to_write.SetType(full_reg_info); 415 reg_to_write = full_reg; 416 } 417 } 418 } 419 420 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 421 if (!process_sp) 422 { 423 error.SetErrorString ("NativeProcessProtocol is NULL"); 424 return error; 425 } 426 427 const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); 428 assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); 429 if (!register_to_write_info_p) 430 { 431 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); 432 return error; 433 } 434 435 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 436 return process_p->WriteRegisterValue(m_thread.GetID(), 437 register_to_write_info_p->byte_offset, 438 register_to_write_info_p->name, 439 value_to_write); 440 } 441 442 Error 443 NativeRegisterContextLinux_arm64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) 444 { 445 Error error; 446 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); 447 if (!reg_info) 448 { 449 error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); 450 return error; 451 } 452 453 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 454 if (!process_sp) 455 { 456 error.SetErrorString ("NativeProcessProtocol is NULL"); 457 return error; 458 } 459 460 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 461 return process_p->ReadRegisterValue(m_thread.GetID(), 462 reg_info->byte_offset, 463 reg_info->name, 464 reg_info->byte_size, 465 reg_value); 466 } 467 468 bool 469 NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const 470 { 471 return reg <= m_reg_info.last_gpr; // GPR's come first. 472 } 473 474 bool 475 NativeRegisterContextLinux_arm64::ReadGPR() 476 { 477 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 478 if (!process_sp) 479 return false; 480 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 481 482 return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 483 } 484 485 bool 486 NativeRegisterContextLinux_arm64::WriteGPR() 487 { 488 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 489 if (!process_sp) 490 return false; 491 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 492 493 return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 494 } 495 496 bool 497 NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const 498 { 499 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 500 } 501 502 bool 503 NativeRegisterContextLinux_arm64::ReadFPR () 504 { 505 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 506 if (!process_sp) 507 return false; 508 509 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 510 return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 511 } 512 513 bool 514 NativeRegisterContextLinux_arm64::WriteFPR () 515 { 516 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 517 if (!process_sp) 518 return false; 519 520 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 521 return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 522 } 523 524 lldb::ByteOrder 525 NativeRegisterContextLinux_arm64::GetByteOrder() const 526 { 527 // Get the target process whose privileged thread was used for the register read. 528 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 529 530 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 531 if (!process_sp) 532 return byte_order; 533 534 if (!process_sp->GetByteOrder (byte_order)) 535 { 536 // FIXME log here 537 } 538 539 return byte_order; 540 } 541 542 size_t 543 NativeRegisterContextLinux_arm64::GetGPRSize() const 544 { 545 return GetRegisterInfoInterface().GetGPRSize(); 546 } 547 548 uint32_t 549 NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 550 { 551 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 552 553 if (log) 554 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 555 556 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 557 if (!process_sp) 558 return false; 559 560 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 561 // Check if our hardware breakpoint and watchpoint information is updated. 562 if (m_refresh_hwdebug_info) 563 { 564 process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, 565 m_max_hbp_supported); 566 m_refresh_hwdebug_info = false; 567 } 568 569 uint32_t control_value, bp_index; 570 571 // Check if size has a valid hardware breakpoint length. 572 if (size != 4) 573 return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint 574 575 // Check 4-byte alignment for hardware breakpoint target address. 576 if (addr & 0x03) 577 return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. 578 579 // Setup control value 580 control_value = 0; 581 control_value |= ((1 << size) - 1) << 5; 582 control_value |= (2 << 1) | 1; 583 584 // Iterate over stored hardware breakpoints 585 // Find a free bp_index or update reference count if duplicate. 586 bp_index = LLDB_INVALID_INDEX32; 587 for (uint32_t i = 0; i < m_max_hbp_supported; i++) 588 { 589 if ((m_hbr_regs[i].control & 1) == 0) 590 { 591 bp_index = i; // Mark last free slot 592 } 593 else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 594 { 595 bp_index = i; // Mark duplicate index 596 break; // Stop searching here 597 } 598 } 599 600 if (bp_index == LLDB_INVALID_INDEX32) 601 return LLDB_INVALID_INDEX32; 602 603 // Add new or update existing watchpoint 604 if ((m_hbr_regs[bp_index].control & 1) == 0) 605 { 606 m_hbr_regs[bp_index].address = addr; 607 m_hbr_regs[bp_index].control = control_value; 608 m_hbr_regs[bp_index].refcount = 1; 609 610 //TODO: PTRACE CALL HERE for an UPDATE 611 } 612 else 613 m_hbr_regs[bp_index].refcount++; 614 615 return bp_index; 616 } 617 618 bool 619 NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) 620 { 621 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 622 623 if (log) 624 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 625 626 if (hw_idx >= m_max_hbp_supported) 627 return false; 628 629 // Update reference count if multiple references. 630 if (m_hbr_regs[hw_idx].refcount > 1) 631 { 632 m_hbr_regs[hw_idx].refcount--; 633 return true; 634 } 635 else if (m_hbr_regs[hw_idx].refcount == 1) 636 { 637 m_hbr_regs[hw_idx].control &= ~1; 638 m_hbr_regs[hw_idx].address = 0; 639 m_hbr_regs[hw_idx].refcount = 0; 640 641 //TODO: PTRACE CALL HERE for an UPDATE 642 return true; 643 } 644 645 return false; 646 } 647 648 uint32_t 649 NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () 650 { 651 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 652 653 if (log) 654 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 655 656 return m_max_hwp_supported; 657 } 658 659 uint32_t 660 NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 661 { 662 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 663 664 if (log) 665 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 666 667 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 668 if (!process_sp) 669 return false; 670 671 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 672 // Check if our hardware breakpoint and watchpoint information is updated. 673 if (m_refresh_hwdebug_info) 674 { 675 process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported, 676 m_max_hbp_supported); 677 m_refresh_hwdebug_info = false; 678 } 679 680 uint32_t control_value, wp_index; 681 682 683 if (watch_flags != 0x1 && watch_flags != 0x2 && watch_flags != 0x3) 684 return 0;//Error ("Invalid read/write bits for watchpoint"); 685 686 // Check if size has a valid hardware watchpoint length. 687 if (size != 1 && size != 2 && size != 4 && size != 8) 688 return 0;//Error ("Invalid size for watchpoint"); 689 690 // Check 8-byte alignment for hardware watchpoint target address. 691 // TODO: Add support for watching un-aligned addresses 692 if (addr & 0x07) 693 return 0;//Error ("LLDB for AArch64 currently supports 8-byte alignment for hardware watchpoint target address."); 694 695 // Setup control value 696 control_value = watch_flags << 3; 697 control_value |= ((1 << size) - 1) << 5; 698 control_value |= (2 << 1) | 1; 699 700 // Iterate over stored watchpoints 701 // Find a free wp_index or update reference count if duplicate. 702 wp_index = LLDB_INVALID_INDEX32; 703 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 704 { 705 if ((m_hwp_regs[i].control & 1) == 0) 706 { 707 wp_index = i; // Mark last free slot 708 } 709 else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 710 { 711 wp_index = i; // Mark duplicate index 712 break; // Stop searching here 713 } 714 } 715 716 if (wp_index == LLDB_INVALID_INDEX32) 717 return LLDB_INVALID_INDEX32; 718 719 // Add new or update existing watchpoint 720 if ((m_hwp_regs[wp_index].control & 1) == 0) 721 { 722 m_hwp_regs[wp_index].address = addr; 723 m_hwp_regs[wp_index].control = control_value; 724 m_hwp_regs[wp_index].refcount = 1; 725 726 // PTRACE call to set corresponding watchpoint register. 727 process_p->WriteHardwareDebugRegs(m_thread.GetID (), &addr, 728 &control_value, 0, wp_index); 729 } 730 else 731 m_hwp_regs[wp_index].refcount++; 732 733 return wp_index; 734 } 735 736 bool 737 NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) 738 { 739 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 740 741 if (log) 742 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 743 744 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 745 if (!process_sp) 746 return false; 747 748 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 749 750 if (wp_index >= m_max_hwp_supported) 751 return false; 752 753 // Update reference count if multiple references. 754 if (m_hwp_regs[wp_index].refcount > 1) 755 { 756 m_hwp_regs[wp_index].refcount--; 757 return true; 758 } 759 else if (m_hwp_regs[wp_index].refcount == 1) 760 { 761 m_hwp_regs[wp_index].control &= ~1; 762 m_hwp_regs[wp_index].address = 0; 763 m_hwp_regs[wp_index].refcount = 0; 764 765 //TODO: PTRACE CALL HERE for an UPDATE 766 process_p->WriteHardwareDebugRegs(m_thread.GetID (), 767 &m_hwp_regs[wp_index].address, 768 &m_hwp_regs[wp_index].control, 769 0, wp_index); 770 return true; 771 } 772 773 return false; 774 } 775 776 Error 777 NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () 778 { 779 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 780 781 if (log) 782 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 783 784 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 785 786 Error ml_error; 787 ml_error.SetErrorToErrno(); 788 if (!process_sp) 789 return ml_error; 790 791 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 792 793 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 794 { 795 if (m_hwp_regs[i].control & 0x01) 796 { 797 m_hwp_regs[i].control &= ~1; 798 m_hwp_regs[i].address = 0; 799 m_hwp_regs[i].refcount = 0; 800 801 process_p->WriteHardwareDebugRegs(m_thread.GetID (), 802 &m_hwp_regs[i].address, 803 &m_hwp_regs[i].control, 804 0, i); 805 } 806 } 807 808 return Error(); 809 } 810 811 uint32_t 812 NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) 813 { 814 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 815 816 if (log) 817 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 818 switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) 819 { 820 case 0x01: 821 return 1; 822 case 0x03: 823 return 2; 824 case 0x0f: 825 return 4; 826 case 0xff: 827 return 8; 828 default: 829 return 0; 830 } 831 } 832 bool 833 NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) 834 { 835 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 836 837 if (log) 838 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 839 840 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 841 return true; 842 else 843 return false; 844 } 845 846 Error 847 NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 848 { 849 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 850 851 if (log) 852 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 853 854 uint32_t watch_size; 855 lldb::addr_t watch_addr; 856 857 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 858 { 859 watch_size = GetWatchpointSize (wp_index); 860 watch_addr = m_hwp_regs[wp_index].address; 861 862 if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 863 && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 864 { 865 return Error(); 866 } 867 } 868 869 wp_index = LLDB_INVALID_INDEX32; 870 return Error(); 871 } 872 873 lldb::addr_t 874 NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) 875 { 876 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 877 878 if (log) 879 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 880 881 if (wp_index >= m_max_hwp_supported) 882 return LLDB_INVALID_ADDRESS; 883 884 if (WatchpointIsEnabled(wp_index)) 885 return m_hwp_regs[wp_index].address; 886 else 887 return LLDB_INVALID_ADDRESS; 888 } 889 890 bool 891 NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable) 892 { 893 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 894 895 if (log) 896 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 897 898 return false; 899 } 900