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