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

source code of lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h