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