1 //===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #if defined (__arm64__) || defined (__aarch64__) 11 12 #include "NativeRegisterContextLinux_arm64.h" 13 14 // C Includes 15 // C++ Includes 16 17 // Other libraries and framework includes 18 #include "lldb/Core/DataBufferHeap.h" 19 #include "lldb/Core/Error.h" 20 #include "lldb/Core/Log.h" 21 #include "lldb/Core/RegisterValue.h" 22 #include "lldb/Host/common/NativeProcessProtocol.h" 23 24 #include "Plugins/Process/Linux/NativeProcessLinux.h" 25 #include "Plugins/Process/Linux/Procfs.h" 26 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" 27 28 // System includes - They have to be included after framework includes because they define some 29 // macros which collide with variable names in other modules 30 #include <sys/socket.h> 31 // NT_PRSTATUS and NT_FPREGSET definition 32 #include <elf.h> 33 34 #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) 35 36 using namespace lldb; 37 using namespace lldb_private; 38 using namespace lldb_private::process_linux; 39 40 // ARM64 general purpose registers. 41 static const uint32_t g_gpr_regnums_arm64[] = 42 { 43 gpr_x0_arm64, 44 gpr_x1_arm64, 45 gpr_x2_arm64, 46 gpr_x3_arm64, 47 gpr_x4_arm64, 48 gpr_x5_arm64, 49 gpr_x6_arm64, 50 gpr_x7_arm64, 51 gpr_x8_arm64, 52 gpr_x9_arm64, 53 gpr_x10_arm64, 54 gpr_x11_arm64, 55 gpr_x12_arm64, 56 gpr_x13_arm64, 57 gpr_x14_arm64, 58 gpr_x15_arm64, 59 gpr_x16_arm64, 60 gpr_x17_arm64, 61 gpr_x18_arm64, 62 gpr_x19_arm64, 63 gpr_x20_arm64, 64 gpr_x21_arm64, 65 gpr_x22_arm64, 66 gpr_x23_arm64, 67 gpr_x24_arm64, 68 gpr_x25_arm64, 69 gpr_x26_arm64, 70 gpr_x27_arm64, 71 gpr_x28_arm64, 72 gpr_fp_arm64, 73 gpr_lr_arm64, 74 gpr_sp_arm64, 75 gpr_pc_arm64, 76 gpr_cpsr_arm64, 77 LLDB_INVALID_REGNUM // register sets need to end with this flag 78 }; 79 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 80 "g_gpr_regnums_arm64 has wrong number of register infos"); 81 82 // ARM64 floating point registers. 83 static const uint32_t g_fpu_regnums_arm64[] = 84 { 85 fpu_v0_arm64, 86 fpu_v1_arm64, 87 fpu_v2_arm64, 88 fpu_v3_arm64, 89 fpu_v4_arm64, 90 fpu_v5_arm64, 91 fpu_v6_arm64, 92 fpu_v7_arm64, 93 fpu_v8_arm64, 94 fpu_v9_arm64, 95 fpu_v10_arm64, 96 fpu_v11_arm64, 97 fpu_v12_arm64, 98 fpu_v13_arm64, 99 fpu_v14_arm64, 100 fpu_v15_arm64, 101 fpu_v16_arm64, 102 fpu_v17_arm64, 103 fpu_v18_arm64, 104 fpu_v19_arm64, 105 fpu_v20_arm64, 106 fpu_v21_arm64, 107 fpu_v22_arm64, 108 fpu_v23_arm64, 109 fpu_v24_arm64, 110 fpu_v25_arm64, 111 fpu_v26_arm64, 112 fpu_v27_arm64, 113 fpu_v28_arm64, 114 fpu_v29_arm64, 115 fpu_v30_arm64, 116 fpu_v31_arm64, 117 fpu_fpsr_arm64, 118 fpu_fpcr_arm64, 119 LLDB_INVALID_REGNUM // register sets need to end with this flag 120 }; 121 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 122 "g_fpu_regnums_arm64 has wrong number of register infos"); 123 124 namespace { 125 // Number of register sets provided by this context. 126 enum 127 { 128 k_num_register_sets = 2 129 }; 130 } 131 132 // Register sets for ARM64. 133 static const RegisterSet 134 g_reg_sets_arm64[k_num_register_sets] = 135 { 136 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 137 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 138 }; 139 140 namespace 141 { 142 143 class ReadRegOperation : public NativeProcessLinux::Operation 144 { 145 public: 146 ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) : 147 m_tid(tid), 148 m_offset(static_cast<uintptr_t>(offset)), 149 m_reg_name(reg_name), 150 m_value(value) 151 { } 152 153 void 154 Execute(NativeProcessLinux *monitor) override; 155 156 private: 157 lldb::tid_t m_tid; 158 uintptr_t m_offset; 159 const char *m_reg_name; 160 RegisterValue &m_value; 161 }; 162 163 class WriteRegOperation : public NativeProcessLinux::Operation 164 { 165 public: 166 WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) : 167 m_tid(tid), 168 m_offset(offset), 169 m_reg_name(reg_name), 170 m_value(value) 171 { } 172 173 void 174 Execute(NativeProcessLinux *monitor) override; 175 176 private: 177 lldb::tid_t m_tid; 178 uintptr_t m_offset; 179 const char *m_reg_name; 180 const RegisterValue &m_value; 181 }; 182 183 class ReadGPROperation : public NativeProcessLinux::Operation 184 { 185 public: 186 ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) 187 : m_tid(tid), m_buf(buf), m_buf_size(buf_size) 188 { } 189 190 void Execute(NativeProcessLinux *monitor) override; 191 192 private: 193 lldb::tid_t m_tid; 194 void *m_buf; 195 size_t m_buf_size; 196 }; 197 198 class WriteGPROperation : public NativeProcessLinux::Operation 199 { 200 public: 201 WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) : 202 m_tid(tid), m_buf(buf), m_buf_size(buf_size) 203 { } 204 205 void Execute(NativeProcessLinux *monitor) override; 206 207 private: 208 lldb::tid_t m_tid; 209 void *m_buf; 210 size_t m_buf_size; 211 }; 212 213 class ReadFPROperation : public NativeProcessLinux::Operation 214 { 215 public: 216 ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) 217 : m_tid(tid), 218 m_buf(buf), 219 m_buf_size(buf_size) 220 { } 221 222 void Execute(NativeProcessLinux *monitor) override; 223 224 private: 225 lldb::tid_t m_tid; 226 void *m_buf; 227 size_t m_buf_size; 228 }; 229 230 class WriteFPROperation : public NativeProcessLinux::Operation 231 { 232 public: 233 WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) 234 : m_tid(tid), m_buf(buf), m_buf_size(buf_size) 235 { } 236 237 void Execute(NativeProcessLinux *monitor) override; 238 239 private: 240 lldb::tid_t m_tid; 241 void *m_buf; 242 size_t m_buf_size; 243 }; 244 245 class ReadDBGROperation : public NativeProcessLinux::Operation 246 { 247 public: 248 ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) 249 : m_tid(tid), 250 m_count_wp(count_wp), 251 m_count_bp(count_bp) 252 { } 253 254 void Execute(NativeProcessLinux *monitor) override; 255 256 private: 257 lldb::tid_t m_tid; 258 unsigned int &m_count_wp; 259 unsigned int &m_count_bp; 260 }; 261 262 class WriteDBGROperation : public NativeProcessLinux::Operation 263 { 264 public: 265 WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, 266 uint32_t *cntrl_buf, int type, int count) 267 : m_tid(tid), 268 m_address(addr_buf), 269 m_control(cntrl_buf), 270 m_type(type), 271 m_count(count) 272 { } 273 274 void Execute(NativeProcessLinux *monitor) override; 275 276 private: 277 lldb::tid_t m_tid; 278 lldb::addr_t * m_address; 279 uint32_t * m_control; 280 int m_type; 281 int m_count; 282 }; 283 284 } // end of anonymous namespace 285 286 void 287 ReadRegOperation::Execute(NativeProcessLinux *monitor) 288 { 289 if (m_offset > sizeof(struct user_pt_regs)) 290 { 291 uintptr_t offset = m_offset - sizeof(struct user_pt_regs); 292 if (offset > sizeof(struct user_fpsimd_state)) 293 { 294 m_error.SetErrorString("invalid offset value"); 295 return; 296 } 297 elf_fpregset_t regs; 298 int regset = NT_FPREGSET; 299 struct iovec ioVec; 300 301 ioVec.iov_base = ®s; 302 ioVec.iov_len = sizeof regs; 303 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 304 if (m_error.Success()) 305 { 306 ArchSpec arch; 307 if (monitor->GetArchitecture(arch)) 308 m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); 309 else 310 m_error.SetErrorString("failed to get architecture"); 311 } 312 } 313 else 314 { 315 elf_gregset_t regs; 316 int regset = NT_PRSTATUS; 317 struct iovec ioVec; 318 319 ioVec.iov_base = ®s; 320 ioVec.iov_len = sizeof regs; 321 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 322 if (m_error.Success()) 323 { 324 ArchSpec arch; 325 if (monitor->GetArchitecture(arch)) 326 m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); 327 else 328 m_error.SetErrorString("failed to get architecture"); 329 } 330 } 331 } 332 333 void 334 WriteRegOperation::Execute(NativeProcessLinux *monitor) 335 { 336 if (m_offset > sizeof(struct user_pt_regs)) 337 { 338 uintptr_t offset = m_offset - sizeof(struct user_pt_regs); 339 if (offset > sizeof(struct user_fpsimd_state)) 340 { 341 m_error.SetErrorString("invalid offset value"); 342 return; 343 } 344 elf_fpregset_t regs; 345 int regset = NT_FPREGSET; 346 struct iovec ioVec; 347 348 ioVec.iov_base = ®s; 349 ioVec.iov_len = sizeof regs; 350 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 351 if (m_error.Success()) 352 { 353 ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); 354 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 355 } 356 } 357 else 358 { 359 elf_gregset_t regs; 360 int regset = NT_PRSTATUS; 361 struct iovec ioVec; 362 363 ioVec.iov_base = ®s; 364 ioVec.iov_len = sizeof regs; 365 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 366 if (m_error.Success()) 367 { 368 ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); 369 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); 370 } 371 } 372 } 373 374 void 375 ReadGPROperation::Execute(NativeProcessLinux *monitor) 376 { 377 int regset = NT_PRSTATUS; 378 struct iovec ioVec; 379 380 ioVec.iov_base = m_buf; 381 ioVec.iov_len = m_buf_size; 382 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); 383 } 384 385 void 386 WriteGPROperation::Execute(NativeProcessLinux *monitor) 387 { 388 int regset = NT_PRSTATUS; 389 struct iovec ioVec; 390 391 ioVec.iov_base = m_buf; 392 ioVec.iov_len = m_buf_size; 393 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); 394 } 395 396 void 397 ReadFPROperation::Execute(NativeProcessLinux *monitor) 398 { 399 int regset = NT_FPREGSET; 400 struct iovec ioVec; 401 402 ioVec.iov_base = m_buf; 403 ioVec.iov_len = m_buf_size; 404 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); 405 } 406 407 void 408 WriteFPROperation::Execute(NativeProcessLinux *monitor) 409 { 410 int regset = NT_FPREGSET; 411 struct iovec ioVec; 412 413 ioVec.iov_base = m_buf; 414 ioVec.iov_len = m_buf_size; 415 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); 416 } 417 418 void 419 ReadDBGROperation::Execute(NativeProcessLinux *monitor) 420 { 421 int regset = NT_ARM_HW_WATCH; 422 struct iovec ioVec; 423 struct user_hwdebug_state dreg_state; 424 425 ioVec.iov_base = &dreg_state; 426 ioVec.iov_len = sizeof (dreg_state); 427 428 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); 429 430 m_count_wp = dreg_state.dbg_info & 0xff; 431 regset = NT_ARM_HW_BREAK; 432 433 NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); 434 m_count_bp = dreg_state.dbg_info & 0xff; 435 } 436 437 void 438 WriteDBGROperation::Execute(NativeProcessLinux *monitor) 439 { 440 struct iovec ioVec; 441 struct user_hwdebug_state dreg_state; 442 443 memset (&dreg_state, 0, sizeof (dreg_state)); 444 ioVec.iov_base = &dreg_state; 445 ioVec.iov_len = sizeof (dreg_state); 446 447 if (m_type == 0) 448 m_type = NT_ARM_HW_WATCH; 449 else 450 m_type = NT_ARM_HW_BREAK; 451 452 for (int i = 0; i < m_count; i++) 453 { 454 dreg_state.dbg_regs[i].addr = m_address[i]; 455 dreg_state.dbg_regs[i].ctrl = m_control[i]; 456 } 457 458 NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error); 459 } 460 461 NativeRegisterContextLinux* 462 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch, 463 NativeThreadProtocol &native_thread, 464 uint32_t concrete_frame_idx) 465 { 466 return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); 467 } 468 469 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch, 470 NativeThreadProtocol &native_thread, 471 uint32_t concrete_frame_idx) : 472 NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch)) 473 { 474 switch (target_arch.GetMachine()) 475 { 476 case llvm::Triple::aarch64: 477 m_reg_info.num_registers = k_num_registers_arm64; 478 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 479 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 480 m_reg_info.last_gpr = k_last_gpr_arm64; 481 m_reg_info.first_fpr = k_first_fpr_arm64; 482 m_reg_info.last_fpr = k_last_fpr_arm64; 483 m_reg_info.first_fpr_v = fpu_v0_arm64; 484 m_reg_info.last_fpr_v = fpu_v31_arm64; 485 m_reg_info.gpr_flags = gpr_cpsr_arm64; 486 break; 487 default: 488 assert(false && "Unhandled target architecture."); 489 break; 490 } 491 492 ::memset(&m_fpr, 0, sizeof (m_fpr)); 493 ::memset(&m_gpr_arm64, 0, sizeof (m_gpr_arm64)); 494 ::memset(&m_hwp_regs, 0, sizeof (m_hwp_regs)); 495 496 // 16 is just a maximum value, query hardware for actual watchpoint count 497 m_max_hwp_supported = 16; 498 m_max_hbp_supported = 16; 499 m_refresh_hwdebug_info = true; 500 } 501 502 uint32_t 503 NativeRegisterContextLinux_arm64::GetRegisterSetCount () const 504 { 505 return k_num_register_sets; 506 } 507 508 const RegisterSet * 509 NativeRegisterContextLinux_arm64::GetRegisterSet (uint32_t set_index) const 510 { 511 if (set_index < k_num_register_sets) 512 return &g_reg_sets_arm64[set_index]; 513 514 return nullptr; 515 } 516 517 Error 518 NativeRegisterContextLinux_arm64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 519 { 520 Error error; 521 522 if (!reg_info) 523 { 524 error.SetErrorString ("reg_info NULL"); 525 return error; 526 } 527 528 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 529 530 if (IsFPR(reg)) 531 { 532 error = ReadFPR(); 533 if (error.Fail()) 534 return error; 535 } 536 else 537 { 538 uint32_t full_reg = reg; 539 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 540 541 if (is_subreg) 542 { 543 // Read the full aligned 64-bit register. 544 full_reg = reg_info->invalidate_regs[0]; 545 } 546 547 error = ReadRegisterRaw(full_reg, reg_value); 548 549 if (error.Success ()) 550 { 551 // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 552 if (is_subreg && (reg_info->byte_offset & 0x1)) 553 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 554 555 // If our return byte size was greater than the return value reg size, then 556 // use the type specified by reg_info rather than the uint64_t default 557 if (reg_value.GetByteSize() > reg_info->byte_size) 558 reg_value.SetType(reg_info); 559 } 560 return error; 561 } 562 563 // Get pointer to m_fpr variable and set the data from it. 564 assert (reg_info->byte_offset < sizeof m_fpr); 565 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 566 switch (reg_info->byte_size) 567 { 568 case 2: 569 reg_value.SetUInt16(*(uint16_t *)src); 570 break; 571 case 4: 572 reg_value.SetUInt32(*(uint32_t *)src); 573 break; 574 case 8: 575 reg_value.SetUInt64(*(uint64_t *)src); 576 break; 577 default: 578 assert(false && "Unhandled data size."); 579 error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 580 break; 581 } 582 583 return error; 584 } 585 586 Error 587 NativeRegisterContextLinux_arm64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 588 { 589 if (!reg_info) 590 return Error ("reg_info NULL"); 591 592 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 593 if (reg_index == LLDB_INVALID_REGNUM) 594 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 595 596 if (IsGPR(reg_index)) 597 return WriteRegisterRaw(reg_index, reg_value); 598 599 if (IsFPR(reg_index)) 600 { 601 // Get pointer to m_fpr variable and set the data to it. 602 assert (reg_info->byte_offset < sizeof(m_fpr)); 603 uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 604 switch (reg_info->byte_size) 605 { 606 case 2: 607 *(uint16_t *)dst = reg_value.GetAsUInt16(); 608 break; 609 case 4: 610 *(uint32_t *)dst = reg_value.GetAsUInt32(); 611 break; 612 case 8: 613 *(uint64_t *)dst = reg_value.GetAsUInt64(); 614 break; 615 default: 616 assert(false && "Unhandled data size."); 617 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 618 } 619 620 Error error = WriteFPR(); 621 if (error.Fail()) 622 return error; 623 624 return Error (); 625 } 626 627 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 628 } 629 630 Error 631 NativeRegisterContextLinux_arm64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 632 { 633 Error error; 634 635 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 636 if (!data_sp) 637 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); 638 639 error = ReadGPR(); 640 if (error.Fail()) 641 return error; 642 643 error = ReadFPR(); 644 if (error.Fail()) 645 return error; 646 647 uint8_t *dst = data_sp->GetBytes (); 648 if (dst == nullptr) 649 { 650 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); 651 return error; 652 } 653 654 ::memcpy (dst, &m_gpr_arm64, GetGPRSize()); 655 dst += GetGPRSize(); 656 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 657 658 return error; 659 } 660 661 Error 662 NativeRegisterContextLinux_arm64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 663 { 664 Error error; 665 666 if (!data_sp) 667 { 668 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 669 return error; 670 } 671 672 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 673 { 674 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 675 return error; 676 } 677 678 679 uint8_t *src = data_sp->GetBytes (); 680 if (src == nullptr) 681 { 682 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 683 return error; 684 } 685 ::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ()); 686 687 error = WriteGPR(); 688 if (error.Fail()) 689 return error; 690 691 src += GetRegisterInfoInterface ().GetGPRSize (); 692 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 693 694 error = WriteFPR(); 695 if (error.Fail()) 696 return error; 697 698 return error; 699 } 700 701 bool 702 NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const 703 { 704 return reg <= m_reg_info.last_gpr; // GPR's come first. 705 } 706 707 bool 708 NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const 709 { 710 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 711 } 712 713 uint32_t 714 NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size) 715 { 716 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 717 718 if (log) 719 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 720 721 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 722 if (!process_sp) 723 return false; 724 725 // Check if our hardware breakpoint and watchpoint information is updated. 726 if (m_refresh_hwdebug_info) 727 { 728 ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); 729 m_refresh_hwdebug_info = false; 730 } 731 732 uint32_t control_value, bp_index; 733 734 // Check if size has a valid hardware breakpoint length. 735 if (size != 4) 736 return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware breakpoint 737 738 // Check 4-byte alignment for hardware breakpoint target address. 739 if (addr & 0x03) 740 return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. 741 742 // Setup control value 743 control_value = 0; 744 control_value |= ((1 << size) - 1) << 5; 745 control_value |= (2 << 1) | 1; 746 747 // Iterate over stored hardware breakpoints 748 // Find a free bp_index or update reference count if duplicate. 749 bp_index = LLDB_INVALID_INDEX32; 750 for (uint32_t i = 0; i < m_max_hbp_supported; i++) 751 { 752 if ((m_hbr_regs[i].control & 1) == 0) 753 { 754 bp_index = i; // Mark last free slot 755 } 756 else if (m_hbr_regs[i].address == addr && m_hbr_regs[i].control == control_value) 757 { 758 bp_index = i; // Mark duplicate index 759 break; // Stop searching here 760 } 761 } 762 763 if (bp_index == LLDB_INVALID_INDEX32) 764 return LLDB_INVALID_INDEX32; 765 766 // Add new or update existing watchpoint 767 if ((m_hbr_regs[bp_index].control & 1) == 0) 768 { 769 m_hbr_regs[bp_index].address = addr; 770 m_hbr_regs[bp_index].control = control_value; 771 m_hbr_regs[bp_index].refcount = 1; 772 773 //TODO: PTRACE CALL HERE for an UPDATE 774 } 775 else 776 m_hbr_regs[bp_index].refcount++; 777 778 return bp_index; 779 } 780 781 bool 782 NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) 783 { 784 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 785 786 if (log) 787 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 788 789 if (hw_idx >= m_max_hbp_supported) 790 return false; 791 792 // Update reference count if multiple references. 793 if (m_hbr_regs[hw_idx].refcount > 1) 794 { 795 m_hbr_regs[hw_idx].refcount--; 796 return true; 797 } 798 else if (m_hbr_regs[hw_idx].refcount == 1) 799 { 800 m_hbr_regs[hw_idx].control &= ~1; 801 m_hbr_regs[hw_idx].address = 0; 802 m_hbr_regs[hw_idx].refcount = 0; 803 804 //TODO: PTRACE CALL HERE for an UPDATE 805 return true; 806 } 807 808 return false; 809 } 810 811 uint32_t 812 NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () 813 { 814 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 815 816 if (log) 817 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 818 819 return m_max_hwp_supported; 820 } 821 822 uint32_t 823 NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags) 824 { 825 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 826 827 if (log) 828 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 829 830 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 831 if (!process_sp) 832 return false; 833 834 835 // Check if our hardware breakpoint and watchpoint information is updated. 836 if (m_refresh_hwdebug_info) 837 { 838 ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported); 839 m_refresh_hwdebug_info = false; 840 } 841 842 uint32_t control_value, wp_index; 843 844 845 if (watch_flags != 0x1 && watch_flags != 0x2 && watch_flags != 0x3) 846 return 0;//Error ("Invalid read/write bits for watchpoint"); 847 848 // Check if size has a valid hardware watchpoint length. 849 if (size != 1 && size != 2 && size != 4 && size != 8) 850 return 0;//Error ("Invalid size for watchpoint"); 851 852 // Check 8-byte alignment for hardware watchpoint target address. 853 // TODO: Add support for watching un-aligned addresses 854 if (addr & 0x07) 855 return 0;//Error ("LLDB for AArch64 currently supports 8-byte alignment for hardware watchpoint target address."); 856 857 // Setup control value 858 control_value = watch_flags << 3; 859 control_value |= ((1 << size) - 1) << 5; 860 control_value |= (2 << 1) | 1; 861 862 // Iterate over stored watchpoints 863 // Find a free wp_index or update reference count if duplicate. 864 wp_index = LLDB_INVALID_INDEX32; 865 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 866 { 867 if ((m_hwp_regs[i].control & 1) == 0) 868 { 869 wp_index = i; // Mark last free slot 870 } 871 else if (m_hwp_regs[i].address == addr && m_hwp_regs[i].control == control_value) 872 { 873 wp_index = i; // Mark duplicate index 874 break; // Stop searching here 875 } 876 } 877 878 if (wp_index == LLDB_INVALID_INDEX32) 879 return LLDB_INVALID_INDEX32; 880 881 // Add new or update existing watchpoint 882 if ((m_hwp_regs[wp_index].control & 1) == 0) 883 { 884 m_hwp_regs[wp_index].address = addr; 885 m_hwp_regs[wp_index].control = control_value; 886 m_hwp_regs[wp_index].refcount = 1; 887 888 // PTRACE call to set corresponding watchpoint register. 889 WriteHardwareDebugRegs(&addr, &control_value, 0, wp_index); 890 } 891 else 892 m_hwp_regs[wp_index].refcount++; 893 894 return wp_index; 895 } 896 897 bool 898 NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) 899 { 900 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 901 902 if (log) 903 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 904 905 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 906 if (!process_sp) 907 return false; 908 909 if (wp_index >= m_max_hwp_supported) 910 return false; 911 912 // Update reference count if multiple references. 913 if (m_hwp_regs[wp_index].refcount > 1) 914 { 915 m_hwp_regs[wp_index].refcount--; 916 return true; 917 } 918 else if (m_hwp_regs[wp_index].refcount == 1) 919 { 920 m_hwp_regs[wp_index].control &= ~1; 921 m_hwp_regs[wp_index].address = 0; 922 m_hwp_regs[wp_index].refcount = 0; 923 924 //TODO: PTRACE CALL HERE for an UPDATE 925 WriteHardwareDebugRegs(&m_hwp_regs[wp_index].address, &m_hwp_regs[wp_index].control, 0, wp_index); 926 return true; 927 } 928 929 return false; 930 } 931 932 Error 933 NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () 934 { 935 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 936 937 if (log) 938 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 939 940 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 941 942 Error ml_error; 943 ml_error.SetErrorToErrno(); 944 if (!process_sp) 945 return ml_error; 946 947 for (uint32_t i = 0; i < m_max_hwp_supported; i++) 948 { 949 if (m_hwp_regs[i].control & 0x01) 950 { 951 m_hwp_regs[i].control &= ~1; 952 m_hwp_regs[i].address = 0; 953 m_hwp_regs[i].refcount = 0; 954 955 WriteHardwareDebugRegs(&m_hwp_regs[i].address, &m_hwp_regs[i].control, 0, i); 956 } 957 } 958 959 return Error(); 960 } 961 962 uint32_t 963 NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) 964 { 965 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 966 967 if (log) 968 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 969 switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) 970 { 971 case 0x01: 972 return 1; 973 case 0x03: 974 return 2; 975 case 0x0f: 976 return 4; 977 case 0xff: 978 return 8; 979 default: 980 return 0; 981 } 982 } 983 bool 984 NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) 985 { 986 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 987 988 if (log) 989 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 990 991 if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) 992 return true; 993 else 994 return false; 995 } 996 997 Error 998 NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) 999 { 1000 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 1001 1002 if (log) 1003 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 1004 1005 uint32_t watch_size; 1006 lldb::addr_t watch_addr; 1007 1008 for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) 1009 { 1010 watch_size = GetWatchpointSize (wp_index); 1011 watch_addr = m_hwp_regs[wp_index].address; 1012 1013 if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) 1014 && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) 1015 { 1016 return Error(); 1017 } 1018 } 1019 1020 wp_index = LLDB_INVALID_INDEX32; 1021 return Error(); 1022 } 1023 1024 lldb::addr_t 1025 NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) 1026 { 1027 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); 1028 1029 if (log) 1030 log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); 1031 1032 if (wp_index >= m_max_hwp_supported) 1033 return LLDB_INVALID_ADDRESS; 1034 1035 if (WatchpointIsEnabled(wp_index)) 1036 return m_hwp_regs[wp_index].address; 1037 else 1038 return LLDB_INVALID_ADDRESS; 1039 } 1040 1041 Error 1042 NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count, 1043 unsigned int &break_count) 1044 { 1045 NativeProcessProtocolSP process_sp (m_thread.GetProcess()); 1046 if (!process_sp) 1047 return Error("NativeProcessProtocol is NULL"); 1048 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get()); 1049 1050 ReadDBGROperation op(m_thread.GetID(), watch_count, break_count); 1051 return process_p->DoOperation(&op); 1052 } 1053 1054 Error 1055 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(lldb::addr_t *addr_buf, 1056 uint32_t *cntrl_buf, 1057 int type, 1058 int count) 1059 { 1060 NativeProcessProtocolSP process_sp (m_thread.GetProcess()); 1061 if (!process_sp) 1062 return Error("NativeProcessProtocol is NULL"); 1063 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get()); 1064 1065 WriteDBGROperation op(m_thread.GetID(), addr_buf, cntrl_buf, type, count); 1066 return process_p->DoOperation(&op); 1067 } 1068 1069 NativeProcessLinux::OperationUP 1070 NativeRegisterContextLinux_arm64::GetReadRegisterValueOperation(uint32_t offset, 1071 const char* reg_name, 1072 uint32_t size, 1073 RegisterValue &value) 1074 { 1075 return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value)); 1076 } 1077 1078 NativeProcessLinux::OperationUP 1079 NativeRegisterContextLinux_arm64::GetWriteRegisterValueOperation(uint32_t offset, 1080 const char* reg_name, 1081 const RegisterValue &value) 1082 { 1083 return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value)); 1084 } 1085 1086 NativeProcessLinux::OperationUP 1087 NativeRegisterContextLinux_arm64::GetReadGPROperation(void *buf, size_t buf_size) 1088 { 1089 return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size)); 1090 } 1091 1092 NativeProcessLinux::OperationUP 1093 NativeRegisterContextLinux_arm64::GetWriteGPROperation(void *buf, size_t buf_size) 1094 { 1095 return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size)); 1096 } 1097 1098 NativeProcessLinux::OperationUP 1099 NativeRegisterContextLinux_arm64::GetReadFPROperation(void *buf, size_t buf_size) 1100 { 1101 return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size)); 1102 } 1103 1104 NativeProcessLinux::OperationUP 1105 NativeRegisterContextLinux_arm64::GetWriteFPROperation(void *buf, size_t buf_size) 1106 { 1107 return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size)); 1108 } 1109 1110 #endif // defined (__arm64__) || defined (__aarch64__) 1111