DNBArchImplX86_64.h revision fe98a2e6d17f0cb3ffa4a071bb43eb76c339adef
1//===-- DNBArchImplX86_64.h -------------------------------------*- 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#ifndef __DNBArchImplX86_64_h__
15#define __DNBArchImplX86_64_h__
16
17#if defined (__i386__) || defined (__x86_64__)
18#include "DNBArch.h"
19#include "../HasAVX.h"
20#include "MachRegisterStatesX86_64.h"
21
22class MachThread;
23
24class DNBArchImplX86_64 : public DNBArchProtocol
25{
26public:
27    DNBArchImplX86_64(MachThread *thread) :
28        m_thread(thread),
29        m_state()
30    {
31    }
32    virtual ~DNBArchImplX86_64()
33    {
34    }
35
36    static  void            Initialize();
37    virtual bool            GetRegisterValue(int set, int reg, DNBRegisterValue *value);
38    virtual bool            SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
39    virtual nub_size_t      GetRegisterContext (void *buf, nub_size_t buf_len);
40    virtual nub_size_t      SetRegisterContext (const void *buf, nub_size_t buf_len);
41
42    virtual kern_return_t   GetRegisterState  (int set, bool force);
43    virtual kern_return_t   SetRegisterState  (int set);
44    virtual bool            RegisterSetStateIsValid (int set) const;
45
46    virtual uint64_t        GetPC(uint64_t failValue);    // Get program counter
47    virtual kern_return_t   SetPC(uint64_t value);
48    virtual uint64_t        GetSP(uint64_t failValue);    // Get stack pointer
49    virtual void            ThreadWillResume();
50    virtual bool            ThreadDidStop();
51    virtual bool            NotifyException(MachException::Data& exc);
52
53    virtual uint32_t        NumSupportedHardwareWatchpoints();
54    virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
55    virtual bool            DisableHardwareWatchpoint (uint32_t hw_break_index);
56
57protected:
58    kern_return_t           EnableHardwareSingleStep (bool enable);
59
60    typedef __x86_64_thread_state_t GPR;
61    typedef __x86_64_float_state_t FPU;
62    typedef __x86_64_exception_state_t EXC;
63    typedef __x86_64_avx_state_t AVX;
64    typedef __x86_64_debug_state_t DBG;
65
66    static const DNBRegisterInfo g_gpr_registers[];
67    static const DNBRegisterInfo g_fpu_registers_no_avx[];
68    static const DNBRegisterInfo g_fpu_registers_avx[];
69    static const DNBRegisterInfo g_exc_registers[];
70    static const DNBRegisterSetInfo g_reg_sets_no_avx[];
71    static const DNBRegisterSetInfo g_reg_sets_avx[];
72    static const size_t k_num_gpr_registers;
73    static const size_t k_num_fpu_registers_no_avx;
74    static const size_t k_num_fpu_registers_avx;
75    static const size_t k_num_exc_registers;
76    static const size_t k_num_all_registers_no_avx;
77    static const size_t k_num_all_registers_avx;
78    static const size_t k_num_register_sets;
79
80    typedef enum RegisterSetTag
81    {
82        e_regSetALL = REGISTER_SET_ALL,
83        e_regSetGPR,
84        e_regSetFPU,
85        e_regSetEXC,
86        e_regSetDBG,
87        kNumRegisterSets
88    } RegisterSet;
89
90    typedef enum RegisterSetWordSizeTag
91    {
92        e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int),
93        e_regSetWordSizeFPR = sizeof(FPU) / sizeof(int),
94        e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int),
95        e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int),
96        e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int)
97    } RegisterSetWordSize;
98
99    enum
100    {
101        Read = 0,
102        Write = 1,
103        kNumErrors = 2
104    };
105
106    struct Context
107    {
108        GPR gpr;
109        union {
110            FPU no_avx;
111            AVX avx;
112        } fpu;
113        EXC exc;
114        DBG dbg;
115    };
116
117    struct State
118    {
119        Context context;
120        kern_return_t gpr_errs[2];    // Read/Write errors
121        kern_return_t fpu_errs[2];    // Read/Write errors
122        kern_return_t exc_errs[2];    // Read/Write errors
123        kern_return_t dbg_errs[2];    // Read/Write errors
124
125        State()
126        {
127            uint32_t i;
128            for (i=0; i<kNumErrors; i++)
129            {
130                gpr_errs[i] = -1;
131                fpu_errs[i] = -1;
132                exc_errs[i] = -1;
133                dbg_errs[i] = -1;
134            }
135        }
136
137        void
138        InvalidateAllRegisterStates()
139        {
140            SetError (e_regSetALL, Read, -1);
141        }
142
143        kern_return_t
144        GetError (int flavor, uint32_t err_idx) const
145        {
146            if (err_idx < kNumErrors)
147            {
148                switch (flavor)
149                {
150                // When getting all errors, just OR all values together to see if
151                // we got any kind of error.
152                case e_regSetALL:    return gpr_errs[err_idx] |
153                                            fpu_errs[err_idx] |
154                                            exc_errs[err_idx];
155                case e_regSetGPR:    return gpr_errs[err_idx];
156                case e_regSetFPU:    return fpu_errs[err_idx];
157                case e_regSetEXC:    return exc_errs[err_idx];
158                case e_regSetDBG:    return dbg_errs[err_idx];
159                default: break;
160                }
161            }
162            return -1;
163        }
164
165        bool
166        SetError (int flavor, uint32_t err_idx, kern_return_t err)
167        {
168            if (err_idx < kNumErrors)
169            {
170                switch (flavor)
171                {
172                case e_regSetALL:
173                    gpr_errs[err_idx] =
174                    fpu_errs[err_idx] =
175                    exc_errs[err_idx] =
176                    dbg_errs[err_idx] = err;
177                    return true;
178
179                case e_regSetGPR:
180                    gpr_errs[err_idx] = err;
181                    return true;
182
183                case e_regSetFPU:
184                    fpu_errs[err_idx] = err;
185                    return true;
186
187                case e_regSetEXC:
188                    exc_errs[err_idx] = err;
189                    return true;
190
191                case e_regSetDBG:
192                    dbg_errs[err_idx] = err;
193                    return true;
194
195                default: break;
196                }
197            }
198            return false;
199        }
200
201        bool
202        RegsAreValid (int flavor) const
203        {
204            return GetError(flavor, Read) == KERN_SUCCESS;
205        }
206    };
207
208    kern_return_t GetGPRState (bool force);
209    kern_return_t GetFPUState (bool force);
210    kern_return_t GetEXCState (bool force);
211    kern_return_t GetDBGState (bool force);
212
213    kern_return_t SetGPRState ();
214    kern_return_t SetFPUState ();
215    kern_return_t SetEXCState ();
216    kern_return_t SetDBGState ();
217
218    static DNBArchProtocol *
219    Create (MachThread *thread);
220
221    static const uint8_t * const
222    SoftwareBreakpointOpcode (nub_size_t byte_size);
223
224    static const DNBRegisterSetInfo *
225    GetRegisterSetInfo(nub_size_t *num_reg_sets);
226
227    static bool
228    CPUHasAVX()
229    {
230        if (s_has_avx == kAVXUnknown)
231            s_has_avx = (::HasAVX() ? kAVXPresent : kAVXNotPresent);
232
233        return (s_has_avx == kAVXPresent);
234    }
235
236    // Helper functions for watchpoint manipulations.
237    static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write);
238    static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index);
239    static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index);
240    static void ClearWatchpointHits(DBG &debug_state);
241    static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
242
243    MachThread *m_thread;
244    State        m_state;
245
246    static enum AVXPresence {
247        kAVXPresent,
248        kAVXNotPresent,
249        kAVXUnknown
250    } s_has_avx;
251};
252
253#endif    // #if defined (__i386__) || defined (__x86_64__)
254#endif    // #ifndef __DNBArchImplX86_64_h__
255