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
35 using namespace lldb;
36 using 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
77 static 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
85 static 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
94 static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
95
96 static size_t k_num_register_infos =
97 llvm::array_lengthof(g_register_infos_arm64_le);
98
RegisterContextDarwin_arm64(Thread & thread,uint32_t concrete_frame_idx)99 RegisterContextDarwin_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
~RegisterContextDarwin_arm64()110 RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
111
InvalidateAllRegisters()112 void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
113 InvalidateAllRegisterStates();
114 }
115
GetRegisterCount()116 size_t RegisterContextDarwin_arm64::GetRegisterCount() {
117 assert(k_num_register_infos == k_num_registers);
118 return k_num_registers;
119 }
120
121 const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)122 RegisterContextDarwin_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
GetRegisterInfosCount()129 size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
130 return k_num_register_infos;
131 }
132
GetRegisterInfos()133 const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
134 return g_register_infos_arm64_le;
135 }
136
137 // Number of registers in each register set
138 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
139 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
140 const 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 //----------------------------------------------------------------------
147 static 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
154 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
155
GetRegisterSetCount()156 size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
157 return k_num_regsets;
158 }
159
GetRegisterSet(size_t reg_set)160 const 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 //----------------------------------------------------------------------
GetSetForNativeRegNum(int reg)169 int 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
ReadGPR(bool force)179 int 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
ReadFPU(bool force)187 int 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
ReadEXC(bool force)195 int 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
ReadDBG(bool force)203 int 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
WriteGPR()211 int 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
WriteFPU()222 int 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
WriteEXC()233 int 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
WriteDBG()244 int 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
ReadRegisterSet(uint32_t set,bool force)255 int 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
WriteRegisterSet(uint32_t set)271 int 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
LogDBGRegisters(Log * log,const DBG & dbg)290 void 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
ReadRegister(const RegisterInfo * reg_info,RegisterValue & value)300 bool 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
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & value)542 bool 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
ReadAllRegisterValues(lldb::DataBufferSP & data_sp)650 bool 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
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)668 bool 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
ConvertRegisterKindToRegisterNumber(RegisterKind kind,uint32_t reg)691 uint32_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
NumSupportedHardwareWatchpoints()925 uint32_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
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)944 uint32_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
ClearHardwareWatchpoint(uint32_t hw_index)1024 bool 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