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