1 //===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===//
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 <stddef.h>
19 
20 #include <memory>
21 
22 #include "RegisterContextDarwin_i386.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 enum {
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 
88 enum {
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 
101 enum {
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, 0
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 
167 static 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      {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
175       gpr_eax},
176      nullptr,
177      nullptr,
178      nullptr,
179      0},
180     {DEFINE_GPR(ebx, nullptr),
181      {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
182       gpr_ebx},
183      nullptr,
184      nullptr,
185      nullptr,
186      0},
187     {DEFINE_GPR(ecx, nullptr),
188      {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
189       gpr_ecx},
190      nullptr,
191      nullptr,
192      nullptr,
193      0},
194     {DEFINE_GPR(edx, nullptr),
195      {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
196       gpr_edx},
197      nullptr,
198      nullptr,
199      nullptr,
200      0},
201     {DEFINE_GPR(edi, nullptr),
202      {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
203       gpr_edi},
204      nullptr,
205      nullptr,
206      nullptr,
207      0},
208     {DEFINE_GPR(esi, nullptr),
209      {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
210       gpr_esi},
211      nullptr,
212      nullptr,
213      nullptr,
214      0},
215     {DEFINE_GPR(ebp, "fp"),
216      {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
217       gpr_ebp},
218      nullptr,
219      nullptr,
220      nullptr,
221      0},
222     {DEFINE_GPR(esp, "sp"),
223      {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
224       gpr_esp},
225      nullptr,
226      nullptr,
227      nullptr,
228      0},
229     {DEFINE_GPR(ss, nullptr),
230      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
231       LLDB_INVALID_REGNUM, gpr_ss},
232      nullptr,
233      nullptr,
234      nullptr,
235      0},
236     {DEFINE_GPR(eflags, "flags"),
237      {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS,
238       LLDB_INVALID_REGNUM, gpr_eflags},
239      nullptr,
240      nullptr,
241      nullptr,
242      0},
243     {DEFINE_GPR(eip, "pc"),
244      {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
245       gpr_eip},
246      nullptr,
247      nullptr,
248      nullptr,
249      0},
250     {DEFINE_GPR(cs, nullptr),
251      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
252       LLDB_INVALID_REGNUM, gpr_cs},
253      nullptr,
254      nullptr,
255      nullptr,
256      0},
257     {DEFINE_GPR(ds, nullptr),
258      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
259       LLDB_INVALID_REGNUM, gpr_ds},
260      nullptr,
261      nullptr,
262      nullptr,
263      0},
264     {DEFINE_GPR(es, nullptr),
265      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
266       LLDB_INVALID_REGNUM, gpr_es},
267      nullptr,
268      nullptr,
269      nullptr,
270      0},
271     {DEFINE_GPR(fs, nullptr),
272      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
273       LLDB_INVALID_REGNUM, gpr_fs},
274      nullptr,
275      nullptr,
276      nullptr,
277      0},
278     {DEFINE_GPR(gs, nullptr),
279      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
280       LLDB_INVALID_REGNUM, gpr_gs},
281      nullptr,
282      nullptr,
283      nullptr,
284      0},
285 
286     {DEFINE_FPU_UINT(fcw),
287      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
288       LLDB_INVALID_REGNUM, fpu_fcw},
289      nullptr,
290      nullptr,
291      nullptr,
292      0},
293     {DEFINE_FPU_UINT(fsw),
294      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
295       LLDB_INVALID_REGNUM, fpu_fsw},
296      nullptr,
297      nullptr,
298      nullptr,
299      0},
300     {DEFINE_FPU_UINT(ftw),
301      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
302       LLDB_INVALID_REGNUM, fpu_ftw},
303      nullptr,
304      nullptr,
305      nullptr,
306      0},
307     {DEFINE_FPU_UINT(fop),
308      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
309       LLDB_INVALID_REGNUM, fpu_fop},
310      nullptr,
311      nullptr,
312      nullptr,
313      0},
314     {DEFINE_FPU_UINT(ip),
315      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
316       LLDB_INVALID_REGNUM, fpu_ip},
317      nullptr,
318      nullptr,
319      nullptr,
320      0},
321     {DEFINE_FPU_UINT(cs),
322      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
323       LLDB_INVALID_REGNUM, fpu_cs},
324      nullptr,
325      nullptr,
326      nullptr,
327      0},
328     {DEFINE_FPU_UINT(dp),
329      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
330       LLDB_INVALID_REGNUM, fpu_dp},
331      nullptr,
332      nullptr,
333      nullptr,
334      0},
335     {DEFINE_FPU_UINT(ds),
336      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
337       LLDB_INVALID_REGNUM, fpu_ds},
338      nullptr,
339      nullptr,
340      nullptr,
341      0},
342     {DEFINE_FPU_UINT(mxcsr),
343      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
344       LLDB_INVALID_REGNUM, fpu_mxcsr},
345      nullptr,
346      nullptr,
347      nullptr,
348      0},
349     {DEFINE_FPU_UINT(mxcsrmask),
350      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
351       LLDB_INVALID_REGNUM, fpu_mxcsrmask},
352      nullptr,
353      nullptr,
354      nullptr,
355      0},
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      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
375       LLDB_INVALID_REGNUM, exc_trapno},
376      nullptr,
377      nullptr,
378      nullptr,
379      0},
380     {DEFINE_EXC(err),
381      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
382       LLDB_INVALID_REGNUM, exc_err},
383      nullptr,
384      nullptr,
385      nullptr,
386      0},
387     {DEFINE_EXC(faultvaddr),
388      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
389       LLDB_INVALID_REGNUM, exc_faultvaddr},
390      nullptr,
391      nullptr,
392      nullptr,
393      0}};
394 
395 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
396 
397 RegisterContextDarwin_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 
408 RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
409 
410 void RegisterContextDarwin_i386::InvalidateAllRegisters() {
411   InvalidateAllRegisterStates();
412 }
413 
414 size_t RegisterContextDarwin_i386::GetRegisterCount() {
415   assert(k_num_register_infos == k_num_registers);
416   return k_num_registers;
417 }
418 
419 const RegisterInfo *
420 RegisterContextDarwin_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 
427 size_t RegisterContextDarwin_i386::GetRegisterInfosCount() {
428   return k_num_register_infos;
429 }
430 
431 const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() {
432   return g_register_infos;
433 }
434 
435 // General purpose registers
436 static 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
441 static 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 
450 static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
451 
452 // Number of registers in each register set
453 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
454 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
455 const size_t k_num_exc_registers = llvm::array_lengthof(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.
460 static const RegisterSet g_reg_sets[] = {
461     {
462         "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
463     },
464     {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
465     {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
466 
467 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
468 
469 size_t RegisterContextDarwin_i386::GetRegisterSetCount() {
470   return k_num_regsets;
471 }
472 
473 const 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.
480 int 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 
490 void 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 
502 int RegisterContextDarwin_i386::ReadGPR(bool force) {
503   int set = GPRRegSet;
504   if (force || !RegisterSetIsCached(set)) {
505     SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
506   }
507   return GetError(set, Read);
508 }
509 
510 int RegisterContextDarwin_i386::ReadFPU(bool force) {
511   int set = FPURegSet;
512   if (force || !RegisterSetIsCached(set)) {
513     SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
514   }
515   return GetError(set, Read);
516 }
517 
518 int RegisterContextDarwin_i386::ReadEXC(bool force) {
519   int set = EXCRegSet;
520   if (force || !RegisterSetIsCached(set)) {
521     SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
522   }
523   return GetError(set, Read);
524 }
525 
526 int RegisterContextDarwin_i386::WriteGPR() {
527   int set = GPRRegSet;
528   if (!RegisterSetIsCached(set)) {
529     SetError(set, Write, -1);
530     return -1;
531   }
532   SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
533   SetError(set, Read, -1);
534   return GetError(set, Write);
535 }
536 
537 int RegisterContextDarwin_i386::WriteFPU() {
538   int set = FPURegSet;
539   if (!RegisterSetIsCached(set)) {
540     SetError(set, Write, -1);
541     return -1;
542   }
543   SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
544   SetError(set, Read, -1);
545   return GetError(set, Write);
546 }
547 
548 int RegisterContextDarwin_i386::WriteEXC() {
549   int set = EXCRegSet;
550   if (!RegisterSetIsCached(set)) {
551     SetError(set, Write, -1);
552     return -1;
553   }
554   SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
555   SetError(set, Read, -1);
556   return GetError(set, Write);
557 }
558 
559 int 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 
573 int 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 
590 bool 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);
594 
595   if (set == -1)
596     return false;
597 
598   if (ReadRegisterSet(set, 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 
707 bool 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);
711 
712   if (set == -1)
713     return false;
714 
715   if (ReadRegisterSet(set, 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(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
789              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(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
803              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 
824 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
825     lldb::DataBufferSP &data_sp) {
826   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
827   if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
828     uint8_t *dst = data_sp->GetBytes();
829     ::memcpy(dst, &gpr, sizeof(gpr));
830     dst += sizeof(gpr);
831 
832     ::memcpy(dst, &fpu, sizeof(fpu));
833     dst += sizeof(gpr);
834 
835     ::memcpy(dst, &exc, sizeof(exc));
836     return true;
837   }
838   return false;
839 }
840 
841 bool 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(&gpr, src, sizeof(gpr));
846     src += sizeof(gpr);
847 
848     ::memcpy(&fpu, src, sizeof(fpu));
849     src += sizeof(gpr);
850 
851     ::memcpy(&exc, src, 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 
864 uint32_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 
943 bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) {
944   if (ReadGPR(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