Home | History | Annotate | Download | only in i386
      1 //===-- DNBArchImplI386.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 __DNBArchImplI386_h__
     15 #define __DNBArchImplI386_h__
     16 
     17 #if defined (__i386__) || defined (__x86_64__)
     18 
     19 #include "DNBArch.h"
     20 #include "../HasAVX.h"
     21 #include "MachRegisterStatesI386.h"
     22 
     23 class MachThread;
     24 
     25 class DNBArchImplI386 : public DNBArchProtocol
     26 {
     27 public:
     28     DNBArchImplI386(MachThread *thread) :
     29         m_thread(thread),
     30         m_state(),
     31         m_2pc_dbg_checkpoint(),
     32         m_2pc_trans_state(Trans_Done)
     33     {
     34     }
     35     virtual ~DNBArchImplI386()
     36     {
     37     }
     38 
     39     static  void            Initialize();
     40 
     41     virtual bool            GetRegisterValue(int set, int reg, DNBRegisterValue *value);
     42     virtual bool            SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
     43     virtual nub_size_t      GetRegisterContext (void *buf, nub_size_t buf_len);
     44     virtual nub_size_t      SetRegisterContext (const void *buf, nub_size_t buf_len);
     45     virtual kern_return_t   GetRegisterState  (int set, bool force);
     46     virtual kern_return_t   SetRegisterState  (int set);
     47     virtual bool            RegisterSetStateIsValid (int set) const;
     48 
     49     virtual uint64_t        GetPC(uint64_t failValue);    // Get program counter
     50     virtual kern_return_t   SetPC(uint64_t value);
     51     virtual uint64_t        GetSP(uint64_t failValue);    // Get stack pointer
     52     virtual void            ThreadWillResume();
     53     virtual bool            ThreadDidStop();
     54     virtual bool            NotifyException(MachException::Data& exc);
     55 
     56     virtual uint32_t        NumSupportedHardwareWatchpoints();
     57     virtual uint32_t        EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task);
     58     virtual bool            DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task);
     59     virtual uint32_t        GetHardwareWatchpointHit(nub_addr_t &addr);
     60 
     61 protected:
     62     kern_return_t           EnableHardwareSingleStep (bool enable);
     63 
     64     typedef __i386_thread_state_t GPR;
     65     typedef __i386_float_state_t FPU;
     66     typedef __i386_exception_state_t EXC;
     67     typedef __i386_avx_state_t AVX;
     68     typedef __i386_debug_state_t DBG;
     69 
     70     static const DNBRegisterInfo g_gpr_registers[];
     71     static const DNBRegisterInfo g_fpu_registers_no_avx[];
     72     static const DNBRegisterInfo g_fpu_registers_avx[];
     73     static const DNBRegisterInfo g_exc_registers[];
     74     static const DNBRegisterSetInfo g_reg_sets_no_avx[];
     75     static const DNBRegisterSetInfo g_reg_sets_avx[];
     76     static const size_t k_num_gpr_registers;
     77     static const size_t k_num_fpu_registers_no_avx;
     78     static const size_t k_num_fpu_registers_avx;
     79     static const size_t k_num_exc_registers;
     80     static const size_t k_num_all_registers_no_avx;
     81     static const size_t k_num_all_registers_avx;
     82     static const size_t k_num_register_sets;
     83 
     84     typedef enum RegisterSetTag
     85     {
     86         e_regSetALL = REGISTER_SET_ALL,
     87         e_regSetGPR,
     88         e_regSetFPU,
     89         e_regSetEXC,
     90         e_regSetDBG,
     91         kNumRegisterSets
     92     } RegisterSet;
     93 
     94     typedef enum RegisterSetWordSizeTag
     95     {
     96         e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int),
     97         e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int),
     98         e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int),
     99         e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int),
    100         e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int)
    101     } RegisterSetWordSize;
    102 
    103     enum
    104     {
    105         Read = 0,
    106         Write = 1,
    107         kNumErrors = 2
    108     };
    109 
    110     struct Context
    111     {
    112         GPR gpr;
    113         union {
    114             FPU no_avx;
    115             AVX avx;
    116         } fpu;
    117         EXC exc;
    118         DBG dbg;
    119     };
    120 
    121     struct State
    122     {
    123         Context context;
    124         kern_return_t gpr_errs[2];    // Read/Write errors
    125         kern_return_t fpu_errs[2];    // Read/Write errors
    126         kern_return_t exc_errs[2];    // Read/Write errors
    127         kern_return_t dbg_errs[2];    // Read/Write errors
    128 
    129         State()
    130         {
    131             uint32_t i;
    132             for (i=0; i<kNumErrors; i++)
    133             {
    134                 gpr_errs[i] = -1;
    135                 fpu_errs[i] = -1;
    136                 exc_errs[i] = -1;
    137                 dbg_errs[i] = -1;
    138             }
    139         }
    140         void InvalidateAllRegisterStates()
    141         {
    142             SetError (e_regSetALL, Read, -1);
    143         }
    144         kern_return_t GetError (int flavor, uint32_t err_idx) const
    145         {
    146             if (err_idx < kNumErrors)
    147             {
    148                 switch (flavor)
    149                 {
    150                 // When getting all errors, just OR all values together to see if
    151                 // we got any kind of error.
    152                 case e_regSetALL:    return gpr_errs[err_idx] |
    153                                             fpu_errs[err_idx] |
    154                                             exc_errs[err_idx];
    155                 case e_regSetGPR:    return gpr_errs[err_idx];
    156                 case e_regSetFPU:    return fpu_errs[err_idx];
    157                 case e_regSetEXC:    return exc_errs[err_idx];
    158                 case e_regSetDBG:    return dbg_errs[err_idx];
    159                 default: break;
    160                 }
    161             }
    162             return -1;
    163         }
    164         bool SetError (int flavor, uint32_t err_idx, kern_return_t err)
    165         {
    166             if (err_idx < kNumErrors)
    167             {
    168                 switch (flavor)
    169                 {
    170                 case e_regSetALL:
    171                     gpr_errs[err_idx] =
    172                     fpu_errs[err_idx] =
    173                     exc_errs[err_idx] =
    174                     dbg_errs[err_idx] = err;
    175                     return true;
    176 
    177                 case e_regSetGPR:
    178                     gpr_errs[err_idx] = err;
    179                     return true;
    180 
    181                 case e_regSetFPU:
    182                     fpu_errs[err_idx] = err;
    183                     return true;
    184 
    185                 case e_regSetEXC:
    186                     exc_errs[err_idx] = err;
    187                     return true;
    188 
    189                 case e_regSetDBG:
    190                     dbg_errs[err_idx] = err;
    191                     return true;
    192 
    193                 default: break;
    194                 }
    195             }
    196             return false;
    197         }
    198         bool RegsAreValid (int flavor) const
    199         {
    200             return GetError(flavor, Read) == KERN_SUCCESS;
    201         }
    202     };
    203 
    204     kern_return_t GetGPRState (bool force);
    205     kern_return_t GetFPUState (bool force);
    206     kern_return_t GetEXCState (bool force);
    207     kern_return_t GetDBGState (bool force);
    208 
    209     kern_return_t SetGPRState ();
    210     kern_return_t SetFPUState ();
    211     kern_return_t SetEXCState ();
    212     kern_return_t SetDBGState (bool also_set_on_task);
    213 
    214     static DNBArchProtocol *
    215     Create (MachThread *thread);
    216 
    217     static const uint8_t * const
    218     SoftwareBreakpointOpcode (nub_size_t byte_size);
    219 
    220     static const DNBRegisterSetInfo *
    221     GetRegisterSetInfo(nub_size_t *num_reg_sets);
    222 
    223     // Helper functions for watchpoint manipulations.
    224     static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write);
    225     static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index);
    226     static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index);
    227     static void ClearWatchpointHits(DBG &debug_state);
    228     static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
    229     static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
    230 
    231     virtual bool StartTransForHWP();
    232     virtual bool RollbackTransForHWP();
    233     virtual bool FinishTransForHWP();
    234     DBG GetDBGCheckpoint();
    235 
    236     MachThread *m_thread;
    237     State       m_state;
    238     DBG         m_2pc_dbg_checkpoint;
    239     uint32_t    m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)?
    240 };
    241 
    242 #endif    // #if defined (__i386__) || defined (__x86_64__)
    243 #endif    // #ifndef __DNBArchImplI386_h__
    244