Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
96381 views
//===-- RegisterContextDarwin_arm64.cpp -----------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "RegisterContextDarwin_arm64.h"9#include "RegisterContextDarwinConstants.h"1011#include "lldb/Target/Process.h"12#include "lldb/Target/Thread.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/DataExtractor.h"15#include "lldb/Utility/Endian.h"16#include "lldb/Utility/Log.h"17#include "lldb/Utility/RegisterValue.h"18#include "lldb/Utility/Scalar.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/Support/Compiler.h"2122#include "Plugins/Process/Utility/InstructionUtils.h"2324#include <memory>2526#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))27#include <sys/types.h>28#include <sys/sysctl.h>29#endif3031#include "Utility/ARM64_DWARF_Registers.h"3233using namespace lldb;34using namespace lldb_private;3536#define GPR_OFFSET(idx) ((idx)*8)37#define GPR_OFFSET_NAME(reg) \38(LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))3940#define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))41#define FPU_OFFSET_NAME(reg) \42(LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))4344#define EXC_OFFSET_NAME(reg) \45(LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) + \46sizeof(RegisterContextDarwin_arm64::GPR) + \47sizeof(RegisterContextDarwin_arm64::FPU))48#define DBG_OFFSET_NAME(reg) \49(LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) + \50sizeof(RegisterContextDarwin_arm64::GPR) + \51sizeof(RegisterContextDarwin_arm64::FPU) + \52sizeof(RegisterContextDarwin_arm64::EXC))5354#define DEFINE_DBG(reg, i) \55#reg, NULL, \56sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]), \57DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \58{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \59LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \60LLDB_INVALID_REGNUM }, \61NULL, NULL, NULL62#define REG_CONTEXT_SIZE \63(sizeof(RegisterContextDarwin_arm64::GPR) + \64sizeof(RegisterContextDarwin_arm64::FPU) + \65sizeof(RegisterContextDarwin_arm64::EXC))6667// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.68#define DECLARE_REGISTER_INFOS_ARM64_STRUCT69#include "RegisterInfos_arm64.h"70#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT7172// General purpose registers73static uint32_t g_gpr_regnums[] = {74gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,75gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,76gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,77gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,78gpr_x28, gpr_fp, gpr_lr, gpr_sp, gpr_pc, gpr_cpsr};7980// Floating point registers81static uint32_t g_fpu_regnums[] = {82fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6,83fpu_v7, fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13,84fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20,85fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25, fpu_v26, fpu_v27,86fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};8788// Exception registers8990static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};9192static size_t k_num_register_infos = std::size(g_register_infos_arm64_le);9394RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(95Thread &thread, uint32_t concrete_frame_idx)96: RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc(), dbg() {97uint32_t i;98for (i = 0; i < kNumErrors; i++) {99gpr_errs[i] = -1;100fpu_errs[i] = -1;101exc_errs[i] = -1;102}103}104105RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default;106107void RegisterContextDarwin_arm64::InvalidateAllRegisters() {108InvalidateAllRegisterStates();109}110111size_t RegisterContextDarwin_arm64::GetRegisterCount() {112assert(k_num_register_infos == k_num_registers);113return k_num_registers;114}115116const RegisterInfo *117RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {118assert(k_num_register_infos == k_num_registers);119if (reg < k_num_registers)120return &g_register_infos_arm64_le[reg];121return nullptr;122}123124size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {125return k_num_register_infos;126}127128const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {129return g_register_infos_arm64_le;130}131132// Number of registers in each register set133const size_t k_num_gpr_registers = std::size(g_gpr_regnums);134const size_t k_num_fpu_registers = std::size(g_fpu_regnums);135const size_t k_num_exc_registers = std::size(g_exc_regnums);136137// Register set definitions. The first definitions at register set index of138// zero is for all registers, followed by other registers sets. The register139// information for the all register set need not be filled in.140static const RegisterSet g_reg_sets[] = {141{142"General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,143},144{"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},145{"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};146147const size_t k_num_regsets = std::size(g_reg_sets);148149size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {150return k_num_regsets;151}152153const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {154if (reg_set < k_num_regsets)155return &g_reg_sets[reg_set];156return nullptr;157}158159// Register information definitions for arm64160int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {161if (reg < fpu_v0)162return GPRRegSet;163else if (reg < exc_far)164return FPURegSet;165else if (reg < k_num_registers)166return EXCRegSet;167return -1;168}169170int RegisterContextDarwin_arm64::ReadGPR(bool force) {171int set = GPRRegSet;172if (force || !RegisterSetIsCached(set)) {173SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));174}175return GetError(GPRRegSet, Read);176}177178int RegisterContextDarwin_arm64::ReadFPU(bool force) {179int set = FPURegSet;180if (force || !RegisterSetIsCached(set)) {181SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));182}183return GetError(FPURegSet, Read);184}185186int RegisterContextDarwin_arm64::ReadEXC(bool force) {187int set = EXCRegSet;188if (force || !RegisterSetIsCached(set)) {189SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));190}191return GetError(EXCRegSet, Read);192}193194int RegisterContextDarwin_arm64::ReadDBG(bool force) {195int set = DBGRegSet;196if (force || !RegisterSetIsCached(set)) {197SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));198}199return GetError(DBGRegSet, Read);200}201202int RegisterContextDarwin_arm64::WriteGPR() {203int set = GPRRegSet;204if (!RegisterSetIsCached(set)) {205SetError(set, Write, -1);206return KERN_INVALID_ARGUMENT;207}208SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));209SetError(set, Read, -1);210return GetError(GPRRegSet, Write);211}212213int RegisterContextDarwin_arm64::WriteFPU() {214int set = FPURegSet;215if (!RegisterSetIsCached(set)) {216SetError(set, Write, -1);217return KERN_INVALID_ARGUMENT;218}219SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));220SetError(set, Read, -1);221return GetError(FPURegSet, Write);222}223224int RegisterContextDarwin_arm64::WriteEXC() {225int set = EXCRegSet;226if (!RegisterSetIsCached(set)) {227SetError(set, Write, -1);228return KERN_INVALID_ARGUMENT;229}230SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));231SetError(set, Read, -1);232return GetError(EXCRegSet, Write);233}234235int RegisterContextDarwin_arm64::WriteDBG() {236int set = DBGRegSet;237if (!RegisterSetIsCached(set)) {238SetError(set, Write, -1);239return KERN_INVALID_ARGUMENT;240}241SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));242SetError(set, Read, -1);243return GetError(DBGRegSet, Write);244}245246int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {247switch (set) {248case GPRRegSet:249return ReadGPR(force);250case FPURegSet:251return ReadFPU(force);252case EXCRegSet:253return ReadEXC(force);254case DBGRegSet:255return ReadDBG(force);256default:257break;258}259return KERN_INVALID_ARGUMENT;260}261262int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {263// Make sure we have a valid context to set.264if (RegisterSetIsCached(set)) {265switch (set) {266case GPRRegSet:267return WriteGPR();268case FPURegSet:269return WriteFPU();270case EXCRegSet:271return WriteEXC();272case DBGRegSet:273return WriteDBG();274default:275break;276}277}278return KERN_INVALID_ARGUMENT;279}280281void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {282if (log) {283for (uint32_t i = 0; i < 16; i++)284LLDB_LOGF(log,285"BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64286" } WVR%-2u/WCR%-2u "287"= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",288i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);289}290}291292bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,293RegisterValue &value) {294const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];295int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);296297if (set == -1)298return false;299300if (ReadRegisterSet(set, false) != KERN_SUCCESS)301return false;302303switch (reg) {304case gpr_x0:305case gpr_x1:306case gpr_x2:307case gpr_x3:308case gpr_x4:309case gpr_x5:310case gpr_x6:311case gpr_x7:312case gpr_x8:313case gpr_x9:314case gpr_x10:315case gpr_x11:316case gpr_x12:317case gpr_x13:318case gpr_x14:319case gpr_x15:320case gpr_x16:321case gpr_x17:322case gpr_x18:323case gpr_x19:324case gpr_x20:325case gpr_x21:326case gpr_x22:327case gpr_x23:328case gpr_x24:329case gpr_x25:330case gpr_x26:331case gpr_x27:332case gpr_x28:333value.SetUInt64(gpr.x[reg - gpr_x0]);334break;335case gpr_fp:336value.SetUInt64(gpr.fp);337break;338case gpr_sp:339value.SetUInt64(gpr.sp);340break;341case gpr_lr:342value.SetUInt64(gpr.lr);343break;344case gpr_pc:345value.SetUInt64(gpr.pc);346break;347case gpr_cpsr:348value.SetUInt64(gpr.cpsr);349break;350351case gpr_w0:352case gpr_w1:353case gpr_w2:354case gpr_w3:355case gpr_w4:356case gpr_w5:357case gpr_w6:358case gpr_w7:359case gpr_w8:360case gpr_w9:361case gpr_w10:362case gpr_w11:363case gpr_w12:364case gpr_w13:365case gpr_w14:366case gpr_w15:367case gpr_w16:368case gpr_w17:369case gpr_w18:370case gpr_w19:371case gpr_w20:372case gpr_w21:373case gpr_w22:374case gpr_w23:375case gpr_w24:376case gpr_w25:377case gpr_w26:378case gpr_w27:379case gpr_w28: {380ProcessSP process_sp(m_thread.GetProcess());381if (process_sp.get()) {382DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),383process_sp->GetAddressByteSize());384offset_t offset = 0;385uint64_t retval = regdata.GetMaxU64(&offset, 8);386uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);387value.SetUInt32(retval_lower32);388}389} break;390391case fpu_v0:392case fpu_v1:393case fpu_v2:394case fpu_v3:395case fpu_v4:396case fpu_v5:397case fpu_v6:398case fpu_v7:399case fpu_v8:400case fpu_v9:401case fpu_v10:402case fpu_v11:403case fpu_v12:404case fpu_v13:405case fpu_v14:406case fpu_v15:407case fpu_v16:408case fpu_v17:409case fpu_v18:410case fpu_v19:411case fpu_v20:412case fpu_v21:413case fpu_v22:414case fpu_v23:415case fpu_v24:416case fpu_v25:417case fpu_v26:418case fpu_v27:419case fpu_v28:420case fpu_v29:421case fpu_v30:422case fpu_v31:423value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size,424endian::InlHostByteOrder());425break;426427case fpu_s0:428case fpu_s1:429case fpu_s2:430case fpu_s3:431case fpu_s4:432case fpu_s5:433case fpu_s6:434case fpu_s7:435case fpu_s8:436case fpu_s9:437case fpu_s10:438case fpu_s11:439case fpu_s12:440case fpu_s13:441case fpu_s14:442case fpu_s15:443case fpu_s16:444case fpu_s17:445case fpu_s18:446case fpu_s19:447case fpu_s20:448case fpu_s21:449case fpu_s22:450case fpu_s23:451case fpu_s24:452case fpu_s25:453case fpu_s26:454case fpu_s27:455case fpu_s28:456case fpu_s29:457case fpu_s30:458case fpu_s31: {459ProcessSP process_sp(m_thread.GetProcess());460if (process_sp.get()) {461DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),462process_sp->GetAddressByteSize());463offset_t offset = 0;464value.SetFloat(regdata.GetFloat(&offset));465}466} break;467468case fpu_d0:469case fpu_d1:470case fpu_d2:471case fpu_d3:472case fpu_d4:473case fpu_d5:474case fpu_d6:475case fpu_d7:476case fpu_d8:477case fpu_d9:478case fpu_d10:479case fpu_d11:480case fpu_d12:481case fpu_d13:482case fpu_d14:483case fpu_d15:484case fpu_d16:485case fpu_d17:486case fpu_d18:487case fpu_d19:488case fpu_d20:489case fpu_d21:490case fpu_d22:491case fpu_d23:492case fpu_d24:493case fpu_d25:494case fpu_d26:495case fpu_d27:496case fpu_d28:497case fpu_d29:498case fpu_d30:499case fpu_d31: {500ProcessSP process_sp(m_thread.GetProcess());501if (process_sp.get()) {502DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(),503process_sp->GetAddressByteSize());504offset_t offset = 0;505value.SetDouble(regdata.GetDouble(&offset));506}507} break;508509case fpu_fpsr:510value.SetUInt32(fpu.fpsr);511break;512513case fpu_fpcr:514value.SetUInt32(fpu.fpcr);515break;516517case exc_exception:518value.SetUInt32(exc.exception);519break;520case exc_esr:521value.SetUInt32(exc.esr);522break;523case exc_far:524value.SetUInt64(exc.far);525break;526527default:528value.SetValueToInvalid();529return false;530}531return true;532}533534bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,535const RegisterValue &value) {536const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];537int set = GetSetForNativeRegNum(reg);538539if (set == -1)540return false;541542if (ReadRegisterSet(set, false) != KERN_SUCCESS)543return false;544545switch (reg) {546case gpr_x0:547case gpr_x1:548case gpr_x2:549case gpr_x3:550case gpr_x4:551case gpr_x5:552case gpr_x6:553case gpr_x7:554case gpr_x8:555case gpr_x9:556case gpr_x10:557case gpr_x11:558case gpr_x12:559case gpr_x13:560case gpr_x14:561case gpr_x15:562case gpr_x16:563case gpr_x17:564case gpr_x18:565case gpr_x19:566case gpr_x20:567case gpr_x21:568case gpr_x22:569case gpr_x23:570case gpr_x24:571case gpr_x25:572case gpr_x26:573case gpr_x27:574case gpr_x28:575case gpr_fp:576case gpr_sp:577case gpr_lr:578case gpr_pc:579case gpr_cpsr:580gpr.x[reg - gpr_x0] = value.GetAsUInt64();581break;582583case fpu_v0:584case fpu_v1:585case fpu_v2:586case fpu_v3:587case fpu_v4:588case fpu_v5:589case fpu_v6:590case fpu_v7:591case fpu_v8:592case fpu_v9:593case fpu_v10:594case fpu_v11:595case fpu_v12:596case fpu_v13:597case fpu_v14:598case fpu_v15:599case fpu_v16:600case fpu_v17:601case fpu_v18:602case fpu_v19:603case fpu_v20:604case fpu_v21:605case fpu_v22:606case fpu_v23:607case fpu_v24:608case fpu_v25:609case fpu_v26:610case fpu_v27:611case fpu_v28:612case fpu_v29:613case fpu_v30:614case fpu_v31:615::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(),616value.GetByteSize());617break;618619case fpu_fpsr:620fpu.fpsr = value.GetAsUInt32();621break;622623case fpu_fpcr:624fpu.fpcr = value.GetAsUInt32();625break;626627case exc_exception:628exc.exception = value.GetAsUInt32();629break;630case exc_esr:631exc.esr = value.GetAsUInt32();632break;633case exc_far:634exc.far = value.GetAsUInt64();635break;636637default:638return false;639}640return WriteRegisterSet(set) == KERN_SUCCESS;641}642643bool RegisterContextDarwin_arm64::ReadAllRegisterValues(644lldb::WritableDataBufferSP &data_sp) {645data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);646if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&647ReadEXC(false) == KERN_SUCCESS) {648uint8_t *dst = data_sp->GetBytes();649::memcpy(dst, &gpr, sizeof(gpr));650dst += sizeof(gpr);651652::memcpy(dst, &fpu, sizeof(fpu));653dst += sizeof(gpr);654655::memcpy(dst, &exc, sizeof(exc));656return true;657}658return false;659}660661bool RegisterContextDarwin_arm64::WriteAllRegisterValues(662const lldb::DataBufferSP &data_sp) {663if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {664const uint8_t *src = data_sp->GetBytes();665::memcpy(&gpr, src, sizeof(gpr));666src += sizeof(gpr);667668::memcpy(&fpu, src, sizeof(fpu));669src += sizeof(gpr);670671::memcpy(&exc, src, sizeof(exc));672uint32_t success_count = 0;673if (WriteGPR() == KERN_SUCCESS)674++success_count;675if (WriteFPU() == KERN_SUCCESS)676++success_count;677if (WriteEXC() == KERN_SUCCESS)678++success_count;679return success_count == 3;680}681return false;682}683684uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(685RegisterKind kind, uint32_t reg) {686if (kind == eRegisterKindGeneric) {687switch (reg) {688case LLDB_REGNUM_GENERIC_PC:689return gpr_pc;690case LLDB_REGNUM_GENERIC_SP:691return gpr_sp;692case LLDB_REGNUM_GENERIC_FP:693return gpr_fp;694case LLDB_REGNUM_GENERIC_RA:695return gpr_lr;696case LLDB_REGNUM_GENERIC_FLAGS:697return gpr_cpsr;698default:699break;700}701} else if (kind == eRegisterKindDWARF) {702switch (reg) {703case arm64_dwarf::x0:704return gpr_x0;705case arm64_dwarf::x1:706return gpr_x1;707case arm64_dwarf::x2:708return gpr_x2;709case arm64_dwarf::x3:710return gpr_x3;711case arm64_dwarf::x4:712return gpr_x4;713case arm64_dwarf::x5:714return gpr_x5;715case arm64_dwarf::x6:716return gpr_x6;717case arm64_dwarf::x7:718return gpr_x7;719case arm64_dwarf::x8:720return gpr_x8;721case arm64_dwarf::x9:722return gpr_x9;723case arm64_dwarf::x10:724return gpr_x10;725case arm64_dwarf::x11:726return gpr_x11;727case arm64_dwarf::x12:728return gpr_x12;729case arm64_dwarf::x13:730return gpr_x13;731case arm64_dwarf::x14:732return gpr_x14;733case arm64_dwarf::x15:734return gpr_x15;735case arm64_dwarf::x16:736return gpr_x16;737case arm64_dwarf::x17:738return gpr_x17;739case arm64_dwarf::x18:740return gpr_x18;741case arm64_dwarf::x19:742return gpr_x19;743case arm64_dwarf::x20:744return gpr_x20;745case arm64_dwarf::x21:746return gpr_x21;747case arm64_dwarf::x22:748return gpr_x22;749case arm64_dwarf::x23:750return gpr_x23;751case arm64_dwarf::x24:752return gpr_x24;753case arm64_dwarf::x25:754return gpr_x25;755case arm64_dwarf::x26:756return gpr_x26;757case arm64_dwarf::x27:758return gpr_x27;759case arm64_dwarf::x28:760return gpr_x28;761762case arm64_dwarf::fp:763return gpr_fp;764case arm64_dwarf::sp:765return gpr_sp;766case arm64_dwarf::lr:767return gpr_lr;768case arm64_dwarf::pc:769return gpr_pc;770case arm64_dwarf::cpsr:771return gpr_cpsr;772773case arm64_dwarf::v0:774return fpu_v0;775case arm64_dwarf::v1:776return fpu_v1;777case arm64_dwarf::v2:778return fpu_v2;779case arm64_dwarf::v3:780return fpu_v3;781case arm64_dwarf::v4:782return fpu_v4;783case arm64_dwarf::v5:784return fpu_v5;785case arm64_dwarf::v6:786return fpu_v6;787case arm64_dwarf::v7:788return fpu_v7;789case arm64_dwarf::v8:790return fpu_v8;791case arm64_dwarf::v9:792return fpu_v9;793case arm64_dwarf::v10:794return fpu_v10;795case arm64_dwarf::v11:796return fpu_v11;797case arm64_dwarf::v12:798return fpu_v12;799case arm64_dwarf::v13:800return fpu_v13;801case arm64_dwarf::v14:802return fpu_v14;803case arm64_dwarf::v15:804return fpu_v15;805case arm64_dwarf::v16:806return fpu_v16;807case arm64_dwarf::v17:808return fpu_v17;809case arm64_dwarf::v18:810return fpu_v18;811case arm64_dwarf::v19:812return fpu_v19;813case arm64_dwarf::v20:814return fpu_v20;815case arm64_dwarf::v21:816return fpu_v21;817case arm64_dwarf::v22:818return fpu_v22;819case arm64_dwarf::v23:820return fpu_v23;821case arm64_dwarf::v24:822return fpu_v24;823case arm64_dwarf::v25:824return fpu_v25;825case arm64_dwarf::v26:826return fpu_v26;827case arm64_dwarf::v27:828return fpu_v27;829case arm64_dwarf::v28:830return fpu_v28;831case arm64_dwarf::v29:832return fpu_v29;833case arm64_dwarf::v30:834return fpu_v30;835case arm64_dwarf::v31:836return fpu_v31;837838default:839break;840}841} else if (kind == eRegisterKindEHFrame) {842switch (reg) {843case arm64_ehframe::x0:844return gpr_x0;845case arm64_ehframe::x1:846return gpr_x1;847case arm64_ehframe::x2:848return gpr_x2;849case arm64_ehframe::x3:850return gpr_x3;851case arm64_ehframe::x4:852return gpr_x4;853case arm64_ehframe::x5:854return gpr_x5;855case arm64_ehframe::x6:856return gpr_x6;857case arm64_ehframe::x7:858return gpr_x7;859case arm64_ehframe::x8:860return gpr_x8;861case arm64_ehframe::x9:862return gpr_x9;863case arm64_ehframe::x10:864return gpr_x10;865case arm64_ehframe::x11:866return gpr_x11;867case arm64_ehframe::x12:868return gpr_x12;869case arm64_ehframe::x13:870return gpr_x13;871case arm64_ehframe::x14:872return gpr_x14;873case arm64_ehframe::x15:874return gpr_x15;875case arm64_ehframe::x16:876return gpr_x16;877case arm64_ehframe::x17:878return gpr_x17;879case arm64_ehframe::x18:880return gpr_x18;881case arm64_ehframe::x19:882return gpr_x19;883case arm64_ehframe::x20:884return gpr_x20;885case arm64_ehframe::x21:886return gpr_x21;887case arm64_ehframe::x22:888return gpr_x22;889case arm64_ehframe::x23:890return gpr_x23;891case arm64_ehframe::x24:892return gpr_x24;893case arm64_ehframe::x25:894return gpr_x25;895case arm64_ehframe::x26:896return gpr_x26;897case arm64_ehframe::x27:898return gpr_x27;899case arm64_ehframe::x28:900return gpr_x28;901case arm64_ehframe::fp:902return gpr_fp;903case arm64_ehframe::sp:904return gpr_sp;905case arm64_ehframe::lr:906return gpr_lr;907case arm64_ehframe::pc:908return gpr_pc;909case arm64_ehframe::cpsr:910return gpr_cpsr;911}912} else if (kind == eRegisterKindLLDB) {913return reg;914}915return LLDB_INVALID_REGNUM;916}917918uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {919#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))920// autodetect how many watchpoints are supported dynamically...921static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;922if (g_num_supported_hw_watchpoints == UINT32_MAX) {923size_t len;924uint32_t n = 0;925len = sizeof(n);926if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {927g_num_supported_hw_watchpoints = n;928}929}930return g_num_supported_hw_watchpoints;931#else932// TODO: figure out remote case here!933return 2;934#endif935}936937uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,938size_t size,939bool read,940bool write) {941// if (log) log->Printf942// ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,943// size = %u, read = %u, write = %u)", addr, size, read, write);944945const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();946947// Can't watch zero bytes948if (size == 0)949return LLDB_INVALID_INDEX32;950951// We must watch for either read or write952if (!read && !write)953return LLDB_INVALID_INDEX32;954955// Can't watch more than 4 bytes per WVR/WCR pair956if (size > 4)957return LLDB_INVALID_INDEX32;958959// We can only watch up to four bytes that follow a 4 byte aligned address960// per watchpoint register pair. Since we have at most so we can only watch961// until the next 4 byte boundary and we need to make sure we can properly962// encode this.963uint32_t addr_word_offset = addr % 4;964// if (log) log->Printf965// ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -966// addr_word_offset = 0x%8.8x", addr_word_offset);967968uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;969// if (log) log->Printf970// ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =971// 0x%8.8x", byte_mask);972if (byte_mask > 0xfu)973return LLDB_INVALID_INDEX32;974975// Read the debug state976int kret = ReadDBG(false);977978if (kret == KERN_SUCCESS) {979// Check to make sure we have the needed hardware support980uint32_t i = 0;981982for (i = 0; i < num_hw_watchpoints; ++i) {983if ((dbg.wcr[i] & WCR_ENABLE) == 0)984break; // We found an available hw breakpoint slot (in i)985}986987// See if we found an available hw breakpoint slot above988if (i < num_hw_watchpoints) {989// Make the byte_mask into a valid Byte Address Select mask990uint32_t byte_address_select = byte_mask << 5;991// Make sure bits 1:0 are clear in our address992dbg.wvr[i] = addr & ~((lldb::addr_t)3);993dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA994// that we will watch995S_USER | // Stop only in user mode996(read ? WCR_LOAD : 0) | // Stop on read access?997(write ? WCR_STORE : 0) | // Stop on write access?998WCR_ENABLE; // Enable this watchpoint;9991000kret = WriteDBG();1001// if (log) log->Printf1002// ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()1003// WriteDBG() => 0x%8.8x.", kret);10041005if (kret == KERN_SUCCESS)1006return i;1007} else {1008// if (log) log->Printf1009// ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():1010// All hardware resources (%u) are in use.",1011// num_hw_watchpoints);1012}1013}1014return LLDB_INVALID_INDEX32;1015}10161017bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {1018int kret = ReadDBG(false);10191020const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();1021if (kret == KERN_SUCCESS) {1022if (hw_index < num_hw_points) {1023dbg.wcr[hw_index] = 0;1024// if (log) log->Printf1025// ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )1026// - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",1027// hw_index,1028// hw_index,1029// dbg.wvr[hw_index],1030// hw_index,1031// dbg.wcr[hw_index]);10321033kret = WriteDBG();10341035if (kret == KERN_SUCCESS)1036return true;1037}1038}1039return false;1040}104110421043