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