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