DNBArchImplX86_64.h revision 20d338fad87eba91de65aa9bec76e01c04472848
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 <mach/mach_types.h>
20#include <mach/thread_status.h>
21
22
23class MachThread;
24
25class DNBArchImplX86_64 : public DNBArchProtocol
26{
27public:
28    DNBArchImplX86_64(MachThread *thread) :
29        m_thread(thread),
30        m_state()
31    {
32    }
33    virtual ~DNBArchImplX86_64()
34    {
35    }
36
37    static  void            Initialize();
38    virtual bool            GetRegisterValue(int set, int reg, DNBRegisterValue *value);
39    virtual bool            SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
40    virtual nub_size_t      GetRegisterContext (void *buf, nub_size_t buf_len);
41    virtual nub_size_t      SetRegisterContext (const void *buf, nub_size_t buf_len);
42
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
54protected:
55    kern_return_t           EnableHardwareSingleStep (bool enable);
56
57    typedef x86_thread_state64_t GPR;
58    typedef x86_float_state64_t FPU;
59    typedef x86_exception_state64_t EXC;
60
61    static const DNBRegisterInfo g_gpr_registers[];
62    static const DNBRegisterInfo g_fpu_registers[];
63    static const DNBRegisterInfo g_exc_registers[];
64    static const DNBRegisterSetInfo g_reg_sets[];
65    static const size_t k_num_gpr_registers;
66    static const size_t k_num_fpu_registers;
67    static const size_t k_num_exc_registers;
68    static const size_t k_num_all_registers;
69    static const size_t k_num_register_sets;
70
71    typedef enum RegisterSetTag
72    {
73        e_regSetALL = REGISTER_SET_ALL,
74        e_regSetGPR,
75        e_regSetFPU,
76        e_regSetEXC,
77        kNumRegisterSets
78    } RegisterSet;
79
80
81    enum
82    {
83        Read = 0,
84        Write = 1,
85        kNumErrors = 2
86    };
87
88    struct Context
89    {
90        GPR gpr;
91        FPU fpu;
92        EXC exc;
93    };
94
95    struct State
96    {
97        Context context;
98        kern_return_t gpr_errs[2];    // Read/Write errors
99        kern_return_t fpu_errs[2];    // Read/Write errors
100        kern_return_t exc_errs[2];    // Read/Write errors
101
102        State()
103        {
104            uint32_t i;
105            for (i=0; i<kNumErrors; i++)
106            {
107                gpr_errs[i] = -1;
108                fpu_errs[i] = -1;
109                exc_errs[i] = -1;
110            }
111        }
112
113        void
114        InvalidateAllRegisterStates()
115        {
116            SetError (e_regSetALL, Read, -1);
117        }
118
119        kern_return_t
120        GetError (int flavor, uint32_t err_idx) const
121        {
122            if (err_idx < kNumErrors)
123            {
124                switch (flavor)
125                {
126                // When getting all errors, just OR all values together to see if
127                // we got any kind of error.
128                case e_regSetALL:    return gpr_errs[err_idx] |
129                                            fpu_errs[err_idx] |
130                                            exc_errs[err_idx];
131                case e_regSetGPR:    return gpr_errs[err_idx];
132                case e_regSetFPU:    return fpu_errs[err_idx];
133                case e_regSetEXC:    return exc_errs[err_idx];
134                default: break;
135                }
136            }
137            return -1;
138        }
139
140        bool
141        SetError (int flavor, uint32_t err_idx, kern_return_t err)
142        {
143            if (err_idx < kNumErrors)
144            {
145                switch (flavor)
146                {
147                case e_regSetALL:
148                    gpr_errs[err_idx] =
149                    fpu_errs[err_idx] =
150                    exc_errs[err_idx] = err;
151                    return true;
152
153                case e_regSetGPR:
154                    gpr_errs[err_idx] = err;
155                    return true;
156
157                case e_regSetFPU:
158                    fpu_errs[err_idx] = err;
159                    return true;
160
161                case e_regSetEXC:
162                    exc_errs[err_idx] = err;
163                    return true;
164
165                default: break;
166                }
167            }
168            return false;
169        }
170
171        bool
172        RegsAreValid (int flavor) const
173        {
174            return GetError(flavor, Read) == KERN_SUCCESS;
175        }
176    };
177
178    kern_return_t GetGPRState (bool force);
179    kern_return_t GetFPUState (bool force);
180    kern_return_t GetEXCState (bool force);
181
182    kern_return_t SetGPRState ();
183    kern_return_t SetFPUState ();
184    kern_return_t SetEXCState ();
185
186    static DNBArchProtocol *
187    Create (MachThread *thread);
188
189    static const uint8_t * const
190    SoftwareBreakpointOpcode (nub_size_t byte_size);
191
192    static const DNBRegisterSetInfo *
193    GetRegisterSetInfo(nub_size_t *num_reg_sets);
194
195    MachThread *m_thread;
196    State        m_state;
197};
198
199#endif    // #if defined (__i386__) || defined (__x86_64__)
200#endif    // #ifndef __DNBArchImplX86_64_h__
201