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