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