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