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