[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / lldb / tools / debugserver / source / MacOSX / arm64 / DNBArchImplARM64.h
blobb492fcaca94b55368f9efb225f4abea0989e3f0f
1 //===-- DNBArchImplARM64.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 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
12 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
14 #include <mach/thread_status.h>
15 #include <map>
17 #if defined(ARM_THREAD_STATE64_COUNT)
19 #include "DNBArch.h"
21 class MachThread;
23 class DNBArchMachARM64 : public DNBArchProtocol {
24 public:
25 enum { kMaxNumThumbITBreakpoints = 4 };
27 DNBArchMachARM64(MachThread *thread)
28 : m_thread(thread), m_state(), m_disabled_watchpoints(),
29 m_disabled_breakpoints(), m_watchpoint_hw_index(-1),
30 m_watchpoint_did_occur(false),
31 m_watchpoint_resume_single_step_enabled(false),
32 m_saved_register_states() {
33 m_disabled_watchpoints.resize(16);
34 m_disabled_breakpoints.resize(16);
35 memset(&m_dbg_save, 0, sizeof(m_dbg_save));
38 virtual ~DNBArchMachARM64() {}
40 static void Initialize();
41 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets);
43 bool GetRegisterValue(uint32_t set, uint32_t reg,
44 DNBRegisterValue *value) override;
45 bool SetRegisterValue(uint32_t set, uint32_t reg,
46 const DNBRegisterValue *value) override;
47 nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override;
48 nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override;
49 uint32_t SaveRegisterState() override;
50 bool RestoreRegisterState(uint32_t save_id) override;
52 kern_return_t GetRegisterState(int set, bool force) override;
53 kern_return_t SetRegisterState(int set) override;
54 bool RegisterSetStateIsValid(int set) const override;
56 uint64_t GetPC(uint64_t failValue) override; // Get program counter
57 kern_return_t SetPC(uint64_t value) override;
58 uint64_t GetSP(uint64_t failValue) override; // Get stack pointer
59 void ThreadWillResume() override;
60 bool ThreadDidStop() override;
61 bool NotifyException(MachException::Data &exc) override;
63 static DNBArchProtocol *Create(MachThread *thread);
64 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size);
65 static uint32_t GetCPUType();
67 uint32_t NumSupportedHardwareBreakpoints() override;
68 uint32_t NumSupportedHardwareWatchpoints() override;
70 uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size,
71 bool also_set_on_task) override;
72 bool DisableHardwareBreakpoint(uint32_t hw_break_index,
73 bool also_set_on_task) override;
74 uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read,
75 bool write, bool also_set_on_task) override;
76 bool DisableHardwareWatchpoint(uint32_t hw_break_index,
77 bool also_set_on_task) override;
78 bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index,
79 bool also_set_on_task);
81 protected:
82 kern_return_t EnableHardwareSingleStep(bool enable);
83 static bool FixGenericRegisterNumber(uint32_t &set, uint32_t &reg);
85 enum RegisterSet {
86 e_regSetALL = REGISTER_SET_ALL,
87 e_regSetGPR, // ARM_THREAD_STATE64,
88 e_regSetVFP, // ARM_NEON_STATE64,
89 e_regSetEXC, // ARM_EXCEPTION_STATE64,
90 e_regSetDBG, // ARM_DEBUG_STATE64,
91 kNumRegisterSets
94 enum {
95 e_regSetGPRCount = ARM_THREAD_STATE64_COUNT,
96 e_regSetVFPCount = ARM_NEON_STATE64_COUNT,
97 e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT,
98 e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT,
101 enum { Read = 0, Write = 1, kNumErrors = 2 };
103 typedef arm_thread_state64_t GPR;
104 typedef arm_neon_state64_t FPU;
105 typedef arm_exception_state64_t EXC;
107 static const DNBRegisterInfo g_gpr_registers[];
108 static const DNBRegisterInfo g_vfp_registers[];
109 static const DNBRegisterInfo g_exc_registers[];
110 static const DNBRegisterSetInfo g_reg_sets[];
112 static const size_t k_num_gpr_registers;
113 static const size_t k_num_vfp_registers;
114 static const size_t k_num_exc_registers;
115 static const size_t k_num_all_registers;
116 static const size_t k_num_register_sets;
118 struct Context {
119 GPR gpr;
120 FPU vfp;
121 EXC exc;
124 struct State {
125 Context context;
126 arm_debug_state64_t dbg;
127 kern_return_t gpr_errs[2]; // Read/Write errors
128 kern_return_t vfp_errs[2]; // Read/Write errors
129 kern_return_t exc_errs[2]; // Read/Write errors
130 kern_return_t dbg_errs[2]; // Read/Write errors
131 State() {
132 uint32_t i;
133 for (i = 0; i < kNumErrors; i++) {
134 gpr_errs[i] = -1;
135 vfp_errs[i] = -1;
136 exc_errs[i] = -1;
137 dbg_errs[i] = -1;
140 void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); }
142 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); }
144 kern_return_t GetError(int set, uint32_t err_idx) const {
145 if (err_idx < kNumErrors) {
146 switch (set) {
147 // When getting all errors, just OR all values together to see if
148 // we got any kind of error.
149 case e_regSetALL:
150 return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] |
151 dbg_errs[err_idx];
152 case e_regSetGPR:
153 return gpr_errs[err_idx];
154 case e_regSetVFP:
155 return vfp_errs[err_idx];
156 case e_regSetEXC:
157 return exc_errs[err_idx];
158 // case e_regSetDBG: return dbg_errs[err_idx];
159 default:
160 break;
163 return -1;
165 bool SetError(int set, uint32_t err_idx, kern_return_t err) {
166 if (err_idx < kNumErrors) {
167 switch (set) {
168 case e_regSetALL:
169 gpr_errs[err_idx] = err;
170 vfp_errs[err_idx] = err;
171 dbg_errs[err_idx] = err;
172 exc_errs[err_idx] = err;
173 return true;
175 case e_regSetGPR:
176 gpr_errs[err_idx] = err;
177 return true;
179 case e_regSetVFP:
180 vfp_errs[err_idx] = err;
181 return true;
183 case e_regSetEXC:
184 exc_errs[err_idx] = err;
185 return true;
187 // case e_regSetDBG:
188 // dbg_errs[err_idx] = err;
189 // return true;
190 default:
191 break;
194 return false;
196 bool RegsAreValid(int set) const {
197 return GetError(set, Read) == KERN_SUCCESS;
201 kern_return_t GetGPRState(bool force);
202 kern_return_t GetVFPState(bool force);
203 kern_return_t GetEXCState(bool force);
204 kern_return_t GetDBGState(bool force);
206 kern_return_t SetGPRState();
207 kern_return_t SetVFPState();
208 kern_return_t SetEXCState();
209 kern_return_t SetDBGState(bool also_set_on_task);
211 // Helper functions for watchpoint implementaions.
213 typedef arm_debug_state64_t DBG;
215 void ClearWatchpointOccurred();
216 bool HasWatchpointOccurred();
217 bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index);
218 nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index);
219 nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
220 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index);
221 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index);
222 uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) override;
224 class disabled_watchpoint {
225 public:
226 disabled_watchpoint() {
227 addr = 0;
228 control = 0;
230 nub_addr_t addr;
231 uint32_t control;
234 protected:
235 MachThread *m_thread;
236 State m_state;
237 arm_debug_state64_t m_dbg_save;
239 // arm64 doesn't keep the disabled watchpoint and breakpoint values in the
240 // debug register context like armv7;
241 // we need to save them aside when we disable them temporarily.
242 std::vector<disabled_watchpoint> m_disabled_watchpoints;
243 std::vector<disabled_watchpoint> m_disabled_breakpoints;
245 // The following member variables should be updated atomically.
246 int32_t m_watchpoint_hw_index;
247 bool m_watchpoint_did_occur;
248 bool m_watchpoint_resume_single_step_enabled;
250 typedef std::map<uint32_t, Context> SaveRegisterStates;
251 SaveRegisterStates m_saved_register_states;
254 #endif // #if defined (ARM_THREAD_STATE64_COUNT)
255 #endif // #if defined (__arm__)
256 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H