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