xref: /llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp (revision 593be023615a456ca6ee0ef9bedc21301d73b73c)
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 
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,
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     {DEFINE_GPR(eax, nullptr),
169      {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
170       gpr_eax},
171      nullptr,
172      nullptr,
173      nullptr,
174     },
175     {DEFINE_GPR(ebx, nullptr),
176      {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
177       gpr_ebx},
178      nullptr,
179      nullptr,
180      nullptr,
181     },
182     {DEFINE_GPR(ecx, nullptr),
183      {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
184       gpr_ecx},
185      nullptr,
186      nullptr,
187      nullptr,
188     },
189     {DEFINE_GPR(edx, nullptr),
190      {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
191       gpr_edx},
192      nullptr,
193      nullptr,
194      nullptr,
195     },
196     {DEFINE_GPR(edi, nullptr),
197      {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
198       gpr_edi},
199      nullptr,
200      nullptr,
201      nullptr,
202     },
203     {DEFINE_GPR(esi, nullptr),
204      {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
205       gpr_esi},
206      nullptr,
207      nullptr,
208      nullptr,
209     },
210     {DEFINE_GPR(ebp, "fp"),
211      {ehframe_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
212       gpr_ebp},
213      nullptr,
214      nullptr,
215      nullptr,
216     },
217     {DEFINE_GPR(esp, "sp"),
218      {ehframe_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
219       gpr_esp},
220      nullptr,
221      nullptr,
222      nullptr,
223     },
224     {DEFINE_GPR(ss, nullptr),
225      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
226       LLDB_INVALID_REGNUM, gpr_ss},
227      nullptr,
228      nullptr,
229      nullptr,
230     },
231     {DEFINE_GPR(eflags, "flags"),
232      {ehframe_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS,
233       LLDB_INVALID_REGNUM, gpr_eflags},
234      nullptr,
235      nullptr,
236      nullptr,
237     },
238     {DEFINE_GPR(eip, "pc"),
239      {ehframe_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
240       gpr_eip},
241      nullptr,
242      nullptr,
243      nullptr,
244     },
245     {DEFINE_GPR(cs, nullptr),
246      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
247       LLDB_INVALID_REGNUM, gpr_cs},
248      nullptr,
249      nullptr,
250      nullptr,
251     },
252     {DEFINE_GPR(ds, nullptr),
253      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
254       LLDB_INVALID_REGNUM, gpr_ds},
255      nullptr,
256      nullptr,
257      nullptr,
258     },
259     {DEFINE_GPR(es, nullptr),
260      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
261       LLDB_INVALID_REGNUM, gpr_es},
262      nullptr,
263      nullptr,
264      nullptr,
265     },
266     {DEFINE_GPR(fs, nullptr),
267      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
268       LLDB_INVALID_REGNUM, gpr_fs},
269      nullptr,
270      nullptr,
271      nullptr,
272     },
273     {DEFINE_GPR(gs, nullptr),
274      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
275       LLDB_INVALID_REGNUM, gpr_gs},
276      nullptr,
277      nullptr,
278      nullptr,
279     },
280 
281     {DEFINE_FPU_UINT(fcw),
282      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
283       LLDB_INVALID_REGNUM, fpu_fcw},
284      nullptr,
285      nullptr,
286      nullptr,
287     },
288     {DEFINE_FPU_UINT(fsw),
289      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
290       LLDB_INVALID_REGNUM, fpu_fsw},
291      nullptr,
292      nullptr,
293      nullptr,
294     },
295     {DEFINE_FPU_UINT(ftw),
296      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
297       LLDB_INVALID_REGNUM, fpu_ftw},
298      nullptr,
299      nullptr,
300      nullptr,
301     },
302     {DEFINE_FPU_UINT(fop),
303      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
304       LLDB_INVALID_REGNUM, fpu_fop},
305      nullptr,
306      nullptr,
307      nullptr,
308     },
309     {DEFINE_FPU_UINT(ip),
310      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
311       LLDB_INVALID_REGNUM, fpu_ip},
312      nullptr,
313      nullptr,
314      nullptr,
315     },
316     {DEFINE_FPU_UINT(cs),
317      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
318       LLDB_INVALID_REGNUM, fpu_cs},
319      nullptr,
320      nullptr,
321      nullptr,
322     },
323     {DEFINE_FPU_UINT(dp),
324      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
325       LLDB_INVALID_REGNUM, fpu_dp},
326      nullptr,
327      nullptr,
328      nullptr,
329     },
330     {DEFINE_FPU_UINT(ds),
331      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
332       LLDB_INVALID_REGNUM, fpu_ds},
333      nullptr,
334      nullptr,
335      nullptr,
336     },
337     {DEFINE_FPU_UINT(mxcsr),
338      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
339       LLDB_INVALID_REGNUM, fpu_mxcsr},
340      nullptr,
341      nullptr,
342      nullptr,
343     },
344     {DEFINE_FPU_UINT(mxcsrmask),
345      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
346       LLDB_INVALID_REGNUM, fpu_mxcsrmask},
347      nullptr,
348      nullptr,
349      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      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
370       LLDB_INVALID_REGNUM, exc_trapno},
371      nullptr,
372      nullptr,
373      nullptr,
374     },
375     {DEFINE_EXC(err),
376      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
377       LLDB_INVALID_REGNUM, exc_err},
378      nullptr,
379      nullptr,
380      nullptr,
381     },
382     {DEFINE_EXC(faultvaddr),
383      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
384       LLDB_INVALID_REGNUM, exc_faultvaddr},
385      nullptr,
386      nullptr,
387      nullptr,
388      }};
389 
390 static size_t k_num_register_infos = std::size(g_register_infos);
391 
392 RegisterContextDarwin_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 
403 RegisterContextDarwin_i386::~RegisterContextDarwin_i386() = default;
404 
405 void RegisterContextDarwin_i386::InvalidateAllRegisters() {
406   InvalidateAllRegisterStates();
407 }
408 
409 size_t RegisterContextDarwin_i386::GetRegisterCount() {
410   assert(k_num_register_infos == k_num_registers);
411   return k_num_registers;
412 }
413 
414 const RegisterInfo *
415 RegisterContextDarwin_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 
422 size_t RegisterContextDarwin_i386::GetRegisterInfosCount() {
423   return k_num_register_infos;
424 }
425 
426 const RegisterInfo *RegisterContextDarwin_i386::GetRegisterInfos() {
427   return g_register_infos;
428 }
429 
430 // General purpose registers
431 static 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
436 static 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 
445 static uint32_t g_exc_regnums[] = {exc_trapno, exc_err, exc_faultvaddr};
446 
447 // Number of registers in each register set
448 const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
449 const size_t k_num_fpu_registers = std::size(g_fpu_regnums);
450 const 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.
455 static const RegisterSet g_reg_sets[] = {
456     {
457         "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
458     },
459     {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
460     {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
461 
462 const size_t k_num_regsets = std::size(g_reg_sets);
463 
464 size_t RegisterContextDarwin_i386::GetRegisterSetCount() {
465   return k_num_regsets;
466 }
467 
468 const 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.
475 int 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 
485 void 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 
497 int RegisterContextDarwin_i386::ReadGPR(bool force) {
498   int set = GPRRegSet;
499   if (force || !RegisterSetIsCached(set)) {
500     SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
501   }
502   return GetError(set, Read);
503 }
504 
505 int RegisterContextDarwin_i386::ReadFPU(bool force) {
506   int set = FPURegSet;
507   if (force || !RegisterSetIsCached(set)) {
508     SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
509   }
510   return GetError(set, Read);
511 }
512 
513 int RegisterContextDarwin_i386::ReadEXC(bool force) {
514   int set = EXCRegSet;
515   if (force || !RegisterSetIsCached(set)) {
516     SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
517   }
518   return GetError(set, Read);
519 }
520 
521 int RegisterContextDarwin_i386::WriteGPR() {
522   int set = GPRRegSet;
523   if (!RegisterSetIsCached(set)) {
524     SetError(set, Write, -1);
525     return -1;
526   }
527   SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
528   SetError(set, Read, -1);
529   return GetError(set, Write);
530 }
531 
532 int RegisterContextDarwin_i386::WriteFPU() {
533   int set = FPURegSet;
534   if (!RegisterSetIsCached(set)) {
535     SetError(set, Write, -1);
536     return -1;
537   }
538   SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
539   SetError(set, Read, -1);
540   return GetError(set, Write);
541 }
542 
543 int RegisterContextDarwin_i386::WriteEXC() {
544   int set = EXCRegSet;
545   if (!RegisterSetIsCached(set)) {
546     SetError(set, Write, -1);
547     return -1;
548   }
549   SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
550   SetError(set, Read, -1);
551   return GetError(set, Write);
552 }
553 
554 int 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 
568 int 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 
585 bool 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);
589 
590   if (set == -1)
591     return false;
592 
593   if (ReadRegisterSet(set, 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 
702 bool 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);
706 
707   if (set == -1)
708     return false;
709 
710   if (ReadRegisterSet(set, 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(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
784              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(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
798              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 
819 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
820     lldb::WritableDataBufferSP &data_sp) {
821   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
822   if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
823     uint8_t *dst = data_sp->GetBytes();
824     ::memcpy(dst, &gpr, sizeof(gpr));
825     dst += sizeof(gpr);
826 
827     ::memcpy(dst, &fpu, sizeof(fpu));
828     dst += sizeof(gpr);
829 
830     ::memcpy(dst, &exc, sizeof(exc));
831     return true;
832   }
833   return false;
834 }
835 
836 bool 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(&gpr, src, sizeof(gpr));
841     src += sizeof(gpr);
842 
843     ::memcpy(&fpu, src, sizeof(fpu));
844     src += sizeof(gpr);
845 
846     ::memcpy(&exc, src, 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 
859 uint32_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 
938 bool RegisterContextDarwin_i386::HardwareSingleStep(bool enable) {
939   if (ReadGPR(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