brintos

brintos / llvm-project-archived public Read only

0
0
Text · 112.0 KiB · e30e02a Raw
3221 lines · cpp
1//===-- DNBArchImplARM64.cpp ------------------------------------*- C++ -*-===//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//  Created by Greg Clayton on 6/25/07.10//11//===----------------------------------------------------------------------===//12 13#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)14 15#include "MacOSX/arm64/DNBArchImplARM64.h"16 17#if defined(ARM_THREAD_STATE64_COUNT)18 19#include "DNB.h"20#include "DNBBreakpoint.h"21#include "DNBLog.h"22#include "DNBRegisterInfo.h"23#include "MacOSX/MachProcess.h"24#include "MacOSX/MachThread.h"25 26#include <cinttypes>27#include <sys/sysctl.h>28 29#undef DEBUGSERVER_IS_ARM64E30#if __has_feature(ptrauth_calls)31#include <ptrauth.h>32#if defined(__LP64__)33#define DEBUGSERVER_IS_ARM64E 134#endif35#endif36 37// Break only in privileged or user mode38// (PAC bits in the DBGWVRn_EL1 watchpoint control register)39#define S_USER ((uint32_t)(2u << 1))40 41#define BCR_ENABLE ((uint32_t)(1u))42#define WCR_ENABLE ((uint32_t)(1u))43 44// Watchpoint load/store45// (LSC bits in the DBGWVRn_EL1 watchpoint control register)46#define WCR_LOAD ((uint32_t)(1u << 3))47#define WCR_STORE ((uint32_t)(1u << 4))48 49// Single instruction step50// (SS bit in the MDSCR_EL1 register)51#define SS_ENABLE ((uint32_t)(1u))52 53static const uint8_t g_arm64_breakpoint_opcode[] = {54    0x00, 0x00, 0x20, 0xD4}; // "brk #0", 0xd4200000 in BE byte order55 56// If we need to set one logical watchpoint by using57// two hardware watchpoint registers, the watchpoint58// will be split into a "high" and "low" watchpoint.59// Record both of them in the LoHi array.60 61// It's safe to initialize to all 0's since62// hi > lo and therefore LoHi[i] cannot be 0.63static uint32_t LoHi[16] = {0};64 65void DNBArchMachARM64::Initialize() {66  DNBArchPluginInfo arch_plugin_info = {67      CPU_TYPE_ARM64, DNBArchMachARM64::Create,68      DNBArchMachARM64::GetRegisterSetInfo,69      DNBArchMachARM64::SoftwareBreakpointOpcode};70 71  // Register this arch plug-in with the main protocol class72  DNBArchProtocol::RegisterArchPlugin(arch_plugin_info);73 74  DNBArchPluginInfo arch_plugin_info_32 = {75      CPU_TYPE_ARM64_32, DNBArchMachARM64::Create,76      DNBArchMachARM64::GetRegisterSetInfo,77      DNBArchMachARM64::SoftwareBreakpointOpcode};78 79  // Register this arch plug-in with the main protocol class80  DNBArchProtocol::RegisterArchPlugin(arch_plugin_info_32);81}82 83DNBArchProtocol *DNBArchMachARM64::Create(MachThread *thread) {84  DNBArchMachARM64 *obj = new DNBArchMachARM64(thread);85 86  return obj;87}88 89const uint8_t *90DNBArchMachARM64::SoftwareBreakpointOpcode(nub_size_t byte_size) {91  return g_arm64_breakpoint_opcode;92}93 94uint32_t DNBArchMachARM64::GetCPUType() { return CPU_TYPE_ARM64; }95 96static std::once_flag g_cpu_has_sme_once;97bool DNBArchMachARM64::CPUHasSME() {98  static bool g_has_sme = false;99  std::call_once(g_cpu_has_sme_once, []() {100    int ret = 0;101    size_t size = sizeof(ret);102    if (sysctlbyname("hw.optional.arm.FEAT_SME", &ret, &size, NULL, 0) != -1)103      g_has_sme = ret == 1;104  });105  return g_has_sme;106}107 108static std::once_flag g_cpu_has_sme2_once;109bool DNBArchMachARM64::CPUHasSME2() {110  static bool g_has_sme2 = false;111  std::call_once(g_cpu_has_sme2_once, []() {112    int ret = 0;113    size_t size = sizeof(ret);114    if (sysctlbyname("hw.optional.arm.FEAT_SME2", &ret, &size, NULL, 0) != -1)115      g_has_sme2 = ret == 1;116  });117  return g_has_sme2;118}119 120static std::once_flag g_sme_max_svl_once;121unsigned int DNBArchMachARM64::GetSMEMaxSVL() {122  static unsigned int g_sme_max_svl = 0;123  std::call_once(g_sme_max_svl_once, []() {124    if (CPUHasSME()) {125      unsigned int ret = 0;126      size_t size = sizeof(ret);127      if (sysctlbyname("hw.optional.arm.sme_max_svl_b", &ret, &size, NULL, 0) !=128          -1)129        g_sme_max_svl = ret;130    }131  });132  return g_sme_max_svl;133}134 135static uint64_t clear_pac_bits(uint64_t value) {136  uint32_t addressing_bits = 0;137  if (!DNBGetAddressingBits(addressing_bits))138    return value;139 140    // On arm64_32, no ptrauth bits to clear141#if !defined(__LP64__)142  return value;143#endif144 145  uint64_t mask = ((1ULL << addressing_bits) - 1);146 147  // Normally PAC bit clearing needs to check b55 and either set the148  // non-addressing bits, or clear them.  But the register values we149  // get from thread_get_state on an arm64e process don't follow this150  // convention?, at least when there's been a PAC auth failure in151  // the inferior.152  // Userland processes are always in low memory, so this153  // hardcoding b55 == 0 PAC stripping behavior here.154 155  return value & mask; // high bits cleared to 0156}157 158uint64_t DNBArchMachARM64::GetPC(uint64_t failValue) {159  // Get program counter160  if (GetGPRState(false) == KERN_SUCCESS)161#if defined(DEBUGSERVER_IS_ARM64E)162    return clear_pac_bits(163        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));164#else165    return m_state.context.gpr.__pc;166#endif167  return failValue;168}169 170kern_return_t DNBArchMachARM64::SetPC(uint64_t value) {171  // Get program counter172  kern_return_t err = GetGPRState(false);173  if (err == KERN_SUCCESS) {174#if defined(__LP64__)175#if __has_feature(ptrauth_calls)176    // The incoming value could be garbage.  Strip it to avoid177    // trapping when it gets resigned in the thread state.178    value = (uint64_t) ptrauth_strip((void*) value, ptrauth_key_function_pointer);179    value = (uint64_t) ptrauth_sign_unauthenticated((void*) value, ptrauth_key_function_pointer, 0);180#endif181    arm_thread_state64_set_pc_fptr (m_state.context.gpr, (void*) value);182#else183    m_state.context.gpr.__pc = value;184#endif185    err = SetGPRState();186  }187  return err == KERN_SUCCESS;188}189 190uint64_t DNBArchMachARM64::GetSP(uint64_t failValue) {191  // Get stack pointer192  if (GetGPRState(false) == KERN_SUCCESS)193#if defined(DEBUGSERVER_IS_ARM64E)194    return clear_pac_bits(195        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp));196#else197    return m_state.context.gpr.__sp;198#endif199  return failValue;200}201 202static void log_signed_registers(arm_thread_state64_t *gpr, const char *desc) {203  if (DNBLogEnabledForAny(LOG_THREAD)) {204    const char *log_str = "%s signed regs "205                          "\n   fp=%16.16llx"206                          "\n   lr=%16.16llx"207                          "\n   sp=%16.16llx"208                          "\n   pc=%16.16llx";209#if defined(DEBUGSERVER_IS_ARM64E)210    DNBLogThreaded(log_str, desc, reinterpret_cast<uint64_t>(gpr->__opaque_fp),211                   reinterpret_cast<uint64_t>(gpr->__opaque_lr),212                   reinterpret_cast<uint64_t>(gpr->__opaque_sp),213                   reinterpret_cast<uint64_t>(gpr->__opaque_pc));214#else215    DNBLogThreaded(log_str, desc, gpr->__fp, gpr->__lr, gpr->__sp, gpr->__pc);216#endif217  }218}219 220kern_return_t DNBArchMachARM64::GetGPRState(bool force) {221  int set = e_regSetGPR;222  // Check if we have valid cached registers223  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)224    return KERN_SUCCESS;225 226  // Read the registers from our thread227  mach_msg_type_number_t count = e_regSetGPRCount;228  kern_return_t kret =229      ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64,230                         (thread_state_t)&m_state.context.gpr, &count);231  log_signed_registers(&m_state.context.gpr, "Values from thread_get_state");232 233#if defined(THREAD_CONVERT_THREAD_STATE_TO_SELF) && defined(__LP64__)234  if (kret == KERN_SUCCESS) {235    mach_msg_type_number_t newcount = ARM_THREAD_STATE64_COUNT;236    arm_thread_state64_t new_gpr;237    kern_return_t convert_kret = thread_convert_thread_state(238        m_thread->MachPortNumber(), THREAD_CONVERT_THREAD_STATE_TO_SELF,239        ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, count,240        (thread_state_t)&new_gpr, &newcount);241    DNBLogThreadedIf(242        LOG_THREAD,243        "converted register values "244        "to debugserver's keys, return value %d, old count %d new count %d",245        convert_kret, count, newcount);246    if (convert_kret == KERN_SUCCESS)247      memcpy(&m_state.context.gpr, &new_gpr, count * 4);248    log_signed_registers(&m_state.context.gpr,249                         "Values after thread_convert_thread_state");250  }251#endif // THREAD_CONVERT_THREAD_STATE_TO_SELF252 253  if (DNBLogEnabledForAny(LOG_THREAD)) {254#if defined(DEBUGSERVER_IS_ARM64E)255    uint64_t log_fp = clear_pac_bits(256        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_fp));257    uint64_t log_lr = clear_pac_bits(258        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_lr));259    uint64_t log_sp = clear_pac_bits(260        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp));261    uint64_t log_pc = clear_pac_bits(262        reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));263#else264    uint64_t log_fp = m_state.context.gpr.__fp;265    uint64_t log_lr = m_state.context.gpr.__lr;266    uint64_t log_sp = m_state.context.gpr.__sp;267    uint64_t log_pc = m_state.context.gpr.__pc;268#endif269    uint64_t *x = &m_state.context.gpr.__x[0];270    DNBLogThreaded(271        "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs"272        "\n   x0=%16.16llx"273        "\n   x1=%16.16llx"274        "\n   x2=%16.16llx"275        "\n   x3=%16.16llx"276        "\n   x4=%16.16llx"277        "\n   x5=%16.16llx"278        "\n   x6=%16.16llx"279        "\n   x7=%16.16llx"280        "\n   x8=%16.16llx"281        "\n   x9=%16.16llx"282        "\n  x10=%16.16llx"283        "\n  x11=%16.16llx"284        "\n  x12=%16.16llx"285        "\n  x13=%16.16llx"286        "\n  x14=%16.16llx"287        "\n  x15=%16.16llx"288        "\n  x16=%16.16llx"289        "\n  x17=%16.16llx"290        "\n  x18=%16.16llx"291        "\n  x19=%16.16llx"292        "\n  x20=%16.16llx"293        "\n  x21=%16.16llx"294        "\n  x22=%16.16llx"295        "\n  x23=%16.16llx"296        "\n  x24=%16.16llx"297        "\n  x25=%16.16llx"298        "\n  x26=%16.16llx"299        "\n  x27=%16.16llx"300        "\n  x28=%16.16llx"301        "\n   fp=%16.16llx"302        "\n   lr=%16.16llx"303        "\n   sp=%16.16llx"304        "\n   pc=%16.16llx"305        "\n cpsr=%8.8x",306        m_thread->MachPortNumber(), e_regSetGPR, e_regSetGPRCount, kret, count,307        x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[0], x[11],308        x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21],309        x[22], x[23], x[24], x[25], x[26], x[27], x[28],310        log_fp, log_lr, log_sp, log_pc, m_state.context.gpr.__cpsr);311  }312  m_state.SetError(set, Read, kret);313  return kret;314}315 316kern_return_t DNBArchMachARM64::GetVFPState(bool force) {317  int set = e_regSetVFP;318  // Check if we have valid cached registers319  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)320    return KERN_SUCCESS;321 322  // Read the registers from our thread323  mach_msg_type_number_t count = e_regSetVFPCount;324  kern_return_t kret =325      ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE64,326                         (thread_state_t)&m_state.context.vfp, &count);327  if (DNBLogEnabledForAny(LOG_THREAD)) {328#if defined(__arm64__) || defined(__aarch64__)329    DNBLogThreaded(330        "thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs"331        "\n   q0  = 0x%16.16llx%16.16llx"332        "\n   q1  = 0x%16.16llx%16.16llx"333        "\n   q2  = 0x%16.16llx%16.16llx"334        "\n   q3  = 0x%16.16llx%16.16llx"335        "\n   q4  = 0x%16.16llx%16.16llx"336        "\n   q5  = 0x%16.16llx%16.16llx"337        "\n   q6  = 0x%16.16llx%16.16llx"338        "\n   q7  = 0x%16.16llx%16.16llx"339        "\n   q8  = 0x%16.16llx%16.16llx"340        "\n   q9  = 0x%16.16llx%16.16llx"341        "\n   q10 = 0x%16.16llx%16.16llx"342        "\n   q11 = 0x%16.16llx%16.16llx"343        "\n   q12 = 0x%16.16llx%16.16llx"344        "\n   q13 = 0x%16.16llx%16.16llx"345        "\n   q14 = 0x%16.16llx%16.16llx"346        "\n   q15 = 0x%16.16llx%16.16llx"347        "\n   q16 = 0x%16.16llx%16.16llx"348        "\n   q17 = 0x%16.16llx%16.16llx"349        "\n   q18 = 0x%16.16llx%16.16llx"350        "\n   q19 = 0x%16.16llx%16.16llx"351        "\n   q20 = 0x%16.16llx%16.16llx"352        "\n   q21 = 0x%16.16llx%16.16llx"353        "\n   q22 = 0x%16.16llx%16.16llx"354        "\n   q23 = 0x%16.16llx%16.16llx"355        "\n   q24 = 0x%16.16llx%16.16llx"356        "\n   q25 = 0x%16.16llx%16.16llx"357        "\n   q26 = 0x%16.16llx%16.16llx"358        "\n   q27 = 0x%16.16llx%16.16llx"359        "\n   q28 = 0x%16.16llx%16.16llx"360        "\n   q29 = 0x%16.16llx%16.16llx"361        "\n   q30 = 0x%16.16llx%16.16llx"362        "\n   q31 = 0x%16.16llx%16.16llx"363        "\n  fpsr = 0x%8.8x"364        "\n  fpcr = 0x%8.8x\n\n",365        m_thread->MachPortNumber(), e_regSetVFP, e_regSetVFPCount, kret, count,366        ((uint64_t *)&m_state.context.vfp.__v[0])[0],367        ((uint64_t *)&m_state.context.vfp.__v[0])[1],368        ((uint64_t *)&m_state.context.vfp.__v[1])[0],369        ((uint64_t *)&m_state.context.vfp.__v[1])[1],370        ((uint64_t *)&m_state.context.vfp.__v[2])[0],371        ((uint64_t *)&m_state.context.vfp.__v[2])[1],372        ((uint64_t *)&m_state.context.vfp.__v[3])[0],373        ((uint64_t *)&m_state.context.vfp.__v[3])[1],374        ((uint64_t *)&m_state.context.vfp.__v[4])[0],375        ((uint64_t *)&m_state.context.vfp.__v[4])[1],376        ((uint64_t *)&m_state.context.vfp.__v[5])[0],377        ((uint64_t *)&m_state.context.vfp.__v[5])[1],378        ((uint64_t *)&m_state.context.vfp.__v[6])[0],379        ((uint64_t *)&m_state.context.vfp.__v[6])[1],380        ((uint64_t *)&m_state.context.vfp.__v[7])[0],381        ((uint64_t *)&m_state.context.vfp.__v[7])[1],382        ((uint64_t *)&m_state.context.vfp.__v[8])[0],383        ((uint64_t *)&m_state.context.vfp.__v[8])[1],384        ((uint64_t *)&m_state.context.vfp.__v[9])[0],385        ((uint64_t *)&m_state.context.vfp.__v[9])[1],386        ((uint64_t *)&m_state.context.vfp.__v[10])[0],387        ((uint64_t *)&m_state.context.vfp.__v[10])[1],388        ((uint64_t *)&m_state.context.vfp.__v[11])[0],389        ((uint64_t *)&m_state.context.vfp.__v[11])[1],390        ((uint64_t *)&m_state.context.vfp.__v[12])[0],391        ((uint64_t *)&m_state.context.vfp.__v[12])[1],392        ((uint64_t *)&m_state.context.vfp.__v[13])[0],393        ((uint64_t *)&m_state.context.vfp.__v[13])[1],394        ((uint64_t *)&m_state.context.vfp.__v[14])[0],395        ((uint64_t *)&m_state.context.vfp.__v[14])[1],396        ((uint64_t *)&m_state.context.vfp.__v[15])[0],397        ((uint64_t *)&m_state.context.vfp.__v[15])[1],398        ((uint64_t *)&m_state.context.vfp.__v[16])[0],399        ((uint64_t *)&m_state.context.vfp.__v[16])[1],400        ((uint64_t *)&m_state.context.vfp.__v[17])[0],401        ((uint64_t *)&m_state.context.vfp.__v[17])[1],402        ((uint64_t *)&m_state.context.vfp.__v[18])[0],403        ((uint64_t *)&m_state.context.vfp.__v[18])[1],404        ((uint64_t *)&m_state.context.vfp.__v[19])[0],405        ((uint64_t *)&m_state.context.vfp.__v[19])[1],406        ((uint64_t *)&m_state.context.vfp.__v[20])[0],407        ((uint64_t *)&m_state.context.vfp.__v[20])[1],408        ((uint64_t *)&m_state.context.vfp.__v[21])[0],409        ((uint64_t *)&m_state.context.vfp.__v[21])[1],410        ((uint64_t *)&m_state.context.vfp.__v[22])[0],411        ((uint64_t *)&m_state.context.vfp.__v[22])[1],412        ((uint64_t *)&m_state.context.vfp.__v[23])[0],413        ((uint64_t *)&m_state.context.vfp.__v[23])[1],414        ((uint64_t *)&m_state.context.vfp.__v[24])[0],415        ((uint64_t *)&m_state.context.vfp.__v[24])[1],416        ((uint64_t *)&m_state.context.vfp.__v[25])[0],417        ((uint64_t *)&m_state.context.vfp.__v[25])[1],418        ((uint64_t *)&m_state.context.vfp.__v[26])[0],419        ((uint64_t *)&m_state.context.vfp.__v[26])[1],420        ((uint64_t *)&m_state.context.vfp.__v[27])[0],421        ((uint64_t *)&m_state.context.vfp.__v[27])[1],422        ((uint64_t *)&m_state.context.vfp.__v[28])[0],423        ((uint64_t *)&m_state.context.vfp.__v[28])[1],424        ((uint64_t *)&m_state.context.vfp.__v[29])[0],425        ((uint64_t *)&m_state.context.vfp.__v[29])[1],426        ((uint64_t *)&m_state.context.vfp.__v[30])[0],427        ((uint64_t *)&m_state.context.vfp.__v[30])[1],428        ((uint64_t *)&m_state.context.vfp.__v[31])[0],429        ((uint64_t *)&m_state.context.vfp.__v[31])[1],430        m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr);431#endif432  }433  m_state.SetError(set, Read, kret);434  return kret;435}436 437kern_return_t DNBArchMachARM64::GetEXCState(bool force) {438  int set = e_regSetEXC;439  // Check if we have valid cached registers440  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)441    return KERN_SUCCESS;442 443  // Read the registers from our thread444  mach_msg_type_number_t count = e_regSetEXCCount;445  kern_return_t kret =446      ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64,447                         (thread_state_t)&m_state.context.exc, &count);448  m_state.SetError(set, Read, kret);449  return kret;450}451 452#if 0453static void DumpDBGState(const arm_debug_state_t &dbg) {454  uint32_t i = 0;455  for (i = 0; i < 16; i++)456    DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } "457                               "WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",458                     i, i, dbg.__bvr[i], dbg.__bcr[i], i, i, dbg.__wvr[i],459                     dbg.__wcr[i]);460}461#endif462 463kern_return_t DNBArchMachARM64::GetDBGState(bool force) {464  int set = e_regSetDBG;465 466  // Check if we have valid cached registers467  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)468    return KERN_SUCCESS;469 470  // Read the registers from our thread471  mach_msg_type_number_t count = e_regSetDBGCount;472  kern_return_t kret =473      ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64,474                         (thread_state_t)&m_state.dbg, &count);475  m_state.SetError(set, Read, kret);476 477  return kret;478}479 480kern_return_t DNBArchMachARM64::GetSVEState(bool force) {481  int set = e_regSetSVE;482  // Check if we have valid cached registers483  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)484    return KERN_SUCCESS;485 486  if (!CPUHasSME())487    return KERN_INVALID_ARGUMENT;488 489  // If the processor is not in Streaming SVE Mode, these thread_get_states490  // will fail, and we may return uninitialized data in the register context.491  memset(&m_state.context.sve.z[0], 0,492         ARM_SVE_Z_STATE_COUNT * sizeof(uint32_t));493  memset(&m_state.context.sve.z[16], 0,494         ARM_SVE_Z_STATE_COUNT * sizeof(uint32_t));495  memset(&m_state.context.sve.p[0], 0,496         ARM_SVE_P_STATE_COUNT * sizeof(uint32_t));497 498  // Read the registers from our thread499  mach_msg_type_number_t count = ARM_SVE_Z_STATE_COUNT;500  kern_return_t kret =501      ::thread_get_state(m_thread->MachPortNumber(), ARM_SVE_Z_STATE1,502                         (thread_state_t)&m_state.context.sve.z[0], &count);503  m_state.SetError(set, Read, kret);504  DNBLogThreadedIf(LOG_THREAD, "Read SVE registers z0..z15 return value %d",505                   kret);506  if (kret != KERN_SUCCESS)507    return kret;508 509  count = ARM_SVE_Z_STATE_COUNT;510  kret = thread_get_state(m_thread->MachPortNumber(), ARM_SVE_Z_STATE2,511                          (thread_state_t)&m_state.context.sve.z[16], &count);512  m_state.SetError(set, Read, kret);513  DNBLogThreadedIf(LOG_THREAD, "Read SVE registers z16..z31 return value %d",514                   kret);515  if (kret != KERN_SUCCESS)516    return kret;517 518  count = ARM_SVE_P_STATE_COUNT;519  kret = thread_get_state(m_thread->MachPortNumber(), ARM_SVE_P_STATE,520                          (thread_state_t)&m_state.context.sve.p[0], &count);521  m_state.SetError(set, Read, kret);522  DNBLogThreadedIf(LOG_THREAD, "Read SVE registers p0..p15 return value %d",523                   kret);524 525  return kret;526}527 528kern_return_t DNBArchMachARM64::GetSMEState(bool force) {529  int set = e_regSetSME;530  // Check if we have valid cached registers531  if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)532    return KERN_SUCCESS;533 534  if (!CPUHasSME())535    return KERN_INVALID_ARGUMENT;536 537  // If the processor is not in Streaming SVE Mode, these thread_get_states538  // will fail, and we may return uninitialized data in the register context.539  memset(&m_state.context.sme.svcr, 0, ARM_SME_STATE_COUNT * sizeof(uint32_t));540  memset(m_state.context.sme.za.data(), 0, m_state.context.sme.za.size());541  if (CPUHasSME2())542    memset(&m_state.context.sme.zt0, 0,543           ARM_SME2_STATE_COUNT * sizeof(uint32_t));544 545  // Read the registers from our thread546  mach_msg_type_number_t count = ARM_SME_STATE_COUNT;547  kern_return_t kret =548      ::thread_get_state(m_thread->MachPortNumber(), ARM_SME_STATE,549                         (thread_state_t)&m_state.context.sme.svcr, &count);550  m_state.SetError(set, Read, kret);551  DNBLogThreadedIf(LOG_THREAD, "Read ARM_SME_STATE return value %d", kret);552  if (kret != KERN_SUCCESS)553    return kret;554 555  size_t za_size = m_state.context.sme.svl_b * m_state.context.sme.svl_b;556  const size_t max_chunk_size = 4096;557  int n_chunks;558  size_t chunk_size;559  if (za_size <= max_chunk_size) {560    n_chunks = 1;561    chunk_size = za_size;562  } else {563    n_chunks = za_size / max_chunk_size;564    chunk_size = max_chunk_size;565  }566  for (int i = 0; i < n_chunks; i++) {567    count = ARM_SME_ZA_STATE_COUNT;568    arm_sme_za_state_t za_state;569    kret = thread_get_state(m_thread->MachPortNumber(), ARM_SME_ZA_STATE1 + i,570                            (thread_state_t)&za_state, &count);571    m_state.SetError(set, Read, kret);572    DNBLogThreadedIf(LOG_THREAD, "Read ARM_SME_STATE return value %d", kret);573    if (kret != KERN_SUCCESS)574      return kret;575    memcpy(m_state.context.sme.za.data() + (i * chunk_size), &za_state,576           chunk_size);577  }578 579  if (CPUHasSME2()) {580    count = ARM_SME2_STATE_COUNT;581    kret = thread_get_state(m_thread->MachPortNumber(), ARM_SME2_STATE,582                            (thread_state_t)&m_state.context.sme.zt0, &count);583    m_state.SetError(set, Read, kret);584    DNBLogThreadedIf(LOG_THREAD, "Read ARM_SME2_STATE return value %d", kret);585    if (kret != KERN_SUCCESS)586      return kret;587  }588 589  return kret;590}591 592kern_return_t DNBArchMachARM64::SetGPRState() {593  arm_thread_state64_t *state_to_set = &m_state.context.gpr;594#if defined(THREAD_CONVERT_THREAD_STATE_FROM_SELF) && defined(__LP64__)595  mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;596  mach_msg_type_number_t new_count = ARM_THREAD_STATE64_COUNT;597  arm_thread_state64_t new_gpr;598  memcpy(&new_gpr, &m_state.context.gpr, count * 4);599  kern_return_t convert_kret = thread_convert_thread_state(600      m_thread->MachPortNumber(), THREAD_CONVERT_THREAD_STATE_FROM_SELF,601      ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, count,602      (thread_state_t)&new_gpr, &new_count);603  if (convert_kret == KERN_SUCCESS)604    state_to_set = &new_gpr;605  DNBLogThreadedIf(LOG_THREAD,606                   "converted register values "607                   "to inferior's keys, return value %d, count %d",608                   convert_kret, new_count);609#endif // THREAD_CONVERT_THREAD_STATE_TO_SELF610 611  int set = e_regSetGPR;612  kern_return_t kret =613      ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64,614                         (thread_state_t)state_to_set, e_regSetGPRCount);615  m_state.SetError(set, Write,616                   kret); // Set the current write error for this register set617  m_state.InvalidateRegisterSetState(set); // Invalidate the current register618                                           // state in case registers are read619                                           // back differently620  return kret;                             // Return the error code621}622 623kern_return_t DNBArchMachARM64::SetVFPState() {624  int set = e_regSetVFP;625  kern_return_t kret = ::thread_set_state(626      m_thread->MachPortNumber(), ARM_NEON_STATE64,627      (thread_state_t)&m_state.context.vfp, e_regSetVFPCount);628  m_state.SetError(set, Write,629                   kret); // Set the current write error for this register set630  m_state.InvalidateRegisterSetState(set); // Invalidate the current register631                                           // state in case registers are read632                                           // back differently633  return kret;                             // Return the error code634}635 636kern_return_t DNBArchMachARM64::SetSVEState() {637  if (!CPUHasSME())638    return KERN_INVALID_ARGUMENT;639 640  int set = e_regSetSVE;641  kern_return_t kret = thread_set_state(642      m_thread->MachPortNumber(), ARM_SVE_Z_STATE1,643      (thread_state_t)&m_state.context.sve.z[0], ARM_SVE_Z_STATE_COUNT);644  m_state.SetError(set, Write, kret);645  DNBLogThreadedIf(LOG_THREAD, "Write ARM_SVE_Z_STATE1 return value %d", kret);646  if (kret != KERN_SUCCESS)647    return kret;648 649  kret = thread_set_state(m_thread->MachPortNumber(), ARM_SVE_Z_STATE2,650                          (thread_state_t)&m_state.context.sve.z[16],651                          ARM_SVE_Z_STATE_COUNT);652  m_state.SetError(set, Write, kret);653  DNBLogThreadedIf(LOG_THREAD, "Write ARM_SVE_Z_STATE2 return value %d", kret);654  if (kret != KERN_SUCCESS)655    return kret;656 657  kret = thread_set_state(m_thread->MachPortNumber(), ARM_SVE_P_STATE,658                          (thread_state_t)&m_state.context.sve.p[0],659                          ARM_SVE_P_STATE_COUNT);660  m_state.SetError(set, Write, kret);661  DNBLogThreadedIf(LOG_THREAD, "Write ARM_SVE_P_STATE return value %d", kret);662  if (kret != KERN_SUCCESS)663    return kret;664 665  return kret;666}667 668kern_return_t DNBArchMachARM64::SetSMEState() {669  if (!CPUHasSME())670    return KERN_INVALID_ARGUMENT;671  kern_return_t kret;672 673  int set = e_regSetSME;674  size_t za_size = m_state.context.sme.svl_b * m_state.context.sme.svl_b;675  const size_t max_chunk_size = 4096;676  int n_chunks;677  size_t chunk_size;678  if (za_size <= max_chunk_size) {679    n_chunks = 1;680    chunk_size = za_size;681  } else {682    n_chunks = za_size / max_chunk_size;683    chunk_size = max_chunk_size;684  }685  for (int i = 0; i < n_chunks; i++) {686    arm_sme_za_state_t za_state;687    memcpy(&za_state, m_state.context.sme.za.data() + (i * chunk_size),688           chunk_size);689    kret = thread_set_state(m_thread->MachPortNumber(), ARM_SME_ZA_STATE1 + i,690                            (thread_state_t)&za_state, ARM_SME_ZA_STATE_COUNT);691    m_state.SetError(set, Write, kret);692    DNBLogThreadedIf(LOG_THREAD, "Write ARM_SME_STATE return value %d", kret);693    if (kret != KERN_SUCCESS)694      return kret;695  }696 697  if (CPUHasSME2()) {698    kret = thread_set_state(m_thread->MachPortNumber(), ARM_SME2_STATE,699                            (thread_state_t)&m_state.context.sme.zt0,700                            ARM_SME2_STATE);701    m_state.SetError(set, Write, kret);702    DNBLogThreadedIf(LOG_THREAD, "Write ARM_SME2_STATE return value %d", kret);703    if (kret != KERN_SUCCESS)704      return kret;705  }706 707  return kret;708}709 710kern_return_t DNBArchMachARM64::SetEXCState() {711  int set = e_regSetEXC;712  kern_return_t kret = ::thread_set_state(713      m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64,714      (thread_state_t)&m_state.context.exc, e_regSetEXCCount);715  m_state.SetError(set, Write,716                   kret); // Set the current write error for this register set717  m_state.InvalidateRegisterSetState(set); // Invalidate the current register718                                           // state in case registers are read719                                           // back differently720  return kret;                             // Return the error code721}722 723kern_return_t DNBArchMachARM64::SetDBGState(bool also_set_on_task) {724  int set = e_regSetDBG;725  kern_return_t kret =726      ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64,727                         (thread_state_t)&m_state.dbg, e_regSetDBGCount);728  if (also_set_on_task) {729    kern_return_t task_kret = task_set_state(730        m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE64,731        (thread_state_t)&m_state.dbg, e_regSetDBGCount);732    if (task_kret != KERN_SUCCESS)733      DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::SetDBGState failed "734                                        "to set debug control register state: "735                                        "0x%8.8x.",736                       task_kret);737  }738  m_state.SetError(set, Write,739                   kret); // Set the current write error for this register set740  m_state.InvalidateRegisterSetState(set); // Invalidate the current register741                                           // state in case registers are read742                                           // back differently743 744  return kret; // Return the error code745}746 747void DNBArchMachARM64::ThreadWillResume() {748  // Do we need to step this thread? If so, let the mach thread tell us so.749  if (m_thread->IsStepping()) {750    EnableHardwareSingleStep(true);751  }752 753  // Disable the triggered watchpoint temporarily before we resume.754  // Plus, we try to enable hardware single step to execute past the instruction755  // which triggered our watchpoint.756  if (m_watchpoint_did_occur) {757    if (m_watchpoint_hw_index >= 0) {758      kern_return_t kret = GetDBGState(false);759      if (kret == KERN_SUCCESS &&760          !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) {761        // The watchpoint might have been disabled by the user.  We don't need762        // to do anything at all763        // to enable hardware single stepping.764        m_watchpoint_did_occur = false;765        m_watchpoint_hw_index = -1;766        return;767      }768 769      DisableHardwareWatchpoint(m_watchpoint_hw_index, false);770      DNBLogThreadedIf(LOG_WATCHPOINTS,771                       "DNBArchMachARM64::ThreadWillResume() "772                       "DisableHardwareWatchpoint(%d) called",773                       m_watchpoint_hw_index);774 775      // Enable hardware single step to move past the watchpoint-triggering776      // instruction.777      m_watchpoint_resume_single_step_enabled =778          (EnableHardwareSingleStep(true) == KERN_SUCCESS);779 780      // If we are not able to enable single step to move past the781      // watchpoint-triggering instruction,782      // at least we should reset the two watchpoint member variables so that783      // the next time around784      // this callback function is invoked, the enclosing logical branch is785      // skipped.786      if (!m_watchpoint_resume_single_step_enabled) {787        // Reset the two watchpoint member variables.788        m_watchpoint_did_occur = false;789        m_watchpoint_hw_index = -1;790        DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::ThreadWillResume()"791                                          " failed to enable single step");792      } else793        DNBLogThreadedIf(LOG_WATCHPOINTS,794                         "DNBArchMachARM64::ThreadWillResume() "795                         "succeeded to enable single step");796    }797  }798}799 800bool DNBArchMachARM64::NotifyException(MachException::Data &exc) {801 802  switch (exc.exc_type) {803  default:804    break;805  case EXC_BREAKPOINT:806    if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) {807      // The data break address is passed as exc_data[1].808      nub_addr_t addr = exc.exc_data[1];809      // Find the hardware index with the side effect of possibly massaging the810      // addr to return the starting address as seen from the debugger side.811      uint32_t hw_index = GetHardwareWatchpointHit(addr);812 813      // One logical watchpoint was split into two watchpoint locations because814      // it was too big.  If the watchpoint exception is indicating the 2nd half815      // of the two-parter, find the address of the 1st half and report that --816      // that's what lldb is going to expect to see.817      DNBLogThreadedIf(LOG_WATCHPOINTS,818                       "DNBArchMachARM64::NotifyException "819                       "watchpoint %d was hit on address "820                       "0x%llx",821                       hw_index, (uint64_t)addr);822      const uint32_t num_watchpoints = NumSupportedHardwareWatchpoints();823      for (uint32_t i = 0; i < num_watchpoints; i++) {824        if (LoHi[i] != 0 && LoHi[i] == hw_index && LoHi[i] != i &&825            GetWatchpointAddressByIndex(i) != INVALID_NUB_ADDRESS) {826          addr = GetWatchpointAddressByIndex(i);827          DNBLogThreadedIf(LOG_WATCHPOINTS,828                           "DNBArchMachARM64::NotifyException "829                           "It is a linked watchpoint; "830                           "rewritten to index %d addr 0x%llx",831                           LoHi[i], (uint64_t)addr);832        }833      }834 835      if (hw_index != INVALID_NUB_HW_INDEX) {836        m_watchpoint_did_occur = true;837        m_watchpoint_hw_index = hw_index;838        exc.exc_data[1] = addr;839        // Piggyback the hw_index in the exc.data.840        exc.exc_data.push_back(hw_index);841      }842 843      return true;844    }845    // detect a __builtin_debugtrap instruction pattern ("brk #0xf000")846    // and advance the $pc past it, so that the user can continue execution.847    // Generally speaking, this knowledge should be centralized in lldb,848    // recognizing the builtin_trap instruction and knowing how to advance849    // the pc past it, so that continue etc work.850    if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_BREAKPOINT) {851      nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);852      if (pc != INVALID_NUB_ADDRESS && pc > 0) {853        DNBBreakpoint *bp =854            m_thread->Process()->Breakpoints().FindByAddress(pc);855        if (bp == nullptr) {856          uint8_t insnbuf[4];857          if (m_thread->Process()->ReadMemory(pc, 4, insnbuf) == 4) {858            uint8_t builtin_debugtrap_insn[4] = {0x00, 0x00, 0x3e,859                                                 0xd4}; // brk #0xf000860            if (memcmp(insnbuf, builtin_debugtrap_insn, 4) == 0) {861              SetPC(pc + 4);862            }863          }864        }865      }866    }867    break;868  }869  return false;870}871 872bool DNBArchMachARM64::ThreadDidStop() {873  bool success = true;874 875  m_state.InvalidateAllRegisterStates();876 877  if (m_watchpoint_resume_single_step_enabled) {878    // Great!  We now disable the hardware single step as well as re-enable the879    // hardware watchpoint.880    // See also ThreadWillResume().881    if (EnableHardwareSingleStep(false) == KERN_SUCCESS) {882      if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) {883        ReenableHardwareWatchpoint(m_watchpoint_hw_index);884        m_watchpoint_resume_single_step_enabled = false;885        m_watchpoint_did_occur = false;886        m_watchpoint_hw_index = -1;887      } else {888        DNBLogError("internal error detected: m_watchpoint_resume_step_enabled "889                    "is true but (m_watchpoint_did_occur && "890                    "m_watchpoint_hw_index >= 0) does not hold!");891      }892    } else {893      DNBLogError("internal error detected: m_watchpoint_resume_step_enabled "894                  "is true but unable to disable single step!");895    }896  }897 898  // Are we stepping a single instruction?899  if (GetGPRState(true) == KERN_SUCCESS) {900    // We are single stepping, was this the primary thread?901    if (m_thread->IsStepping()) {902      // This was the primary thread, we need to clear the trace903      // bit if so.904      success = EnableHardwareSingleStep(false) == KERN_SUCCESS;905    } else {906      // The MachThread will automatically restore the suspend count907      // in ThreadDidStop(), so we don't need to do anything here if908      // we weren't the primary thread the last time909    }910  }911  return success;912}913 914// Set the single step bit in the processor status register.915kern_return_t DNBArchMachARM64::EnableHardwareSingleStep(bool enable) {916  DNBError err;917  DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable);918 919  err = GetGPRState(false);920 921  if (err.Fail()) {922    err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);923    return err.Status();924  }925 926  err = GetDBGState(false);927 928  if (err.Fail()) {929    err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__);930    return err.Status();931  }932 933#if defined(DEBUGSERVER_IS_ARM64E)934  uint64_t pc = clear_pac_bits(935      reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));936#else937  uint64_t pc = m_state.context.gpr.__pc;938#endif939 940  if (enable) {941    DNBLogThreadedIf(LOG_STEP,942                     "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx",943                     __FUNCTION__, pc);944    m_state.dbg.__mdscr_el1 |= SS_ENABLE;945  } else {946    DNBLogThreadedIf(LOG_STEP,947                     "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx",948                     __FUNCTION__, pc);949    m_state.dbg.__mdscr_el1 &= ~(SS_ENABLE);950  }951 952  return SetDBGState(false);953}954 955// return 1 if bit "BIT" is set in "value"956static inline uint32_t bit(uint32_t value, uint32_t bit) {957  return (value >> bit) & 1u;958}959 960// return the bitfield "value[msbit:lsbit]".961static inline uint64_t bits(uint64_t value, uint32_t msbit, uint32_t lsbit) {962  assert(msbit >= lsbit);963  uint64_t shift_left = sizeof(value) * 8 - 1 - msbit;964  value <<=965      shift_left; // shift anything above the msbit off of the unsigned edge966  value >>= shift_left + lsbit; // shift it back again down to the lsbit967                                // (including undoing any shift from above)968  return value;                 // return our result969}970 971uint32_t DNBArchMachARM64::NumSupportedHardwareWatchpoints() {972  // Set the init value to something that will let us know that we need to973  // autodetect how many watchpoints are supported dynamically...974  static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;975  if (g_num_supported_hw_watchpoints == UINT_MAX) {976    // Set this to zero in case we can't tell if there are any HW breakpoints977    g_num_supported_hw_watchpoints = 0;978 979    size_t len;980    uint32_t n = 0;981    len = sizeof(n);982    if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {983      g_num_supported_hw_watchpoints = n;984      DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n);985    } else {986// For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in987// EL0 so it can't988// access that reg.  The kernel should have filled in the sysctls based on it989// though.990#if defined(__arm__)991      uint32_t register_DBGDIDR;992 993      asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR));994      uint32_t numWRPs = bits(register_DBGDIDR, 31, 28);995      // Zero is reserved for the WRP count, so don't increment it if it is zero996      if (numWRPs > 0)997        numWRPs++;998      g_num_supported_hw_watchpoints = numWRPs;999      DNBLogThreadedIf(LOG_THREAD,1000                       "Number of supported hw watchpoints via asm():  %d",1001                       g_num_supported_hw_watchpoints);1002#endif1003    }1004  }1005  return g_num_supported_hw_watchpoints;1006}1007 1008uint32_t DNBArchMachARM64::NumSupportedHardwareBreakpoints() {1009  // Set the init value to something that will let us know that we need to1010  // autodetect how many breakpoints are supported dynamically...1011  static uint32_t g_num_supported_hw_breakpoints = UINT_MAX;1012  if (g_num_supported_hw_breakpoints == UINT_MAX) {1013    // Set this to zero in case we can't tell if there are any HW breakpoints1014    g_num_supported_hw_breakpoints = 0;1015 1016    size_t len;1017    uint32_t n = 0;1018    len = sizeof(n);1019    if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) {1020      g_num_supported_hw_breakpoints = n;1021      DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n);1022    } else {1023// For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in1024// EL0 so it can't access that reg.  The kernel should have filled in the1025// sysctls based on it though.1026#if defined(__arm__)1027      uint32_t register_DBGDIDR;1028 1029      asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR));1030      uint32_t numWRPs = bits(register_DBGDIDR, 31, 28);1031      // Zero is reserved for the WRP count, so don't increment it if it is zero1032      if (numWRPs > 0)1033        numWRPs++;1034      g_num_supported_hw_breakpoints = numWRPs;1035      DNBLogThreadedIf(LOG_THREAD,1036                       "Number of supported hw breakpoint via asm():  %d",1037                       g_num_supported_hw_breakpoints);1038#endif1039    }1040  }1041  return g_num_supported_hw_breakpoints;1042}1043 1044uint32_t DNBArchMachARM64::EnableHardwareBreakpoint(nub_addr_t addr,1045                                                    nub_size_t size,1046                                                    bool also_set_on_task) {1047  DNBLogThreadedIf(LOG_WATCHPOINTS,1048                   "DNBArchMachARM64::EnableHardwareBreakpoint(addr = "1049                   "0x%8.8llx, size = %zu)",1050                   (uint64_t)addr, size);1051 1052  const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();1053 1054  nub_addr_t aligned_bp_address = addr;1055  uint32_t control_value = 0;1056 1057  switch (size) {1058  case 2:1059    control_value = (0x3 << 5) | 7;1060    aligned_bp_address &= ~1;1061    break;1062  case 4:1063    control_value = (0xfu << 5) | 7;1064    aligned_bp_address &= ~3;1065    break;1066  };1067 1068  // Read the debug state1069  kern_return_t kret = GetDBGState(false);1070  if (kret == KERN_SUCCESS) {1071    // Check to make sure we have the needed hardware support1072    uint32_t i = 0;1073 1074    for (i = 0; i < num_hw_breakpoints; ++i) {1075      if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0)1076        break; // We found an available hw breakpoint slot (in i)1077    }1078 1079    // See if we found an available hw breakpoint slot above1080    if (i < num_hw_breakpoints) {1081      m_state.dbg.__bvr[i] = aligned_bp_address;1082      m_state.dbg.__bcr[i] = control_value;1083 1084      DNBLogThreadedIf(LOG_WATCHPOINTS,1085                       "DNBArchMachARM64::EnableHardwareBreakpoint() "1086                       "adding breakpoint on address 0x%llx with control "1087                       "register value 0x%x",1088                       (uint64_t)m_state.dbg.__bvr[i],1089                       (uint32_t)m_state.dbg.__bcr[i]);1090 1091      kret = SetDBGState(also_set_on_task);1092 1093      DNBLogThreadedIf(LOG_WATCHPOINTS,1094                       "DNBArchMachARM64::"1095                       "EnableHardwareBreakpoint() "1096                       "SetDBGState() => 0x%8.8x.",1097                       kret);1098 1099      if (kret == KERN_SUCCESS)1100        return i;1101    } else {1102      DNBLogThreadedIf(LOG_WATCHPOINTS,1103                       "DNBArchMachARM64::"1104                       "EnableHardwareBreakpoint(): All "1105                       "hardware resources (%u) are in use.",1106                       num_hw_breakpoints);1107    }1108  }1109  return INVALID_NUB_HW_INDEX;1110}1111 1112// This should be `std::bit_ceil(aligned_size)` but1113// that requires C++20.1114// Calculates the smallest integral power of two that is not smaller than x.1115static uint64_t bit_ceil(uint64_t input) {1116  if (input <= 1 || __builtin_popcount(input) == 1)1117    return input;1118 1119  return 1ULL << (64 - __builtin_clzll(input));1120}1121 1122std::vector<DNBArchMachARM64::WatchpointSpec>1123DNBArchMachARM64::AlignRequestedWatchpoint(nub_addr_t requested_addr,1124                                           nub_size_t requested_size) {1125 1126  // Can't watch zero bytes1127  if (requested_size == 0)1128    return {};1129 1130  // Smallest size we can watch on AArch64 is 8 bytes1131  constexpr nub_size_t min_watchpoint_alignment = 8;1132  nub_size_t aligned_size = std::max(requested_size, min_watchpoint_alignment);1133 1134  /// Round up \a requested_size to the next power-of-2 size, at least 81135  /// bytes1136  /// requested_size == 8   -> aligned_size == 81137  /// requested_size == 9   -> aligned_size == 161138  aligned_size = aligned_size = bit_ceil(aligned_size);1139 1140  nub_addr_t aligned_start = requested_addr & ~(aligned_size - 1);1141  // Does this power-of-2 memory range, aligned to power-of-2, completely1142  // encompass the requested watch region.1143  if (aligned_start + aligned_size >= requested_addr + requested_size) {1144    WatchpointSpec wp;1145    wp.aligned_start = aligned_start;1146    wp.requested_start = requested_addr;1147    wp.aligned_size = aligned_size;1148    wp.requested_size = requested_size;1149    return {{wp}};1150  }1151 1152  // We need to split this into two watchpoints, split on the aligned_size1153  // boundary and re-evaluate the alignment of each half.1154  //1155  // requested_addr 48 requested_size 20 -> aligned_size 321156  //                              aligned_start 321157  //                              split_addr 641158  //                              first_requested_addr 481159  //                              first_requested_size 161160  //                              second_requested_addr 641161  //                              second_requested_size 41162  nub_addr_t split_addr = aligned_start + aligned_size;1163 1164  nub_addr_t first_requested_addr = requested_addr;1165  nub_size_t first_requested_size = split_addr - requested_addr;1166  nub_addr_t second_requested_addr = split_addr;1167  nub_size_t second_requested_size = requested_size - first_requested_size;1168 1169  std::vector<WatchpointSpec> first_wp =1170      AlignRequestedWatchpoint(first_requested_addr, first_requested_size);1171  std::vector<WatchpointSpec> second_wp =1172      AlignRequestedWatchpoint(second_requested_addr, second_requested_size);1173  if (first_wp.size() != 1 || second_wp.size() != 1)1174    return {};1175 1176  return {{first_wp[0], second_wp[0]}};1177}1178 1179uint32_t DNBArchMachARM64::EnableHardwareWatchpoint(nub_addr_t addr,1180                                                    nub_size_t size, bool read,1181                                                    bool write,1182                                                    bool also_set_on_task) {1183  DNBLogThreadedIf(LOG_WATCHPOINTS,1184                   "DNBArchMachARM64::EnableHardwareWatchpoint(addr = "1185                   "0x%8.8llx, size = %zu, read = %u, write = %u)",1186                   (uint64_t)addr, size, read, write);1187 1188  std::vector<DNBArchMachARM64::WatchpointSpec> wps =1189      AlignRequestedWatchpoint(addr, size);1190  DNBLogThreadedIf(LOG_WATCHPOINTS,1191                   "DNBArchMachARM64::EnableHardwareWatchpoint() using %zu "1192                   "hardware watchpoints",1193                   wps.size());1194 1195  if (wps.size() == 0)1196    return INVALID_NUB_HW_INDEX;1197 1198  // We must watch for either read or write1199  if (read == false && write == false)1200    return INVALID_NUB_HW_INDEX;1201 1202  // Only one hardware watchpoint needed1203  // to implement the user's request.1204  if (wps.size() == 1) {1205    if (wps[0].aligned_size <= 8)1206      return SetBASWatchpoint(wps[0], read, write, also_set_on_task);1207    else1208      return SetMASKWatchpoint(wps[0], read, write, also_set_on_task);1209  }1210 1211  // We have multiple WatchpointSpecs1212 1213  std::vector<uint32_t> wp_slots_used;1214  for (size_t i = 0; i < wps.size(); i++) {1215    uint32_t idx =1216        EnableHardwareWatchpoint(wps[i].requested_start, wps[i].requested_size,1217                                 read, write, also_set_on_task);1218    if (idx != INVALID_NUB_HW_INDEX)1219      wp_slots_used.push_back(idx);1220  }1221 1222  // Did we fail to set all of the WatchpointSpecs needed1223  // for this user's request?1224  if (wps.size() != wp_slots_used.size()) {1225    for (int wp_slot : wp_slots_used)1226      DisableHardwareWatchpoint(wp_slot, also_set_on_task);1227    return INVALID_NUB_HW_INDEX;1228  }1229 1230  LoHi[wp_slots_used[0]] = wp_slots_used[1];1231  return wp_slots_used[0];1232}1233 1234uint32_t DNBArchMachARM64::SetBASWatchpoint(DNBArchMachARM64::WatchpointSpec wp,1235                                            bool read, bool write,1236                                            bool also_set_on_task) {1237  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();1238 1239  nub_addr_t aligned_dword_addr = wp.aligned_start;1240  nub_addr_t watching_offset = wp.requested_start - wp.aligned_start;1241  nub_size_t watching_size = wp.requested_size;1242 1243  // If user asks to watch 3 bytes at 0x1005,1244  // aligned_dword_addr 0x10001245  // watching_offset 51246  // watching_size 31247 1248  // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the1249  // above.1250  // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4,1251  // etc, up to 0b11111111 for 8.1252  // then we shift those bits left by the offset into this dword that we are1253  // interested in.1254  // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of1255  // 0b11110000.1256  uint32_t byte_address_select = ((1 << watching_size) - 1) << watching_offset;1257 1258  // Read the debug state1259  kern_return_t kret = GetDBGState(false);1260  if (kret != KERN_SUCCESS)1261    return INVALID_NUB_HW_INDEX;1262 1263  // Check to make sure we have the needed hardware support1264  uint32_t i = 0;1265 1266  for (i = 0; i < num_hw_watchpoints; ++i) {1267    if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)1268      break; // We found an available hw watchpoint slot1269  }1270  if (i == num_hw_watchpoints) {1271    DNBLogThreadedIf(LOG_WATCHPOINTS,1272                     "DNBArchMachARM64::"1273                     "SetBASWatchpoint(): All "1274                     "hardware resources (%u) are in use.",1275                     num_hw_watchpoints);1276    return INVALID_NUB_HW_INDEX;1277  }1278 1279  DNBLogThreadedIf(LOG_WATCHPOINTS,1280                   "DNBArchMachARM64::"1281                   "SetBASWatchpoint() "1282                   "set hardware register %d to BAS watchpoint "1283                   "aligned start address 0x%llx, watch region start "1284                   "offset %lld, number of bytes %zu",1285                   i, aligned_dword_addr, watching_offset, watching_size);1286 1287  // Clear any previous LoHi joined-watchpoint that may have been in use1288  LoHi[i] = 0;1289 1290  // shift our Byte Address Select bits up to the correct bit range for the1291  // DBGWCRn_EL11292  byte_address_select = byte_address_select << 5;1293 1294  // Make sure bits 1:0 are clear in our address1295  m_state.dbg.__wvr[i] = aligned_dword_addr;       // DVA (Data Virtual Address)1296  m_state.dbg.__wcr[i] = byte_address_select |     // Which bytes that follow1297                                                   // the DVA that we will watch1298                         S_USER |                  // Stop only in user mode1299                         (read ? WCR_LOAD : 0) |   // Stop on read access?1300                         (write ? WCR_STORE : 0) | // Stop on write access?1301                         WCR_ENABLE;               // Enable this watchpoint;1302 1303  DNBLogThreadedIf(LOG_WATCHPOINTS,1304                   "DNBArchMachARM64::SetBASWatchpoint() "1305                   "adding watchpoint on address 0x%llx with control "1306                   "register value 0x%x",1307                   (uint64_t)m_state.dbg.__wvr[i],1308                   (uint32_t)m_state.dbg.__wcr[i]);1309 1310  kret = SetDBGState(also_set_on_task);1311  // DumpDBGState(m_state.dbg);1312 1313  DNBLogThreadedIf(LOG_WATCHPOINTS,1314                   "DNBArchMachARM64::"1315                   "SetBASWatchpoint() "1316                   "SetDBGState() => 0x%8.8x.",1317                   kret);1318 1319  if (kret == KERN_SUCCESS)1320    return i;1321 1322  return INVALID_NUB_HW_INDEX;1323}1324 1325uint32_t1326DNBArchMachARM64::SetMASKWatchpoint(DNBArchMachARM64::WatchpointSpec wp,1327                                    bool read, bool write,1328                                    bool also_set_on_task) {1329  const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();1330 1331  // Read the debug state1332  kern_return_t kret = GetDBGState(false);1333  if (kret != KERN_SUCCESS)1334    return INVALID_NUB_HW_INDEX;1335 1336  // Check to make sure we have the needed hardware support1337  uint32_t i = 0;1338 1339  for (i = 0; i < num_hw_watchpoints; ++i) {1340    if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)1341      break; // We found an available hw watchpoint slot1342  }1343  if (i == num_hw_watchpoints) {1344    DNBLogThreadedIf(LOG_WATCHPOINTS,1345                     "DNBArchMachARM64::"1346                     "SetMASKWatchpoint(): All "1347                     "hardware resources (%u) are in use.",1348                     num_hw_watchpoints);1349    return INVALID_NUB_HW_INDEX;1350  }1351 1352  DNBLogThreadedIf(LOG_WATCHPOINTS,1353                   "DNBArchMachARM64::"1354                   "SetMASKWatchpoint() "1355                   "set hardware register %d to MASK watchpoint "1356                   "aligned start address 0x%llx, aligned size %zu",1357                   i, wp.aligned_start, wp.aligned_size);1358 1359  // Clear any previous LoHi joined-watchpoint that may have been in use1360  LoHi[i] = 0;1361 1362  // MASK field is the number of low bits that are masked off1363  // when comparing the address with the DBGWVR<n>_EL1 values.1364  // If aligned size is 16, that means we ignore low 4 bits, 0b1111.1365  // popcount(16 - 1) give us the correct value of 4.1366  // 2GB is max watchable region, which is 31 bits (low bits 0x7fffffff1367  // masked off) -- a MASK value of 31.1368  const uint64_t mask = __builtin_popcountl(wp.aligned_size - 1) << 24;1369  // A '0b11111111' BAS value needed for mask watchpoints plus a1370  // nonzero mask value.1371  const uint64_t not_bas_wp = 0xff << 5;1372 1373  m_state.dbg.__wvr[i] = wp.aligned_start;1374  m_state.dbg.__wcr[i] = mask | not_bas_wp | S_USER | // Stop only in user mode1375                         (read ? WCR_LOAD : 0) |      // Stop on read access?1376                         (write ? WCR_STORE : 0) |    // Stop on write access?1377                         WCR_ENABLE;                  // Enable this watchpoint;1378 1379  DNBLogThreadedIf(LOG_WATCHPOINTS,1380                   "DNBArchMachARM64::SetMASKWatchpoint() "1381                   "adding watchpoint on address 0x%llx with control "1382                   "register value 0x%llx",1383                   (uint64_t)m_state.dbg.__wvr[i],1384                   (uint64_t)m_state.dbg.__wcr[i]);1385 1386  kret = SetDBGState(also_set_on_task);1387 1388  DNBLogThreadedIf(LOG_WATCHPOINTS,1389                   "DNBArchMachARM64::"1390                   "SetMASKWatchpoint() "1391                   "SetDBGState() => 0x%8.8x.",1392                   kret);1393 1394  if (kret == KERN_SUCCESS)1395    return i;1396 1397  return INVALID_NUB_HW_INDEX;1398}1399 1400bool DNBArchMachARM64::ReenableHardwareWatchpoint(uint32_t hw_index) {1401  // If this logical watchpoint # is actually implemented using1402  // two hardware watchpoint registers, re-enable both of them.1403 1404  if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) {1405    return ReenableHardwareWatchpoint_helper(hw_index) &&1406           ReenableHardwareWatchpoint_helper(LoHi[hw_index]);1407  } else {1408    return ReenableHardwareWatchpoint_helper(hw_index);1409  }1410}1411 1412bool DNBArchMachARM64::ReenableHardwareWatchpoint_helper(uint32_t hw_index) {1413  kern_return_t kret = GetDBGState(false);1414  if (kret != KERN_SUCCESS)1415    return false;1416 1417  const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();1418  if (hw_index >= num_hw_points)1419    return false;1420 1421  m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr;1422  m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control;1423 1424  DNBLogThreadedIf(LOG_WATCHPOINTS,1425                   "DNBArchMachARM64::"1426                   "ReenableHardwareWatchpoint_helper( %u ) - WVR%u = "1427                   "0x%8.8llx  WCR%u = 0x%8.8llx",1428                   hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index],1429                   hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]);1430 1431  kret = SetDBGState(false);1432 1433  return (kret == KERN_SUCCESS);1434}1435 1436bool DNBArchMachARM64::DisableHardwareWatchpoint(uint32_t hw_index,1437                                                 bool also_set_on_task) {1438  if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) {1439    return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task) &&1440           DisableHardwareWatchpoint_helper(LoHi[hw_index], also_set_on_task);1441  } else {1442    return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task);1443  }1444}1445 1446bool DNBArchMachARM64::DisableHardwareWatchpoint_helper(uint32_t hw_index,1447                                                        bool also_set_on_task) {1448  kern_return_t kret = GetDBGState(false);1449  if (kret != KERN_SUCCESS)1450    return false;1451 1452  const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();1453  if (hw_index >= num_hw_points)1454    return false;1455 1456  m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index];1457  m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index];1458 1459  m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE);1460  DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::"1461                                    "DisableHardwareWatchpoint( %u ) - WVR%u = "1462                                    "0x%8.8llx  WCR%u = 0x%8.8llx",1463                   hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index],1464                   hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]);1465 1466  kret = SetDBGState(also_set_on_task);1467 1468  return (kret == KERN_SUCCESS);1469}1470 1471bool DNBArchMachARM64::DisableHardwareBreakpoint(uint32_t hw_index,1472                                                 bool also_set_on_task) {1473  kern_return_t kret = GetDBGState(false);1474  if (kret != KERN_SUCCESS)1475    return false;1476 1477  const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();1478  if (hw_index >= num_hw_points)1479    return false;1480 1481  m_disabled_breakpoints[hw_index].addr = m_state.dbg.__bvr[hw_index];1482  m_disabled_breakpoints[hw_index].control = m_state.dbg.__bcr[hw_index];1483 1484  m_state.dbg.__bcr[hw_index] = 0;1485  DNBLogThreadedIf(LOG_WATCHPOINTS,1486                   "DNBArchMachARM64::"1487                   "DisableHardwareBreakpoint( %u ) - WVR%u = "1488                   "0x%8.8llx  BCR%u = 0x%8.8llx",1489                   hw_index, hw_index, (uint64_t)m_state.dbg.__bvr[hw_index],1490                   hw_index, (uint64_t)m_state.dbg.__bcr[hw_index]);1491 1492  kret = SetDBGState(also_set_on_task);1493 1494  return (kret == KERN_SUCCESS);1495}1496 1497// This is for checking the Byte Address Select bits in the DBRWCRn_EL1 control1498// register.1499// Returns -1 if the trailing bit patterns are not one of:1500// { 0b???????1, 0b??????10, 0b?????100, 0b????1000, 0b???10000, 0b??100000,1501// 0b?1000000, 0b10000000 }.1502static inline int32_t LowestBitSet(uint32_t val) {1503  for (unsigned i = 0; i < 8; ++i) {1504    if (bit(val, i))1505      return i;1506  }1507  return -1;1508}1509 1510// Iterate through the debug registers; return the index of the first watchpoint1511// whose address matches.1512// As a side effect, the starting address as understood by the debugger is1513// returned which could be1514// different from 'addr' passed as an in/out argument.1515uint32_t DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr) {1516  // Read the debug state1517  kern_return_t kret = GetDBGState(true);1518  // DumpDBGState(m_state.dbg);1519  DNBLogThreadedIf(1520      LOG_WATCHPOINTS,1521      "DNBArchMachARM64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.",1522      kret);1523  DNBLogThreadedIf(LOG_WATCHPOINTS,1524                   "DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx",1525                   (uint64_t)addr);1526 1527  if (kret == KERN_SUCCESS) {1528    DBG &debug_state = m_state.dbg;1529    uint32_t i, num = NumSupportedHardwareWatchpoints();1530    for (i = 0; i < num; ++i) {1531      nub_addr_t wp_addr = GetWatchAddress(debug_state, i);1532 1533      DNBLogThreadedIf(LOG_WATCHPOINTS,1534                       "DNBArchImplARM64::"1535                       "GetHardwareWatchpointHit() slot: %u "1536                       "(addr = 0x%llx, WCR = 0x%llx)",1537                       i, wp_addr, debug_state.__wcr[i]);1538 1539      if (!IsWatchpointEnabled(debug_state, i))1540        continue;1541 1542      // DBGWCR<n>EL1.BAS are the bits of the doubleword that are watched1543      // with a BAS watchpoint.1544      uint32_t bas_bits = bits(debug_state.__wcr[i], 12, 5);1545      // DBGWCR<n>EL1.MASK is the number of bits that are masked off the1546      // virtual address when comparing to DBGWVR<n>_EL1.1547      uint32_t mask = bits(debug_state.__wcr[i], 28, 24);1548 1549      const bool is_bas_watchpoint = mask == 0;1550 1551      DNBLogThreadedIf(1552          LOG_WATCHPOINTS,1553          "DNBArchImplARM64::"1554          "GetHardwareWatchpointHit() slot: %u %s",1555          i, is_bas_watchpoint ? "is BAS watchpoint" : "is MASK watchpoint");1556 1557      if (is_bas_watchpoint) {1558        if (bits(wp_addr, 48, 3) != bits(addr, 48, 3))1559          continue;1560      } else {1561        if (bits(wp_addr, 48, mask) == bits(addr, 48, mask)) {1562          DNBLogThreadedIf(LOG_WATCHPOINTS,1563                           "DNBArchImplARM64::"1564                           "GetHardwareWatchpointHit() slot: %u matched MASK "1565                           "ignoring %u low bits",1566                           i, mask);1567          return i;1568        }1569      }1570 1571      if (is_bas_watchpoint) {1572        // Sanity check the bas_bits1573        uint32_t lsb = LowestBitSet(bas_bits);1574        if (lsb < 0)1575          continue;1576 1577        uint64_t byte_to_match = bits(addr, 2, 0);1578 1579        if (bas_bits & (1 << byte_to_match)) {1580          addr = wp_addr + lsb;1581          DNBLogThreadedIf(LOG_WATCHPOINTS,1582                           "DNBArchImplARM64::"1583                           "GetHardwareWatchpointHit() slot: %u matched BAS",1584                           i);1585          return i;1586        }1587      }1588    }1589  }1590  return INVALID_NUB_HW_INDEX;1591}1592 1593nub_addr_t DNBArchMachARM64::GetWatchpointAddressByIndex(uint32_t hw_index) {1594  kern_return_t kret = GetDBGState(true);1595  if (kret != KERN_SUCCESS)1596    return INVALID_NUB_ADDRESS;1597  const uint32_t num = NumSupportedHardwareWatchpoints();1598  if (hw_index >= num)1599    return INVALID_NUB_ADDRESS;1600  if (IsWatchpointEnabled(m_state.dbg, hw_index))1601    return GetWatchAddress(m_state.dbg, hw_index);1602  return INVALID_NUB_ADDRESS;1603}1604 1605bool DNBArchMachARM64::IsWatchpointEnabled(const DBG &debug_state,1606                                           uint32_t hw_index) {1607  // Watchpoint Control Registers, bitfield definitions1608  // ...1609  // Bits    Value    Description1610  // [0]     0        Watchpoint disabled1611  //         1        Watchpoint enabled.1612  return (debug_state.__wcr[hw_index] & 1u);1613}1614 1615nub_addr_t DNBArchMachARM64::GetWatchAddress(const DBG &debug_state,1616                                             uint32_t hw_index) {1617  // Watchpoint Value Registers, bitfield definitions1618  // Bits        Description1619  // [31:2]      Watchpoint value (word address, i.e., 4-byte aligned)1620  // [1:0]       RAZ/SBZP1621  return bits(debug_state.__wvr[hw_index], 63, 0);1622}1623 1624// Register information definitions for 64 bit ARMv8.1625enum gpr_regnums {1626  gpr_x0 = 0,1627  gpr_x1,1628  gpr_x2,1629  gpr_x3,1630  gpr_x4,1631  gpr_x5,1632  gpr_x6,1633  gpr_x7,1634  gpr_x8,1635  gpr_x9,1636  gpr_x10,1637  gpr_x11,1638  gpr_x12,1639  gpr_x13,1640  gpr_x14,1641  gpr_x15,1642  gpr_x16,1643  gpr_x17,1644  gpr_x18,1645  gpr_x19,1646  gpr_x20,1647  gpr_x21,1648  gpr_x22,1649  gpr_x23,1650  gpr_x24,1651  gpr_x25,1652  gpr_x26,1653  gpr_x27,1654  gpr_x28,1655  gpr_fp,1656  gpr_x29 = gpr_fp,1657  gpr_lr,1658  gpr_x30 = gpr_lr,1659  gpr_sp,1660  gpr_x31 = gpr_sp,1661  gpr_pc,1662  gpr_cpsr,1663  gpr_w0,1664  gpr_w1,1665  gpr_w2,1666  gpr_w3,1667  gpr_w4,1668  gpr_w5,1669  gpr_w6,1670  gpr_w7,1671  gpr_w8,1672  gpr_w9,1673  gpr_w10,1674  gpr_w11,1675  gpr_w12,1676  gpr_w13,1677  gpr_w14,1678  gpr_w15,1679  gpr_w16,1680  gpr_w17,1681  gpr_w18,1682  gpr_w19,1683  gpr_w20,1684  gpr_w21,1685  gpr_w22,1686  gpr_w23,1687  gpr_w24,1688  gpr_w25,1689  gpr_w26,1690  gpr_w27,1691  gpr_w281692 1693};1694 1695enum {1696  vfp_v0 = 0,1697  vfp_v1,1698  vfp_v2,1699  vfp_v3,1700  vfp_v4,1701  vfp_v5,1702  vfp_v6,1703  vfp_v7,1704  vfp_v8,1705  vfp_v9,1706  vfp_v10,1707  vfp_v11,1708  vfp_v12,1709  vfp_v13,1710  vfp_v14,1711  vfp_v15,1712  vfp_v16,1713  vfp_v17,1714  vfp_v18,1715  vfp_v19,1716  vfp_v20,1717  vfp_v21,1718  vfp_v22,1719  vfp_v23,1720  vfp_v24,1721  vfp_v25,1722  vfp_v26,1723  vfp_v27,1724  vfp_v28,1725  vfp_v29,1726  vfp_v30,1727  vfp_v31,1728  vfp_fpsr,1729  vfp_fpcr,1730 1731  // lower 32 bits of the corresponding vfp_v<n> reg.1732  vfp_s0,1733  vfp_s1,1734  vfp_s2,1735  vfp_s3,1736  vfp_s4,1737  vfp_s5,1738  vfp_s6,1739  vfp_s7,1740  vfp_s8,1741  vfp_s9,1742  vfp_s10,1743  vfp_s11,1744  vfp_s12,1745  vfp_s13,1746  vfp_s14,1747  vfp_s15,1748  vfp_s16,1749  vfp_s17,1750  vfp_s18,1751  vfp_s19,1752  vfp_s20,1753  vfp_s21,1754  vfp_s22,1755  vfp_s23,1756  vfp_s24,1757  vfp_s25,1758  vfp_s26,1759  vfp_s27,1760  vfp_s28,1761  vfp_s29,1762  vfp_s30,1763  vfp_s31,1764 1765  // lower 64 bits of the corresponding vfp_v<n> reg.1766  vfp_d0,1767  vfp_d1,1768  vfp_d2,1769  vfp_d3,1770  vfp_d4,1771  vfp_d5,1772  vfp_d6,1773  vfp_d7,1774  vfp_d8,1775  vfp_d9,1776  vfp_d10,1777  vfp_d11,1778  vfp_d12,1779  vfp_d13,1780  vfp_d14,1781  vfp_d15,1782  vfp_d16,1783  vfp_d17,1784  vfp_d18,1785  vfp_d19,1786  vfp_d20,1787  vfp_d21,1788  vfp_d22,1789  vfp_d23,1790  vfp_d24,1791  vfp_d25,1792  vfp_d26,1793  vfp_d27,1794  vfp_d28,1795  vfp_d29,1796  vfp_d30,1797  vfp_d311798};1799 1800enum {1801  sve_z0,1802  sve_z1,1803  sve_z2,1804  sve_z3,1805  sve_z4,1806  sve_z5,1807  sve_z6,1808  sve_z7,1809  sve_z8,1810  sve_z9,1811  sve_z10,1812  sve_z11,1813  sve_z12,1814  sve_z13,1815  sve_z14,1816  sve_z15,1817  sve_z16,1818  sve_z17,1819  sve_z18,1820  sve_z19,1821  sve_z20,1822  sve_z21,1823  sve_z22,1824  sve_z23,1825  sve_z24,1826  sve_z25,1827  sve_z26,1828  sve_z27,1829  sve_z28,1830  sve_z29,1831  sve_z30,1832  sve_z31,1833  sve_p0,1834  sve_p1,1835  sve_p2,1836  sve_p3,1837  sve_p4,1838  sve_p5,1839  sve_p6,1840  sve_p7,1841  sve_p8,1842  sve_p9,1843  sve_p10,1844  sve_p11,1845  sve_p12,1846  sve_p13,1847  sve_p14,1848  sve_p151849};1850 1851enum { sme_svcr, sme_tpidr2, sme_svl_b, sme_za, sme_zt0 };1852 1853enum { exc_far = 0, exc_esr, exc_exception };1854 1855// These numbers from the "DWARF for the ARM 64-bit Architecture (AArch64)"1856// document.1857 1858enum {1859  dwarf_x0 = 0,1860  dwarf_x1,1861  dwarf_x2,1862  dwarf_x3,1863  dwarf_x4,1864  dwarf_x5,1865  dwarf_x6,1866  dwarf_x7,1867  dwarf_x8,1868  dwarf_x9,1869  dwarf_x10,1870  dwarf_x11,1871  dwarf_x12,1872  dwarf_x13,1873  dwarf_x14,1874  dwarf_x15,1875  dwarf_x16,1876  dwarf_x17,1877  dwarf_x18,1878  dwarf_x19,1879  dwarf_x20,1880  dwarf_x21,1881  dwarf_x22,1882  dwarf_x23,1883  dwarf_x24,1884  dwarf_x25,1885  dwarf_x26,1886  dwarf_x27,1887  dwarf_x28,1888  dwarf_x29,1889  dwarf_x30,1890  dwarf_x31,1891  dwarf_pc = 32,1892  dwarf_elr_mode = 33,1893  dwarf_fp = dwarf_x29,1894  dwarf_lr = dwarf_x30,1895  dwarf_sp = dwarf_x31,1896  // 34-63 reserved1897 1898  // V0-V31 (128 bit vector registers)1899  dwarf_v0 = 64,1900  dwarf_v1,1901  dwarf_v2,1902  dwarf_v3,1903  dwarf_v4,1904  dwarf_v5,1905  dwarf_v6,1906  dwarf_v7,1907  dwarf_v8,1908  dwarf_v9,1909  dwarf_v10,1910  dwarf_v11,1911  dwarf_v12,1912  dwarf_v13,1913  dwarf_v14,1914  dwarf_v15,1915  dwarf_v16,1916  dwarf_v17,1917  dwarf_v18,1918  dwarf_v19,1919  dwarf_v20,1920  dwarf_v21,1921  dwarf_v22,1922  dwarf_v23,1923  dwarf_v24,1924  dwarf_v25,1925  dwarf_v26,1926  dwarf_v27,1927  dwarf_v28,1928  dwarf_v29,1929  dwarf_v30,1930  dwarf_v311931 1932  // 96-127 reserved1933};1934 1935enum {1936  debugserver_gpr_x0 = 0,1937  debugserver_gpr_x1,1938  debugserver_gpr_x2,1939  debugserver_gpr_x3,1940  debugserver_gpr_x4,1941  debugserver_gpr_x5,1942  debugserver_gpr_x6,1943  debugserver_gpr_x7,1944  debugserver_gpr_x8,1945  debugserver_gpr_x9,1946  debugserver_gpr_x10,1947  debugserver_gpr_x11,1948  debugserver_gpr_x12,1949  debugserver_gpr_x13,1950  debugserver_gpr_x14,1951  debugserver_gpr_x15,1952  debugserver_gpr_x16,1953  debugserver_gpr_x17,1954  debugserver_gpr_x18,1955  debugserver_gpr_x19,1956  debugserver_gpr_x20,1957  debugserver_gpr_x21,1958  debugserver_gpr_x22,1959  debugserver_gpr_x23,1960  debugserver_gpr_x24,1961  debugserver_gpr_x25,1962  debugserver_gpr_x26,1963  debugserver_gpr_x27,1964  debugserver_gpr_x28,1965  debugserver_gpr_fp, // x291966  debugserver_gpr_lr, // x301967  debugserver_gpr_sp, // sp aka xsp1968  debugserver_gpr_pc,1969  debugserver_gpr_cpsr,1970  debugserver_vfp_v0,1971  debugserver_vfp_v1,1972  debugserver_vfp_v2,1973  debugserver_vfp_v3,1974  debugserver_vfp_v4,1975  debugserver_vfp_v5,1976  debugserver_vfp_v6,1977  debugserver_vfp_v7,1978  debugserver_vfp_v8,1979  debugserver_vfp_v9,1980  debugserver_vfp_v10,1981  debugserver_vfp_v11,1982  debugserver_vfp_v12,1983  debugserver_vfp_v13,1984  debugserver_vfp_v14,1985  debugserver_vfp_v15,1986  debugserver_vfp_v16,1987  debugserver_vfp_v17,1988  debugserver_vfp_v18,1989  debugserver_vfp_v19,1990  debugserver_vfp_v20,1991  debugserver_vfp_v21,1992  debugserver_vfp_v22,1993  debugserver_vfp_v23,1994  debugserver_vfp_v24,1995  debugserver_vfp_v25,1996  debugserver_vfp_v26,1997  debugserver_vfp_v27,1998  debugserver_vfp_v28,1999  debugserver_vfp_v29,2000  debugserver_vfp_v30,2001  debugserver_vfp_v31,2002  debugserver_vfp_fpsr,2003  debugserver_vfp_fpcr,2004  debugserver_sve_z0,2005  debugserver_sve_z1,2006  debugserver_sve_z2,2007  debugserver_sve_z3,2008  debugserver_sve_z4,2009  debugserver_sve_z5,2010  debugserver_sve_z6,2011  debugserver_sve_z7,2012  debugserver_sve_z8,2013  debugserver_sve_z9,2014  debugserver_sve_z10,2015  debugserver_sve_z11,2016  debugserver_sve_z12,2017  debugserver_sve_z13,2018  debugserver_sve_z14,2019  debugserver_sve_z15,2020  debugserver_sve_z16,2021  debugserver_sve_z17,2022  debugserver_sve_z18,2023  debugserver_sve_z19,2024  debugserver_sve_z20,2025  debugserver_sve_z21,2026  debugserver_sve_z22,2027  debugserver_sve_z23,2028  debugserver_sve_z24,2029  debugserver_sve_z25,2030  debugserver_sve_z26,2031  debugserver_sve_z27,2032  debugserver_sve_z28,2033  debugserver_sve_z29,2034  debugserver_sve_z30,2035  debugserver_sve_z31,2036  debugserver_sve_p0,2037  debugserver_sve_p1,2038  debugserver_sve_p2,2039  debugserver_sve_p3,2040  debugserver_sve_p4,2041  debugserver_sve_p5,2042  debugserver_sve_p6,2043  debugserver_sve_p7,2044  debugserver_sve_p8,2045  debugserver_sve_p9,2046  debugserver_sve_p10,2047  debugserver_sve_p11,2048  debugserver_sve_p12,2049  debugserver_sve_p13,2050  debugserver_sve_p14,2051  debugserver_sve_p15,2052  debugserver_sme_svcr,2053  debugserver_sme_tpidr2,2054  debugserver_sme_svl_b,2055  debugserver_sme_za,2056  debugserver_sme_zt02057};2058 2059const char *g_contained_x0[]{"x0", NULL};2060const char *g_contained_x1[]{"x1", NULL};2061const char *g_contained_x2[]{"x2", NULL};2062const char *g_contained_x3[]{"x3", NULL};2063const char *g_contained_x4[]{"x4", NULL};2064const char *g_contained_x5[]{"x5", NULL};2065const char *g_contained_x6[]{"x6", NULL};2066const char *g_contained_x7[]{"x7", NULL};2067const char *g_contained_x8[]{"x8", NULL};2068const char *g_contained_x9[]{"x9", NULL};2069const char *g_contained_x10[]{"x10", NULL};2070const char *g_contained_x11[]{"x11", NULL};2071const char *g_contained_x12[]{"x12", NULL};2072const char *g_contained_x13[]{"x13", NULL};2073const char *g_contained_x14[]{"x14", NULL};2074const char *g_contained_x15[]{"x15", NULL};2075const char *g_contained_x16[]{"x16", NULL};2076const char *g_contained_x17[]{"x17", NULL};2077const char *g_contained_x18[]{"x18", NULL};2078const char *g_contained_x19[]{"x19", NULL};2079const char *g_contained_x20[]{"x20", NULL};2080const char *g_contained_x21[]{"x21", NULL};2081const char *g_contained_x22[]{"x22", NULL};2082const char *g_contained_x23[]{"x23", NULL};2083const char *g_contained_x24[]{"x24", NULL};2084const char *g_contained_x25[]{"x25", NULL};2085const char *g_contained_x26[]{"x26", NULL};2086const char *g_contained_x27[]{"x27", NULL};2087const char *g_contained_x28[]{"x28", NULL};2088 2089const char *g_invalidate_x0[]{"x0", "w0", NULL};2090const char *g_invalidate_x1[]{"x1", "w1", NULL};2091const char *g_invalidate_x2[]{"x2", "w2", NULL};2092const char *g_invalidate_x3[]{"x3", "w3", NULL};2093const char *g_invalidate_x4[]{"x4", "w4", NULL};2094const char *g_invalidate_x5[]{"x5", "w5", NULL};2095const char *g_invalidate_x6[]{"x6", "w6", NULL};2096const char *g_invalidate_x7[]{"x7", "w7", NULL};2097const char *g_invalidate_x8[]{"x8", "w8", NULL};2098const char *g_invalidate_x9[]{"x9", "w9", NULL};2099const char *g_invalidate_x10[]{"x10", "w10", NULL};2100const char *g_invalidate_x11[]{"x11", "w11", NULL};2101const char *g_invalidate_x12[]{"x12", "w12", NULL};2102const char *g_invalidate_x13[]{"x13", "w13", NULL};2103const char *g_invalidate_x14[]{"x14", "w14", NULL};2104const char *g_invalidate_x15[]{"x15", "w15", NULL};2105const char *g_invalidate_x16[]{"x16", "w16", NULL};2106const char *g_invalidate_x17[]{"x17", "w17", NULL};2107const char *g_invalidate_x18[]{"x18", "w18", NULL};2108const char *g_invalidate_x19[]{"x19", "w19", NULL};2109const char *g_invalidate_x20[]{"x20", "w20", NULL};2110const char *g_invalidate_x21[]{"x21", "w21", NULL};2111const char *g_invalidate_x22[]{"x22", "w22", NULL};2112const char *g_invalidate_x23[]{"x23", "w23", NULL};2113const char *g_invalidate_x24[]{"x24", "w24", NULL};2114const char *g_invalidate_x25[]{"x25", "w25", NULL};2115const char *g_invalidate_x26[]{"x26", "w26", NULL};2116const char *g_invalidate_x27[]{"x27", "w27", NULL};2117const char *g_invalidate_x28[]{"x28", "w28", NULL};2118 2119#define GPR_OFFSET_IDX(idx) (offsetof(DNBArchMachARM64::GPR, __x[idx]))2120 2121#define GPR_OFFSET_NAME(reg) (offsetof(DNBArchMachARM64::GPR, __##reg))2122 2123// These macros will auto define the register name, alt name, register size,2124// register offset, encoding, format and native register. This ensures that2125// the register state structures are defined correctly and have the correct2126// sizes and offsets.2127#define DEFINE_GPR_IDX(idx, reg, alt, gen)                                     \2128  {                                                                            \2129    e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_IDX(idx),      \2130        dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL,            \2131        g_invalidate_x##idx                                                    \2132  }2133#define DEFINE_GPR_NAME(reg, alt, gen)                                         \2134  {                                                                            \2135    e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_NAME(reg),     \2136        dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, NULL       \2137  }2138#define DEFINE_PSEUDO_GPR_IDX(idx, reg)                                        \2139  {                                                                            \2140    e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, 4, 0, INVALID_NUB_REGNUM,   \2141        INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,            \2142        g_contained_x##idx, g_invalidate_x##idx                                \2143  }2144 2145//_STRUCT_ARM_THREAD_STATE642146//{2147//	uint64_t    x[29];	/* General purpose registers x0-x28 */2148//	uint64_t    fp;		/* Frame pointer x29 */2149//	uint64_t    lr;		/* Link register x30 */2150//	uint64_t    sp;		/* Stack pointer x31 */2151//	uint64_t    pc;		/* Program counter */2152//	uint32_t    cpsr;	/* Current program status register */2153//};2154 2155// General purpose registers2156const DNBRegisterInfo DNBArchMachARM64::g_gpr_registers[] = {2157    DEFINE_GPR_IDX(0, x0, "arg1", GENERIC_REGNUM_ARG1),2158    DEFINE_GPR_IDX(1, x1, "arg2", GENERIC_REGNUM_ARG2),2159    DEFINE_GPR_IDX(2, x2, "arg3", GENERIC_REGNUM_ARG3),2160    DEFINE_GPR_IDX(3, x3, "arg4", GENERIC_REGNUM_ARG4),2161    DEFINE_GPR_IDX(4, x4, "arg5", GENERIC_REGNUM_ARG5),2162    DEFINE_GPR_IDX(5, x5, "arg6", GENERIC_REGNUM_ARG6),2163    DEFINE_GPR_IDX(6, x6, "arg7", GENERIC_REGNUM_ARG7),2164    DEFINE_GPR_IDX(7, x7, "arg8", GENERIC_REGNUM_ARG8),2165    DEFINE_GPR_IDX(8, x8, NULL, INVALID_NUB_REGNUM),2166    DEFINE_GPR_IDX(9, x9, NULL, INVALID_NUB_REGNUM),2167    DEFINE_GPR_IDX(10, x10, NULL, INVALID_NUB_REGNUM),2168    DEFINE_GPR_IDX(11, x11, NULL, INVALID_NUB_REGNUM),2169    DEFINE_GPR_IDX(12, x12, NULL, INVALID_NUB_REGNUM),2170    DEFINE_GPR_IDX(13, x13, NULL, INVALID_NUB_REGNUM),2171    DEFINE_GPR_IDX(14, x14, NULL, INVALID_NUB_REGNUM),2172    DEFINE_GPR_IDX(15, x15, NULL, INVALID_NUB_REGNUM),2173    DEFINE_GPR_IDX(16, x16, NULL, INVALID_NUB_REGNUM),2174    DEFINE_GPR_IDX(17, x17, NULL, INVALID_NUB_REGNUM),2175    DEFINE_GPR_IDX(18, x18, NULL, INVALID_NUB_REGNUM),2176    DEFINE_GPR_IDX(19, x19, NULL, INVALID_NUB_REGNUM),2177    DEFINE_GPR_IDX(20, x20, NULL, INVALID_NUB_REGNUM),2178    DEFINE_GPR_IDX(21, x21, NULL, INVALID_NUB_REGNUM),2179    DEFINE_GPR_IDX(22, x22, NULL, INVALID_NUB_REGNUM),2180    DEFINE_GPR_IDX(23, x23, NULL, INVALID_NUB_REGNUM),2181    DEFINE_GPR_IDX(24, x24, NULL, INVALID_NUB_REGNUM),2182    DEFINE_GPR_IDX(25, x25, NULL, INVALID_NUB_REGNUM),2183    DEFINE_GPR_IDX(26, x26, NULL, INVALID_NUB_REGNUM),2184    DEFINE_GPR_IDX(27, x27, NULL, INVALID_NUB_REGNUM),2185    DEFINE_GPR_IDX(28, x28, NULL, INVALID_NUB_REGNUM),2186    // For the G/g packet we want to show where the offset into the regctx2187    // is for fp/lr/sp/pc, but we cannot directly access them on arm64e2188    // devices (and therefore can't offsetof() them)) - add the offset based2189    // on the last accessible register by hand for advertising the location2190    // in the regctx to lldb.  We'll go through the accessor functions when2191    // we read/write them here.2192    {2193       e_regSetGPR, gpr_fp, "fp", "x29", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 8,2194       dwarf_fp, dwarf_fp, GENERIC_REGNUM_FP, debugserver_gpr_fp, NULL, NULL2195    },2196    {2197       e_regSetGPR, gpr_lr, "lr", "x30", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 16,2198       dwarf_lr, dwarf_lr, GENERIC_REGNUM_RA, debugserver_gpr_lr, NULL, NULL2199    },2200    {2201       e_regSetGPR, gpr_sp, "sp", "xsp", Uint, Hex, 8, GPR_OFFSET_IDX(28) + 24,2202       dwarf_sp, dwarf_sp, GENERIC_REGNUM_SP, debugserver_gpr_sp, NULL, NULL2203    },2204    {2205       e_regSetGPR, gpr_pc, "pc", NULL, Uint, Hex, 8, GPR_OFFSET_IDX(28) + 32,2206       dwarf_pc, dwarf_pc, GENERIC_REGNUM_PC, debugserver_gpr_pc, NULL, NULL2207    },2208 2209    // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp,2210    // lr.2211    // this should be specified for arm64 too even though debugserver is only2212    // used for2213    // userland debugging.2214    {e_regSetGPR, gpr_cpsr, "cpsr", "flags", Uint, Hex, 4,2215     GPR_OFFSET_NAME(cpsr), dwarf_elr_mode, dwarf_elr_mode, GENERIC_REGNUM_FLAGS,2216     debugserver_gpr_cpsr, NULL, NULL},2217 2218    DEFINE_PSEUDO_GPR_IDX(0, w0),2219    DEFINE_PSEUDO_GPR_IDX(1, w1),2220    DEFINE_PSEUDO_GPR_IDX(2, w2),2221    DEFINE_PSEUDO_GPR_IDX(3, w3),2222    DEFINE_PSEUDO_GPR_IDX(4, w4),2223    DEFINE_PSEUDO_GPR_IDX(5, w5),2224    DEFINE_PSEUDO_GPR_IDX(6, w6),2225    DEFINE_PSEUDO_GPR_IDX(7, w7),2226    DEFINE_PSEUDO_GPR_IDX(8, w8),2227    DEFINE_PSEUDO_GPR_IDX(9, w9),2228    DEFINE_PSEUDO_GPR_IDX(10, w10),2229    DEFINE_PSEUDO_GPR_IDX(11, w11),2230    DEFINE_PSEUDO_GPR_IDX(12, w12),2231    DEFINE_PSEUDO_GPR_IDX(13, w13),2232    DEFINE_PSEUDO_GPR_IDX(14, w14),2233    DEFINE_PSEUDO_GPR_IDX(15, w15),2234    DEFINE_PSEUDO_GPR_IDX(16, w16),2235    DEFINE_PSEUDO_GPR_IDX(17, w17),2236    DEFINE_PSEUDO_GPR_IDX(18, w18),2237    DEFINE_PSEUDO_GPR_IDX(19, w19),2238    DEFINE_PSEUDO_GPR_IDX(20, w20),2239    DEFINE_PSEUDO_GPR_IDX(21, w21),2240    DEFINE_PSEUDO_GPR_IDX(22, w22),2241    DEFINE_PSEUDO_GPR_IDX(23, w23),2242    DEFINE_PSEUDO_GPR_IDX(24, w24),2243    DEFINE_PSEUDO_GPR_IDX(25, w25),2244    DEFINE_PSEUDO_GPR_IDX(26, w26),2245    DEFINE_PSEUDO_GPR_IDX(27, w27),2246    DEFINE_PSEUDO_GPR_IDX(28, w28)};2247 2248const char *g_contained_v0[]{"v0", NULL};2249const char *g_contained_v1[]{"v1", NULL};2250const char *g_contained_v2[]{"v2", NULL};2251const char *g_contained_v3[]{"v3", NULL};2252const char *g_contained_v4[]{"v4", NULL};2253const char *g_contained_v5[]{"v5", NULL};2254const char *g_contained_v6[]{"v6", NULL};2255const char *g_contained_v7[]{"v7", NULL};2256const char *g_contained_v8[]{"v8", NULL};2257const char *g_contained_v9[]{"v9", NULL};2258const char *g_contained_v10[]{"v10", NULL};2259const char *g_contained_v11[]{"v11", NULL};2260const char *g_contained_v12[]{"v12", NULL};2261const char *g_contained_v13[]{"v13", NULL};2262const char *g_contained_v14[]{"v14", NULL};2263const char *g_contained_v15[]{"v15", NULL};2264const char *g_contained_v16[]{"v16", NULL};2265const char *g_contained_v17[]{"v17", NULL};2266const char *g_contained_v18[]{"v18", NULL};2267const char *g_contained_v19[]{"v19", NULL};2268const char *g_contained_v20[]{"v20", NULL};2269const char *g_contained_v21[]{"v21", NULL};2270const char *g_contained_v22[]{"v22", NULL};2271const char *g_contained_v23[]{"v23", NULL};2272const char *g_contained_v24[]{"v24", NULL};2273const char *g_contained_v25[]{"v25", NULL};2274const char *g_contained_v26[]{"v26", NULL};2275const char *g_contained_v27[]{"v27", NULL};2276const char *g_contained_v28[]{"v28", NULL};2277const char *g_contained_v29[]{"v29", NULL};2278const char *g_contained_v30[]{"v30", NULL};2279const char *g_contained_v31[]{"v31", NULL};2280 2281const char *g_invalidate_v[32][4]{2282    {"v0", "d0", "s0", NULL},    {"v1", "d1", "s1", NULL},2283    {"v2", "d2", "s2", NULL},    {"v3", "d3", "s3", NULL},2284    {"v4", "d4", "s4", NULL},    {"v5", "d5", "s5", NULL},2285    {"v6", "d6", "s6", NULL},    {"v7", "d7", "s7", NULL},2286    {"v8", "d8", "s8", NULL},    {"v9", "d9", "s9", NULL},2287    {"v10", "d10", "s10", NULL}, {"v11", "d11", "s11", NULL},2288    {"v12", "d12", "s12", NULL}, {"v13", "d13", "s13", NULL},2289    {"v14", "d14", "s14", NULL}, {"v15", "d15", "s15", NULL},2290    {"v16", "d16", "s16", NULL}, {"v17", "d17", "s17", NULL},2291    {"v18", "d18", "s18", NULL}, {"v19", "d19", "s19", NULL},2292    {"v20", "d20", "s20", NULL}, {"v21", "d21", "s21", NULL},2293    {"v22", "d22", "s22", NULL}, {"v23", "d23", "s23", NULL},2294    {"v24", "d24", "s24", NULL}, {"v25", "d25", "s25", NULL},2295    {"v26", "d26", "s26", NULL}, {"v27", "d27", "s27", NULL},2296    {"v28", "d28", "s28", NULL}, {"v29", "d29", "s29", NULL},2297    {"v30", "d30", "s30", NULL}, {"v31", "d31", "s31", NULL}};2298 2299const char *g_invalidate_z[32][5]{2300    {"z0", "v0", "d0", "s0", NULL},     {"z1", "v1", "d1", "s1", NULL},2301    {"z2", "v2", "d2", "s2", NULL},     {"z3", "v3", "d3", "s3", NULL},2302    {"z4", "v4", "d4", "s4", NULL},     {"z5", "v5", "d5", "s5", NULL},2303    {"z6", "v6", "d6", "s6", NULL},     {"z7", "v7", "d7", "s7", NULL},2304    {"z8", "v8", "d8", "s8", NULL},     {"z9", "v9", "d9", "s9", NULL},2305    {"z10", "v10", "d10", "s10", NULL}, {"z11", "v11", "d11", "s11", NULL},2306    {"z12", "v12", "d12", "s12", NULL}, {"z13", "v13", "d13", "s13", NULL},2307    {"z14", "v14", "d14", "s14", NULL}, {"z15", "v15", "d15", "s15", NULL},2308    {"z16", "v16", "d16", "s16", NULL}, {"z17", "v17", "d17", "s17", NULL},2309    {"z18", "v18", "d18", "s18", NULL}, {"z19", "v19", "d19", "s19", NULL},2310    {"z20", "v20", "d20", "s20", NULL}, {"z21", "v21", "d21", "s21", NULL},2311    {"z22", "v22", "d22", "s22", NULL}, {"z23", "v23", "d23", "s23", NULL},2312    {"z24", "v24", "d24", "s24", NULL}, {"z25", "v25", "d25", "s25", NULL},2313    {"z26", "v26", "d26", "s26", NULL}, {"z27", "v27", "d27", "s27", NULL},2314    {"z28", "v28", "d28", "s28", NULL}, {"z29", "v29", "d29", "s29", NULL},2315    {"z30", "v30", "d30", "s30", NULL}, {"z31", "v31", "d31", "s31", NULL}};2316 2317const char *g_contained_z0[]{"z0", NULL};2318const char *g_contained_z1[]{"z1", NULL};2319const char *g_contained_z2[]{"z2", NULL};2320const char *g_contained_z3[]{"z3", NULL};2321const char *g_contained_z4[]{"z4", NULL};2322const char *g_contained_z5[]{"z5", NULL};2323const char *g_contained_z6[]{"z6", NULL};2324const char *g_contained_z7[]{"z7", NULL};2325const char *g_contained_z8[]{"z8", NULL};2326const char *g_contained_z9[]{"z9", NULL};2327const char *g_contained_z10[]{"z10", NULL};2328const char *g_contained_z11[]{"z11", NULL};2329const char *g_contained_z12[]{"z12", NULL};2330const char *g_contained_z13[]{"z13", NULL};2331const char *g_contained_z14[]{"z14", NULL};2332const char *g_contained_z15[]{"z15", NULL};2333const char *g_contained_z16[]{"z16", NULL};2334const char *g_contained_z17[]{"z17", NULL};2335const char *g_contained_z18[]{"z18", NULL};2336const char *g_contained_z19[]{"z19", NULL};2337const char *g_contained_z20[]{"z20", NULL};2338const char *g_contained_z21[]{"z21", NULL};2339const char *g_contained_z22[]{"z22", NULL};2340const char *g_contained_z23[]{"z23", NULL};2341const char *g_contained_z24[]{"z24", NULL};2342const char *g_contained_z25[]{"z25", NULL};2343const char *g_contained_z26[]{"z26", NULL};2344const char *g_contained_z27[]{"z27", NULL};2345const char *g_contained_z28[]{"z28", NULL};2346const char *g_contained_z29[]{"z29", NULL};2347const char *g_contained_z30[]{"z30", NULL};2348const char *g_contained_z31[]{"z31", NULL};2349 2350#if defined(__arm64__) || defined(__aarch64__)2351#define VFP_V_OFFSET_IDX(idx)                                                  \2352  (offsetof(DNBArchMachARM64::FPU, __v) + (idx * 16) +                         \2353   offsetof(DNBArchMachARM64::Context, vfp))2354#else2355#define VFP_V_OFFSET_IDX(idx)                                                  \2356  (offsetof(DNBArchMachARM64::FPU, opaque) + (idx * 16) +                      \2357   offsetof(DNBArchMachARM64::Context, vfp))2358#endif2359#define EXC_OFFSET(reg)                                                        \2360  (offsetof(DNBArchMachARM64::EXC, reg) +                                      \2361   offsetof(DNBArchMachARM64::Context, exc))2362#define SVE_OFFSET_Z_IDX(idx)                                                  \2363  (offsetof(DNBArchMachARM64::SVE, z[idx]) +                                   \2364   offsetof(DNBArchMachARM64::Context, sve))2365#define SVE_OFFSET_P_IDX(idx)                                                  \2366  (offsetof(DNBArchMachARM64::SVE, p[idx]) +                                   \2367   offsetof(DNBArchMachARM64::Context, sve))2368#define SME_OFFSET(reg)                                                        \2369  (offsetof(DNBArchMachARM64::SME, reg) +                                      \2370   offsetof(DNBArchMachARM64::Context, sme))2371 2372//_STRUCT_ARM_EXCEPTION_STATE642373//{2374//	uint64_t	far; /* Virtual Fault Address */2375//	uint32_t	esr; /* Exception syndrome */2376//	uint32_t	exception; /* number of arm exception taken */2377//};2378 2379// Exception registers2380const DNBRegisterInfo DNBArchMachARM64::g_exc_registers[] = {2381    {e_regSetEXC, exc_far, "far", NULL, Uint, Hex, 8, EXC_OFFSET(__far),2382     INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2383     INVALID_NUB_REGNUM, NULL, NULL},2384    {e_regSetEXC, exc_esr, "esr", NULL, Uint, Hex, 4, EXC_OFFSET(__esr),2385     INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2386     INVALID_NUB_REGNUM, NULL, NULL},2387    {e_regSetEXC, exc_exception, "exception", NULL, Uint, Hex, 4,2388     EXC_OFFSET(__exception), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2389     INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}};2390 2391// Number of registers in each register set2392const size_t DNBArchMachARM64::k_num_gpr_registers =2393    sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo);2394const size_t DNBArchMachARM64::k_num_exc_registers =2395    sizeof(g_exc_registers) / sizeof(DNBRegisterInfo);2396 2397static std::vector<DNBRegisterInfo> g_sve_registers;2398static void initialize_sve_registers() {2399  static const char *g_z_regnames[32] = {2400      "z0",  "z1",  "z2",  "z3",  "z4",  "z5",  "z6",  "z7",2401      "z8",  "z9",  "z10", "z11", "z12", "z13", "z14", "z15",2402      "z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",2403      "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31"};2404  static const char *g_p_regnames[16] = {2405      "p0", "p1", "p2",  "p3",  "p4",  "p5",  "p6",  "p7",2406      "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15"};2407 2408  if (DNBArchMachARM64::CPUHasSME()) {2409    uint32_t svl_bytes = DNBArchMachARM64::GetSMEMaxSVL();2410    for (uint32_t i = 0; i < 32; i++) {2411      g_sve_registers.push_back(2412          {DNBArchMachARM64::e_regSetSVE, (uint32_t)sve_z0 + i, g_z_regnames[i],2413           NULL, Vector, VectorOfUInt8, svl_bytes,2414           static_cast<uint32_t>(SVE_OFFSET_Z_IDX(i)), INVALID_NUB_REGNUM,2415           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2416           (uint32_t)debugserver_sve_z0 + i, NULL, g_invalidate_z[i]});2417    }2418    for (uint32_t i = 0; i < 16; i++) {2419      g_sve_registers.push_back(2420          {DNBArchMachARM64::e_regSetSVE, (uint32_t)sve_p0 + i, g_p_regnames[i],2421           NULL, Vector, VectorOfUInt8, svl_bytes / 8,2422           (uint32_t)SVE_OFFSET_P_IDX(i), INVALID_NUB_REGNUM,2423           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2424           (uint32_t)debugserver_sve_p0 + i, NULL, NULL});2425    }2426  }2427}2428 2429static std::vector<DNBRegisterInfo> g_vfp_registers;2430static void initialize_vfp_registers() {2431  static const char *g_v_regnames[32] = {2432      "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",2433      "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",2434      "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",2435      "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};2436  static const char *g_q_regnames[32] = {2437      "q0",  "q1",  "q2",  "q3",  "q4",  "q5",  "q6",  "q7",2438      "q8",  "q9",  "q10", "q11", "q12", "q13", "q14", "q15",2439      "q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23",2440      "q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31"};2441 2442  static const char *g_d_regnames[32] = {2443      "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",2444      "d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",2445      "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",2446      "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};2447 2448  static const char *g_s_regnames[32] = {2449      "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",2450      "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",2451      "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",2452      "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"};2453 2454  for (uint32_t i = 0; i < 32; i++)2455    if (DNBArchMachARM64::CPUHasSME())2456      g_vfp_registers.push_back(2457          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_v0 + i, g_v_regnames[i],2458           g_q_regnames[i], Vector, VectorOfUInt8, 16,2459           static_cast<uint32_t>(VFP_V_OFFSET_IDX(i)), INVALID_NUB_REGNUM,2460           (uint32_t)dwarf_v0 + i, INVALID_NUB_REGNUM,2461           (uint32_t)debugserver_vfp_v0 + i, NULL, g_invalidate_z[i]});2462    else2463      g_vfp_registers.push_back(2464          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_v0 + i, g_v_regnames[i],2465           g_q_regnames[i], Vector, VectorOfUInt8, 16,2466           static_cast<uint32_t>(VFP_V_OFFSET_IDX(i)), INVALID_NUB_REGNUM,2467           (uint32_t)dwarf_v0 + i, INVALID_NUB_REGNUM,2468           (uint32_t)debugserver_vfp_v0 + i, NULL, g_invalidate_v[i]});2469 2470  g_vfp_registers.push_back(2471      {DNBArchMachARM64::e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4,2472       VFP_V_OFFSET_IDX(32) + 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2473       INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL});2474  g_vfp_registers.push_back(2475      {DNBArchMachARM64::e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4,2476       VFP_V_OFFSET_IDX(32) + 4, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2477       INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL});2478 2479  for (uint32_t i = 0; i < 32; i++)2480    if (DNBArchMachARM64::CPUHasSME())2481      g_vfp_registers.push_back(2482          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_d0 + i, g_d_regnames[i],2483           NULL, IEEE754, Float, 8, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2484           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, g_invalidate_z[i]});2485    else2486      g_vfp_registers.push_back(2487          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_d0 + i, g_d_regnames[i],2488           NULL, IEEE754, Float, 8, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2489           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, g_invalidate_v[i]});2490 2491  for (uint32_t i = 0; i < 32; i++)2492    if (DNBArchMachARM64::CPUHasSME())2493      g_vfp_registers.push_back(2494          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_s0 + i, g_s_regnames[i],2495           NULL, IEEE754, Float, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2496           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, g_invalidate_z[i]});2497    else2498      g_vfp_registers.push_back(2499          {DNBArchMachARM64::e_regSetVFP, (uint32_t)vfp_s0 + i, g_s_regnames[i],2500           NULL, IEEE754, Float, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2501           INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, g_invalidate_v[i]});2502}2503 2504static std::once_flag g_vfp_once;2505DNBRegisterInfo *2506DNBArchMachARM64::get_vfp_registerinfo(size_t &num_vfp_registers) {2507  std::call_once(g_vfp_once, []() { initialize_vfp_registers(); });2508  num_vfp_registers = g_vfp_registers.size();2509  if (num_vfp_registers > 0)2510    return g_vfp_registers.data();2511  else2512    return nullptr;2513}2514 2515static std::once_flag g_sve_once;2516DNBRegisterInfo *2517DNBArchMachARM64::get_sve_registerinfo(size_t &num_sve_registers) {2518  std::call_once(g_sve_once, []() { initialize_sve_registers(); });2519  num_sve_registers = g_sve_registers.size();2520  if (num_sve_registers > 0)2521    return g_sve_registers.data();2522  else2523    return nullptr;2524}2525 2526static std::vector<DNBRegisterInfo> g_sme_registers;2527static void initialize_sme_registers() {2528  if (DNBArchMachARM64::CPUHasSME()) {2529    uint32_t svl_bytes = DNBArchMachARM64::GetSMEMaxSVL();2530    g_sme_registers.push_back(2531        {DNBArchMachARM64::e_regSetSME, sme_svcr, "svcr", NULL, Uint, Hex, 8,2532         SME_OFFSET(svcr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2533         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL});2534    g_sme_registers.push_back(2535        {DNBArchMachARM64::e_regSetSME, sme_tpidr2, "tpidr2", NULL, Uint, Hex,2536         8, SME_OFFSET(tpidr2), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2537         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL});2538    g_sme_registers.push_back(2539        {DNBArchMachARM64::e_regSetSME, sme_svl_b, "svl", NULL, Uint, Hex, 2,2540         SME_OFFSET(svl_b), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2541         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL});2542    uint32_t za_max_size = svl_bytes * svl_bytes;2543    g_sme_registers.push_back({DNBArchMachARM64::e_regSetSME, sme_za, "za",2544                               NULL, Vector, VectorOfUInt8, za_max_size,2545                               SME_OFFSET(za), INVALID_NUB_REGNUM,2546                               INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2547                               INVALID_NUB_REGNUM, NULL, NULL});2548  }2549  if (DNBArchMachARM64::CPUHasSME2()) {2550    g_sme_registers.push_back({DNBArchMachARM64::e_regSetSME, sme_zt0, "zt0",2551                               NULL, Vector, VectorOfUInt8, 64, SME_OFFSET(zt0),2552                               INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,2553                               INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL,2554                               NULL});2555  }2556}2557 2558static std::once_flag g_sme_once;2559DNBRegisterInfo *2560DNBArchMachARM64::get_sme_registerinfo(size_t &num_sme_registers) {2561  std::call_once(g_sme_once, []() { initialize_sme_registers(); });2562  num_sme_registers = g_sme_registers.size();2563  if (num_sme_registers > 0)2564    return g_sme_registers.data();2565  else2566    return nullptr;2567}2568 2569static std::vector<DNBRegisterSetInfo> g_reg_sets;2570void DNBArchMachARM64::initialize_reg_sets() {2571  nub_size_t num_all_registers = DNBArchMachARM64::k_num_gpr_registers +2572                                 DNBArchMachARM64::k_num_exc_registers;2573  size_t num_vfp_registers = 0;2574  DNBRegisterInfo *vfp_reginfos =2575      DNBArchMachARM64::get_vfp_registerinfo(num_vfp_registers);2576  size_t num_sve_registers = 0;2577  DNBRegisterInfo *sve_reginfos =2578      DNBArchMachARM64::get_sve_registerinfo(num_sve_registers);2579  size_t num_sme_registers = 0;2580  DNBRegisterInfo *sme_reginfos =2581      DNBArchMachARM64::get_sme_registerinfo(num_sme_registers);2582  num_all_registers +=2583      num_vfp_registers + num_sve_registers + num_sme_registers;2584  g_reg_sets.push_back({"ARM64 Registers", NULL, num_all_registers});2585  g_reg_sets.push_back({"General Purpose Registers",2586                        DNBArchMachARM64::g_gpr_registers,2587                        DNBArchMachARM64::k_num_gpr_registers});2588  g_reg_sets.push_back(2589      {"Floating Point Registers", vfp_reginfos, num_vfp_registers});2590  g_reg_sets.push_back({"Exception State Registers",2591                        DNBArchMachARM64::g_exc_registers,2592                        DNBArchMachARM64::k_num_exc_registers});2593  if (DNBArchMachARM64::CPUHasSME()) {2594    g_reg_sets.push_back({"Scalable Vector Extension Registers", sve_reginfos,2595                          num_sve_registers});2596    g_reg_sets.push_back({"Scalable Matrix Extension Registers", sme_reginfos,2597                          num_sme_registers});2598  }2599}2600 2601static std::once_flag g_initialize_register_set_info;2602const DNBRegisterSetInfo *2603DNBArchMachARM64::GetRegisterSetInfo(nub_size_t *num_reg_sets) {2604  std::call_once(g_initialize_register_set_info,2605                 []() { initialize_reg_sets(); });2606  *num_reg_sets = g_reg_sets.size();2607  return g_reg_sets.data();2608}2609 2610bool DNBArchMachARM64::FixGenericRegisterNumber(uint32_t &set, uint32_t &reg) {2611  if (set == REGISTER_SET_GENERIC) {2612    switch (reg) {2613    case GENERIC_REGNUM_PC: // Program Counter2614      set = e_regSetGPR;2615      reg = gpr_pc;2616      break;2617 2618    case GENERIC_REGNUM_SP: // Stack Pointer2619      set = e_regSetGPR;2620      reg = gpr_sp;2621      break;2622 2623    case GENERIC_REGNUM_FP: // Frame Pointer2624      set = e_regSetGPR;2625      reg = gpr_fp;2626      break;2627 2628    case GENERIC_REGNUM_RA: // Return Address2629      set = e_regSetGPR;2630      reg = gpr_lr;2631      break;2632 2633    case GENERIC_REGNUM_FLAGS: // Processor flags register2634      set = e_regSetGPR;2635      reg = gpr_cpsr;2636      break;2637 2638    case GENERIC_REGNUM_ARG1:2639    case GENERIC_REGNUM_ARG2:2640    case GENERIC_REGNUM_ARG3:2641    case GENERIC_REGNUM_ARG4:2642    case GENERIC_REGNUM_ARG5:2643    case GENERIC_REGNUM_ARG6:2644      set = e_regSetGPR;2645      reg = gpr_x0 + reg - GENERIC_REGNUM_ARG1;2646      break;2647 2648    default:2649      return false;2650    }2651  }2652  return true;2653}2654bool DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg,2655                                        DNBRegisterValue *value) {2656  if (!FixGenericRegisterNumber(set, reg))2657    return false;2658 2659  if (GetRegisterState(set, false) != KERN_SUCCESS)2660    return false;2661 2662  const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);2663  if (regInfo) {2664    uint16_t max_svl_bytes = GetSMEMaxSVL();2665    value->info = *regInfo;2666    switch (set) {2667    case e_regSetGPR:2668      if (reg <= gpr_pc) {2669        switch (reg) {2670#if defined(DEBUGSERVER_IS_ARM64E)2671        case gpr_pc:2672          value->value.uint64 = clear_pac_bits(2673              reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));2674          break;2675        case gpr_lr:2676          value->value.uint64 = arm_thread_state64_get_lr(m_state.context.gpr);2677          break;2678        case gpr_sp:2679          value->value.uint64 = clear_pac_bits(2680              reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp));2681          break;2682        case gpr_fp:2683          value->value.uint64 = clear_pac_bits(2684              reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_fp));2685          break;2686#else2687        case gpr_pc:2688          value->value.uint64 = clear_pac_bits(m_state.context.gpr.__pc);2689          break;2690        case gpr_lr:2691          value->value.uint64 = clear_pac_bits(m_state.context.gpr.__lr);2692          break;2693        case gpr_sp:2694          value->value.uint64 = clear_pac_bits(m_state.context.gpr.__sp);2695          break;2696        case gpr_fp:2697          value->value.uint64 = clear_pac_bits(m_state.context.gpr.__fp);2698          break;2699#endif2700        default:2701          value->value.uint64 = m_state.context.gpr.__x[reg];2702        }2703        return true;2704      } else if (reg == gpr_cpsr) {2705        value->value.uint32 = m_state.context.gpr.__cpsr;2706        return true;2707      }2708      break;2709 2710    case e_regSetVFP:2711 2712      if (reg >= vfp_v0 && reg <= vfp_v31) {2713#if defined(__arm64__) || defined(__aarch64__)2714        memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_v0],2715               16);2716#else2717        memcpy(&value->value.v_uint8,2718               ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16),2719               16);2720#endif2721        return true;2722      } else if (reg == vfp_fpsr) {2723#if defined(__arm64__) || defined(__aarch64__)2724        memcpy(&value->value.uint32, &m_state.context.vfp.__fpsr, 4);2725#else2726        memcpy(&value->value.uint32,2727               ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0, 4);2728#endif2729        return true;2730      } else if (reg == vfp_fpcr) {2731#if defined(__arm64__) || defined(__aarch64__)2732        memcpy(&value->value.uint32, &m_state.context.vfp.__fpcr, 4);2733#else2734        memcpy(&value->value.uint32,2735               ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 4, 4);2736#endif2737        return true;2738      } else if (reg >= vfp_s0 && reg <= vfp_s31) {2739#if defined(__arm64__) || defined(__aarch64__)2740        memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_s0],2741               4);2742#else2743        memcpy(&value->value.v_uint8,2744               ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16),2745               4);2746#endif2747        return true;2748      } else if (reg >= vfp_d0 && reg <= vfp_d31) {2749#if defined(__arm64__) || defined(__aarch64__)2750        memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_d0],2751               8);2752#else2753        memcpy(&value->value.v_uint8,2754               ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16),2755               8);2756#endif2757        return true;2758      }2759      break;2760 2761    case e_regSetSVE:2762      if (GetRegisterState(e_regSetSVE, false) != KERN_SUCCESS)2763        return false;2764 2765      if (reg >= sve_z0 && reg <= sve_z31) {2766        memset(&value->value.v_uint8, 0, max_svl_bytes);2767        memcpy(&value->value.v_uint8, &m_state.context.sve.z[reg - sve_z0],2768               max_svl_bytes);2769        return true;2770      } else if (reg >= sve_p0 && reg <= sve_p15) {2771        memset(&value->value.v_uint8, 0, max_svl_bytes / 8);2772        memcpy(&value->value.v_uint8, &m_state.context.sve.p[reg - sve_p0],2773               max_svl_bytes / 8);2774        return true;2775      }2776      break;2777 2778    case e_regSetSME:2779      if (GetRegisterState(e_regSetSME, false) != KERN_SUCCESS)2780        return false;2781 2782      if (reg == sme_svcr) {2783        value->value.uint64 = m_state.context.sme.svcr;2784        return true;2785      } else if (reg == sme_tpidr2) {2786        value->value.uint64 = m_state.context.sme.tpidr2;2787        return true;2788      } else if (reg == sme_svl_b) {2789        value->value.uint64 = m_state.context.sme.svl_b;2790        return true;2791      } else if (reg == sme_za) {2792        memcpy(&value->value.v_uint8, m_state.context.sme.za.data(),2793               max_svl_bytes * max_svl_bytes);2794        return true;2795      } else if (reg == sme_zt0) {2796        memcpy(&value->value.v_uint8, &m_state.context.sme.zt0, 64);2797        return true;2798      }2799      break;2800 2801    case e_regSetEXC:2802      if (reg == exc_far) {2803        value->value.uint64 = m_state.context.exc.__far;2804        return true;2805      } else if (reg == exc_esr) {2806        value->value.uint32 = m_state.context.exc.__esr;2807        return true;2808      } else if (reg == exc_exception) {2809        value->value.uint32 = m_state.context.exc.__exception;2810        return true;2811      }2812      break;2813    }2814  }2815  return false;2816}2817 2818bool DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg,2819                                        const DNBRegisterValue *value) {2820  if (!FixGenericRegisterNumber(set, reg))2821    return false;2822 2823  if (GetRegisterState(set, false) != KERN_SUCCESS)2824    return false;2825 2826  bool success = false;2827  const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);2828  if (regInfo) {2829    switch (set) {2830    case e_regSetGPR:2831      if (reg <= gpr_pc) {2832#if defined(__LP64__)2833          uint64_t signed_value = value->value.uint64;2834#if __has_feature(ptrauth_calls)2835          // The incoming value could be garbage.  Strip it to avoid2836          // trapping when it gets resigned in the thread state.2837          signed_value = (uint64_t) ptrauth_strip((void*) signed_value, ptrauth_key_function_pointer);2838          signed_value = (uint64_t) ptrauth_sign_unauthenticated((void*) signed_value, ptrauth_key_function_pointer, 0);2839#endif2840        if (reg == gpr_pc)2841         arm_thread_state64_set_pc_fptr (m_state.context.gpr, (void*) signed_value);2842        else if (reg == gpr_lr)2843          arm_thread_state64_set_lr_fptr (m_state.context.gpr, (void*) signed_value);2844        else if (reg == gpr_sp)2845          arm_thread_state64_set_sp (m_state.context.gpr, value->value.uint64);2846        else if (reg == gpr_fp)2847          arm_thread_state64_set_fp (m_state.context.gpr, value->value.uint64);2848        else2849          m_state.context.gpr.__x[reg] = value->value.uint64;2850#else2851        m_state.context.gpr.__x[reg] = value->value.uint64;2852#endif2853        success = true;2854      } else if (reg == gpr_cpsr) {2855        m_state.context.gpr.__cpsr = value->value.uint32;2856        success = true;2857      }2858      break;2859 2860    case e_regSetVFP:2861      if (reg >= vfp_v0 && reg <= vfp_v31) {2862#if defined(__arm64__) || defined(__aarch64__)2863        memcpy(&m_state.context.vfp.__v[reg - vfp_v0], &value->value.v_uint8,2864               16);2865#else2866        memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16),2867               &value->value.v_uint8, 16);2868#endif2869        success = true;2870      } else if (reg == vfp_fpsr) {2871#if defined(__arm64__) || defined(__aarch64__)2872        memcpy(&m_state.context.vfp.__fpsr, &value->value.uint32, 4);2873#else2874        memcpy(((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0,2875               &value->value.uint32, 4);2876#endif2877        success = true;2878      } else if (reg == vfp_fpcr) {2879#if defined(__arm64__) || defined(__aarch64__)2880        memcpy(&m_state.context.vfp.__fpcr, &value->value.uint32, 4);2881#else2882        memcpy(((uint8_t *)m_state.context.vfp.opaque) + (32 * 16) + 4,2883               &value->value.uint32, 4);2884#endif2885        success = true;2886      } else if (reg >= vfp_s0 && reg <= vfp_s31) {2887#if defined(__arm64__) || defined(__aarch64__)2888        memcpy(&m_state.context.vfp.__v[reg - vfp_s0], &value->value.v_uint8,2889               4);2890#else2891        memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16),2892               &value->value.v_uint8, 4);2893#endif2894        success = true;2895      } else if (reg >= vfp_d0 && reg <= vfp_d31) {2896#if defined(__arm64__) || defined(__aarch64__)2897        memcpy(&m_state.context.vfp.__v[reg - vfp_d0], &value->value.v_uint8,2898               8);2899#else2900        memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16),2901               &value->value.v_uint8, 8);2902#endif2903        success = true;2904      }2905      break;2906 2907    case e_regSetSVE:2908      if (reg >= sve_z0 && reg <= sve_z31) {2909        uint16_t max_svl_bytes = GetSMEMaxSVL();2910        memcpy(&m_state.context.sve.z[reg - sve_z0], &value->value.v_uint8,2911               max_svl_bytes);2912        success = true;2913      }2914      if (reg >= sve_p0 && reg <= sve_p15) {2915        uint16_t max_svl_bytes = GetSMEMaxSVL();2916        memcpy(&m_state.context.sve.p[reg - sve_p0], &value->value.v_uint8,2917               max_svl_bytes / 8);2918        success = true;2919      }2920      break;2921 2922    case e_regSetSME:2923      // Cannot change ARM_SME_STATE registers with thread_set_state2924      if (reg == sme_svcr || reg == sme_tpidr2 || reg == sme_svl_b)2925        return false;2926      if (reg == sme_za) {2927        uint16_t max_svl_bytes = GetSMEMaxSVL();2928        memcpy(m_state.context.sme.za.data(), &value->value.v_uint8,2929               max_svl_bytes * max_svl_bytes);2930        success = true;2931      }2932      if (reg == sme_zt0) {2933        memcpy(&m_state.context.sme.zt0, &value->value.v_uint8, 64);2934        success = true;2935      }2936      break;2937 2938    case e_regSetEXC:2939      if (reg == exc_far) {2940        m_state.context.exc.__far = value->value.uint64;2941        success = true;2942      } else if (reg == exc_esr) {2943        m_state.context.exc.__esr = value->value.uint32;2944        success = true;2945      } else if (reg == exc_exception) {2946        m_state.context.exc.__exception = value->value.uint32;2947        success = true;2948      }2949      break;2950    }2951  }2952  if (success)2953    return SetRegisterState(set) == KERN_SUCCESS;2954  return false;2955}2956 2957kern_return_t DNBArchMachARM64::GetRegisterState(int set, bool force) {2958  switch (set) {2959  case e_regSetALL: {2960    kern_return_t retval = GetGPRState(force) | GetVFPState(force) |2961                           GetEXCState(force) | GetDBGState(force);2962    // If the processor is not in Streaming SVE Mode currently, these2963    // two will fail to read.  Don't return that as an error, it will2964    // be the most common case.2965    if (CPUHasSME()) {2966      GetSVEState(force);2967      GetSMEState(force);2968    }2969    return retval;2970  }2971  case e_regSetGPR:2972    return GetGPRState(force);2973  case e_regSetVFP:2974    return GetVFPState(force);2975  case e_regSetSVE:2976    return GetSVEState(force);2977  case e_regSetSME:2978    return GetSMEState(force);2979  case e_regSetEXC:2980    return GetEXCState(force);2981  case e_regSetDBG:2982    return GetDBGState(force);2983  default:2984    break;2985  }2986  return KERN_INVALID_ARGUMENT;2987}2988 2989kern_return_t DNBArchMachARM64::SetRegisterState(int set) {2990  // Make sure we have a valid context to set.2991  kern_return_t err = GetRegisterState(set, false);2992  if (err != KERN_SUCCESS)2993    return err;2994 2995  switch (set) {2996  case e_regSetALL: {2997    kern_return_t ret =2998        SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false);2999    if (CPUHasSME()) {3000      SetSVEState();3001      SetSMEState();3002    }3003    return ret;3004  }3005  case e_regSetGPR:3006    return SetGPRState();3007  case e_regSetVFP:3008    return SetVFPState();3009  case e_regSetSVE:3010    return SetSVEState();3011  case e_regSetSME:3012    return SetSMEState();3013  case e_regSetEXC:3014    return SetEXCState();3015  case e_regSetDBG:3016    return SetDBGState(false);3017  default:3018    break;3019  }3020  return KERN_INVALID_ARGUMENT;3021}3022 3023bool DNBArchMachARM64::RegisterSetStateIsValid(int set) const {3024  return m_state.RegsAreValid(set);3025}3026 3027nub_size_t DNBArchMachARM64::GetRegisterContext(void *buf, nub_size_t buf_len) {3028  nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) +3029                    sizeof(m_state.context.exc);3030  const bool cpu_has_sme = CPUHasSME();3031  if (cpu_has_sme) {3032    size += sizeof(m_state.context.sve);3033    // ZA register is in a std::vector<uint8_t> so we need to add3034    // the sizes of the SME manually.3035    size += ARM_SME_STATE_COUNT * sizeof(uint32_t);3036    size += m_state.context.sme.za.size();3037    size += ARM_SME2_STATE_COUNT * sizeof(uint32_t);3038  }3039 3040  if (buf && buf_len) {3041    if (size > buf_len)3042      size = buf_len;3043 3044    bool force = false;3045    if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force))3046      return 0;3047    // Don't error out if SME/SVE fail to read. These can only be read3048    // when the process is in Streaming SVE Mode, so the failure to read3049    // them will be common.3050    if (cpu_has_sme) {3051      GetSVEState(force);3052      GetSMEState(force);3053    }3054 3055    // Copy each struct individually to avoid any padding that might be between3056    // the structs in m_state.context3057    uint8_t *p = (uint8_t *)buf;3058    ::memcpy(p, &m_state.context.gpr, sizeof(m_state.context.gpr));3059    p += sizeof(m_state.context.gpr);3060    ::memcpy(p, &m_state.context.vfp, sizeof(m_state.context.vfp));3061    p += sizeof(m_state.context.vfp);3062    if (cpu_has_sme) {3063      ::memcpy(p, &m_state.context.sve, sizeof(m_state.context.sve));3064      p += sizeof(m_state.context.sve);3065 3066      memcpy(p, &m_state.context.sme.svcr,3067             ARM_SME_STATE_COUNT * sizeof(uint32_t));3068      p += ARM_SME_STATE_COUNT * sizeof(uint32_t);3069      memcpy(p, m_state.context.sme.za.data(), m_state.context.sme.za.size());3070      p += m_state.context.sme.za.size();3071      if (CPUHasSME2()) {3072        memcpy(p, &m_state.context.sme.zt0,3073               ARM_SME2_STATE_COUNT * sizeof(uint32_t));3074        p += ARM_SME2_STATE_COUNT * sizeof(uint32_t);3075      }3076    }3077    ::memcpy(p, &m_state.context.exc, sizeof(m_state.context.exc));3078    p += sizeof(m_state.context.exc);3079 3080    size_t bytes_written = p - (uint8_t *)buf;3081    UNUSED_IF_ASSERT_DISABLED(bytes_written);3082    assert(bytes_written == size);3083  }3084  DNBLogThreadedIf(3085      LOG_THREAD,3086      "DNBArchMachARM64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf,3087      buf_len, size);3088  // Return the size of the register context even if NULL was passed in3089  return size;3090}3091 3092nub_size_t DNBArchMachARM64::SetRegisterContext(const void *buf,3093                                                nub_size_t buf_len) {3094  nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) +3095                    sizeof(m_state.context.exc);3096  if (CPUHasSME()) {3097    // m_state.context.za is three status registers, then a std::vector<uint8_t>3098    // for ZA, then zt0, so the size of the data is not statically knowable.3099    nub_size_t sme_size = ARM_SME_STATE_COUNT * sizeof(uint32_t);3100    sme_size += m_state.context.sme.za.size();3101    sme_size += ARM_SME2_STATE_COUNT * sizeof(uint32_t);3102 3103    size += sizeof(m_state.context.sve) + sme_size;3104  }3105 3106  if (buf == NULL || buf_len == 0)3107    size = 0;3108 3109  if (size) {3110    if (size > buf_len)3111      size = buf_len;3112 3113    // Copy each struct individually to avoid any padding that might be between3114    // the structs in m_state.context3115    uint8_t *p = const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(buf));3116    ::memcpy(&m_state.context.gpr, p, sizeof(m_state.context.gpr));3117    p += sizeof(m_state.context.gpr);3118    ::memcpy(&m_state.context.vfp, p, sizeof(m_state.context.vfp));3119    p += sizeof(m_state.context.vfp);3120    if (CPUHasSME()) {3121      memcpy(&m_state.context.sve, p, sizeof(m_state.context.sve));3122      p += sizeof(m_state.context.sve);3123      memcpy(&m_state.context.sme.svcr, p,3124             ARM_SME_STATE_COUNT * sizeof(uint32_t));3125      p += ARM_SME_STATE_COUNT * sizeof(uint32_t);3126      memcpy(m_state.context.sme.za.data(), p, m_state.context.sme.za.size());3127      p += m_state.context.sme.za.size();3128      if (CPUHasSME2()) {3129        memcpy(&m_state.context.sme.zt0, p,3130               ARM_SME2_STATE_COUNT * sizeof(uint32_t));3131        p += ARM_SME2_STATE_COUNT * sizeof(uint32_t);3132      }3133    }3134    ::memcpy(&m_state.context.exc, p, sizeof(m_state.context.exc));3135    p += sizeof(m_state.context.exc);3136 3137    size_t bytes_written = p - reinterpret_cast<const uint8_t *>(buf);3138    UNUSED_IF_ASSERT_DISABLED(bytes_written);3139    assert(bytes_written == size);3140    SetGPRState();3141    SetVFPState();3142    if (CPUHasSME()) {3143      SetSVEState();3144      SetSMEState();3145    }3146    SetEXCState();3147  }3148  DNBLogThreadedIf(3149      LOG_THREAD,3150      "DNBArchMachARM64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf,3151      buf_len, size);3152  return size;3153}3154 3155uint32_t DNBArchMachARM64::SaveRegisterState() {3156  kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());3157  DNBLogThreadedIf(3158      LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "3159                  "(SetGPRState() for stop_count = %u)",3160      m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());3161 3162  // Always re-read the registers because above we call thread_abort_safely();3163  bool force = true;3164 3165  if ((kret = GetGPRState(force)) != KERN_SUCCESS) {3166    DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () "3167                                 "error: GPR regs failed to read: %u ",3168                     kret);3169  } else if ((kret = GetVFPState(force)) != KERN_SUCCESS) {3170    DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () "3171                                 "error: %s regs failed to read: %u",3172                     "VFP", kret);3173  } else {3174    if (CPUHasSME()) {3175      // These can fail when processor is not in streaming SVE mode,3176      // and that failure should be ignored.3177      GetSVEState(force);3178      GetSMEState(force);3179    }3180    const uint32_t save_id = GetNextRegisterStateSaveID();3181    m_saved_register_states[save_id] = m_state.context;3182    return save_id;3183  }3184  return UINT32_MAX;3185}3186 3187bool DNBArchMachARM64::RestoreRegisterState(uint32_t save_id) {3188  SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);3189  if (pos != m_saved_register_states.end()) {3190    m_state.context.gpr = pos->second.gpr;3191    m_state.context.vfp = pos->second.vfp;3192    kern_return_t kret;3193    bool success = true;3194    if ((kret = SetGPRState()) != KERN_SUCCESS) {3195      DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState "3196                                   "(save_id = %u) error: GPR regs failed to "3197                                   "write: %u",3198                       save_id, kret);3199      success = false;3200    } else if ((kret = SetVFPState()) != KERN_SUCCESS) {3201      DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState "3202                                   "(save_id = %u) error: %s regs failed to "3203                                   "write: %u",3204                       save_id, "VFP", kret);3205      success = false;3206    }3207    if (CPUHasSME()) {3208      // These can fail when processor is not in streaming SVE mode,3209      // and that failure should be ignored.3210      SetSVEState();3211      SetSMEState();3212    }3213    m_saved_register_states.erase(pos);3214    return success;3215  }3216  return false;3217}3218 3219#endif // #if defined (ARM_THREAD_STATE64_COUNT)3220#endif // #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)3221