DNBArchImpl.h revision e350394e5b4bd5c32f70951a035a889bfd0194e4
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===//
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                     The LLVM Compiler Infrastructure
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This file is distributed under the University of Illinois Open Source
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// License. See LICENSE.TXT for details.
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//===----------------------------------------------------------------------===//
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  Created by Greg Clayton on 6/25/07.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//===----------------------------------------------------------------------===//
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef __DebugNubArchMachARM_h__
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __DebugNubArchMachARM_h__
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined (__arm__)
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "DNBArch.h"
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <ARMDisassembler/ARMDisassembler.h>
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass MachThread;
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass DNBArchMachARM : public DNBArchProtocol
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownpublic:
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    enum { kMaxNumThumbITBreakpoints = 4 };
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DNBArchMachARM(MachThread *thread) :
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_thread(thread),
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_state(),
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS),
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_sw_single_step_next_pc(INVALID_NUB_ADDRESS),
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_sw_single_step_break_id(INVALID_NUB_BREAK_ID),
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_sw_single_step_itblock_break_count(0),
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        m_last_decode_pc(INVALID_NUB_ADDRESS)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        memset(&m_dbg_save, 0, sizeof(m_dbg_save));
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ThumbStaticsInit(&m_last_decode_thumb);
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        for (int i = 0; i < kMaxNumThumbITBreakpoints; i++)
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            m_sw_single_step_itblock_break_id[i] = INVALID_NUB_BREAK_ID;
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual ~DNBArchMachARM()
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    {
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static void Initialize();
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static const DNBRegisterSetInfo *
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GetRegisterSetInfo(nub_size_t *num_reg_sets);
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            GetRegisterValue(int set, int reg, DNBRegisterValue *value);
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual nub_size_t      GetRegisterContext (void *buf, nub_size_t buf_len);
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual nub_size_t      SetRegisterContext (const void *buf, nub_size_t buf_len);
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual kern_return_t   GetRegisterState  (int set, bool force);
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual kern_return_t   SetRegisterState  (int set);
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            RegisterSetStateIsValid (int set) const;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint64_t        GetPC(uint64_t failValue);    // Get program counter
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual kern_return_t   SetPC(uint64_t value);
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint64_t        GetSP(uint64_t failValue);    // Get stack pointer
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual void            ThreadWillResume();
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            ThreadDidStop();
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            NotifyException(MachException::Data& exc);
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static DNBArchProtocol *Create (MachThread *thread);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static uint32_t         GetCPUType();
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint32_t        NumSupportedHardwareBreakpoints();
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint32_t        NumSupportedHardwareWatchpoints();
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint32_t        EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size);
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            DisableHardwareBreakpoint (uint32_t hw_break_index);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    virtual bool            DisableHardwareWatchpoint (uint32_t hw_break_index);
82    virtual bool            StepNotComplete ();
83    virtual void            HardwareWatchpointStateChanged ();
84    virtual uint32_t        GetHardwareWatchpointHit(nub_addr_t &addr);
85
86    typedef arm_debug_state_t DBG;
87
88protected:
89
90
91    kern_return_t           EnableHardwareSingleStep (bool enable);
92    kern_return_t           SetSingleStepSoftwareBreakpoints ();
93
94    bool                    ConditionPassed(uint8_t condition, uint32_t cpsr);
95#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
96    bool                    ComputeNextPC(nub_addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, nub_addr_t *targetPC);
97    arm_error_t             DecodeInstructionUsingDisassembler(nub_addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc);
98    void                    DecodeITBlockInstructions(nub_addr_t curr_pc);
99#endif
100    void                    EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb);
101    static nub_bool_t       BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton);
102
103    typedef enum RegisterSetTag
104    {
105        e_regSetALL = REGISTER_SET_ALL,
106        e_regSetGPR = ARM_THREAD_STATE,
107        e_regSetVFP = ARM_VFP_STATE,
108        e_regSetEXC = ARM_EXCEPTION_STATE,
109        e_regSetDBG = ARM_DEBUG_STATE,
110        kNumRegisterSets
111    } RegisterSet;
112
113    enum
114    {
115        Read = 0,
116        Write = 1,
117        kNumErrors = 2
118    };
119
120    typedef arm_thread_state_t GPR;
121    typedef arm_vfp_state_t FPU;
122    typedef arm_exception_state_t EXC;
123
124    static const DNBRegisterInfo g_gpr_registers[];
125    static const DNBRegisterInfo g_vfp_registers[];
126    static const DNBRegisterInfo g_exc_registers[];
127    static const DNBRegisterSetInfo g_reg_sets[];
128
129    static const size_t k_num_gpr_registers;
130    static const size_t k_num_vfp_registers;
131    static const size_t k_num_exc_registers;
132    static const size_t k_num_all_registers;
133    static const size_t k_num_register_sets;
134
135    struct Context
136    {
137        GPR gpr;
138        FPU vfp;
139        EXC exc;
140    };
141
142    // See also HardwareWatchpointStateChanged() which updates this class-wide variable.
143    static DBG Global_Debug_State;
144    static bool Valid_Global_Debug_State;
145
146    struct State
147    {
148        Context                 context;
149        DBG                     dbg;
150        kern_return_t           gpr_errs[2];    // Read/Write errors
151        kern_return_t           vfp_errs[2];    // Read/Write errors
152        kern_return_t           exc_errs[2];    // Read/Write errors
153        kern_return_t           dbg_errs[2];    // Read/Write errors
154        State()
155        {
156            uint32_t i;
157            for (i=0; i<kNumErrors; i++)
158            {
159                gpr_errs[i] = -1;
160                vfp_errs[i] = -1;
161                exc_errs[i] = -1;
162                dbg_errs[i] = -1;
163            }
164        }
165        void InvalidateRegisterSetState(int set)
166        {
167            SetError (set, Read, -1);
168        }
169        kern_return_t GetError (int set, uint32_t err_idx) const
170        {
171            if (err_idx < kNumErrors)
172            {
173                switch (set)
174                {
175                // When getting all errors, just OR all values together to see if
176                // we got any kind of error.
177                case e_regSetALL:   return gpr_errs[err_idx] |
178                                           vfp_errs[err_idx] |
179                                           exc_errs[err_idx] |
180                                           dbg_errs[err_idx] ;
181                case e_regSetGPR:   return gpr_errs[err_idx];
182                case e_regSetVFP:   return vfp_errs[err_idx];
183                case e_regSetEXC:   return exc_errs[err_idx];
184                case e_regSetDBG:   return dbg_errs[err_idx];
185                default: break;
186                }
187            }
188            return -1;
189        }
190        bool SetError (int set, uint32_t err_idx, kern_return_t err)
191        {
192            if (err_idx < kNumErrors)
193            {
194                switch (set)
195                {
196                case e_regSetALL:
197                    gpr_errs[err_idx] = err;
198                    vfp_errs[err_idx] = err;
199                    dbg_errs[err_idx] = err;
200                    exc_errs[err_idx] = err;
201                    return true;
202
203                case e_regSetGPR:
204                    gpr_errs[err_idx] = err;
205                    return true;
206
207                case e_regSetVFP:
208                    vfp_errs[err_idx] = err;
209                    return true;
210
211                case e_regSetEXC:
212                    exc_errs[err_idx] = err;
213                    return true;
214
215                case e_regSetDBG:
216                    dbg_errs[err_idx] = err;
217                    return true;
218                default: break;
219                }
220            }
221            return false;
222        }
223        bool RegsAreValid (int set) const
224        {
225            return GetError(set, Read) == KERN_SUCCESS;
226        }
227    };
228
229    kern_return_t GetGPRState (bool force);
230    kern_return_t GetVFPState (bool force);
231    kern_return_t GetEXCState (bool force);
232    kern_return_t GetDBGState (bool force);
233
234    kern_return_t SetGPRState ();
235    kern_return_t SetVFPState ();
236    kern_return_t SetEXCState ();
237    kern_return_t SetDBGState ();
238
239    // Helper functions for watchpoint implementaions.
240    static void ClearWatchpointOccurred();
241    static bool HasWatchpointOccurred();
242    static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
243    static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
244
245protected:
246    MachThread *    m_thread;
247    State           m_state;
248    DBG             m_dbg_save;
249    nub_addr_t      m_hw_single_chained_step_addr;
250    // Software single stepping support
251    nub_addr_t      m_sw_single_step_next_pc;
252    nub_break_t     m_sw_single_step_break_id;
253    nub_break_t     m_sw_single_step_itblock_break_id[kMaxNumThumbITBreakpoints];
254    nub_addr_t      m_sw_single_step_itblock_break_count;
255    // Disassembler state
256#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK)
257    thumb_static_data_t m_last_decode_thumb;
258    arm_decoded_instruction_t m_last_decode_arm;
259#endif
260    nub_addr_t      m_last_decode_pc;
261
262};
263
264#endif    // #if defined (__arm__)
265#endif    // #ifndef __DebugNubArchMachARM_h__
266