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

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