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