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