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/minidump/RegisterContextMinidump_ARM.cpp
96383 views
1
//===-- RegisterContextMinidump_ARM.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 "RegisterContextMinidump_ARM.h"
10
11
#include "Utility/ARM_DWARF_Registers.h"
12
#include "Utility/ARM_ehframe_Registers.h"
13
#include "lldb/Utility/RegisterValue.h"
14
#include "lldb/Utility/DataExtractor.h"
15
#include "lldb/Utility/LLDBAssert.h"
16
#include "lldb/lldb-enumerations.h"
17
18
// C includes
19
#include <cassert>
20
21
// C++ includes
22
23
using namespace lldb;
24
using namespace lldb_private;
25
using namespace minidump;
26
27
#define INV LLDB_INVALID_REGNUM
28
#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
29
30
#define DEF_R(i) \
31
{ \
32
"r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \
33
{ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr, \
34
nullptr, \
35
}
36
37
#define DEF_R_ARG(i, n) \
38
{ \
39
"r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \
40
{ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, \
41
reg_r##i}, \
42
nullptr, nullptr, nullptr, \
43
}
44
45
#define DEF_D(i) \
46
{ \
47
"d" #i, nullptr, 8, OFFSET(d) + i * 8, eEncodingVector, \
48
eFormatVectorOfUInt8, {dwarf_d##i, dwarf_d##i, INV, INV, reg_d##i}, \
49
nullptr, nullptr, nullptr, \
50
}
51
52
#define DEF_S(i) \
53
{ \
54
"s" #i, nullptr, 4, OFFSET(s) + i * 4, eEncodingIEEE754, eFormatFloat, \
55
{dwarf_s##i, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr, \
56
nullptr, \
57
}
58
59
#define DEF_Q(i) \
60
{ \
61
"q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector, \
62
eFormatVectorOfUInt8, {dwarf_q##i, dwarf_q##i, INV, INV, reg_q##i}, \
63
nullptr, nullptr, nullptr, \
64
}
65
66
// Zero based LLDB register numbers for this register context
67
enum {
68
// General Purpose Registers
69
reg_r0,
70
reg_r1,
71
reg_r2,
72
reg_r3,
73
reg_r4,
74
reg_r5,
75
reg_r6,
76
reg_r7,
77
reg_r8,
78
reg_r9,
79
reg_r10,
80
reg_r11,
81
reg_r12,
82
reg_sp,
83
reg_lr,
84
reg_pc,
85
reg_cpsr,
86
// Floating Point Registers
87
reg_fpscr,
88
reg_d0,
89
reg_d1,
90
reg_d2,
91
reg_d3,
92
reg_d4,
93
reg_d5,
94
reg_d6,
95
reg_d7,
96
reg_d8,
97
reg_d9,
98
reg_d10,
99
reg_d11,
100
reg_d12,
101
reg_d13,
102
reg_d14,
103
reg_d15,
104
reg_d16,
105
reg_d17,
106
reg_d18,
107
reg_d19,
108
reg_d20,
109
reg_d21,
110
reg_d22,
111
reg_d23,
112
reg_d24,
113
reg_d25,
114
reg_d26,
115
reg_d27,
116
reg_d28,
117
reg_d29,
118
reg_d30,
119
reg_d31,
120
reg_s0,
121
reg_s1,
122
reg_s2,
123
reg_s3,
124
reg_s4,
125
reg_s5,
126
reg_s6,
127
reg_s7,
128
reg_s8,
129
reg_s9,
130
reg_s10,
131
reg_s11,
132
reg_s12,
133
reg_s13,
134
reg_s14,
135
reg_s15,
136
reg_s16,
137
reg_s17,
138
reg_s18,
139
reg_s19,
140
reg_s20,
141
reg_s21,
142
reg_s22,
143
reg_s23,
144
reg_s24,
145
reg_s25,
146
reg_s26,
147
reg_s27,
148
reg_s28,
149
reg_s29,
150
reg_s30,
151
reg_s31,
152
reg_q0,
153
reg_q1,
154
reg_q2,
155
reg_q3,
156
reg_q4,
157
reg_q5,
158
reg_q6,
159
reg_q7,
160
reg_q8,
161
reg_q9,
162
reg_q10,
163
reg_q11,
164
reg_q12,
165
reg_q13,
166
reg_q14,
167
reg_q15,
168
k_num_regs
169
};
170
171
static RegisterInfo g_reg_info_apple_fp = {
172
"fp",
173
"r7",
174
4,
175
OFFSET(r) + 7 * 4,
176
eEncodingUint,
177
eFormatHex,
178
{ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
179
nullptr,
180
nullptr,
181
nullptr,
182
};
183
184
static RegisterInfo g_reg_info_fp = {
185
"fp",
186
"r11",
187
4,
188
OFFSET(r) + 11 * 4,
189
eEncodingUint,
190
eFormatHex,
191
{ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
192
nullptr,
193
nullptr,
194
nullptr,
195
};
196
197
// Register info definitions for this register context
198
static RegisterInfo g_reg_infos[] = {
199
DEF_R_ARG(0, 1),
200
DEF_R_ARG(1, 2),
201
DEF_R_ARG(2, 3),
202
DEF_R_ARG(3, 4),
203
DEF_R(4),
204
DEF_R(5),
205
DEF_R(6),
206
DEF_R(7),
207
DEF_R(8),
208
DEF_R(9),
209
DEF_R(10),
210
DEF_R(11),
211
DEF_R(12),
212
{"sp",
213
"r13",
214
4,
215
OFFSET(r) + 13 * 4,
216
eEncodingUint,
217
eFormatHex,
218
{ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
219
nullptr,
220
nullptr,
221
nullptr,
222
},
223
{"lr",
224
"r14",
225
4,
226
OFFSET(r) + 14 * 4,
227
eEncodingUint,
228
eFormatHex,
229
{ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
230
nullptr,
231
nullptr,
232
nullptr,
233
},
234
{"pc",
235
"r15",
236
4,
237
OFFSET(r) + 15 * 4,
238
eEncodingUint,
239
eFormatHex,
240
{ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
241
nullptr,
242
nullptr,
243
nullptr,
244
},
245
{"cpsr",
246
"psr",
247
4,
248
OFFSET(cpsr),
249
eEncodingUint,
250
eFormatHex,
251
{ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
252
nullptr,
253
nullptr,
254
nullptr,
255
},
256
{"fpscr",
257
nullptr,
258
8,
259
OFFSET(fpscr),
260
eEncodingUint,
261
eFormatHex,
262
{INV, INV, INV, INV, reg_fpscr},
263
nullptr,
264
nullptr,
265
nullptr,
266
},
267
DEF_D(0),
268
DEF_D(1),
269
DEF_D(2),
270
DEF_D(3),
271
DEF_D(4),
272
DEF_D(5),
273
DEF_D(6),
274
DEF_D(7),
275
DEF_D(8),
276
DEF_D(9),
277
DEF_D(10),
278
DEF_D(11),
279
DEF_D(12),
280
DEF_D(13),
281
DEF_D(14),
282
DEF_D(15),
283
DEF_D(16),
284
DEF_D(17),
285
DEF_D(18),
286
DEF_D(19),
287
DEF_D(20),
288
DEF_D(21),
289
DEF_D(22),
290
DEF_D(23),
291
DEF_D(24),
292
DEF_D(25),
293
DEF_D(26),
294
DEF_D(27),
295
DEF_D(28),
296
DEF_D(29),
297
DEF_D(30),
298
DEF_D(31),
299
DEF_S(0),
300
DEF_S(1),
301
DEF_S(2),
302
DEF_S(3),
303
DEF_S(4),
304
DEF_S(5),
305
DEF_S(6),
306
DEF_S(7),
307
DEF_S(8),
308
DEF_S(9),
309
DEF_S(10),
310
DEF_S(11),
311
DEF_S(12),
312
DEF_S(13),
313
DEF_S(14),
314
DEF_S(15),
315
DEF_S(16),
316
DEF_S(17),
317
DEF_S(18),
318
DEF_S(19),
319
DEF_S(20),
320
DEF_S(21),
321
DEF_S(22),
322
DEF_S(23),
323
DEF_S(24),
324
DEF_S(25),
325
DEF_S(26),
326
DEF_S(27),
327
DEF_S(28),
328
DEF_S(29),
329
DEF_S(30),
330
DEF_S(31),
331
DEF_Q(0),
332
DEF_Q(1),
333
DEF_Q(2),
334
DEF_Q(3),
335
DEF_Q(4),
336
DEF_Q(5),
337
DEF_Q(6),
338
DEF_Q(7),
339
DEF_Q(8),
340
DEF_Q(9),
341
DEF_Q(10),
342
DEF_Q(11),
343
DEF_Q(12),
344
DEF_Q(13),
345
DEF_Q(14),
346
DEF_Q(15)};
347
348
constexpr size_t k_num_reg_infos = std::size(g_reg_infos);
349
350
// ARM general purpose registers.
351
const uint32_t g_gpr_regnums[] = {
352
reg_r0,
353
reg_r1,
354
reg_r2,
355
reg_r3,
356
reg_r4,
357
reg_r5,
358
reg_r6,
359
reg_r7,
360
reg_r8,
361
reg_r9,
362
reg_r10,
363
reg_r11,
364
reg_r12,
365
reg_sp,
366
reg_lr,
367
reg_pc,
368
reg_cpsr,
369
LLDB_INVALID_REGNUM // register sets need to end with this flag
370
};
371
const uint32_t g_fpu_regnums[] = {
372
reg_fpscr,
373
reg_d0,
374
reg_d1,
375
reg_d2,
376
reg_d3,
377
reg_d4,
378
reg_d5,
379
reg_d6,
380
reg_d7,
381
reg_d8,
382
reg_d9,
383
reg_d10,
384
reg_d11,
385
reg_d12,
386
reg_d13,
387
reg_d14,
388
reg_d15,
389
reg_d16,
390
reg_d17,
391
reg_d18,
392
reg_d19,
393
reg_d20,
394
reg_d21,
395
reg_d22,
396
reg_d23,
397
reg_d24,
398
reg_d25,
399
reg_d26,
400
reg_d27,
401
reg_d28,
402
reg_d29,
403
reg_d30,
404
reg_d31,
405
reg_s0,
406
reg_s1,
407
reg_s2,
408
reg_s3,
409
reg_s4,
410
reg_s5,
411
reg_s6,
412
reg_s7,
413
reg_s8,
414
reg_s9,
415
reg_s10,
416
reg_s11,
417
reg_s12,
418
reg_s13,
419
reg_s14,
420
reg_s15,
421
reg_s16,
422
reg_s17,
423
reg_s18,
424
reg_s19,
425
reg_s20,
426
reg_s21,
427
reg_s22,
428
reg_s23,
429
reg_s24,
430
reg_s25,
431
reg_s26,
432
reg_s27,
433
reg_s28,
434
reg_s29,
435
reg_s30,
436
reg_s31,
437
reg_q0,
438
reg_q1,
439
reg_q2,
440
reg_q3,
441
reg_q4,
442
reg_q5,
443
reg_q6,
444
reg_q7,
445
reg_q8,
446
reg_q9,
447
reg_q10,
448
reg_q11,
449
reg_q12,
450
reg_q13,
451
reg_q14,
452
reg_q15,
453
LLDB_INVALID_REGNUM // register sets need to end with this flag
454
};
455
456
// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
457
constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;
458
constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;
459
460
static RegisterSet g_reg_sets[] = {
461
{"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
462
{"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
463
};
464
465
constexpr size_t k_num_reg_sets = std::size(g_reg_sets);
466
467
RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(
468
lldb_private::Thread &thread, const DataExtractor &data, bool apple)
469
: RegisterContext(thread, 0), m_apple(apple) {
470
lldb::offset_t offset = 0;
471
m_regs.context_flags = data.GetU32(&offset);
472
for (unsigned i = 0; i < std::size(m_regs.r); ++i)
473
m_regs.r[i] = data.GetU32(&offset);
474
m_regs.cpsr = data.GetU32(&offset);
475
m_regs.fpscr = data.GetU64(&offset);
476
for (unsigned i = 0; i < std::size(m_regs.d); ++i)
477
m_regs.d[i] = data.GetU64(&offset);
478
lldbassert(k_num_regs == k_num_reg_infos);
479
}
480
481
size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() {
482
return k_num_regs;
483
}
484
485
// Used for unit testing so we can verify register info is filled in for
486
// all register flavors (DWARF, EH Frame, generic, etc).
487
size_t RegisterContextMinidump_ARM::GetRegisterCount() {
488
return GetRegisterCountStatic();
489
}
490
491
// Used for unit testing so we can verify register info is filled in.
492
const RegisterInfo *
493
RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg,
494
bool apple) {
495
if (reg < k_num_reg_infos) {
496
if (apple) {
497
if (reg == reg_r7)
498
return &g_reg_info_apple_fp;
499
} else {
500
if (reg == reg_r11)
501
return &g_reg_info_fp;
502
}
503
return &g_reg_infos[reg];
504
}
505
return nullptr;
506
}
507
508
const RegisterInfo *
509
RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
510
return GetRegisterInfoAtIndexStatic(reg, m_apple);
511
}
512
513
size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
514
return k_num_reg_sets;
515
}
516
517
const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
518
if (set < k_num_reg_sets)
519
return &g_reg_sets[set];
520
return nullptr;
521
}
522
523
const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {
524
if (reg < k_num_reg_infos)
525
return g_reg_infos[reg].name;
526
return nullptr;
527
}
528
529
bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
530
RegisterValue &reg_value) {
531
Status error;
532
reg_value.SetFromMemoryData(
533
*reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
534
reg_info->byte_size, lldb::eByteOrderLittle, error);
535
return error.Success();
536
}
537
538
bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,
539
const RegisterValue &) {
540
return false;
541
}
542
543
uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(
544
lldb::RegisterKind kind, uint32_t num) {
545
for (size_t i = 0; i < k_num_regs; ++i) {
546
if (g_reg_infos[i].kinds[kind] == num)
547
return i;
548
}
549
return LLDB_INVALID_REGNUM;
550
}
551
552