1042 lines · cpp
1//===-- RegisterContextDarwin_arm64.cpp -----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "RegisterContextDarwin_arm64.h"10#include "RegisterContextDarwinConstants.h"11 12#include "lldb/Target/Process.h"13#include "lldb/Target/Thread.h"14#include "lldb/Utility/DataBufferHeap.h"15#include "lldb/Utility/DataExtractor.h"16#include "lldb/Utility/Endian.h"17#include "lldb/Utility/Log.h"18#include "lldb/Utility/RegisterValue.h"19#include "lldb/Utility/Scalar.h"20#include "llvm/ADT/STLExtras.h"21#include "llvm/Support/Compiler.h"22 23#include "Plugins/Process/Utility/InstructionUtils.h"24 25#include <memory>26 27#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))28#include <sys/types.h>29#include <sys/sysctl.h>30#endif31 32#include "Utility/ARM64_DWARF_Registers.h"33 34using namespace lldb;35using namespace lldb_private;36 37#define GPR_OFFSET(idx) ((idx)*8)38#define GPR_OFFSET_NAME(reg) \39 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))40 41#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))42#define FPU_OFFSET_NAME(reg) \43 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))44 45#define EXC_OFFSET_NAME(reg) \46 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) + \47 sizeof(RegisterContextDarwin_arm64::GPR) + \48 sizeof(RegisterContextDarwin_arm64::FPU))49#define DBG_OFFSET_NAME(reg) \50 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) + \51 sizeof(RegisterContextDarwin_arm64::GPR) + \52 sizeof(RegisterContextDarwin_arm64::FPU) + \53 sizeof(RegisterContextDarwin_arm64::EXC))54 55#define DEFINE_DBG(reg, i) \56 #reg, NULL, \57 sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]), \58 DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \59 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \60 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \61 LLDB_INVALID_REGNUM }, \62 NULL, NULL, NULL63#define REG_CONTEXT_SIZE \64 (sizeof(RegisterContextDarwin_arm64::GPR) + \65 sizeof(RegisterContextDarwin_arm64::FPU) + \66 sizeof(RegisterContextDarwin_arm64::EXC))67 68// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.69#define DECLARE_REGISTER_INFOS_ARM64_STRUCT70#include "RegisterInfos_arm64.h"71#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT72 73// General purpose registers74static uint32_t g_gpr_regnums[] = {75 gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,76 gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,77 gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,78 gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,79 gpr_x28, gpr_fp, gpr_lr, gpr_sp, gpr_pc, gpr_cpsr};80 81// Floating point registers82static uint32_t g_fpu_regnums[] = {83 fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6,84 fpu_v7, fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13,85 fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20,86 fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25, fpu_v26, fpu_v27,87 fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};88 89// Exception registers90 91static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};92 93static size_t k_num_register_infos = std::size(g_register_infos_arm64_le);94 95RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(96 Thread &thread, uint32_t concrete_frame_idx)97 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc(), dbg() {98 uint32_t i;99 for (i = 0; i < kNumErrors; i++) {100 gpr_errs[i] = -1;101 fpu_errs[i] = -1;102 exc_errs[i] = -1;103 }104}105 106RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default;107 108void RegisterContextDarwin_arm64::InvalidateAllRegisters() {109 InvalidateAllRegisterStates();110}111 112size_t RegisterContextDarwin_arm64::GetRegisterCount() {113 assert(k_num_register_infos == k_num_registers);114 return k_num_registers;115}116 117const RegisterInfo *118RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {119 assert(k_num_register_infos == k_num_registers);120 if (reg < k_num_registers)121 return &g_register_infos_arm64_le[reg];122 return nullptr;123}124 125size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {126 return k_num_register_infos;127}128 129const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {130 return g_register_infos_arm64_le;131}132 133// Number of registers in each register set134const size_t k_num_gpr_registers = std::size(g_gpr_regnums);135const size_t k_num_fpu_registers = std::size(g_fpu_regnums);136const size_t k_num_exc_registers = std::size(g_exc_regnums);137 138// Register set definitions. The first definitions at register set index of139// zero is for all registers, followed by other registers sets. The register140// information for the all register set need not be filled in.141static const RegisterSet g_reg_sets[] = {142 {143 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,144 },145 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},146 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};147 148const size_t k_num_regsets = std::size(g_reg_sets);149 150size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {151 return k_num_regsets;152}153 154const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {155 if (reg_set < k_num_regsets)156 return &g_reg_sets[reg_set];157 return nullptr;158}159 160// Register information definitions for arm64161int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {162 if (reg < fpu_v0)163 return GPRRegSet;164 else if (reg < exc_far)165 return FPURegSet;166 else if (reg < k_num_registers)167 return EXCRegSet;168 return -1;169}170 171int RegisterContextDarwin_arm64::ReadGPR(bool force) {172 int set = GPRRegSet;173 if (force || !RegisterSetIsCached(set)) {174 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));175 }176 return GetError(GPRRegSet, Read);177}178 179int RegisterContextDarwin_arm64::ReadFPU(bool force) {180 int set = FPURegSet;181 if (force || !RegisterSetIsCached(set)) {182 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));183 }184 return GetError(FPURegSet, Read);185}186 187int RegisterContextDarwin_arm64::ReadEXC(bool force) {188 int set = EXCRegSet;189 if (force || !RegisterSetIsCached(set)) {190 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));191 }192 return GetError(EXCRegSet, Read);193}194 195int RegisterContextDarwin_arm64::ReadDBG(bool force) {196 int set = DBGRegSet;197 if (force || !RegisterSetIsCached(set)) {198 SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));199 }200 return GetError(DBGRegSet, Read);201}202 203int RegisterContextDarwin_arm64::WriteGPR() {204 int set = GPRRegSet;205 if (!RegisterSetIsCached(set)) {206 SetError(set, Write, -1);207 return KERN_INVALID_ARGUMENT;208 }209 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));210 SetError(set, Read, -1);211 return GetError(GPRRegSet, Write);212}213 214int RegisterContextDarwin_arm64::WriteFPU() {215 int set = FPURegSet;216 if (!RegisterSetIsCached(set)) {217 SetError(set, Write, -1);218 return KERN_INVALID_ARGUMENT;219 }220 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));221 SetError(set, Read, -1);222 return GetError(FPURegSet, Write);223}224 225int RegisterContextDarwin_arm64::WriteEXC() {226 int set = EXCRegSet;227 if (!RegisterSetIsCached(set)) {228 SetError(set, Write, -1);229 return KERN_INVALID_ARGUMENT;230 }231 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));232 SetError(set, Read, -1);233 return GetError(EXCRegSet, Write);234}235 236int RegisterContextDarwin_arm64::WriteDBG() {237 int set = DBGRegSet;238 if (!RegisterSetIsCached(set)) {239 SetError(set, Write, -1);240 return KERN_INVALID_ARGUMENT;241 }242 SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));243 SetError(set, Read, -1);244 return GetError(DBGRegSet, Write);245}246 247int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {248 switch (set) {249 case GPRRegSet:250 return ReadGPR(force);251 case FPURegSet:252 return ReadFPU(force);253 case EXCRegSet:254 return ReadEXC(force);255 case DBGRegSet:256 return ReadDBG(force);257 default:258 break;259 }260 return KERN_INVALID_ARGUMENT;261}262 263int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {264 // Make sure we have a valid context to set.265 if (RegisterSetIsCached(set)) {266 switch (set) {267 case GPRRegSet:268 return WriteGPR();269 case FPURegSet:270 return WriteFPU();271 case EXCRegSet:272 return WriteEXC();273 case DBGRegSet:274 return WriteDBG();275 default:276 break;277 }278 }279 return KERN_INVALID_ARGUMENT;280}281 282void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {283 if (log) {284 for (uint32_t i = 0; i < 16; i++)285 LLDB_LOGF(log,286 "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64287 " } WVR%-2u/WCR%-2u "288 "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",289 i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);290 }291}292 293bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,294 RegisterValue &value) {295 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];296 int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);297 298 if (set == -1)299 return false;300 301 if (ReadRegisterSet(set, false) != KERN_SUCCESS)302 return false;303 304 switch (reg) {305 case gpr_x0:306 case gpr_x1:307 case gpr_x2:308 case gpr_x3:309 case gpr_x4:310 case gpr_x5:311 case gpr_x6:312 case gpr_x7:313 case gpr_x8:314 case gpr_x9:315 case gpr_x10:316 case gpr_x11:317 case gpr_x12:318 case gpr_x13:319 case gpr_x14:320 case gpr_x15:321 case gpr_x16:322 case gpr_x17:323 case gpr_x18:324 case gpr_x19:325 case gpr_x20:326 case gpr_x21:327 case gpr_x22:328 case gpr_x23:329 case gpr_x24:330 case gpr_x25:331 case gpr_x26:332 case gpr_x27:333 case gpr_x28:334 value.SetUInt64(gpr.x[reg - gpr_x0]);335 break;336 case gpr_fp:337 value.SetUInt64(gpr.fp);338 break;339 case gpr_sp:340 value.SetUInt64(gpr.sp);341 break;342 case gpr_lr:343 value.SetUInt64(gpr.lr);344 break;345 case gpr_pc:346 value.SetUInt64(gpr.pc);347 break;348 case gpr_cpsr:349 value.SetUInt64(gpr.cpsr);350 break;351 352 case gpr_w0:353 case gpr_w1:354 case gpr_w2:355 case gpr_w3:356 case gpr_w4:357 case gpr_w5:358 case gpr_w6:359 case gpr_w7:360 case gpr_w8:361 case gpr_w9:362 case gpr_w10:363 case gpr_w11:364 case gpr_w12:365 case gpr_w13:366 case gpr_w14:367 case gpr_w15:368 case gpr_w16:369 case gpr_w17:370 case gpr_w18:371 case gpr_w19:372 case gpr_w20:373 case gpr_w21:374 case gpr_w22:375 case gpr_w23:376 case gpr_w24:377 case gpr_w25:378 case gpr_w26:379 case gpr_w27:380 case gpr_w28: {381 ProcessSP process_sp(m_thread.GetProcess());382 if (process_sp.get()) {383 DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),384 process_sp->GetAddressByteSize());385 offset_t offset = 0;386 uint64_t retval = regdata.GetMaxU64(&offset, 8);387 uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);388 value.SetUInt32(retval_lower32);389 }390 } break;391 392 case fpu_v0:393 case fpu_v1:394 case fpu_v2:395 case fpu_v3:396 case fpu_v4:397 case fpu_v5:398 case fpu_v6:399 case fpu_v7:400 case fpu_v8:401 case fpu_v9:402 case fpu_v10:403 case fpu_v11:404 case fpu_v12:405 case fpu_v13:406 case fpu_v14:407 case fpu_v15:408 case fpu_v16:409 case fpu_v17:410 case fpu_v18:411 case fpu_v19:412 case fpu_v20:413 case fpu_v21:414 case fpu_v22:415 case fpu_v23:416 case fpu_v24:417 case fpu_v25:418 case fpu_v26:419 case fpu_v27:420 case fpu_v28:421 case fpu_v29:422 case fpu_v30:423 case fpu_v31:424 value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size,425 endian::InlHostByteOrder());426 break;427 428 case fpu_s0:429 case fpu_s1:430 case fpu_s2:431 case fpu_s3:432 case fpu_s4:433 case fpu_s5:434 case fpu_s6:435 case fpu_s7:436 case fpu_s8:437 case fpu_s9:438 case fpu_s10:439 case fpu_s11:440 case fpu_s12:441 case fpu_s13:442 case fpu_s14:443 case fpu_s15:444 case fpu_s16:445 case fpu_s17:446 case fpu_s18:447 case fpu_s19:448 case fpu_s20:449 case fpu_s21:450 case fpu_s22:451 case fpu_s23:452 case fpu_s24:453 case fpu_s25:454 case fpu_s26:455 case fpu_s27:456 case fpu_s28:457 case fpu_s29:458 case fpu_s30:459 case fpu_s31: {460 ProcessSP process_sp(m_thread.GetProcess());461 if (process_sp.get()) {462 DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),463 process_sp->GetAddressByteSize());464 offset_t offset = 0;465 value.SetFloat(regdata.GetFloat(&offset));466 }467 } break;468 469 case fpu_d0:470 case fpu_d1:471 case fpu_d2:472 case fpu_d3:473 case fpu_d4:474 case fpu_d5:475 case fpu_d6:476 case fpu_d7:477 case fpu_d8:478 case fpu_d9:479 case fpu_d10:480 case fpu_d11:481 case fpu_d12:482 case fpu_d13:483 case fpu_d14:484 case fpu_d15:485 case fpu_d16:486 case fpu_d17:487 case fpu_d18:488 case fpu_d19:489 case fpu_d20:490 case fpu_d21:491 case fpu_d22:492 case fpu_d23:493 case fpu_d24:494 case fpu_d25:495 case fpu_d26:496 case fpu_d27:497 case fpu_d28:498 case fpu_d29:499 case fpu_d30:500 case fpu_d31: {501 ProcessSP process_sp(m_thread.GetProcess());502 if (process_sp.get()) {503 DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(),504 process_sp->GetAddressByteSize());505 offset_t offset = 0;506 value.SetDouble(regdata.GetDouble(&offset));507 }508 } break;509 510 case fpu_fpsr:511 value.SetUInt32(fpu.fpsr);512 break;513 514 case fpu_fpcr:515 value.SetUInt32(fpu.fpcr);516 break;517 518 case exc_exception:519 value.SetUInt32(exc.exception);520 break;521 case exc_esr:522 value.SetUInt32(exc.esr);523 break;524 case exc_far:525 value.SetUInt64(exc.far);526 break;527 528 default:529 value.SetValueToInvalid();530 return false;531 }532 return true;533}534 535bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,536 const RegisterValue &value) {537 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];538 int set = GetSetForNativeRegNum(reg);539 540 if (set == -1)541 return false;542 543 if (ReadRegisterSet(set, false) != KERN_SUCCESS)544 return false;545 546 switch (reg) {547 case gpr_x0:548 case gpr_x1:549 case gpr_x2:550 case gpr_x3:551 case gpr_x4:552 case gpr_x5:553 case gpr_x6:554 case gpr_x7:555 case gpr_x8:556 case gpr_x9:557 case gpr_x10:558 case gpr_x11:559 case gpr_x12:560 case gpr_x13:561 case gpr_x14:562 case gpr_x15:563 case gpr_x16:564 case gpr_x17:565 case gpr_x18:566 case gpr_x19:567 case gpr_x20:568 case gpr_x21:569 case gpr_x22:570 case gpr_x23:571 case gpr_x24:572 case gpr_x25:573 case gpr_x26:574 case gpr_x27:575 case gpr_x28:576 case gpr_fp:577 case gpr_sp:578 case gpr_lr:579 case gpr_pc:580 case gpr_cpsr:581 gpr.x[reg - gpr_x0] = value.GetAsUInt64();582 break;583 584 case fpu_v0:585 case fpu_v1:586 case fpu_v2:587 case fpu_v3:588 case fpu_v4:589 case fpu_v5:590 case fpu_v6:591 case fpu_v7:592 case fpu_v8:593 case fpu_v9:594 case fpu_v10:595 case fpu_v11:596 case fpu_v12:597 case fpu_v13:598 case fpu_v14:599 case fpu_v15:600 case fpu_v16:601 case fpu_v17:602 case fpu_v18:603 case fpu_v19:604 case fpu_v20:605 case fpu_v21:606 case fpu_v22:607 case fpu_v23:608 case fpu_v24:609 case fpu_v25:610 case fpu_v26:611 case fpu_v27:612 case fpu_v28:613 case fpu_v29:614 case fpu_v30:615 case fpu_v31:616 ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(),617 value.GetByteSize());618 break;619 620 case fpu_fpsr:621 fpu.fpsr = value.GetAsUInt32();622 break;623 624 case fpu_fpcr:625 fpu.fpcr = value.GetAsUInt32();626 break;627 628 case exc_exception:629 exc.exception = value.GetAsUInt32();630 break;631 case exc_esr:632 exc.esr = value.GetAsUInt32();633 break;634 case exc_far:635 exc.far = value.GetAsUInt64();636 break;637 638 default:639 return false;640 }641 return WriteRegisterSet(set) == KERN_SUCCESS;642}643 644bool RegisterContextDarwin_arm64::ReadAllRegisterValues(645 lldb::WritableDataBufferSP &data_sp) {646 data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);647 if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&648 ReadEXC(false) == KERN_SUCCESS) {649 uint8_t *dst = data_sp->GetBytes();650 ::memcpy(dst, &gpr, sizeof(gpr));651 dst += sizeof(gpr);652 653 ::memcpy(dst, &fpu, sizeof(fpu));654 dst += sizeof(gpr);655 656 ::memcpy(dst, &exc, sizeof(exc));657 return true;658 }659 return false;660}661 662bool RegisterContextDarwin_arm64::WriteAllRegisterValues(663 const lldb::DataBufferSP &data_sp) {664 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {665 const uint8_t *src = data_sp->GetBytes();666 ::memcpy(&gpr, src, sizeof(gpr));667 src += sizeof(gpr);668 669 ::memcpy(&fpu, src, sizeof(fpu));670 src += sizeof(gpr);671 672 ::memcpy(&exc, src, sizeof(exc));673 uint32_t success_count = 0;674 if (WriteGPR() == KERN_SUCCESS)675 ++success_count;676 if (WriteFPU() == KERN_SUCCESS)677 ++success_count;678 if (WriteEXC() == KERN_SUCCESS)679 ++success_count;680 return success_count == 3;681 }682 return false;683}684 685uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(686 RegisterKind kind, uint32_t reg) {687 if (kind == eRegisterKindGeneric) {688 switch (reg) {689 case LLDB_REGNUM_GENERIC_PC:690 return gpr_pc;691 case LLDB_REGNUM_GENERIC_SP:692 return gpr_sp;693 case LLDB_REGNUM_GENERIC_FP:694 return gpr_fp;695 case LLDB_REGNUM_GENERIC_RA:696 return gpr_lr;697 case LLDB_REGNUM_GENERIC_FLAGS:698 return gpr_cpsr;699 default:700 break;701 }702 } else if (kind == eRegisterKindDWARF) {703 switch (reg) {704 case arm64_dwarf::x0:705 return gpr_x0;706 case arm64_dwarf::x1:707 return gpr_x1;708 case arm64_dwarf::x2:709 return gpr_x2;710 case arm64_dwarf::x3:711 return gpr_x3;712 case arm64_dwarf::x4:713 return gpr_x4;714 case arm64_dwarf::x5:715 return gpr_x5;716 case arm64_dwarf::x6:717 return gpr_x6;718 case arm64_dwarf::x7:719 return gpr_x7;720 case arm64_dwarf::x8:721 return gpr_x8;722 case arm64_dwarf::x9:723 return gpr_x9;724 case arm64_dwarf::x10:725 return gpr_x10;726 case arm64_dwarf::x11:727 return gpr_x11;728 case arm64_dwarf::x12:729 return gpr_x12;730 case arm64_dwarf::x13:731 return gpr_x13;732 case arm64_dwarf::x14:733 return gpr_x14;734 case arm64_dwarf::x15:735 return gpr_x15;736 case arm64_dwarf::x16:737 return gpr_x16;738 case arm64_dwarf::x17:739 return gpr_x17;740 case arm64_dwarf::x18:741 return gpr_x18;742 case arm64_dwarf::x19:743 return gpr_x19;744 case arm64_dwarf::x20:745 return gpr_x20;746 case arm64_dwarf::x21:747 return gpr_x21;748 case arm64_dwarf::x22:749 return gpr_x22;750 case arm64_dwarf::x23:751 return gpr_x23;752 case arm64_dwarf::x24:753 return gpr_x24;754 case arm64_dwarf::x25:755 return gpr_x25;756 case arm64_dwarf::x26:757 return gpr_x26;758 case arm64_dwarf::x27:759 return gpr_x27;760 case arm64_dwarf::x28:761 return gpr_x28;762 763 case arm64_dwarf::fp:764 return gpr_fp;765 case arm64_dwarf::sp:766 return gpr_sp;767 case arm64_dwarf::lr:768 return gpr_lr;769 case arm64_dwarf::pc:770 return gpr_pc;771 case arm64_dwarf::cpsr:772 return gpr_cpsr;773 774 case arm64_dwarf::v0:775 return fpu_v0;776 case arm64_dwarf::v1:777 return fpu_v1;778 case arm64_dwarf::v2:779 return fpu_v2;780 case arm64_dwarf::v3:781 return fpu_v3;782 case arm64_dwarf::v4:783 return fpu_v4;784 case arm64_dwarf::v5:785 return fpu_v5;786 case arm64_dwarf::v6:787 return fpu_v6;788 case arm64_dwarf::v7:789 return fpu_v7;790 case arm64_dwarf::v8:791 return fpu_v8;792 case arm64_dwarf::v9:793 return fpu_v9;794 case arm64_dwarf::v10:795 return fpu_v10;796 case arm64_dwarf::v11:797 return fpu_v11;798 case arm64_dwarf::v12:799 return fpu_v12;800 case arm64_dwarf::v13:801 return fpu_v13;802 case arm64_dwarf::v14:803 return fpu_v14;804 case arm64_dwarf::v15:805 return fpu_v15;806 case arm64_dwarf::v16:807 return fpu_v16;808 case arm64_dwarf::v17:809 return fpu_v17;810 case arm64_dwarf::v18:811 return fpu_v18;812 case arm64_dwarf::v19:813 return fpu_v19;814 case arm64_dwarf::v20:815 return fpu_v20;816 case arm64_dwarf::v21:817 return fpu_v21;818 case arm64_dwarf::v22:819 return fpu_v22;820 case arm64_dwarf::v23:821 return fpu_v23;822 case arm64_dwarf::v24:823 return fpu_v24;824 case arm64_dwarf::v25:825 return fpu_v25;826 case arm64_dwarf::v26:827 return fpu_v26;828 case arm64_dwarf::v27:829 return fpu_v27;830 case arm64_dwarf::v28:831 return fpu_v28;832 case arm64_dwarf::v29:833 return fpu_v29;834 case arm64_dwarf::v30:835 return fpu_v30;836 case arm64_dwarf::v31:837 return fpu_v31;838 839 default:840 break;841 }842 } else if (kind == eRegisterKindEHFrame) {843 switch (reg) {844 case arm64_ehframe::x0:845 return gpr_x0;846 case arm64_ehframe::x1:847 return gpr_x1;848 case arm64_ehframe::x2:849 return gpr_x2;850 case arm64_ehframe::x3:851 return gpr_x3;852 case arm64_ehframe::x4:853 return gpr_x4;854 case arm64_ehframe::x5:855 return gpr_x5;856 case arm64_ehframe::x6:857 return gpr_x6;858 case arm64_ehframe::x7:859 return gpr_x7;860 case arm64_ehframe::x8:861 return gpr_x8;862 case arm64_ehframe::x9:863 return gpr_x9;864 case arm64_ehframe::x10:865 return gpr_x10;866 case arm64_ehframe::x11:867 return gpr_x11;868 case arm64_ehframe::x12:869 return gpr_x12;870 case arm64_ehframe::x13:871 return gpr_x13;872 case arm64_ehframe::x14:873 return gpr_x14;874 case arm64_ehframe::x15:875 return gpr_x15;876 case arm64_ehframe::x16:877 return gpr_x16;878 case arm64_ehframe::x17:879 return gpr_x17;880 case arm64_ehframe::x18:881 return gpr_x18;882 case arm64_ehframe::x19:883 return gpr_x19;884 case arm64_ehframe::x20:885 return gpr_x20;886 case arm64_ehframe::x21:887 return gpr_x21;888 case arm64_ehframe::x22:889 return gpr_x22;890 case arm64_ehframe::x23:891 return gpr_x23;892 case arm64_ehframe::x24:893 return gpr_x24;894 case arm64_ehframe::x25:895 return gpr_x25;896 case arm64_ehframe::x26:897 return gpr_x26;898 case arm64_ehframe::x27:899 return gpr_x27;900 case arm64_ehframe::x28:901 return gpr_x28;902 case arm64_ehframe::fp:903 return gpr_fp;904 case arm64_ehframe::sp:905 return gpr_sp;906 case arm64_ehframe::lr:907 return gpr_lr;908 case arm64_ehframe::pc:909 return gpr_pc;910 case arm64_ehframe::cpsr:911 return gpr_cpsr;912 }913 } else if (kind == eRegisterKindLLDB) {914 return reg;915 }916 return LLDB_INVALID_REGNUM;917}918 919uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {920#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))921 // autodetect how many watchpoints are supported dynamically...922 static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;923 if (g_num_supported_hw_watchpoints == UINT32_MAX) {924 size_t len;925 uint32_t n = 0;926 len = sizeof(n);927 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {928 g_num_supported_hw_watchpoints = n;929 }930 }931 return g_num_supported_hw_watchpoints;932#else933 // TODO: figure out remote case here!934 return 2;935#endif936}937 938uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,939 size_t size,940 bool read,941 bool write) {942 // if (log) log->Printf943 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,944 // size = %u, read = %u, write = %u)", addr, size, read, write);945 946 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();947 948 // Can't watch zero bytes949 if (size == 0)950 return LLDB_INVALID_INDEX32;951 952 // We must watch for either read or write953 if (!read && !write)954 return LLDB_INVALID_INDEX32;955 956 // Can't watch more than 4 bytes per WVR/WCR pair957 if (size > 4)958 return LLDB_INVALID_INDEX32;959 960 // We can only watch up to four bytes that follow a 4 byte aligned address961 // per watchpoint register pair. Since we have at most so we can only watch962 // until the next 4 byte boundary and we need to make sure we can properly963 // encode this.964 uint32_t addr_word_offset = addr % 4;965 // if (log) log->Printf966 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -967 // addr_word_offset = 0x%8.8x", addr_word_offset);968 969 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;970 // if (log) log->Printf971 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =972 // 0x%8.8x", byte_mask);973 if (byte_mask > 0xfu)974 return LLDB_INVALID_INDEX32;975 976 // Read the debug state977 int kret = ReadDBG(false);978 979 if (kret == KERN_SUCCESS) {980 // Check to make sure we have the needed hardware support981 uint32_t i = 0;982 983 for (i = 0; i < num_hw_watchpoints; ++i) {984 if ((dbg.wcr[i] & WCR_ENABLE) == 0)985 break; // We found an available hw breakpoint slot (in i)986 }987 988 // See if we found an available hw breakpoint slot above989 if (i < num_hw_watchpoints) {990 // Make the byte_mask into a valid Byte Address Select mask991 uint32_t byte_address_select = byte_mask << 5;992 // Make sure bits 1:0 are clear in our address993 dbg.wvr[i] = addr & ~((lldb::addr_t)3);994 dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA995 // that we will watch996 S_USER | // Stop only in user mode997 (read ? WCR_LOAD : 0) | // Stop on read access?998 (write ? WCR_STORE : 0) | // Stop on write access?999 WCR_ENABLE; // Enable this watchpoint;1000 1001 kret = WriteDBG();1002 // if (log) log->Printf1003 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()1004 // WriteDBG() => 0x%8.8x.", kret);1005 1006 if (kret == KERN_SUCCESS)1007 return i;1008 } else {1009 // if (log) log->Printf1010 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():1011 // All hardware resources (%u) are in use.",1012 // num_hw_watchpoints);1013 }1014 }1015 return LLDB_INVALID_INDEX32;1016}1017 1018bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {1019 int kret = ReadDBG(false);1020 1021 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();1022 if (kret == KERN_SUCCESS) {1023 if (hw_index < num_hw_points) {1024 dbg.wcr[hw_index] = 0;1025 // if (log) log->Printf1026 // ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )1027 // - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",1028 // hw_index,1029 // hw_index,1030 // dbg.wvr[hw_index],1031 // hw_index,1032 // dbg.wcr[hw_index]);1033 1034 kret = WriteDBG();1035 1036 if (kret == KERN_SUCCESS)1037 return true;1038 }1039 }1040 return false;1041}1042