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