1 //===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 6/25/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #if defined (__i386__) || defined (__x86_64__)
15 
16 #include <sys/cdefs.h>
17 
18 #include "MacOSX/i386/DNBArchImplI386.h"
19 #include "DNBLog.h"
20 #include "MachThread.h"
21 #include "MachProcess.h"
22 
23 #if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG)
24 enum debugState {
25     debugStateUnknown,
26     debugStateOff,
27     debugStateOn
28 };
29 
30 static debugState sFPUDebugState = debugStateUnknown;
31 static debugState sAVXForceState = debugStateUnknown;
32 
33 static bool DebugFPURegs ()
34 {
35     if (sFPUDebugState == debugStateUnknown)
36     {
37         if (getenv("DNB_DEBUG_FPU_REGS"))
38             sFPUDebugState = debugStateOn;
39         else
40             sFPUDebugState = debugStateOff;
41     }
42 
43     return (sFPUDebugState == debugStateOn);
44 }
45 
46 static bool ForceAVXRegs ()
47 {
48     if (sFPUDebugState == debugStateUnknown)
49     {
50         if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
51             sAVXForceState = debugStateOn;
52         else
53             sAVXForceState = debugStateOff;
54     }
55 
56     return (sAVXForceState == debugStateOn);
57 }
58 
59 #define DEBUG_FPU_REGS (DebugFPURegs())
60 #define FORCE_AVX_REGS (ForceAVXRegs())
61 #else
62 #define DEBUG_FPU_REGS (0)
63 #define FORCE_AVX_REGS (0)
64 #endif
65 
66 enum
67 {
68     gpr_eax         = 0,
69     gpr_ebx         = 1,
70     gpr_ecx         = 2,
71     gpr_edx         = 3,
72     gpr_edi         = 4,
73     gpr_esi         = 5,
74     gpr_ebp         = 6,
75     gpr_esp         = 7,
76     gpr_ss          = 8,
77     gpr_eflags      = 9,
78     gpr_eip         = 10,
79     gpr_cs          = 11,
80     gpr_ds          = 12,
81     gpr_es          = 13,
82     gpr_fs          = 14,
83     gpr_gs          = 15,
84     k_num_gpr_regs
85 };
86 
87 enum {
88     fpu_fcw,
89     fpu_fsw,
90     fpu_ftw,
91     fpu_fop,
92     fpu_ip,
93     fpu_cs,
94     fpu_dp,
95     fpu_ds,
96     fpu_mxcsr,
97     fpu_mxcsrmask,
98     fpu_stmm0,
99     fpu_stmm1,
100     fpu_stmm2,
101     fpu_stmm3,
102     fpu_stmm4,
103     fpu_stmm5,
104     fpu_stmm6,
105     fpu_stmm7,
106     fpu_xmm0,
107     fpu_xmm1,
108     fpu_xmm2,
109     fpu_xmm3,
110     fpu_xmm4,
111     fpu_xmm5,
112     fpu_xmm6,
113     fpu_xmm7,
114     fpu_ymm0,
115     fpu_ymm1,
116     fpu_ymm2,
117     fpu_ymm3,
118     fpu_ymm4,
119     fpu_ymm5,
120     fpu_ymm6,
121     fpu_ymm7,
122     k_num_fpu_regs,
123 
124     // Aliases
125     fpu_fctrl = fpu_fcw,
126     fpu_fstat = fpu_fsw,
127     fpu_ftag  = fpu_ftw,
128     fpu_fiseg = fpu_cs,
129     fpu_fioff = fpu_ip,
130     fpu_foseg = fpu_ds,
131     fpu_fooff = fpu_dp
132 };
133 
134 enum {
135     exc_trapno,
136     exc_err,
137     exc_faultvaddr,
138     k_num_exc_regs,
139 };
140 
141 
142 enum
143 {
144     gcc_eax = 0,
145     gcc_ecx,
146     gcc_edx,
147     gcc_ebx,
148     gcc_ebp,
149     gcc_esp,
150     gcc_esi,
151     gcc_edi,
152     gcc_eip,
153     gcc_eflags
154 };
155 
156 enum
157 {
158     dwarf_eax = 0,
159     dwarf_ecx,
160     dwarf_edx,
161     dwarf_ebx,
162     dwarf_esp,
163     dwarf_ebp,
164     dwarf_esi,
165     dwarf_edi,
166     dwarf_eip,
167     dwarf_eflags,
168     dwarf_stmm0 = 11,
169     dwarf_stmm1,
170     dwarf_stmm2,
171     dwarf_stmm3,
172     dwarf_stmm4,
173     dwarf_stmm5,
174     dwarf_stmm6,
175     dwarf_stmm7,
176     dwarf_xmm0 = 21,
177     dwarf_xmm1,
178     dwarf_xmm2,
179     dwarf_xmm3,
180     dwarf_xmm4,
181     dwarf_xmm5,
182     dwarf_xmm6,
183     dwarf_xmm7,
184     dwarf_ymm0 = dwarf_xmm0,
185     dwarf_ymm1 = dwarf_xmm1,
186     dwarf_ymm2 = dwarf_xmm2,
187     dwarf_ymm3 = dwarf_xmm3,
188     dwarf_ymm4 = dwarf_xmm4,
189     dwarf_ymm5 = dwarf_xmm5,
190     dwarf_ymm6 = dwarf_xmm6,
191     dwarf_ymm7 = dwarf_xmm7,
192 };
193 
194 enum
195 {
196     gdb_eax        =  0,
197     gdb_ecx        =  1,
198     gdb_edx        =  2,
199     gdb_ebx        =  3,
200     gdb_esp        =  4,
201     gdb_ebp        =  5,
202     gdb_esi        =  6,
203     gdb_edi        =  7,
204     gdb_eip        =  8,
205     gdb_eflags     =  9,
206     gdb_cs         = 10,
207     gdb_ss         = 11,
208     gdb_ds         = 12,
209     gdb_es         = 13,
210     gdb_fs         = 14,
211     gdb_gs         = 15,
212     gdb_stmm0      = 16,
213     gdb_stmm1      = 17,
214     gdb_stmm2      = 18,
215     gdb_stmm3      = 19,
216     gdb_stmm4      = 20,
217     gdb_stmm5      = 21,
218     gdb_stmm6      = 22,
219     gdb_stmm7      = 23,
220     gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl,
221     gdb_fstat      = 25,    gdb_fsw     = gdb_fstat,
222     gdb_ftag       = 26,    gdb_ftw     = gdb_ftag,
223     gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg,
224     gdb_fioff      = 28,    gdb_ip      = gdb_fioff,
225     gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg,
226     gdb_fooff      = 30,    gdb_dp      = gdb_fooff,
227     gdb_fop        = 31,
228     gdb_xmm0       = 32,
229     gdb_xmm1       = 33,
230     gdb_xmm2       = 34,
231     gdb_xmm3       = 35,
232     gdb_xmm4       = 36,
233     gdb_xmm5       = 37,
234     gdb_xmm6       = 38,
235     gdb_xmm7       = 39,
236     gdb_mxcsr      = 40,
237     gdb_mm0        = 41,
238     gdb_mm1        = 42,
239     gdb_mm2        = 43,
240     gdb_mm3        = 44,
241     gdb_mm4        = 45,
242     gdb_mm5        = 46,
243     gdb_mm6        = 47,
244     gdb_mm7        = 48,
245     gdb_ymm0       = gdb_xmm0,
246     gdb_ymm1       = gdb_xmm1,
247     gdb_ymm2       = gdb_xmm2,
248     gdb_ymm3       = gdb_xmm3,
249     gdb_ymm4       = gdb_xmm4,
250     gdb_ymm5       = gdb_xmm5,
251     gdb_ymm6       = gdb_xmm6,
252     gdb_ymm7       = gdb_xmm7
253 };
254 
255 // AVX support isn't working at all from user space, so disable it for now.
256 enum DNBArchImplI386::AVXPresence DNBArchImplI386::s_has_avx = DNBArchImplI386::kAVXNotPresent;
257 
258 uint64_t
259 DNBArchImplI386::GetPC(uint64_t failValue)
260 {
261     // Get program counter
262     if (GetGPRState(false) == KERN_SUCCESS)
263         return m_state.context.gpr.__eip;
264     return failValue;
265 }
266 
267 kern_return_t
268 DNBArchImplI386::SetPC(uint64_t value)
269 {
270     // Get program counter
271     kern_return_t err = GetGPRState(false);
272     if (err == KERN_SUCCESS)
273     {
274         m_state.context.gpr.__eip = value;
275         err = SetGPRState();
276     }
277     return err == KERN_SUCCESS;
278 }
279 
280 uint64_t
281 DNBArchImplI386::GetSP(uint64_t failValue)
282 {
283     // Get stack pointer
284     if (GetGPRState(false) == KERN_SUCCESS)
285         return m_state.context.gpr.__esp;
286     return failValue;
287 }
288 
289 // Uncomment the value below to verify the values in the debugger.
290 //#define DEBUG_GPR_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
291 //#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg
292 
293 kern_return_t
294 DNBArchImplI386::GetGPRState(bool force)
295 {
296     if (force || m_state.GetError(e_regSetGPR, Read))
297     {
298 #if DEBUG_GPR_VALUES
299         SET_GPR(eax);
300         SET_GPR(ebx);
301         SET_GPR(ecx);
302         SET_GPR(edx);
303         SET_GPR(edi);
304         SET_GPR(esi);
305         SET_GPR(ebp);
306         SET_GPR(esp);
307         SET_GPR(ss);
308         SET_GPR(eflags);
309         SET_GPR(eip);
310         SET_GPR(cs);
311         SET_GPR(ds);
312         SET_GPR(es);
313         SET_GPR(fs);
314         SET_GPR(gs);
315         m_state.SetError(e_regSetGPR, Read, 0);
316 #else
317         mach_msg_type_number_t count = e_regSetWordSizeGPR;
318         m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count));
319 #endif
320     }
321     return m_state.GetError(e_regSetGPR, Read);
322 }
323 
324 // Uncomment the value below to verify the values in the debugger.
325 //#define DEBUG_FPU_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
326 
327 kern_return_t
328 DNBArchImplI386::GetFPUState(bool force)
329 {
330     if (force || m_state.GetError(e_regSetFPU, Read))
331     {
332         if (DEBUG_FPU_REGS)
333         {
334             if (CPUHasAVX() || FORCE_AVX_REGS)
335             {
336                 m_state.context.fpu.avx.__fpu_reserved[0] = -1;
337                 m_state.context.fpu.avx.__fpu_reserved[1] = -1;
338                 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234;
339                 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678;
340                 m_state.context.fpu.avx.__fpu_ftw = 1;
341                 m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX;
342                 m_state.context.fpu.avx.__fpu_fop = 2;
343                 m_state.context.fpu.avx.__fpu_ip = 3;
344                 m_state.context.fpu.avx.__fpu_cs = 4;
345                 m_state.context.fpu.avx.__fpu_rsrv2 = 5;
346                 m_state.context.fpu.avx.__fpu_dp = 6;
347                 m_state.context.fpu.avx.__fpu_ds = 7;
348                 m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX;
349                 m_state.context.fpu.avx.__fpu_mxcsr = 8;
350                 m_state.context.fpu.avx.__fpu_mxcsrmask = 9;
351                 int i;
352                 for (i=0; i<16; ++i)
353                 {
354                     if (i<10)
355                     {
356                         m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a';
357                         m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b';
358                         m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c';
359                         m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd';
360                         m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e';
361                         m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f';
362                         m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g';
363                         m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h';
364                     }
365                     else
366                     {
367                         m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
368                         m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
369                         m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
370                         m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
371                         m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
372                         m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
373                         m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
374                         m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
375                     }
376 
377                     m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0';
378                     m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1';
379                     m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2';
380                     m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3';
381                     m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4';
382                     m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5';
383                     m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6';
384                     m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7';
385                 }
386                 for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
387                     m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN;
388                 m_state.context.fpu.avx.__fpu_reserved1 = -1;
389                 for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i)
390                     m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
391 
392                 for (i = 0; i < 16; ++i)
393                 {
394                     m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0';
395                     m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1';
396                     m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2';
397                     m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3';
398                     m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4';
399                     m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5';
400                     m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6';
401                     m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7';
402                 }
403             }
404             else
405             {
406                 m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
407                 m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
408                 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
409                 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
410                 m_state.context.fpu.no_avx.__fpu_ftw = 1;
411                 m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
412                 m_state.context.fpu.no_avx.__fpu_fop = 2;
413                 m_state.context.fpu.no_avx.__fpu_ip = 3;
414                 m_state.context.fpu.no_avx.__fpu_cs = 4;
415                 m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
416                 m_state.context.fpu.no_avx.__fpu_dp = 6;
417                 m_state.context.fpu.no_avx.__fpu_ds = 7;
418                 m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
419                 m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
420                 m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
421                 int i;
422                 for (i=0; i<16; ++i)
423                 {
424                     if (i<10)
425                     {
426                         m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
427                         m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
428                         m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
429                         m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
430                         m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
431                         m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
432                         m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
433                         m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
434                     }
435                     else
436                     {
437                         m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
438                         m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
439                         m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
440                         m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
441                         m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
442                         m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
443                         m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
444                         m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
445                     }
446 
447                     m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
448                     m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
449                     m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
450                     m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
451                     m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
452                     m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
453                     m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
454                     m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
455                 }
456                 for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
457                     m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
458                 m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
459             }
460             m_state.SetError(e_regSetFPU, Read, 0);
461         }
462         else
463         {
464             if (CPUHasAVX() || FORCE_AVX_REGS)
465             {
466                 mach_msg_type_number_t count = e_regSetWordSizeAVX;
467                 m_state.SetError (e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count));
468                 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in)) => 0x%8.8x",
469                                   m_thread->ThreadID(), __i386_AVX_STATE, count, e_regSetWordSizeAVX,
470                                   m_state.GetError(e_regSetFPU, Read));
471             }
472             else
473             {
474                 mach_msg_type_number_t count = e_regSetWordSizeFPU;
475                 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count));
476                 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x",
477                                   m_thread->ThreadID(), __i386_FLOAT_STATE, count, e_regSetWordSizeFPU,
478                                   m_state.GetError(e_regSetFPU, Read));
479             }
480         }
481     }
482     return m_state.GetError(e_regSetFPU, Read);
483 }
484 
485 kern_return_t
486 DNBArchImplI386::GetEXCState(bool force)
487 {
488     if (force || m_state.GetError(e_regSetEXC, Read))
489     {
490         mach_msg_type_number_t count = e_regSetWordSizeEXC;
491         m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->ThreadID(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count));
492     }
493     return m_state.GetError(e_regSetEXC, Read);
494 }
495 
496 kern_return_t
497 DNBArchImplI386::SetGPRState()
498 {
499     m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->ThreadID(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR));
500     return m_state.GetError(e_regSetGPR, Write);
501 }
502 
503 kern_return_t
504 DNBArchImplI386::SetFPUState()
505 {
506     if (DEBUG_FPU_REGS)
507     {
508         m_state.SetError(e_regSetFPU, Write, 0);
509         return m_state.GetError(e_regSetFPU, Write);
510     }
511     else
512     {
513         if (CPUHasAVX() || FORCE_AVX_REGS)
514             m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX));
515         else
516             m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU));
517         return m_state.GetError(e_regSetFPU, Write);
518     }
519 }
520 
521 kern_return_t
522 DNBArchImplI386::SetEXCState()
523 {
524     m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->ThreadID(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC));
525     return m_state.GetError(e_regSetEXC, Write);
526 }
527 
528 kern_return_t
529 DNBArchImplI386::GetDBGState(bool force)
530 {
531     if (force || m_state.GetError(e_regSetDBG, Read))
532     {
533         mach_msg_type_number_t count = e_regSetWordSizeDBG;
534         m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->ThreadID(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count));
535     }
536     return m_state.GetError(e_regSetDBG, Read);
537 }
538 
539 kern_return_t
540 DNBArchImplI386::SetDBGState()
541 {
542     m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->ThreadID(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG));
543     return m_state.GetError(e_regSetDBG, Write);
544 }
545 
546 void
547 DNBArchImplI386::ThreadWillResume()
548 {
549     // Do we need to step this thread? If so, let the mach thread tell us so.
550     if (m_thread->IsStepping())
551     {
552         // This is the primary thread, let the arch do anything it needs
553         EnableHardwareSingleStep(true);
554     }
555 
556     // Reset the debug status register, if necessary, before we resume.
557     kern_return_t kret = GetDBGState(false);
558     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
559     if (kret != KERN_SUCCESS)
560         return;
561 
562     DBG &debug_state = m_state.context.dbg;
563     bool need_reset = false;
564     uint32_t i, num = NumSupportedHardwareWatchpoints();
565     for (i = 0; i < num; ++i)
566         if (IsWatchpointHit(debug_state, i))
567             need_reset = true;
568 
569     if (need_reset)
570     {
571         ClearWatchpointHits(debug_state);
572         kret = SetDBGState();
573         DNBLogThreadedIf(LOG_WATCHPOINTS,"DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
574     }
575 }
576 
577 bool
578 DNBArchImplI386::ThreadDidStop()
579 {
580     bool success = true;
581 
582     m_state.InvalidateAllRegisterStates();
583 
584     // Are we stepping a single instruction?
585     if (GetGPRState(true) == KERN_SUCCESS)
586     {
587         // We are single stepping, was this the primary thread?
588         if (m_thread->IsStepping())
589         {
590             // This was the primary thread, we need to clear the trace
591             // bit if so.
592             success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
593         }
594         else
595         {
596             // The MachThread will automatically restore the suspend count
597             // in ThreadDidStop(), so we don't need to do anything here if
598             // we weren't the primary thread the last time
599         }
600     }
601     return success;
602 }
603 
604 bool
605 DNBArchImplI386::NotifyException(MachException::Data& exc)
606 {
607     switch (exc.exc_type)
608     {
609     case EXC_BAD_ACCESS:
610         break;
611     case EXC_BAD_INSTRUCTION:
612         break;
613     case EXC_ARITHMETIC:
614         break;
615     case EXC_EMULATION:
616         break;
617     case EXC_SOFTWARE:
618         break;
619     case EXC_BREAKPOINT:
620         if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
621         {
622             // exc_code = EXC_I386_BPT
623             //
624             nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
625             if (pc != INVALID_NUB_ADDRESS && pc > 0)
626             {
627                 pc -= 1;
628                 // Check for a breakpoint at one byte prior to the current PC value
629                 // since the PC will be just past the trap.
630 
631                 nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc);
632                 if (NUB_BREAK_ID_IS_VALID(breakID))
633                 {
634                     // Backup the PC for i386 since the trap was taken and the PC
635                     // is at the address following the single byte trap instruction.
636                     if (m_state.context.gpr.__eip > 0)
637                     {
638                         m_state.context.gpr.__eip = pc;
639                         // Write the new PC back out
640                         SetGPRState ();
641                     }
642                 }
643                 return true;
644             }
645         }
646         else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1)
647         {
648             // exc_code = EXC_I386_SGL
649             //
650             // Check whether this corresponds to a watchpoint hit event.
651             // If yes, set the exc_sub_code to the data break address.
652             nub_addr_t addr = 0;
653             uint32_t hw_index = GetHardwareWatchpointHit(addr);
654             if (hw_index != INVALID_NUB_HW_INDEX)
655             {
656                 exc.exc_data[1] = addr;
657                 // Piggyback the hw_index in the exc.data.
658                 exc.exc_data.push_back(hw_index);
659             }
660 
661             return true;
662         }
663         break;
664     case EXC_SYSCALL:
665         break;
666     case EXC_MACH_SYSCALL:
667         break;
668     case EXC_RPC_ALERT:
669         break;
670     }
671     return false;
672 }
673 
674 uint32_t
675 DNBArchImplI386::NumSupportedHardwareWatchpoints()
676 {
677     // Available debug address registers: dr0, dr1, dr2, dr3.
678     return 4;
679 }
680 
681 static uint32_t
682 size_and_rw_bits(nub_size_t size, bool read, bool write)
683 {
684     uint32_t rw;
685     if (read) {
686         rw = 0x3; // READ or READ/WRITE
687     } else if (write) {
688         rw = 0x1; // WRITE
689     } else {
690         assert(0 && "read and write cannot both be false");
691     }
692 
693     switch (size) {
694     case 1:
695         return rw;
696     case 2:
697         return (0x1 << 2) | rw;
698     case 4:
699         return (0x3 << 2) | rw;
700     case 8:
701         return (0x2 << 2) | rw;
702     default:
703         assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
704     }
705 }
706 void
707 DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write)
708 {
709     // Set both dr7 (debug control register) and dri (debug address register).
710 
711     // dr7{7-0} encodes the local/gloabl enable bits:
712     //  global enable --. .-- local enable
713     //                  | |
714     //                  v v
715     //      dr0 -> bits{1-0}
716     //      dr1 -> bits{3-2}
717     //      dr2 -> bits{5-4}
718     //      dr3 -> bits{7-6}
719     //
720     // dr7{31-16} encodes the rw/len bits:
721     //  b_x+3, b_x+2, b_x+1, b_x
722     //      where bits{x+1, x} => rw
723     //            0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused)
724     //      and bits{x+3, x+2} => len
725     //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
726     //
727     //      dr0 -> bits{19-16}
728     //      dr1 -> bits{23-20}
729     //      dr2 -> bits{27-24}
730     //      dr3 -> bits{31-28}
731     debug_state.__dr7 |= (1 << (2*hw_index) |
732                           size_and_rw_bits(size, read, write) << (16+4*hw_index));
733     uint32_t addr_32 = addr & 0xffffffff;
734     switch (hw_index) {
735     case 0:
736         debug_state.__dr0 = addr_32; break;
737     case 1:
738         debug_state.__dr1 = addr_32; break;
739     case 2:
740         debug_state.__dr2 = addr_32; break;
741     case 3:
742         debug_state.__dr3 = addr_32; break;
743     default:
744         assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
745     }
746     return;
747 }
748 
749 void
750 DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index)
751 {
752     debug_state.__dr7 &= ~(3 << (2*hw_index));
753     switch (hw_index) {
754     case 0:
755         debug_state.__dr0 = 0; break;
756     case 1:
757         debug_state.__dr1 = 0; break;
758     case 2:
759         debug_state.__dr2 = 0; break;
760     case 3:
761         debug_state.__dr3 = 0; break;
762     default:
763         assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
764     }
765     return;
766 }
767 
768 bool
769 DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index)
770 {
771     // Check dr7 (debug control register) for local/global enable bits:
772     //  global enable --. .-- local enable
773     //                  | |
774     //                  v v
775     //      dr0 -> bits{1-0}
776     //      dr1 -> bits{3-2}
777     //      dr2 -> bits{5-4}
778     //      dr3 -> bits{7-6}
779     return (debug_state.__dr7 & (3 << (2*hw_index))) == 0;
780 }
781 
782 // Resets local copy of debug status register to wait for the next debug excpetion.
783 void
784 DNBArchImplI386::ClearWatchpointHits(DBG &debug_state)
785 {
786     // See also IsWatchpointHit().
787     debug_state.__dr6 = 0;
788     return;
789 }
790 
791 bool
792 DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index)
793 {
794     // Check dr6 (debug status register) whether a watchpoint hits:
795     //          is watchpoint hit?
796     //                  |
797     //                  v
798     //      dr0 -> bits{0}
799     //      dr1 -> bits{1}
800     //      dr2 -> bits{2}
801     //      dr3 -> bits{3}
802     return (debug_state.__dr6 & (1 << hw_index));
803 }
804 
805 nub_addr_t
806 DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
807 {
808     switch (hw_index) {
809     case 0:
810         return debug_state.__dr0;
811     case 1:
812         return debug_state.__dr1;
813     case 2:
814         return debug_state.__dr2;
815     case 3:
816         return debug_state.__dr3;
817     default:
818         assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
819     }
820 }
821 
822 uint32_t
823 DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
824 {
825     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
826 
827     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
828 
829     // Can only watch 1, 2, 4, or 8 bytes.
830     if (!(size == 1 || size == 2 || size == 4 || size == 8))
831         return INVALID_NUB_HW_INDEX;
832 
833     // We must watch for either read or write
834     if (read == false && write == false)
835         return INVALID_NUB_HW_INDEX;
836 
837     // Read the debug state
838     kern_return_t kret = GetDBGState(false);
839 
840     if (kret == KERN_SUCCESS)
841     {
842         // Check to make sure we have the needed hardware support
843         uint32_t i = 0;
844 
845         DBG &debug_state = m_state.context.dbg;
846         for (i = 0; i < num_hw_watchpoints; ++i)
847         {
848             if (IsWatchpointVacant(debug_state, i))
849                 break;
850         }
851 
852         // See if we found an available hw breakpoint slot above
853         if (i < num_hw_watchpoints)
854         {
855             // Modify our local copy of the debug state, first.
856             SetWatchpoint(debug_state, i, addr, size, read, write);
857             // Now set the watch point in the inferior.
858             kret = SetDBGState();
859             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
860 
861             if (kret == KERN_SUCCESS)
862                 return i;
863         }
864         else
865         {
866             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
867         }
868     }
869     return INVALID_NUB_HW_INDEX;
870 }
871 
872 bool
873 DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index)
874 {
875     kern_return_t kret = GetDBGState(false);
876 
877     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
878     if (kret == KERN_SUCCESS)
879     {
880         DBG &debug_state = m_state.context.dbg;
881         if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index))
882         {
883             // Modify our local copy of the debug state, first.
884             ClearWatchpoint(debug_state, hw_index);
885             // Now disable the watch point in the inferior.
886             kret = SetDBGState();
887             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::DisableHardwareWatchpoint( %u )",
888                              hw_index);
889 
890             if (kret == KERN_SUCCESS)
891                 return true;
892         }
893     }
894     return false;
895 }
896 
897 DNBArchImplI386::DBG DNBArchImplI386::Global_Debug_State = {0,0,0,0,0,0,0,0};
898 bool DNBArchImplI386::Valid_Global_Debug_State = false;
899 
900 // Use this callback from MachThread, which in turn was called from MachThreadList, to update
901 // the global view of the hardware watchpoint state, so that when new thread comes along, they
902 // get to inherit the existing hardware watchpoint state.
903 void
904 DNBArchImplI386::HardwareWatchpointStateChanged ()
905 {
906     Global_Debug_State = m_state.context.dbg;
907     Valid_Global_Debug_State = true;
908 }
909 
910 // Iterate through the debug status register; return the index of the first hit.
911 uint32_t
912 DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr)
913 {
914     // Read the debug state
915     kern_return_t kret = GetDBGState(false);
916     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
917     if (kret == KERN_SUCCESS)
918     {
919         DBG &debug_state = m_state.context.dbg;
920         uint32_t i, num = NumSupportedHardwareWatchpoints();
921         for (i = 0; i < num; ++i)
922         {
923             if (IsWatchpointHit(debug_state, i))
924             {
925                 addr = GetWatchAddress(debug_state, i);
926                 DNBLogThreadedIf(LOG_WATCHPOINTS,
927                                  "DNBArchImplI386::GetHardwareWatchpointHit() found => %u (addr = %8.8p).",
928                                  i, addr);
929                 return i;
930             }
931         }
932     }
933     return INVALID_NUB_HW_INDEX;
934 }
935 
936 // Set the single step bit in the processor status register.
937 kern_return_t
938 DNBArchImplI386::EnableHardwareSingleStep (bool enable)
939 {
940     if (GetGPRState(false) == KERN_SUCCESS)
941     {
942         const uint32_t trace_bit = 0x100u;
943         if (enable)
944             m_state.context.gpr.__eflags |= trace_bit;
945         else
946             m_state.context.gpr.__eflags &= ~trace_bit;
947         return SetGPRState();
948     }
949     return m_state.GetError(e_regSetGPR, Read);
950 }
951 
952 
953 //----------------------------------------------------------------------
954 // Register information defintions
955 //----------------------------------------------------------------------
956 
957 
958 #define GPR_OFFSET(reg) (offsetof (DNBArchImplI386::GPR, __##reg))
959 #define FPU_OFFSET(reg) (offsetof (DNBArchImplI386::FPU, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.no_avx))
960 #define AVX_OFFSET(reg) (offsetof (DNBArchImplI386::AVX, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.avx))
961 #define EXC_OFFSET(reg) (offsetof (DNBArchImplI386::EXC, __##reg)     + offsetof (DNBArchImplI386::Context, exc))
962 
963 #define GPR_SIZE(reg)       (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg))
964 #define FPU_SIZE_UINT(reg)  (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg))
965 #define FPU_SIZE_MMST(reg)  (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg))
966 #define FPU_SIZE_XMM(reg)   (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg))
967 #define FPU_SIZE_YMM(reg)   (32)
968 #define EXC_SIZE(reg)       (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg))
969 
970 // This does not accurately identify the location of ymm0...7 in
971 // Context.fpu.avx.  That is because there is a bunch of padding
972 // in Context.fpu.avx that we don't need.  Offset macros lay out
973 // the register state that Debugserver transmits to the debugger
974 // -- not to interpret the thread_get_state info.
975 #define AVX_OFFSET_YMM(n)   (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n))
976 
977 // These macros will auto define the register name, alt name, register size,
978 // register offset, encoding, format and native register. This ensures that
979 // the register state structures are defined correctly and have the correct
980 // sizes and offsets.
981 
982 // General purpose registers for 64 bit
983 const DNBRegisterInfo
984 DNBArchImplI386::g_gpr_registers[] =
985 {
986 { e_regSetGPR, gpr_eax,     "eax"   , NULL      , Uint, Hex, GPR_SIZE(eax),     GPR_OFFSET(eax)     , gcc_eax   , dwarf_eax     , -1                    , gdb_eax   },
987 { e_regSetGPR, gpr_ebx,     "ebx"   , NULL      , Uint, Hex, GPR_SIZE(ebx),     GPR_OFFSET(ebx)     , gcc_ebx   , dwarf_ebx     , -1                    , gdb_ebx   },
988 { e_regSetGPR, gpr_ecx,     "ecx"   , NULL      , Uint, Hex, GPR_SIZE(ecx),     GPR_OFFSET(ecx)     , gcc_ecx   , dwarf_ecx     , -1                    , gdb_ecx   },
989 { e_regSetGPR, gpr_edx,     "edx"   , NULL      , Uint, Hex, GPR_SIZE(edx),     GPR_OFFSET(edx)     , gcc_edx   , dwarf_edx     , -1                    , gdb_edx   },
990 { e_regSetGPR, gpr_edi,     "edi"   , NULL      , Uint, Hex, GPR_SIZE(edi),     GPR_OFFSET(edi)     , gcc_edi   , dwarf_edi     , -1                    , gdb_edi   },
991 { e_regSetGPR, gpr_esi,     "esi"   , NULL      , Uint, Hex, GPR_SIZE(esi),     GPR_OFFSET(esi)     , gcc_esi   , dwarf_esi     , -1                    , gdb_esi   },
992 { e_regSetGPR, gpr_ebp,     "ebp"   , "fp"      , Uint, Hex, GPR_SIZE(ebp),     GPR_OFFSET(ebp)     , gcc_ebp   , dwarf_ebp     , GENERIC_REGNUM_FP     , gdb_ebp   },
993 { e_regSetGPR, gpr_esp,     "esp"   , "sp"      , Uint, Hex, GPR_SIZE(esp),     GPR_OFFSET(esp)     , gcc_esp   , dwarf_esp     , GENERIC_REGNUM_SP     , gdb_esp   },
994 { e_regSetGPR, gpr_ss,      "ss"    , NULL      , Uint, Hex, GPR_SIZE(ss),      GPR_OFFSET(ss)      , -1        , -1            , -1                    , gdb_ss    },
995 { e_regSetGPR, gpr_eflags,  "eflags", "flags"   , Uint, Hex, GPR_SIZE(eflags),  GPR_OFFSET(eflags)  , gcc_eflags, dwarf_eflags  , GENERIC_REGNUM_FLAGS  , gdb_eflags},
996 { e_regSetGPR, gpr_eip,     "eip"   , "pc"      , Uint, Hex, GPR_SIZE(eip),     GPR_OFFSET(eip)     , gcc_eip   , dwarf_eip     , GENERIC_REGNUM_PC     , gdb_eip   },
997 { e_regSetGPR, gpr_cs,      "cs"    , NULL      , Uint, Hex, GPR_SIZE(cs),      GPR_OFFSET(cs)      , -1        , -1            , -1                    , gdb_cs    },
998 { e_regSetGPR, gpr_ds,      "ds"    , NULL      , Uint, Hex, GPR_SIZE(ds),      GPR_OFFSET(ds)      , -1        , -1            , -1                    , gdb_ds    },
999 { e_regSetGPR, gpr_es,      "es"    , NULL      , Uint, Hex, GPR_SIZE(es),      GPR_OFFSET(es)      , -1        , -1            , -1                    , gdb_es    },
1000 { e_regSetGPR, gpr_fs,      "fs"    , NULL      , Uint, Hex, GPR_SIZE(fs),      GPR_OFFSET(fs)      , -1        , -1            , -1                    , gdb_fs    },
1001 { e_regSetGPR, gpr_gs,      "gs"    , NULL      , Uint, Hex, GPR_SIZE(gs),      GPR_OFFSET(gs)      , -1        , -1            , -1                    , gdb_gs    }
1002 };
1003 
1004 
1005 const DNBRegisterInfo
1006 DNBArchImplI386::g_fpu_registers_no_avx[] =
1007 {
1008 { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , FPU_OFFSET(fcw)       , -1, -1, -1, -1 },
1009 { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , FPU_OFFSET(fsw)       , -1, -1, -1, -1 },
1010 { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , FPU_OFFSET(ftw)       , -1, -1, -1, -1 },
1011 { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , FPU_OFFSET(fop)       , -1, -1, -1, -1 },
1012 { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , FPU_OFFSET(ip)        , -1, -1, -1, -1 },
1013 { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , FPU_OFFSET(cs)        , -1, -1, -1, -1 },
1014 { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , FPU_OFFSET(dp)        , -1, -1, -1, -1 },
1015 { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , FPU_OFFSET(ds)        , -1, -1, -1, -1 },
1016 { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , FPU_OFFSET(mxcsr)     , -1, -1, -1, -1 },
1017 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 },
1018 
1019 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), -1, dwarf_stmm0, -1, gdb_stmm0 },
1020 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), -1, dwarf_stmm1, -1, gdb_stmm1 },
1021 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), -1, dwarf_stmm2, -1, gdb_stmm2 },
1022 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), -1, dwarf_stmm3, -1, gdb_stmm3 },
1023 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), -1, dwarf_stmm4, -1, gdb_stmm4 },
1024 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), -1, dwarf_stmm5, -1, gdb_stmm5 },
1025 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), -1, dwarf_stmm6, -1, gdb_stmm6 },
1026 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), -1, dwarf_stmm7, -1, gdb_stmm7 },
1027 
1028 { e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), -1, dwarf_xmm0, -1, gdb_xmm0 },
1029 { e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), -1, dwarf_xmm1, -1, gdb_xmm1 },
1030 { e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), -1, dwarf_xmm2, -1, gdb_xmm2 },
1031 { e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), -1, dwarf_xmm3, -1, gdb_xmm3 },
1032 { e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), -1, dwarf_xmm4, -1, gdb_xmm4 },
1033 { e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), -1, dwarf_xmm5, -1, gdb_xmm5 },
1034 { e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), -1, dwarf_xmm6, -1, gdb_xmm6 },
1035 { e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), -1, dwarf_xmm7, -1, gdb_xmm7 }
1036 };
1037 
1038 const DNBRegisterInfo
1039 DNBArchImplI386::g_fpu_registers_avx[] =
1040 {
1041 { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , AVX_OFFSET(fcw)       , -1, -1, -1, -1 },
1042 { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , AVX_OFFSET(fsw)       , -1, -1, -1, -1 },
1043 { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , AVX_OFFSET(ftw)       , -1, -1, -1, -1 },
1044 { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , AVX_OFFSET(fop)       , -1, -1, -1, -1 },
1045 { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , AVX_OFFSET(ip)        , -1, -1, -1, -1 },
1046 { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , AVX_OFFSET(cs)        , -1, -1, -1, -1 },
1047 { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , AVX_OFFSET(dp)        , -1, -1, -1, -1 },
1048 { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , AVX_OFFSET(ds)        , -1, -1, -1, -1 },
1049 { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , AVX_OFFSET(mxcsr)     , -1, -1, -1, -1 },
1050 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , -1, -1, -1, -1 },
1051 
1052 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), -1, dwarf_stmm0, -1, gdb_stmm0 },
1053 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), -1, dwarf_stmm1, -1, gdb_stmm1 },
1054 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), -1, dwarf_stmm2, -1, gdb_stmm2 },
1055 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), -1, dwarf_stmm3, -1, gdb_stmm3 },
1056 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), -1, dwarf_stmm4, -1, gdb_stmm4 },
1057 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), -1, dwarf_stmm5, -1, gdb_stmm5 },
1058 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), -1, dwarf_stmm6, -1, gdb_stmm6 },
1059 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), -1, dwarf_stmm7, -1, gdb_stmm7 },
1060 
1061 { e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), AVX_OFFSET(xmm0), -1, dwarf_xmm0, -1, gdb_xmm0 },
1062 { e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), AVX_OFFSET(xmm1), -1, dwarf_xmm1, -1, gdb_xmm1 },
1063 { e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), AVX_OFFSET(xmm2), -1, dwarf_xmm2, -1, gdb_xmm2 },
1064 { e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), AVX_OFFSET(xmm3), -1, dwarf_xmm3, -1, gdb_xmm3 },
1065 { e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), AVX_OFFSET(xmm4), -1, dwarf_xmm4, -1, gdb_xmm4 },
1066 { e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), AVX_OFFSET(xmm5), -1, dwarf_xmm5, -1, gdb_xmm5 },
1067 { e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), AVX_OFFSET(xmm6), -1, dwarf_xmm6, -1, gdb_xmm6 },
1068 { e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), AVX_OFFSET(xmm7), -1, dwarf_xmm7, -1, gdb_xmm7 },
1069 
1070 { e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), -1, dwarf_ymm0, -1, gdb_ymm0 },
1071 { e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), -1, dwarf_ymm1, -1, gdb_ymm1 },
1072 { e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), -1, dwarf_ymm2, -1, gdb_ymm2 },
1073 { e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), -1, dwarf_ymm3, -1, gdb_ymm3 },
1074 { e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), -1, dwarf_ymm4, -1, gdb_ymm4 },
1075 { e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), -1, dwarf_ymm5, -1, gdb_ymm5 },
1076 { e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), -1, dwarf_ymm6, -1, gdb_ymm6 },
1077 { e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), -1, dwarf_ymm7, -1, gdb_ymm7 },
1078 };
1079 
1080 const DNBRegisterInfo
1081 DNBArchImplI386::g_exc_registers[] =
1082 {
1083 { e_regSetEXC, exc_trapno,      "trapno"    , NULL, Uint, Hex, EXC_SIZE (trapno)    , EXC_OFFSET (trapno)       , -1, -1, -1, -1 },
1084 { e_regSetEXC, exc_err,         "err"       , NULL, Uint, Hex, EXC_SIZE (err)       , EXC_OFFSET (err)          , -1, -1, -1, -1 },
1085 { e_regSetEXC, exc_faultvaddr,  "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr)   , -1, -1, -1, -1 }
1086 };
1087 
1088 // Number of registers in each register set
1089 const size_t DNBArchImplI386::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
1090 const size_t DNBArchImplI386::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo);
1091 const size_t DNBArchImplI386::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo);
1092 const size_t DNBArchImplI386::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
1093 const size_t DNBArchImplI386::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
1094 const size_t DNBArchImplI386::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
1095 
1096 //----------------------------------------------------------------------
1097 // Register set definitions. The first definitions at register set index
1098 // of zero is for all registers, followed by other registers sets. The
1099 // register information for the all register set need not be filled in.
1100 //----------------------------------------------------------------------
1101 const DNBRegisterSetInfo
1102 DNBArchImplI386::g_reg_sets_no_avx[] =
1103 {
1104     { "i386 Registers",             NULL,                   k_num_all_registers_no_avx },
1105     { "General Purpose Registers",  g_gpr_registers,        k_num_gpr_registers        },
1106     { "Floating Point Registers",   g_fpu_registers_no_avx, k_num_fpu_registers_no_avx },
1107     { "Exception State Registers",  g_exc_registers,        k_num_exc_registers        }
1108 };
1109 
1110 const DNBRegisterSetInfo
1111 DNBArchImplI386::g_reg_sets_avx[] =
1112 {
1113     { "i386 Registers",             NULL,                   k_num_all_registers_avx },
1114     { "General Purpose Registers",  g_gpr_registers,        k_num_gpr_registers     },
1115     { "Floating Point Registers",   g_fpu_registers_avx,    k_num_fpu_registers_avx },
1116     { "Exception State Registers",  g_exc_registers,        k_num_exc_registers     }
1117 };
1118 
1119 // Total number of register sets for this architecture
1120 const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets_no_avx)/sizeof(DNBRegisterSetInfo);
1121 
1122 DNBArchProtocol *
1123 DNBArchImplI386::Create (MachThread *thread)
1124 {
1125     DNBArchImplI386 *obj = new DNBArchImplI386 (thread);
1126 
1127     // When new thread comes along, it tries to inherit from the global debug state, if it is valid.
1128     if (Valid_Global_Debug_State)
1129     {
1130         obj->m_state.context.dbg = Global_Debug_State;
1131         kern_return_t kret = obj->SetDBGState();
1132         DNBLogThreadedIf(LOG_WATCHPOINTS,
1133                          "DNBArchImplX86_64::Create() Inherit and SetDBGState() => 0x%8.8x.", kret);
1134     }
1135     return obj;
1136 }
1137 
1138 const uint8_t * const
1139 DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size)
1140 {
1141     static const uint8_t g_breakpoint_opcode[] = { 0xCC };
1142     if (byte_size == 1)
1143         return g_breakpoint_opcode;
1144     return NULL;
1145 }
1146 
1147 const DNBRegisterSetInfo *
1148 DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets)
1149 {
1150     *num_reg_sets = k_num_register_sets;
1151     if (CPUHasAVX() || FORCE_AVX_REGS)
1152         return g_reg_sets_avx;
1153     else
1154         return g_reg_sets_no_avx;
1155 }
1156 
1157 
1158 void
1159 DNBArchImplI386::Initialize()
1160 {
1161     DNBArchPluginInfo arch_plugin_info =
1162     {
1163         CPU_TYPE_I386,
1164         DNBArchImplI386::Create,
1165         DNBArchImplI386::GetRegisterSetInfo,
1166         DNBArchImplI386::SoftwareBreakpointOpcode
1167     };
1168 
1169     // Register this arch plug-in with the main protocol class
1170     DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
1171 }
1172 
1173 bool
1174 DNBArchImplI386::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
1175 {
1176     if (set == REGISTER_SET_GENERIC)
1177     {
1178         switch (reg)
1179         {
1180         case GENERIC_REGNUM_PC:     // Program Counter
1181             set = e_regSetGPR;
1182             reg = gpr_eip;
1183             break;
1184 
1185         case GENERIC_REGNUM_SP:     // Stack Pointer
1186             set = e_regSetGPR;
1187             reg = gpr_esp;
1188             break;
1189 
1190         case GENERIC_REGNUM_FP:     // Frame Pointer
1191             set = e_regSetGPR;
1192             reg = gpr_ebp;
1193             break;
1194 
1195         case GENERIC_REGNUM_FLAGS:  // Processor flags register
1196             set = e_regSetGPR;
1197             reg = gpr_eflags;
1198             break;
1199 
1200         case GENERIC_REGNUM_RA:     // Return Address
1201         default:
1202             return false;
1203         }
1204     }
1205 
1206     if (GetRegisterState(set, false) != KERN_SUCCESS)
1207         return false;
1208 
1209     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1210     if (regInfo)
1211     {
1212         value->info = *regInfo;
1213         switch (set)
1214         {
1215         case e_regSetGPR:
1216             if (reg < k_num_gpr_registers)
1217             {
1218                 value->value.uint32 = ((uint32_t*)(&m_state.context.gpr))[reg];
1219                 return true;
1220             }
1221             break;
1222 
1223         case e_regSetFPU:
1224             if (CPUHasAVX() || FORCE_AVX_REGS)
1225             {
1226                 switch (reg)
1227                 {
1228                 case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw));    return true;
1229                 case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw));    return true;
1230                 case fpu_ftw:       value->value.uint8  = m_state.context.fpu.avx.__fpu_ftw;                      return true;
1231                 case fpu_fop:       value->value.uint16 = m_state.context.fpu.avx.__fpu_fop;                      return true;
1232                 case fpu_ip:        value->value.uint32 = m_state.context.fpu.avx.__fpu_ip;                       return true;
1233                 case fpu_cs:        value->value.uint16 = m_state.context.fpu.avx.__fpu_cs;                       return true;
1234                 case fpu_dp:        value->value.uint32 = m_state.context.fpu.avx.__fpu_dp;                       return true;
1235                 case fpu_ds:        value->value.uint16 = m_state.context.fpu.avx.__fpu_ds;                       return true;
1236                 case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr;                    return true;
1237                 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask;                return true;
1238 
1239                 case fpu_stmm0:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, 10);    return true;
1240                 case fpu_stmm1:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, 10);    return true;
1241                 case fpu_stmm2:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, 10);    return true;
1242                 case fpu_stmm3:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, 10);    return true;
1243                 case fpu_stmm4:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, 10);    return true;
1244                 case fpu_stmm5:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, 10);    return true;
1245                 case fpu_stmm6:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, 10);    return true;
1246                 case fpu_stmm7:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, 10);    return true;
1247 
1248                 case fpu_xmm0:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, 16);    return true;
1249                 case fpu_xmm1:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, 16);    return true;
1250                 case fpu_xmm2:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, 16);    return true;
1251                 case fpu_xmm3:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, 16);    return true;
1252                 case fpu_xmm4:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, 16);    return true;
1253                 case fpu_xmm5:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, 16);    return true;
1254                 case fpu_xmm6:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, 16);    return true;
1255                 case fpu_xmm7:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, 16);    return true;
1256 
1257 #define MEMCPY_YMM(n)                                                                           \
1258     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, 16);            \
1259     memcpy((&value->value.uint8) + 16, m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16);
1260                 case fpu_ymm0:      MEMCPY_YMM(0);  return true;
1261                 case fpu_ymm1:      MEMCPY_YMM(1);  return true;
1262                 case fpu_ymm2:      MEMCPY_YMM(2);  return true;
1263                 case fpu_ymm3:      MEMCPY_YMM(3);  return true;
1264                 case fpu_ymm4:      MEMCPY_YMM(4);  return true;
1265                 case fpu_ymm5:      MEMCPY_YMM(5);  return true;
1266                 case fpu_ymm6:      MEMCPY_YMM(6);  return true;
1267                 case fpu_ymm7:      MEMCPY_YMM(7);  return true;
1268 #undef MEMCPY_YMM
1269                 }
1270             }
1271             else
1272             {
1273                 switch (reg)
1274                 {
1275                 case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));    return true;
1276                 case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));    return true;
1277                 case fpu_ftw:       value->value.uint8  = m_state.context.fpu.no_avx.__fpu_ftw;                      return true;
1278                 case fpu_fop:       value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;                      return true;
1279                 case fpu_ip:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;                       return true;
1280                 case fpu_cs:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;                       return true;
1281                 case fpu_dp:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;                       return true;
1282                 case fpu_ds:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;                       return true;
1283                 case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;                    return true;
1284                 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;                return true;
1285 
1286                 case fpu_stmm0:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10);    return true;
1287                 case fpu_stmm1:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10);    return true;
1288                 case fpu_stmm2:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10);    return true;
1289                 case fpu_stmm3:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10);    return true;
1290                 case fpu_stmm4:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10);    return true;
1291                 case fpu_stmm5:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10);    return true;
1292                 case fpu_stmm6:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10);    return true;
1293                 case fpu_stmm7:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10);    return true;
1294 
1295                 case fpu_xmm0:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16);    return true;
1296                 case fpu_xmm1:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16);    return true;
1297                 case fpu_xmm2:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16);    return true;
1298                 case fpu_xmm3:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16);    return true;
1299                 case fpu_xmm4:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16);    return true;
1300                 case fpu_xmm5:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16);    return true;
1301                 case fpu_xmm6:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16);    return true;
1302                 case fpu_xmm7:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16);    return true;
1303                 }
1304             }
1305             break;
1306 
1307         case e_regSetEXC:
1308             if (reg < k_num_exc_registers)
1309             {
1310                 value->value.uint32 = (&m_state.context.exc.__trapno)[reg];
1311                 return true;
1312             }
1313             break;
1314         }
1315     }
1316     return false;
1317 }
1318 
1319 
1320 bool
1321 DNBArchImplI386::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
1322 {
1323     if (set == REGISTER_SET_GENERIC)
1324     {
1325         switch (reg)
1326         {
1327         case GENERIC_REGNUM_PC:     // Program Counter
1328             set = e_regSetGPR;
1329             reg = gpr_eip;
1330             break;
1331 
1332         case GENERIC_REGNUM_SP:     // Stack Pointer
1333             set = e_regSetGPR;
1334             reg = gpr_esp;
1335             break;
1336 
1337         case GENERIC_REGNUM_FP:     // Frame Pointer
1338             set = e_regSetGPR;
1339             reg = gpr_ebp;
1340             break;
1341 
1342         case GENERIC_REGNUM_FLAGS:  // Processor flags register
1343             set = e_regSetGPR;
1344             reg = gpr_eflags;
1345             break;
1346 
1347         case GENERIC_REGNUM_RA:     // Return Address
1348         default:
1349             return false;
1350         }
1351     }
1352 
1353     if (GetRegisterState(set, false) != KERN_SUCCESS)
1354         return false;
1355 
1356     bool success = false;
1357     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1358     if (regInfo)
1359     {
1360         switch (set)
1361         {
1362         case e_regSetGPR:
1363             if (reg < k_num_gpr_registers)
1364             {
1365                 ((uint32_t*)(&m_state.context.gpr))[reg] = value->value.uint32;
1366                 success = true;
1367             }
1368             break;
1369 
1370         case e_regSetFPU:
1371             if (CPUHasAVX() || FORCE_AVX_REGS)
1372             {
1373                 switch (reg)
1374                 {
1375                 case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1376                 case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1377                 case fpu_ftw:       m_state.context.fpu.avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1378                 case fpu_fop:       m_state.context.fpu.avx.__fpu_fop = value->value.uint16;                      success = true; break;
1379                 case fpu_ip:        m_state.context.fpu.avx.__fpu_ip = value->value.uint32;                       success = true; break;
1380                 case fpu_cs:        m_state.context.fpu.avx.__fpu_cs = value->value.uint16;                       success = true; break;
1381                 case fpu_dp:        m_state.context.fpu.avx.__fpu_dp = value->value.uint32;                       success = true; break;
1382                 case fpu_ds:        m_state.context.fpu.avx.__fpu_ds = value->value.uint16;                       success = true; break;
1383                 case fpu_mxcsr:     m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1384                 case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1385 
1386                 case fpu_stmm0:     memcpy (m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1387                 case fpu_stmm1:     memcpy (m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1388                 case fpu_stmm2:     memcpy (m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1389                 case fpu_stmm3:     memcpy (m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1390                 case fpu_stmm4:     memcpy (m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1391                 case fpu_stmm5:     memcpy (m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1392                 case fpu_stmm6:     memcpy (m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1393                 case fpu_stmm7:     memcpy (m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1394 
1395                 case fpu_xmm0:      memcpy(m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1396                 case fpu_xmm1:      memcpy(m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1397                 case fpu_xmm2:      memcpy(m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1398                 case fpu_xmm3:      memcpy(m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1399                 case fpu_xmm4:      memcpy(m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1400                 case fpu_xmm5:      memcpy(m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1401                 case fpu_xmm6:      memcpy(m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1402                 case fpu_xmm7:      memcpy(m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1403 
1404 #define MEMCPY_YMM(n)                                                                           \
1405     memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, 16);            \
1406     memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, (&value->value.uint8) + 16, 16);
1407                 case fpu_ymm0:      MEMCPY_YMM(0);  return true;
1408                 case fpu_ymm1:      MEMCPY_YMM(1);  return true;
1409                 case fpu_ymm2:      MEMCPY_YMM(2);  return true;
1410                 case fpu_ymm3:      MEMCPY_YMM(3);  return true;
1411                 case fpu_ymm4:      MEMCPY_YMM(4);  return true;
1412                 case fpu_ymm5:      MEMCPY_YMM(5);  return true;
1413                 case fpu_ymm6:      MEMCPY_YMM(6);  return true;
1414                 case fpu_ymm7:      MEMCPY_YMM(7);  return true;
1415 #undef MEMCPY_YMM
1416                 }
1417             }
1418             else
1419             {
1420                 switch (reg)
1421                 {
1422                 case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1423                 case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1424                 case fpu_ftw:       m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1425                 case fpu_fop:       m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;                      success = true; break;
1426                 case fpu_ip:        m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;                       success = true; break;
1427                 case fpu_cs:        m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;                       success = true; break;
1428                 case fpu_dp:        m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;                       success = true; break;
1429                 case fpu_ds:        m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;                       success = true; break;
1430                 case fpu_mxcsr:     m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1431                 case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1432 
1433                 case fpu_stmm0:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1434                 case fpu_stmm1:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1435                 case fpu_stmm2:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1436                 case fpu_stmm3:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1437                 case fpu_stmm4:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1438                 case fpu_stmm5:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1439                 case fpu_stmm6:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1440                 case fpu_stmm7:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1441 
1442                 case fpu_xmm0:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1443                 case fpu_xmm1:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1444                 case fpu_xmm2:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1445                 case fpu_xmm3:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1446                 case fpu_xmm4:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1447                 case fpu_xmm5:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1448                 case fpu_xmm6:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1449                 case fpu_xmm7:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1450                 }
1451             }
1452             break;
1453 
1454         case e_regSetEXC:
1455             if (reg < k_num_exc_registers)
1456             {
1457                 (&m_state.context.exc.__trapno)[reg] = value->value.uint32;
1458                 success = true;
1459             }
1460             break;
1461         }
1462     }
1463 
1464     if (success)
1465         return SetRegisterState(set) == KERN_SUCCESS;
1466     return false;
1467 }
1468 
1469 
1470 nub_size_t
1471 DNBArchImplI386::GetRegisterContext (void *buf, nub_size_t buf_len)
1472 {
1473     nub_size_t size = sizeof (m_state.context);
1474 
1475     if (buf && buf_len)
1476     {
1477         if (size > buf_len)
1478             size = buf_len;
1479 
1480         bool force = false;
1481         kern_return_t kret;
1482         if ((kret = GetGPRState(force)) != KERN_SUCCESS)
1483         {
1484             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) error: GPR regs failed to read: %u ", buf, buf_len, kret);
1485             size = 0;
1486         }
1487         else if ((kret = GetFPUState(force)) != KERN_SUCCESS)
1488         {
1489             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) error: %s regs failed to read: %u", buf, buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
1490             size = 0;
1491         }
1492         else if ((kret = GetEXCState(force)) != KERN_SUCCESS)
1493         {
1494             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) error: EXC regs failed to read: %u", buf, buf_len, kret);
1495             size = 0;
1496         }
1497         else
1498         {
1499             // Success
1500             ::memcpy (buf, &m_state.context, size);
1501         }
1502     }
1503     DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
1504     // Return the size of the register context even if NULL was passed in
1505     return size;
1506 }
1507 
1508 nub_size_t
1509 DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len)
1510 {
1511     nub_size_t size = sizeof (m_state.context);
1512     if (buf == NULL || buf_len == 0)
1513         size = 0;
1514 
1515     if (size)
1516     {
1517         if (size > buf_len)
1518             size = buf_len;
1519 
1520         ::memcpy (&m_state.context, buf, size);
1521         kern_return_t kret;
1522         if ((kret = SetGPRState()) != KERN_SUCCESS)
1523             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) error: GPR regs failed to write: %u", buf, buf_len, kret);
1524         if ((kret = SetFPUState()) != KERN_SUCCESS)
1525             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) error: %s regs failed to write: %u", buf, buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
1526         if ((kret = SetEXCState()) != KERN_SUCCESS)
1527             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) error: EXP regs failed to write: %u", buf, buf_len, kret);
1528     }
1529     DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
1530     return size;
1531 }
1532 
1533 
1534 
1535 kern_return_t
1536 DNBArchImplI386::GetRegisterState(int set, bool force)
1537 {
1538     switch (set)
1539     {
1540     case e_regSetALL:    return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
1541     case e_regSetGPR:    return GetGPRState(force);
1542     case e_regSetFPU:    return GetFPUState(force);
1543     case e_regSetEXC:    return GetEXCState(force);
1544     default: break;
1545     }
1546     return KERN_INVALID_ARGUMENT;
1547 }
1548 
1549 kern_return_t
1550 DNBArchImplI386::SetRegisterState(int set)
1551 {
1552     // Make sure we have a valid context to set.
1553     if (RegisterSetStateIsValid(set))
1554     {
1555         switch (set)
1556         {
1557         case e_regSetALL:    return SetGPRState() | SetFPUState() | SetEXCState();
1558         case e_regSetGPR:    return SetGPRState();
1559         case e_regSetFPU:    return SetFPUState();
1560         case e_regSetEXC:    return SetEXCState();
1561         default: break;
1562         }
1563     }
1564     return KERN_INVALID_ARGUMENT;
1565 }
1566 
1567 bool
1568 DNBArchImplI386::RegisterSetStateIsValid (int set) const
1569 {
1570     return m_state.RegsAreValid(set);
1571 }
1572 
1573 #endif    // #if defined (__i386__)
1574