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