1//===-- RegisterContextDarwin_x86_64.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 <cinttypes>
10#include <cstdarg>
11#include <cstddef>
12
13#include <memory>
14
15#include "lldb/Utility/DataBufferHeap.h"
16#include "lldb/Utility/DataExtractor.h"
17#include "lldb/Utility/Endian.h"
18#include "lldb/Utility/Log.h"
19#include "lldb/Utility/RegisterValue.h"
20#include "lldb/Utility/Scalar.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/Support/Compiler.h"
23
24#include "RegisterContextDarwin_x86_64.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29enum {
30 gpr_rax = 0,
31 gpr_rbx,
32 gpr_rcx,
33 gpr_rdx,
34 gpr_rdi,
35 gpr_rsi,
36 gpr_rbp,
37 gpr_rsp,
38 gpr_r8,
39 gpr_r9,
40 gpr_r10,
41 gpr_r11,
42 gpr_r12,
43 gpr_r13,
44 gpr_r14,
45 gpr_r15,
46 gpr_rip,
47 gpr_rflags,
48 gpr_cs,
49 gpr_fs,
50 gpr_gs,
51
52 fpu_fcw,
53 fpu_fsw,
54 fpu_ftw,
55 fpu_fop,
56 fpu_ip,
57 fpu_cs,
58 fpu_dp,
59 fpu_ds,
60 fpu_mxcsr,
61 fpu_mxcsrmask,
62 fpu_stmm0,
63 fpu_stmm1,
64 fpu_stmm2,
65 fpu_stmm3,
66 fpu_stmm4,
67 fpu_stmm5,
68 fpu_stmm6,
69 fpu_stmm7,
70 fpu_xmm0,
71 fpu_xmm1,
72 fpu_xmm2,
73 fpu_xmm3,
74 fpu_xmm4,
75 fpu_xmm5,
76 fpu_xmm6,
77 fpu_xmm7,
78 fpu_xmm8,
79 fpu_xmm9,
80 fpu_xmm10,
81 fpu_xmm11,
82 fpu_xmm12,
83 fpu_xmm13,
84 fpu_xmm14,
85 fpu_xmm15,
86
87 exc_trapno,
88 exc_err,
89 exc_faultvaddr,
90
91 k_num_registers,
92
93 // Aliases
94 fpu_fctrl = fpu_fcw,
95 fpu_fstat = fpu_fsw,
96 fpu_ftag = fpu_ftw,
97 fpu_fiseg = fpu_cs,
98 fpu_fioff = fpu_ip,
99 fpu_foseg = fpu_ds,
100 fpu_fooff = fpu_dp
101};
102
103enum ehframe_dwarf_regnums {
104 ehframe_dwarf_gpr_rax = 0,
105 ehframe_dwarf_gpr_rdx,
106 ehframe_dwarf_gpr_rcx,
107 ehframe_dwarf_gpr_rbx,
108 ehframe_dwarf_gpr_rsi,
109 ehframe_dwarf_gpr_rdi,
110 ehframe_dwarf_gpr_rbp,
111 ehframe_dwarf_gpr_rsp,
112 ehframe_dwarf_gpr_r8,
113 ehframe_dwarf_gpr_r9,
114 ehframe_dwarf_gpr_r10,
115 ehframe_dwarf_gpr_r11,
116 ehframe_dwarf_gpr_r12,
117 ehframe_dwarf_gpr_r13,
118 ehframe_dwarf_gpr_r14,
119 ehframe_dwarf_gpr_r15,
120 ehframe_dwarf_gpr_rip,
121 ehframe_dwarf_fpu_xmm0,
122 ehframe_dwarf_fpu_xmm1,
123 ehframe_dwarf_fpu_xmm2,
124 ehframe_dwarf_fpu_xmm3,
125 ehframe_dwarf_fpu_xmm4,
126 ehframe_dwarf_fpu_xmm5,
127 ehframe_dwarf_fpu_xmm6,
128 ehframe_dwarf_fpu_xmm7,
129 ehframe_dwarf_fpu_xmm8,
130 ehframe_dwarf_fpu_xmm9,
131 ehframe_dwarf_fpu_xmm10,
132 ehframe_dwarf_fpu_xmm11,
133 ehframe_dwarf_fpu_xmm12,
134 ehframe_dwarf_fpu_xmm13,
135 ehframe_dwarf_fpu_xmm14,
136 ehframe_dwarf_fpu_xmm15,
137 ehframe_dwarf_fpu_stmm0,
138 ehframe_dwarf_fpu_stmm1,
139 ehframe_dwarf_fpu_stmm2,
140 ehframe_dwarf_fpu_stmm3,
141 ehframe_dwarf_fpu_stmm4,
142 ehframe_dwarf_fpu_stmm5,
143 ehframe_dwarf_fpu_stmm6,
144 ehframe_dwarf_fpu_stmm7
145
146};
147
148#define GPR_OFFSET(reg) \
149 (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::GPR, reg))
150#define FPU_OFFSET(reg) \
151 (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::FPU, reg) + \
152 sizeof(RegisterContextDarwin_x86_64::GPR))
153#define EXC_OFFSET(reg) \
154 (LLVM_EXTENSION offsetof(RegisterContextDarwin_x86_64::EXC, reg) + \
155 sizeof(RegisterContextDarwin_x86_64::GPR) + \
156 sizeof(RegisterContextDarwin_x86_64::FPU))
157
158// These macros will auto define the register name, alt name, register size,
159// register offset, encoding, format and native register. This ensures that the
160// register state structures are defined correctly and have the correct sizes
161// and offsets.
162#define DEFINE_GPR(reg, alt) \
163 #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *) NULL)->reg), \
164 GPR_OFFSET(reg), eEncodingUint, eFormatHex
165#define DEFINE_FPU_UINT(reg) \
166 #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *) NULL)->reg), \
167 FPU_OFFSET(reg), eEncodingUint, eFormatHex
168#define DEFINE_FPU_VECT(reg, i) \
169 #reg #i, NULL, \
170 sizeof(((RegisterContextDarwin_x86_64::FPU *) NULL)->reg[i].bytes), \
171 FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, \
172 {ehframe_dwarf_fpu_##reg##i, \
173 ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, \
174 LLDB_INVALID_REGNUM, fpu_##reg##i }, \
175 nullptr, nullptr, nullptr,
176#define DEFINE_EXC(reg) \
177 #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *) NULL)->reg), \
178 EXC_OFFSET(reg), eEncodingUint, eFormatHex
179
180#define REG_CONTEXT_SIZE \
181 (sizeof(RegisterContextDarwin_x86_64::GPR) + \
182 sizeof(RegisterContextDarwin_x86_64::FPU) + \
183 sizeof(RegisterContextDarwin_x86_64::EXC))
184
185// General purpose registers for 64 bit
186static RegisterInfo g_register_infos[] = {
187 // Macro auto defines most stuff EH_FRAME DWARF
188 // GENERIC PROCESS PLUGIN LLDB
189 // =============================== ======================
190 // =================== ========================== ====================
191 // ===================
192 {DEFINE_GPR(rax, nullptr),
193 .kinds: {ehframe_dwarf_gpr_rax, ehframe_dwarf_gpr_rax, LLDB_INVALID_REGNUM,
194 LLDB_INVALID_REGNUM, gpr_rax},
195 .value_regs: nullptr,
196 .invalidate_regs: nullptr,
197 .flags_type: nullptr,
198 },
199 {DEFINE_GPR(rbx, nullptr),
200 .kinds: {ehframe_dwarf_gpr_rbx, ehframe_dwarf_gpr_rbx, LLDB_INVALID_REGNUM,
201 LLDB_INVALID_REGNUM, gpr_rbx},
202 .value_regs: nullptr,
203 .invalidate_regs: nullptr,
204 .flags_type: nullptr,
205 },
206 {DEFINE_GPR(rcx, nullptr),
207 .kinds: {ehframe_dwarf_gpr_rcx, ehframe_dwarf_gpr_rcx, LLDB_INVALID_REGNUM,
208 LLDB_INVALID_REGNUM, gpr_rcx},
209 .value_regs: nullptr,
210 .invalidate_regs: nullptr,
211 .flags_type: nullptr,
212 },
213 {DEFINE_GPR(rdx, nullptr),
214 .kinds: {ehframe_dwarf_gpr_rdx, ehframe_dwarf_gpr_rdx, LLDB_INVALID_REGNUM,
215 LLDB_INVALID_REGNUM, gpr_rdx},
216 .value_regs: nullptr,
217 .invalidate_regs: nullptr,
218 .flags_type: nullptr,
219 },
220 {DEFINE_GPR(rdi, nullptr),
221 .kinds: {ehframe_dwarf_gpr_rdi, ehframe_dwarf_gpr_rdi, LLDB_INVALID_REGNUM,
222 LLDB_INVALID_REGNUM, gpr_rdi},
223 .value_regs: nullptr,
224 .invalidate_regs: nullptr,
225 .flags_type: nullptr,
226 },
227 {DEFINE_GPR(rsi, nullptr),
228 .kinds: {ehframe_dwarf_gpr_rsi, ehframe_dwarf_gpr_rsi, LLDB_INVALID_REGNUM,
229 LLDB_INVALID_REGNUM, gpr_rsi},
230 .value_regs: nullptr,
231 .invalidate_regs: nullptr,
232 .flags_type: nullptr,
233 },
234 {DEFINE_GPR(rbp, "fp"),
235 .kinds: {ehframe_dwarf_gpr_rbp, ehframe_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP,
236 LLDB_INVALID_REGNUM, gpr_rbp},
237 .value_regs: nullptr,
238 .invalidate_regs: nullptr,
239 .flags_type: nullptr,
240 },
241 {DEFINE_GPR(rsp, "sp"),
242 .kinds: {ehframe_dwarf_gpr_rsp, ehframe_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP,
243 LLDB_INVALID_REGNUM, gpr_rsp},
244 .value_regs: nullptr,
245 .invalidate_regs: nullptr,
246 .flags_type: nullptr,
247 },
248 {DEFINE_GPR(r8, nullptr),
249 .kinds: {ehframe_dwarf_gpr_r8, ehframe_dwarf_gpr_r8, LLDB_INVALID_REGNUM,
250 LLDB_INVALID_REGNUM, gpr_r8},
251 .value_regs: nullptr,
252 .invalidate_regs: nullptr,
253 .flags_type: nullptr,
254 },
255 {DEFINE_GPR(r9, nullptr),
256 .kinds: {ehframe_dwarf_gpr_r9, ehframe_dwarf_gpr_r9, LLDB_INVALID_REGNUM,
257 LLDB_INVALID_REGNUM, gpr_r9},
258 .value_regs: nullptr,
259 .invalidate_regs: nullptr,
260 .flags_type: nullptr,
261 },
262 {DEFINE_GPR(r10, nullptr),
263 .kinds: {ehframe_dwarf_gpr_r10, ehframe_dwarf_gpr_r10, LLDB_INVALID_REGNUM,
264 LLDB_INVALID_REGNUM, gpr_r10},
265 .value_regs: nullptr,
266 .invalidate_regs: nullptr,
267 .flags_type: nullptr,
268 },
269 {DEFINE_GPR(r11, nullptr),
270 .kinds: {ehframe_dwarf_gpr_r11, ehframe_dwarf_gpr_r11, LLDB_INVALID_REGNUM,
271 LLDB_INVALID_REGNUM, gpr_r11},
272 .value_regs: nullptr,
273 .invalidate_regs: nullptr,
274 .flags_type: nullptr,
275 },
276 {DEFINE_GPR(r12, nullptr),
277 .kinds: {ehframe_dwarf_gpr_r12, ehframe_dwarf_gpr_r12, LLDB_INVALID_REGNUM,
278 LLDB_INVALID_REGNUM, gpr_r12},
279 .value_regs: nullptr,
280 .invalidate_regs: nullptr,
281 .flags_type: nullptr,
282 },
283 {DEFINE_GPR(r13, nullptr),
284 .kinds: {ehframe_dwarf_gpr_r13, ehframe_dwarf_gpr_r13, LLDB_INVALID_REGNUM,
285 LLDB_INVALID_REGNUM, gpr_r13},
286 .value_regs: nullptr,
287 .invalidate_regs: nullptr,
288 .flags_type: nullptr,
289 },
290 {DEFINE_GPR(r14, nullptr),
291 .kinds: {ehframe_dwarf_gpr_r14, ehframe_dwarf_gpr_r14, LLDB_INVALID_REGNUM,
292 LLDB_INVALID_REGNUM, gpr_r14},
293 .value_regs: nullptr,
294 .invalidate_regs: nullptr,
295 .flags_type: nullptr,
296 },
297 {DEFINE_GPR(r15, nullptr),
298 .kinds: {ehframe_dwarf_gpr_r15, ehframe_dwarf_gpr_r15, LLDB_INVALID_REGNUM,
299 LLDB_INVALID_REGNUM, gpr_r15},
300 .value_regs: nullptr,
301 .invalidate_regs: nullptr,
302 .flags_type: nullptr,
303 },
304 {DEFINE_GPR(rip, "pc"),
305 .kinds: {ehframe_dwarf_gpr_rip, ehframe_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC,
306 LLDB_INVALID_REGNUM, gpr_rip},
307 .value_regs: nullptr,
308 .invalidate_regs: nullptr,
309 .flags_type: nullptr,
310 },
311 {DEFINE_GPR(rflags, "flags"),
312 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
313 LLDB_INVALID_REGNUM, gpr_rflags},
314 .value_regs: nullptr,
315 .invalidate_regs: nullptr,
316 .flags_type: nullptr,
317 },
318 {DEFINE_GPR(cs, nullptr),
319 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
320 LLDB_INVALID_REGNUM, gpr_cs},
321 .value_regs: nullptr,
322 .invalidate_regs: nullptr,
323 .flags_type: nullptr,
324 },
325 {DEFINE_GPR(fs, nullptr),
326 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
327 LLDB_INVALID_REGNUM, gpr_fs},
328 .value_regs: nullptr,
329 .invalidate_regs: nullptr,
330 .flags_type: nullptr,
331 },
332 {DEFINE_GPR(gs, nullptr),
333 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
334 LLDB_INVALID_REGNUM, gpr_gs},
335 .value_regs: nullptr,
336 .invalidate_regs: nullptr,
337 .flags_type: nullptr,
338 },
339
340 {DEFINE_FPU_UINT(fcw),
341 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
342 LLDB_INVALID_REGNUM, fpu_fcw},
343 .value_regs: nullptr,
344 .invalidate_regs: nullptr,
345 .flags_type: nullptr,
346 },
347 {DEFINE_FPU_UINT(fsw),
348 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
349 LLDB_INVALID_REGNUM, fpu_fsw},
350 .value_regs: nullptr,
351 .invalidate_regs: nullptr,
352 .flags_type: nullptr,
353 },
354 {DEFINE_FPU_UINT(ftw),
355 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
356 LLDB_INVALID_REGNUM, fpu_ftw},
357 .value_regs: nullptr,
358 .invalidate_regs: nullptr,
359 .flags_type: nullptr,
360 },
361 {DEFINE_FPU_UINT(fop),
362 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
363 LLDB_INVALID_REGNUM, fpu_fop},
364 .value_regs: nullptr,
365 .invalidate_regs: nullptr,
366 .flags_type: nullptr,
367 },
368 {DEFINE_FPU_UINT(ip),
369 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
370 LLDB_INVALID_REGNUM, fpu_ip},
371 .value_regs: nullptr,
372 .invalidate_regs: nullptr,
373 .flags_type: nullptr,
374 },
375 {DEFINE_FPU_UINT(cs),
376 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
377 LLDB_INVALID_REGNUM, fpu_cs},
378 .value_regs: nullptr,
379 .invalidate_regs: nullptr,
380 .flags_type: nullptr,
381 },
382 {DEFINE_FPU_UINT(dp),
383 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
384 LLDB_INVALID_REGNUM, fpu_dp},
385 .value_regs: nullptr,
386 .invalidate_regs: nullptr,
387 .flags_type: nullptr,
388 },
389 {DEFINE_FPU_UINT(ds),
390 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
391 LLDB_INVALID_REGNUM, fpu_ds},
392 .value_regs: nullptr,
393 .invalidate_regs: nullptr,
394 .flags_type: nullptr,
395 },
396 {DEFINE_FPU_UINT(mxcsr),
397 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
398 LLDB_INVALID_REGNUM, fpu_mxcsr},
399 .value_regs: nullptr,
400 .invalidate_regs: nullptr,
401 .flags_type: nullptr,
402 },
403 {DEFINE_FPU_UINT(mxcsrmask),
404 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
405 LLDB_INVALID_REGNUM, fpu_mxcsrmask},
406 .value_regs: nullptr,
407 .invalidate_regs: nullptr,
408 .flags_type: nullptr,
409 },
410 {DEFINE_FPU_VECT(stmm, 0)},
411 {DEFINE_FPU_VECT(stmm, 1)},
412 {DEFINE_FPU_VECT(stmm, 2)},
413 {DEFINE_FPU_VECT(stmm, 3)},
414 {DEFINE_FPU_VECT(stmm, 4)},
415 {DEFINE_FPU_VECT(stmm, 5)},
416 {DEFINE_FPU_VECT(stmm, 6)},
417 {DEFINE_FPU_VECT(stmm, 7)},
418 {DEFINE_FPU_VECT(xmm, 0)},
419 {DEFINE_FPU_VECT(xmm, 1)},
420 {DEFINE_FPU_VECT(xmm, 2)},
421 {DEFINE_FPU_VECT(xmm, 3)},
422 {DEFINE_FPU_VECT(xmm, 4)},
423 {DEFINE_FPU_VECT(xmm, 5)},
424 {DEFINE_FPU_VECT(xmm, 6)},
425 {DEFINE_FPU_VECT(xmm, 7)},
426 {DEFINE_FPU_VECT(xmm, 8)},
427 {DEFINE_FPU_VECT(xmm, 9)},
428 {DEFINE_FPU_VECT(xmm, 10)},
429 {DEFINE_FPU_VECT(xmm, 11)},
430 {DEFINE_FPU_VECT(xmm, 12)},
431 {DEFINE_FPU_VECT(xmm, 13)},
432 {DEFINE_FPU_VECT(xmm, 14)},
433 {DEFINE_FPU_VECT(xmm, 15)},
434
435 {DEFINE_EXC(trapno),
436 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
437 LLDB_INVALID_REGNUM, exc_trapno},
438 .value_regs: nullptr,
439 .invalidate_regs: nullptr,
440 .flags_type: nullptr,
441 },
442 {DEFINE_EXC(err),
443 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
444 LLDB_INVALID_REGNUM, exc_err},
445 .value_regs: nullptr,
446 .invalidate_regs: nullptr,
447 .flags_type: nullptr,
448 },
449 {DEFINE_EXC(faultvaddr),
450 .kinds: {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
451 LLDB_INVALID_REGNUM, exc_faultvaddr},
452 .value_regs: nullptr,
453 .invalidate_regs: nullptr,
454 .flags_type: nullptr,
455 }};
456
457static size_t k_num_register_infos = std::size(g_register_infos);
458
459RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64(
460 Thread &thread, uint32_t concrete_frame_idx)
461 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
462 uint32_t i;
463 for (i = 0; i < kNumErrors; i++) {
464 gpr_errs[i] = -1;
465 fpu_errs[i] = -1;
466 exc_errs[i] = -1;
467 }
468}
469
470RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() = default;
471
472void RegisterContextDarwin_x86_64::InvalidateAllRegisters() {
473 InvalidateAllRegisterStates();
474}
475
476size_t RegisterContextDarwin_x86_64::GetRegisterCount() {
477 assert(k_num_register_infos == k_num_registers);
478 return k_num_registers;
479}
480
481const RegisterInfo *
482RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex(size_t reg) {
483 assert(k_num_register_infos == k_num_registers);
484 if (reg < k_num_registers)
485 return &g_register_infos[reg];
486 return nullptr;
487}
488
489size_t RegisterContextDarwin_x86_64::GetRegisterInfosCount() {
490 return k_num_register_infos;
491}
492
493const lldb_private::RegisterInfo *
494RegisterContextDarwin_x86_64::GetRegisterInfos() {
495 return g_register_infos;
496}
497
498static uint32_t g_gpr_regnums[] = {
499 gpr_rax, gpr_rbx, gpr_rcx, gpr_rdx, gpr_rdi, gpr_rsi, gpr_rbp,
500 gpr_rsp, gpr_r8, gpr_r9, gpr_r10, gpr_r11, gpr_r12, gpr_r13,
501 gpr_r14, gpr_r15, gpr_rip, gpr_rflags, gpr_cs, gpr_fs, gpr_gs};
502
503static uint32_t g_fpu_regnums[] = {
504 fpu_fcw, fpu_fsw, fpu_ftw, fpu_fop, fpu_ip, fpu_cs,
505 fpu_dp, fpu_ds, fpu_mxcsr, fpu_mxcsrmask, fpu_stmm0, fpu_stmm1,
506 fpu_stmm2, fpu_stmm3, fpu_stmm4, fpu_stmm5, fpu_stmm6, fpu_stmm7,
507 fpu_xmm0, fpu_xmm1, fpu_xmm2, fpu_xmm3, fpu_xmm4, fpu_xmm5,
508 fpu_xmm6, fpu_xmm7, fpu_xmm8, fpu_xmm9, fpu_xmm10, fpu_xmm11,
509 fpu_xmm12, fpu_xmm13, fpu_xmm14, fpu_xmm15};
510
511static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
512
513// Number of registers in each register set
514const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
515const size_t k_num_fpu_registers = std::size(g_fpu_regnums);
516const size_t k_num_exc_registers = std::size(g_exc_regnums);
517
518// Register set definitions. The first definitions at register set index of
519// zero is for all registers, followed by other registers sets. The register
520// information for the all register set need not be filled in.
521static const RegisterSet g_reg_sets[] = {
522 {
523 .name: "General Purpose Registers", .short_name: "gpr", .num_registers: k_num_gpr_registers, .registers: g_gpr_regnums,
524 },
525 {.name: "Floating Point Registers", .short_name: "fpu", .num_registers: k_num_fpu_registers, .registers: g_fpu_regnums},
526 {.name: "Exception State Registers", .short_name: "exc", .num_registers: k_num_exc_registers, .registers: g_exc_regnums}};
527
528const size_t k_num_regsets = std::size(g_reg_sets);
529
530size_t RegisterContextDarwin_x86_64::GetRegisterSetCount() {
531 return k_num_regsets;
532}
533
534const RegisterSet *
535RegisterContextDarwin_x86_64::GetRegisterSet(size_t reg_set) {
536 if (reg_set < k_num_regsets)
537 return &g_reg_sets[reg_set];
538 return nullptr;
539}
540
541int RegisterContextDarwin_x86_64::GetSetForNativeRegNum(int reg_num) {
542 if (reg_num < fpu_fcw)
543 return GPRRegSet;
544 else if (reg_num < exc_trapno)
545 return FPURegSet;
546 else if (reg_num < k_num_registers)
547 return EXCRegSet;
548 return -1;
549}
550
551int RegisterContextDarwin_x86_64::ReadGPR(bool force) {
552 int set = GPRRegSet;
553 if (force || !RegisterSetIsCached(set)) {
554 SetError(flavor: set, err_idx: Read, err: DoReadGPR(tid: GetThreadID(), flavor: set, gpr));
555 }
556 return GetError(flavor: GPRRegSet, err_idx: Read);
557}
558
559int RegisterContextDarwin_x86_64::ReadFPU(bool force) {
560 int set = FPURegSet;
561 if (force || !RegisterSetIsCached(set)) {
562 SetError(flavor: set, err_idx: Read, err: DoReadFPU(tid: GetThreadID(), flavor: set, fpu));
563 }
564 return GetError(flavor: FPURegSet, err_idx: Read);
565}
566
567int RegisterContextDarwin_x86_64::ReadEXC(bool force) {
568 int set = EXCRegSet;
569 if (force || !RegisterSetIsCached(set)) {
570 SetError(flavor: set, err_idx: Read, err: DoReadEXC(tid: GetThreadID(), flavor: set, exc));
571 }
572 return GetError(flavor: EXCRegSet, err_idx: Read);
573}
574
575int RegisterContextDarwin_x86_64::WriteGPR() {
576 int set = GPRRegSet;
577 if (!RegisterSetIsCached(set)) {
578 SetError(flavor: set, err_idx: Write, err: -1);
579 return -1;
580 }
581 SetError(flavor: set, err_idx: Write, err: DoWriteGPR(tid: GetThreadID(), flavor: set, gpr));
582 SetError(flavor: set, err_idx: Read, err: -1);
583 return GetError(flavor: set, err_idx: Write);
584}
585
586int RegisterContextDarwin_x86_64::WriteFPU() {
587 int set = FPURegSet;
588 if (!RegisterSetIsCached(set)) {
589 SetError(flavor: set, err_idx: Write, err: -1);
590 return -1;
591 }
592 SetError(flavor: set, err_idx: Write, err: DoWriteFPU(tid: GetThreadID(), flavor: set, fpu));
593 SetError(flavor: set, err_idx: Read, err: -1);
594 return GetError(flavor: set, err_idx: Write);
595}
596
597int RegisterContextDarwin_x86_64::WriteEXC() {
598 int set = EXCRegSet;
599 if (!RegisterSetIsCached(set)) {
600 SetError(flavor: set, err_idx: Write, err: -1);
601 return -1;
602 }
603 SetError(flavor: set, err_idx: Write, err: DoWriteEXC(tid: GetThreadID(), flavor: set, exc));
604 SetError(flavor: set, err_idx: Read, err: -1);
605 return GetError(flavor: set, err_idx: Write);
606}
607
608int RegisterContextDarwin_x86_64::ReadRegisterSet(uint32_t set, bool force) {
609 switch (set) {
610 case GPRRegSet:
611 return ReadGPR(force);
612 case FPURegSet:
613 return ReadFPU(force);
614 case EXCRegSet:
615 return ReadEXC(force);
616 default:
617 break;
618 }
619 return -1;
620}
621
622int RegisterContextDarwin_x86_64::WriteRegisterSet(uint32_t set) {
623 // Make sure we have a valid context to set.
624 switch (set) {
625 case GPRRegSet:
626 return WriteGPR();
627 case FPURegSet:
628 return WriteFPU();
629 case EXCRegSet:
630 return WriteEXC();
631 default:
632 break;
633 }
634 return -1;
635}
636
637bool RegisterContextDarwin_x86_64::ReadRegister(const RegisterInfo *reg_info,
638 RegisterValue &value) {
639 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
640 int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum(reg_num: reg);
641 if (set == -1)
642 return false;
643
644 if (ReadRegisterSet(set, force: false) != 0)
645 return false;
646
647 switch (reg) {
648 case gpr_rax:
649 case gpr_rbx:
650 case gpr_rcx:
651 case gpr_rdx:
652 case gpr_rdi:
653 case gpr_rsi:
654 case gpr_rbp:
655 case gpr_rsp:
656 case gpr_r8:
657 case gpr_r9:
658 case gpr_r10:
659 case gpr_r11:
660 case gpr_r12:
661 case gpr_r13:
662 case gpr_r14:
663 case gpr_r15:
664 case gpr_rip:
665 case gpr_rflags:
666 case gpr_cs:
667 case gpr_fs:
668 case gpr_gs:
669 value = (&gpr.rax)[reg - gpr_rax];
670 break;
671
672 case fpu_fcw:
673 value = fpu.fcw;
674 break;
675
676 case fpu_fsw:
677 value = fpu.fsw;
678 break;
679
680 case fpu_ftw:
681 value = fpu.ftw;
682 break;
683
684 case fpu_fop:
685 value = fpu.fop;
686 break;
687
688 case fpu_ip:
689 value = fpu.ip;
690 break;
691
692 case fpu_cs:
693 value = fpu.cs;
694 break;
695
696 case fpu_dp:
697 value = fpu.dp;
698 break;
699
700 case fpu_ds:
701 value = fpu.ds;
702 break;
703
704 case fpu_mxcsr:
705 value = fpu.mxcsr;
706 break;
707
708 case fpu_mxcsrmask:
709 value = fpu.mxcsrmask;
710 break;
711
712 case fpu_stmm0:
713 case fpu_stmm1:
714 case fpu_stmm2:
715 case fpu_stmm3:
716 case fpu_stmm4:
717 case fpu_stmm5:
718 case fpu_stmm6:
719 case fpu_stmm7:
720 value.SetBytes(bytes: fpu.stmm[reg - fpu_stmm0].bytes, length: reg_info->byte_size,
721 byte_order: endian::InlHostByteOrder());
722 break;
723
724 case fpu_xmm0:
725 case fpu_xmm1:
726 case fpu_xmm2:
727 case fpu_xmm3:
728 case fpu_xmm4:
729 case fpu_xmm5:
730 case fpu_xmm6:
731 case fpu_xmm7:
732 case fpu_xmm8:
733 case fpu_xmm9:
734 case fpu_xmm10:
735 case fpu_xmm11:
736 case fpu_xmm12:
737 case fpu_xmm13:
738 case fpu_xmm14:
739 case fpu_xmm15:
740 value.SetBytes(bytes: fpu.xmm[reg - fpu_xmm0].bytes, length: reg_info->byte_size,
741 byte_order: endian::InlHostByteOrder());
742 break;
743
744 case exc_trapno:
745 value = exc.trapno;
746 break;
747
748 case exc_err:
749 value = exc.err;
750 break;
751
752 case exc_faultvaddr:
753 value = exc.faultvaddr;
754 break;
755
756 default:
757 return false;
758 }
759 return true;
760}
761
762bool RegisterContextDarwin_x86_64::WriteRegister(const RegisterInfo *reg_info,
763 const RegisterValue &value) {
764 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
765 int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum(reg_num: reg);
766
767 if (set == -1)
768 return false;
769
770 if (ReadRegisterSet(set, force: false) != 0)
771 return false;
772
773 switch (reg) {
774 case gpr_rax:
775 case gpr_rbx:
776 case gpr_rcx:
777 case gpr_rdx:
778 case gpr_rdi:
779 case gpr_rsi:
780 case gpr_rbp:
781 case gpr_rsp:
782 case gpr_r8:
783 case gpr_r9:
784 case gpr_r10:
785 case gpr_r11:
786 case gpr_r12:
787 case gpr_r13:
788 case gpr_r14:
789 case gpr_r15:
790 case gpr_rip:
791 case gpr_rflags:
792 case gpr_cs:
793 case gpr_fs:
794 case gpr_gs:
795 (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64();
796 break;
797
798 case fpu_fcw:
799 fpu.fcw = value.GetAsUInt16();
800 break;
801
802 case fpu_fsw:
803 fpu.fsw = value.GetAsUInt16();
804 break;
805
806 case fpu_ftw:
807 fpu.ftw = value.GetAsUInt8();
808 break;
809
810 case fpu_fop:
811 fpu.fop = value.GetAsUInt16();
812 break;
813
814 case fpu_ip:
815 fpu.ip = value.GetAsUInt32();
816 break;
817
818 case fpu_cs:
819 fpu.cs = value.GetAsUInt16();
820 break;
821
822 case fpu_dp:
823 fpu.dp = value.GetAsUInt32();
824 break;
825
826 case fpu_ds:
827 fpu.ds = value.GetAsUInt16();
828 break;
829
830 case fpu_mxcsr:
831 fpu.mxcsr = value.GetAsUInt32();
832 break;
833
834 case fpu_mxcsrmask:
835 fpu.mxcsrmask = value.GetAsUInt32();
836 break;
837
838 case fpu_stmm0:
839 case fpu_stmm1:
840 case fpu_stmm2:
841 case fpu_stmm3:
842 case fpu_stmm4:
843 case fpu_stmm5:
844 case fpu_stmm6:
845 case fpu_stmm7:
846 ::memcpy(dest: fpu.stmm[reg - fpu_stmm0].bytes, src: value.GetBytes(),
847 n: value.GetByteSize());
848 break;
849
850 case fpu_xmm0:
851 case fpu_xmm1:
852 case fpu_xmm2:
853 case fpu_xmm3:
854 case fpu_xmm4:
855 case fpu_xmm5:
856 case fpu_xmm6:
857 case fpu_xmm7:
858 case fpu_xmm8:
859 case fpu_xmm9:
860 case fpu_xmm10:
861 case fpu_xmm11:
862 case fpu_xmm12:
863 case fpu_xmm13:
864 case fpu_xmm14:
865 case fpu_xmm15:
866 ::memcpy(dest: fpu.xmm[reg - fpu_xmm0].bytes, src: value.GetBytes(),
867 n: value.GetByteSize());
868 return false;
869
870 case exc_trapno:
871 exc.trapno = value.GetAsUInt32();
872 break;
873
874 case exc_err:
875 exc.err = value.GetAsUInt32();
876 break;
877
878 case exc_faultvaddr:
879 exc.faultvaddr = value.GetAsUInt64();
880 break;
881
882 default:
883 return false;
884 }
885 return WriteRegisterSet(set) == 0;
886}
887
888bool RegisterContextDarwin_x86_64::ReadAllRegisterValues(
889 lldb::WritableDataBufferSP &data_sp) {
890 data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, args: 0);
891 if (ReadGPR(force: false) == 0 && ReadFPU(force: false) == 0 && ReadEXC(force: false) == 0) {
892 uint8_t *dst = data_sp->GetBytes();
893 ::memcpy(dest: dst, src: &gpr, n: sizeof(gpr));
894 dst += sizeof(gpr);
895
896 ::memcpy(dest: dst, src: &fpu, n: sizeof(fpu));
897 dst += sizeof(gpr);
898
899 ::memcpy(dest: dst, src: &exc, n: sizeof(exc));
900 return true;
901 }
902 return false;
903}
904
905bool RegisterContextDarwin_x86_64::WriteAllRegisterValues(
906 const lldb::DataBufferSP &data_sp) {
907 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
908 const uint8_t *src = data_sp->GetBytes();
909 ::memcpy(dest: &gpr, src: src, n: sizeof(gpr));
910 src += sizeof(gpr);
911
912 ::memcpy(dest: &fpu, src: src, n: sizeof(fpu));
913 src += sizeof(gpr);
914
915 ::memcpy(dest: &exc, src: src, n: sizeof(exc));
916 uint32_t success_count = 0;
917 if (WriteGPR() == 0)
918 ++success_count;
919 if (WriteFPU() == 0)
920 ++success_count;
921 if (WriteEXC() == 0)
922 ++success_count;
923 return success_count == 3;
924 }
925 return false;
926}
927
928uint32_t RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber(
929 lldb::RegisterKind kind, uint32_t reg) {
930 if (kind == eRegisterKindGeneric) {
931 switch (reg) {
932 case LLDB_REGNUM_GENERIC_PC:
933 return gpr_rip;
934 case LLDB_REGNUM_GENERIC_SP:
935 return gpr_rsp;
936 case LLDB_REGNUM_GENERIC_FP:
937 return gpr_rbp;
938 case LLDB_REGNUM_GENERIC_FLAGS:
939 return gpr_rflags;
940 case LLDB_REGNUM_GENERIC_RA:
941 default:
942 break;
943 }
944 } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
945 switch (reg) {
946 case ehframe_dwarf_gpr_rax:
947 return gpr_rax;
948 case ehframe_dwarf_gpr_rdx:
949 return gpr_rdx;
950 case ehframe_dwarf_gpr_rcx:
951 return gpr_rcx;
952 case ehframe_dwarf_gpr_rbx:
953 return gpr_rbx;
954 case ehframe_dwarf_gpr_rsi:
955 return gpr_rsi;
956 case ehframe_dwarf_gpr_rdi:
957 return gpr_rdi;
958 case ehframe_dwarf_gpr_rbp:
959 return gpr_rbp;
960 case ehframe_dwarf_gpr_rsp:
961 return gpr_rsp;
962 case ehframe_dwarf_gpr_r8:
963 return gpr_r8;
964 case ehframe_dwarf_gpr_r9:
965 return gpr_r9;
966 case ehframe_dwarf_gpr_r10:
967 return gpr_r10;
968 case ehframe_dwarf_gpr_r11:
969 return gpr_r11;
970 case ehframe_dwarf_gpr_r12:
971 return gpr_r12;
972 case ehframe_dwarf_gpr_r13:
973 return gpr_r13;
974 case ehframe_dwarf_gpr_r14:
975 return gpr_r14;
976 case ehframe_dwarf_gpr_r15:
977 return gpr_r15;
978 case ehframe_dwarf_gpr_rip:
979 return gpr_rip;
980 case ehframe_dwarf_fpu_xmm0:
981 return fpu_xmm0;
982 case ehframe_dwarf_fpu_xmm1:
983 return fpu_xmm1;
984 case ehframe_dwarf_fpu_xmm2:
985 return fpu_xmm2;
986 case ehframe_dwarf_fpu_xmm3:
987 return fpu_xmm3;
988 case ehframe_dwarf_fpu_xmm4:
989 return fpu_xmm4;
990 case ehframe_dwarf_fpu_xmm5:
991 return fpu_xmm5;
992 case ehframe_dwarf_fpu_xmm6:
993 return fpu_xmm6;
994 case ehframe_dwarf_fpu_xmm7:
995 return fpu_xmm7;
996 case ehframe_dwarf_fpu_xmm8:
997 return fpu_xmm8;
998 case ehframe_dwarf_fpu_xmm9:
999 return fpu_xmm9;
1000 case ehframe_dwarf_fpu_xmm10:
1001 return fpu_xmm10;
1002 case ehframe_dwarf_fpu_xmm11:
1003 return fpu_xmm11;
1004 case ehframe_dwarf_fpu_xmm12:
1005 return fpu_xmm12;
1006 case ehframe_dwarf_fpu_xmm13:
1007 return fpu_xmm13;
1008 case ehframe_dwarf_fpu_xmm14:
1009 return fpu_xmm14;
1010 case ehframe_dwarf_fpu_xmm15:
1011 return fpu_xmm15;
1012 case ehframe_dwarf_fpu_stmm0:
1013 return fpu_stmm0;
1014 case ehframe_dwarf_fpu_stmm1:
1015 return fpu_stmm1;
1016 case ehframe_dwarf_fpu_stmm2:
1017 return fpu_stmm2;
1018 case ehframe_dwarf_fpu_stmm3:
1019 return fpu_stmm3;
1020 case ehframe_dwarf_fpu_stmm4:
1021 return fpu_stmm4;
1022 case ehframe_dwarf_fpu_stmm5:
1023 return fpu_stmm5;
1024 case ehframe_dwarf_fpu_stmm6:
1025 return fpu_stmm6;
1026 case ehframe_dwarf_fpu_stmm7:
1027 return fpu_stmm7;
1028 default:
1029 break;
1030 }
1031 } else if (kind == eRegisterKindLLDB) {
1032 return reg;
1033 }
1034 return LLDB_INVALID_REGNUM;
1035}
1036
1037bool RegisterContextDarwin_x86_64::HardwareSingleStep(bool enable) {
1038 if (ReadGPR(force: true) != 0)
1039 return false;
1040
1041 const uint64_t trace_bit = 0x100ull;
1042 if (enable) {
1043
1044 if (gpr.rflags & trace_bit)
1045 return true; // trace bit is already set, there is nothing to do
1046 else
1047 gpr.rflags |= trace_bit;
1048 } else {
1049 if (gpr.rflags & trace_bit)
1050 gpr.rflags &= ~trace_bit;
1051 else
1052 return true; // trace bit is clear, there is nothing to do
1053 }
1054
1055 return WriteGPR() == 0;
1056}
1057

source code of lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp