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 assert (reg_info->byte_offset < sizeof m_fpr); 233 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 234 switch (reg_info->byte_size) 235 { 236 case 2: 237 reg_value.SetUInt16(*(uint16_t *)src); 238 break; 239 case 4: 240 reg_value.SetUInt32(*(uint32_t *)src); 241 break; 242 case 8: 243 reg_value.SetUInt64(*(uint64_t *)src); 244 break; 245 default: 246 assert(false && "Unhandled data size."); 247 error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 248 break; 249 } 250 251 return error; 252 } 253 254 Error 255 NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 256 { 257 if (!reg_info) 258 return Error ("reg_info NULL"); 259 260 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 261 if (reg_index == LLDB_INVALID_REGNUM) 262 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 263 264 if (IsGPR(reg_index)) 265 return WriteRegisterRaw(reg_index, reg_value); 266 267 if (IsFPR(reg_index)) 268 { 269 // Get pointer to m_fpr variable and set the data to it. 270 assert (reg_info->byte_offset < sizeof(m_fpr)); 271 uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 272 switch (reg_info->byte_size) 273 { 274 case 2: 275 *(uint16_t *)dst = reg_value.GetAsUInt16(); 276 break; 277 case 4: 278 *(uint32_t *)dst = reg_value.GetAsUInt32(); 279 break; 280 case 8: 281 *(uint64_t *)dst = reg_value.GetAsUInt64(); 282 break; 283 default: 284 assert(false && "Unhandled data size."); 285 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 286 } 287 288 Error error = WriteFPR(); 289 if (error.Fail()) 290 return error; 291 292 return Error (); 293 } 294 295 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 296 } 297 298 Error 299 NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 300 { 301 Error error; 302 303 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 304 if (!data_sp) 305 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); 306 307 error = ReadGPR(); 308 if (error.Fail()) 309 return error; 310 311 error = ReadFPR(); 312 if (error.Fail()) 313 return error; 314 315 uint8_t *dst = data_sp->GetBytes (); 316 if (dst == nullptr) 317 { 318 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE); 319 return error; 320 } 321 322 ::memcpy (dst, &m_gpr_arm, GetGPRSize()); 323 dst += GetGPRSize(); 324 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 325 326 return error; 327 } 328 329 Error 330 NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 331 { 332 Error error; 333 334 if (!data_sp) 335 { 336 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 337 return error; 338 } 339 340 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 341 { 342 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 ()); 343 return error; 344 } 345 346 347 uint8_t *src = data_sp->GetBytes (); 348 if (src == nullptr) 349 { 350 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 351 return error; 352 } 353 ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); 354 355 error = WriteGPR(); 356 if (error.Fail()) 357 return error; 358 359 src += GetRegisterInfoInterface ().GetGPRSize (); 360 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 361 362 error = WriteFPR(); 363 if (error.Fail()) 364 return error; 365 366 return error; 367 } 368 369 bool 370 NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const 371 { 372 return reg <= m_reg_info.last_gpr; // GPR's come first. 373 } 374 375 bool 376 NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const 377 { 378 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 379 } 380 381 uint32_t 382 NativeRegisterContextLinux_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 383 { 384 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 385 386 if (log) 387 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 388 389 Error error; 390 391 // Read hardware breakpoint and watchpoint information. 392 error = ReadHardwareDebugInfo (); 393 394 if (error.Fail()) 395 return LLDB_INVALID_INDEX32; 396 397 uint32_t control_value = 0, bp_index = 0; 398 399 // Check if size has a valid hardware breakpoint length. 400 // Thumb instructions are 2-bytes but we have no way here to determine 401 // if target address is a thumb or arm instruction. 402 // TODO: Add support for setting thumb mode hardware breakpoints 403 if (size != 4 && size != 2) 404 return LLDB_INVALID_INDEX32; 405 406 // Setup control value 407 // Make the byte_mask into a valid Byte Address Select mask 408 control_value = 0xfu << 5; 409 410 // Enable this breakpoint and make it stop in privileged or user mode; 411 control_value |= 7; 412 413 // Make sure bits 1:0 are clear in our address 414 // This should be different once we support thumb here. 415 addr &= ~((lldb::addr_t)3); 416 417 // Iterate over stored hardware breakpoints 418 // Find a free bp_index or update reference count if duplicate. 419 bp_index = LLDB_INVALID_INDEX32; 420 421 for (uint32_t i = 0; i < m_max_hbp_supported; i++) 422 { 423 if ((m_hbr_regs[i].control & 1) == 0) 424 { 425 bp_index = i; // Mark last free slot 426 } 427 else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 428 { 429 bp_index = i; // Mark duplicate index 430 break; // Stop searching here 431 } 432 } 433 434 if (bp_index == LLDB_INVALID_INDEX32) 435 return LLDB_INVALID_INDEX32; 436 437 // Add new or update existing watchpoint 438 if ((m_hbr_regs[bp_index].control & 1) == 0) 439 { 440 m_hbr_regs[bp_index].address = addr; 441 m_hbr_regs[bp_index].control = control_value; 442 m_hbr_regs[bp_index].refcount = 1; 443 444 // PTRACE call to set corresponding hardware breakpoint register. 445 error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); 446 447 if (error.Fail()) 448 return LLDB_INVALID_INDEX32; 449 } 450 else 451 m_hbr_regs[bp_index].refcount++; 452 453 return bp_index; 454 } 455 456 bool 457 NativeRegisterContextLinux_arm::ClearHardwareBreakpoint (uint32_t hw_idx) 458 { 459 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 460 461 if (log) 462 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 463 464 Error error; 465 466 // Read hardware breakpoint and watchpoint information. 467 error = ReadHardwareDebugInfo (); 468 469 if (error.Fail()) 470 return LLDB_INVALID_INDEX32; 471 472 if (hw_idx >= m_max_hbp_supported) 473 return false; 474 475 // Update reference count if multiple references. 476 if (m_hbr_regs[hw_idx].refcount > 1) 477 { 478 m_hbr_regs[hw_idx].refcount--; 479 return true; 480 } 481 else if (m_hbr_regs[hw_idx].refcount == 1) 482 { 483 m_hbr_regs[hw_idx].control &= ~1; 484 m_hbr_regs[hw_idx].address = 0; 485 m_hbr_regs[hw_idx].refcount = 0; 486 487 // PTRACE call to clear corresponding hardware breakpoint register. 488 WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); 489 490 if (error.Fail()) 491 return LLDB_INVALID_INDEX32; 492 493 return true; 494 } 495 496 return false; 497 } 498 499 uint32_t 500 NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints () 501 { 502 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 503 504 if (log) 505 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 506 507 Error error; 508 509 // Read hardware breakpoint and watchpoint information. 510 error = ReadHardwareDebugInfo (); 511 512 if (error.Fail()) 513 return LLDB_INVALID_INDEX32; 514 515 return m_max_hwp_supported; 516 } 517 518 uint32_t 519 NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 520 { 521 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 522 523 if (log) 524 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 525 526 Error error; 527 528 // Read hardware breakpoint and watchpoint information. 529 error = ReadHardwareDebugInfo (); 530 531 if (error.Fail()) 532 return LLDB_INVALID_INDEX32; 533 534 uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; 535 536 // Check if we are setting watchpoint other than read/write/access 537 // Also update watchpoint flag to match Arm write-read bit configuration. 538 switch (watch_flags) 539 { 540 case 1: 541 watch_flags = 2; 542 break; 543 case 2: 544 watch_flags = 1; 545 break; 546 case 3: 547 break; 548 default: 549 return LLDB_INVALID_INDEX32; 550 } 551 552 // Can't watch zero bytes 553 // Can't watch more than 4 bytes per WVR/WCR pair 554 555 if (size == 0 || size > 4) 556 return LLDB_INVALID_INDEX32; 557 558 // We can only watch up to four bytes that follow a 4 byte aligned address 559 // per watchpoint register pair, so make sure we can properly encode this. 560 addr_word_offset = addr % 4; 561 byte_mask = ((1u << size) - 1u) << addr_word_offset; 562 563 // Check if we need multiple watchpoint register 564 if (byte_mask > 0xfu) 565 return LLDB_INVALID_INDEX32; 566 567 // Setup control value 568 // Make the byte_mask into a valid Byte Address Select mask 569 control_value = byte_mask << 5; 570 571 //Turn on appropriate watchpoint flags read or write 572 control_value |= (watch_flags << 3); 573 574 // Enable this watchpoint and make it stop in privileged or user mode; 575 control_value |= 7; 576 577 // Make sure bits 1:0 are clear in our address 578 addr &= ~((lldb::addr_t)3); 579 580 // Iterate over stored watchpoints 581 // Find a free wp_index or update reference count if duplicate. 582 wp_index = LLDB_INVALID_INDEX32; 583 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 584 { 585 if ((m_hwp_regs[i].control & 1) == 0) 586 { 587 wp_index = i; // Mark last free slot 588 } 589 else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 590 { 591 wp_index = i; // Mark duplicate index 592 break; // Stop searching here 593 } 594 } 595 596 if (wp_index == LLDB_INVALID_INDEX32) 597 return LLDB_INVALID_INDEX32; 598 599 // Add new or update existing watchpoint 600 if ((m_hwp_regs[wp_index].control & 1) == 0) 601 { 602 // Update watchpoint in local cache 603 m_hwp_regs[wp_index].address = addr; 604 m_hwp_regs[wp_index].control = control_value; 605 m_hwp_regs[wp_index].refcount = 1; 606 607 // PTRACE call to set corresponding watchpoint register. 608 error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 609 610 if (error.Fail()) 611 return LLDB_INVALID_INDEX32; 612 } 613 else 614 m_hwp_regs[wp_index].refcount++; 615 616 return wp_index; 617 } 618 619 bool 620 NativeRegisterContextLinux_arm::ClearHardwareWatchpoint (uint32_t wp_index) 621 { 622 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 623 624 if (log) 625 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 626 627 Error error; 628 629 // Read hardware breakpoint and watchpoint information. 630 error = ReadHardwareDebugInfo (); 631 632 if (error.Fail()) 633 return LLDB_INVALID_INDEX32; 634 635 if (wp_index >= m_max_hwp_supported) 636 return false; 637 638 // Update reference count if multiple references. 639 if (m_hwp_regs[wp_index].refcount > 1) 640 { 641 m_hwp_regs[wp_index].refcount--; 642 return true; 643 } 644 else if (m_hwp_regs[wp_index].refcount == 1) 645 { 646 // Update watchpoint in local cache 647 m_hwp_regs[wp_index].control &= ~1; 648 m_hwp_regs[wp_index].address = 0; 649 m_hwp_regs[wp_index].refcount = 0; 650 651 // Ptrace call to update hardware debug registers 652 error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); 653 654 if (error.Fail()) 655 return false; 656 657 return true; 658 } 659 660 return false; 661 } 662 663 Error 664 NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints () 665 { 666 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 667 668 if (log) 669 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 670 671 Error error; 672 673 // Read hardware breakpoint and watchpoint information. 674 error = ReadHardwareDebugInfo (); 675 676 if (error.Fail()) 677 return error; 678 679 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 680 { 681 if (m_hwp_regs[i].control & 0x01) 682 { 683 // Clear watchpoints in local cache 684 m_hwp_regs[i].control &= ~1; 685 m_hwp_regs[i].address = 0; 686 m_hwp_regs[i].refcount = 0; 687 688 // Ptrace call to update hardware debug registers 689 error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); 690 691 if (error.Fail()) 692 return error; 693 } 694 } 695 696 return Error(); 697 } 698 699 uint32_t 700 NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) 701 { 702 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 703 704 if (log) 705 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 706 707 switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) 708 { 709 case 0x01: 710 return 1; 711 case 0x03: 712 return 2; 713 case 0x07: 714 return 3; 715 case 0x0f: 716 return 4; 717 default: 718 return 0; 719 } 720 } 721 bool 722 NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) 723 { 724 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 725 726 if (log) 727 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 728 729 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 730 return true; 731 else 732 return false; 733 } 734 735 Error 736 NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 737 { 738 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 739 740 if (log) 741 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 742 743 uint32_t watch_size; 744 lldb::addr_t watch_addr; 745 746 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 747 { 748 watch_size = GetWatchpointSize (wp_index); 749 watch_addr = m_hwp_regs[wp_index].address; 750 751 if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 752 && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 753 { 754 return Error(); 755 } 756 } 757 758 wp_index = LLDB_INVALID_INDEX32; 759 return Error(); 760 } 761 762 lldb::addr_t 763 NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index) 764 { 765 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 766 767 if (log) 768 log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); 769 770 if (wp_index >= m_max_hwp_supported) 771 return LLDB_INVALID_ADDRESS; 772 773 if (WatchpointIsEnabled(wp_index)) 774 return m_hwp_regs[wp_index].address; 775 else 776 return LLDB_INVALID_ADDRESS; 777 } 778 779 Error 780 NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() 781 { 782 Error error; 783 784 if (!m_refresh_hwdebug_info) 785 { 786 return Error(); 787 } 788 789 unsigned int cap_val; 790 791 error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), nullptr, &cap_val, sizeof(unsigned int)); 792 793 if (error.Fail()) 794 return error; 795 796 m_max_hwp_supported = (cap_val >> 8) & 0xff; 797 m_max_hbp_supported = cap_val & 0xff; 798 m_refresh_hwdebug_info = false; 799 800 return error; 801 } 802 803 Error 804 NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_index) 805 { 806 Error error; 807 808 lldb::addr_t *addr_buf; 809 uint32_t *ctrl_buf; 810 811 if (hwbType == eDREGTypeWATCH) 812 { 813 addr_buf = &m_hwp_regs[hwb_index].address; 814 ctrl_buf = &m_hwp_regs[hwb_index].control; 815 816 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 817 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1), 818 addr_buf, sizeof(unsigned int)); 819 820 if (error.Fail()) 821 return error; 822 823 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 824 m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2), 825 ctrl_buf, sizeof(unsigned int)); 826 } 827 else 828 { 829 addr_buf = &m_hwp_regs[hwb_index].address; 830 ctrl_buf = &m_hwp_regs[hwb_index].control; 831 832 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 833 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1), 834 addr_buf, sizeof(unsigned int)); 835 836 if (error.Fail()) 837 return error; 838 839 error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS, 840 m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2), 841 ctrl_buf, sizeof(unsigned int)); 842 843 } 844 845 return error; 846 } 847 #endif // defined(__arm__) 848