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