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

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