LLDB mainline
RegisterContextWindows_arm64.cpp
Go to the documentation of this file.
1//===-- RegisterContextWindows_arm64.cpp ----------------------------------===//
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#if defined(__aarch64__) || defined(_M_ARM64)
10
14#include "lldb/Utility/Status.h"
16
18#include "TargetThreadWindows.h"
19
20#include "llvm/ADT/STLExtras.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25#define GPR_OFFSET(idx) 0
26#define GPR_OFFSET_NAME(reg) 0
27
28#define FPU_OFFSET(idx) 0
29#define FPU_OFFSET_NAME(reg) 0
30
31#define EXC_OFFSET_NAME(reg) 0
32#define DBG_OFFSET_NAME(reg) 0
33
34#define DEFINE_DBG(reg, i) \
35 #reg, nullptr, 0, DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \
36 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
37 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \
38 nullptr, nullptr, nullptr
39
40// Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
41#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
43#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
44
45static size_t k_num_register_infos = std::size(g_register_infos_arm64_le);
46
47// Array of lldb register numbers used to define the set of all General Purpose
48// Registers
49uint32_t g_gpr_reg_indices[] = {
55
56 gpr_w0, gpr_w1, gpr_w2, gpr_w3, gpr_w4, gpr_w5, gpr_w6, gpr_w7,
57 gpr_w8, gpr_w9, gpr_w10, gpr_w11, gpr_w12, gpr_w13, gpr_w14, gpr_w15,
58 gpr_w16, gpr_w17, gpr_w18, gpr_w19, gpr_w20, gpr_w21, gpr_w22, gpr_w23,
59 gpr_w24, gpr_w25, gpr_w26, gpr_w27, gpr_w28,
60};
61
62uint32_t g_fpu_reg_indices[] = {
63 fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6, fpu_v7,
64 fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13, fpu_v14, fpu_v15,
65 fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20, fpu_v21, fpu_v22, fpu_v23,
66 fpu_v24, fpu_v25, fpu_v26, fpu_v27, fpu_v28, fpu_v29, fpu_v30, fpu_v31,
67
72
73 fpu_d0, fpu_d1, fpu_d2, fpu_d3, fpu_d4, fpu_d5, fpu_d6, fpu_d7,
74 fpu_d8, fpu_d9, fpu_d10, fpu_d11, fpu_d12, fpu_d13, fpu_d14, fpu_d15,
75 fpu_d16, fpu_d17, fpu_d18, fpu_d19, fpu_d20, fpu_d21, fpu_d22, fpu_d23,
76 fpu_d24, fpu_d25, fpu_d26, fpu_d27, fpu_d28, fpu_d29, fpu_d30, fpu_d31,
77
78 fpu_fpsr, fpu_fpcr,
79};
80
81RegisterSet g_register_sets[] = {
82 {"General Purpose Registers", "gpr", std::size(g_gpr_reg_indices),
83 g_gpr_reg_indices},
84 {"Floating Point Registers", "fpu", std::size(g_fpu_reg_indices),
85 g_fpu_reg_indices},
86};
87
88// Constructors and Destructors
89RegisterContextWindows_arm64::RegisterContextWindows_arm64(
90 Thread &thread, uint32_t concrete_frame_idx)
91 : RegisterContextWindows(thread, concrete_frame_idx) {}
92
93RegisterContextWindows_arm64::~RegisterContextWindows_arm64() {}
94
95size_t RegisterContextWindows_arm64::GetRegisterCount() {
96 return std::size(g_register_infos_arm64_le);
97}
98
99const RegisterInfo *
100RegisterContextWindows_arm64::GetRegisterInfoAtIndex(size_t reg) {
101 if (reg < k_num_register_infos)
102 return &g_register_infos_arm64_le[reg];
103 return nullptr;
104}
105
106size_t RegisterContextWindows_arm64::GetRegisterSetCount() {
107 return std::size(g_register_sets);
108}
109
110const RegisterSet *
111RegisterContextWindows_arm64::GetRegisterSet(size_t reg_set) {
112 return &g_register_sets[reg_set];
113}
114
115bool RegisterContextWindows_arm64::ReadRegister(const RegisterInfo *reg_info,
116 RegisterValue &reg_value) {
117 if (!CacheAllRegisterValues())
118 return false;
119
120 if (reg_info == nullptr)
121 return false;
122
123 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
124
125 switch (reg) {
126 case gpr_x0:
127 case gpr_x1:
128 case gpr_x2:
129 case gpr_x3:
130 case gpr_x4:
131 case gpr_x5:
132 case gpr_x6:
133 case gpr_x7:
134 case gpr_x8:
135 case gpr_x9:
136 case gpr_x10:
137 case gpr_x11:
138 case gpr_x12:
139 case gpr_x13:
140 case gpr_x14:
141 case gpr_x15:
142 case gpr_x16:
143 case gpr_x17:
144 case gpr_x18:
145 case gpr_x19:
146 case gpr_x20:
147 case gpr_x21:
148 case gpr_x22:
149 case gpr_x23:
150 case gpr_x24:
151 case gpr_x25:
152 case gpr_x26:
153 case gpr_x27:
154 case gpr_x28:
155 reg_value.SetUInt64(m_context.X[reg - gpr_x0]);
156 break;
157
158 case gpr_fp:
159 reg_value.SetUInt64(m_context.Fp);
160 break;
161 case gpr_sp:
162 reg_value.SetUInt64(m_context.Sp);
163 break;
164 case gpr_lr:
165 reg_value.SetUInt64(m_context.Lr);
166 break;
167 case gpr_pc:
168 reg_value.SetUInt64(m_context.Pc);
169 break;
170 case gpr_cpsr:
171 reg_value.SetUInt32(m_context.Cpsr);
172 break;
173
174 case gpr_w0:
175 case gpr_w1:
176 case gpr_w2:
177 case gpr_w3:
178 case gpr_w4:
179 case gpr_w5:
180 case gpr_w6:
181 case gpr_w7:
182 case gpr_w8:
183 case gpr_w9:
184 case gpr_w10:
185 case gpr_w11:
186 case gpr_w12:
187 case gpr_w13:
188 case gpr_w14:
189 case gpr_w15:
190 case gpr_w16:
191 case gpr_w17:
192 case gpr_w18:
193 case gpr_w19:
194 case gpr_w20:
195 case gpr_w21:
196 case gpr_w22:
197 case gpr_w23:
198 case gpr_w24:
199 case gpr_w25:
200 case gpr_w26:
201 case gpr_w27:
202 case gpr_w28:
203 reg_value.SetUInt32(
204 static_cast<uint32_t>(m_context.X[reg - gpr_w0] & 0xffffffff));
205 break;
206
207 case fpu_v0:
208 case fpu_v1:
209 case fpu_v2:
210 case fpu_v3:
211 case fpu_v4:
212 case fpu_v5:
213 case fpu_v6:
214 case fpu_v7:
215 case fpu_v8:
216 case fpu_v9:
217 case fpu_v10:
218 case fpu_v11:
219 case fpu_v12:
220 case fpu_v13:
221 case fpu_v14:
222 case fpu_v15:
223 case fpu_v16:
224 case fpu_v17:
225 case fpu_v18:
226 case fpu_v19:
227 case fpu_v20:
228 case fpu_v21:
229 case fpu_v22:
230 case fpu_v23:
231 case fpu_v24:
232 case fpu_v25:
233 case fpu_v26:
234 case fpu_v27:
235 case fpu_v28:
236 case fpu_v29:
237 case fpu_v30:
238 case fpu_v31:
239 reg_value.SetBytes(m_context.V[reg - fpu_v0].B, reg_info->byte_size,
241 break;
242
243 case fpu_s0:
244 case fpu_s1:
245 case fpu_s2:
246 case fpu_s3:
247 case fpu_s4:
248 case fpu_s5:
249 case fpu_s6:
250 case fpu_s7:
251 case fpu_s8:
252 case fpu_s9:
253 case fpu_s10:
254 case fpu_s11:
255 case fpu_s12:
256 case fpu_s13:
257 case fpu_s14:
258 case fpu_s15:
259 case fpu_s16:
260 case fpu_s17:
261 case fpu_s18:
262 case fpu_s19:
263 case fpu_s20:
264 case fpu_s21:
265 case fpu_s22:
266 case fpu_s23:
267 case fpu_s24:
268 case fpu_s25:
269 case fpu_s26:
270 case fpu_s27:
271 case fpu_s28:
272 case fpu_s29:
273 case fpu_s30:
274 case fpu_s31:
275 reg_value.SetFloat(m_context.V[reg - fpu_s0].S[0]);
276 break;
277
278 case fpu_d0:
279 case fpu_d1:
280 case fpu_d2:
281 case fpu_d3:
282 case fpu_d4:
283 case fpu_d5:
284 case fpu_d6:
285 case fpu_d7:
286 case fpu_d8:
287 case fpu_d9:
288 case fpu_d10:
289 case fpu_d11:
290 case fpu_d12:
291 case fpu_d13:
292 case fpu_d14:
293 case fpu_d15:
294 case fpu_d16:
295 case fpu_d17:
296 case fpu_d18:
297 case fpu_d19:
298 case fpu_d20:
299 case fpu_d21:
300 case fpu_d22:
301 case fpu_d23:
302 case fpu_d24:
303 case fpu_d25:
304 case fpu_d26:
305 case fpu_d27:
306 case fpu_d28:
307 case fpu_d29:
308 case fpu_d30:
309 case fpu_d31:
310 reg_value.SetDouble(m_context.V[reg - fpu_d0].D[0]);
311 break;
312
313 case fpu_fpsr:
314 reg_value.SetUInt32(m_context.Fpsr);
315 break;
316
317 case fpu_fpcr:
318 reg_value.SetUInt32(m_context.Fpcr);
319 break;
320
321 default:
322 reg_value.SetValueToInvalid();
323 return false;
324 }
325 return true;
326}
327
328bool RegisterContextWindows_arm64::WriteRegister(
329 const RegisterInfo *reg_info, const RegisterValue &reg_value) {
330 // Since we cannot only write a single register value to the inferior, we
331 // need to make sure our cached copy of the register values are fresh.
332 // Otherwise when writing one register, we may also overwrite some other
333 // register with a stale value.
334 if (!CacheAllRegisterValues())
335 return false;
336
337 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
338
339 switch (reg) {
340 case gpr_x0:
341 case gpr_x1:
342 case gpr_x2:
343 case gpr_x3:
344 case gpr_x4:
345 case gpr_x5:
346 case gpr_x6:
347 case gpr_x7:
348 case gpr_x8:
349 case gpr_x9:
350 case gpr_x10:
351 case gpr_x11:
352 case gpr_x12:
353 case gpr_x13:
354 case gpr_x14:
355 case gpr_x15:
356 case gpr_x16:
357 case gpr_x17:
358 case gpr_x18:
359 case gpr_x19:
360 case gpr_x20:
361 case gpr_x21:
362 case gpr_x22:
363 case gpr_x23:
364 case gpr_x24:
365 case gpr_x25:
366 case gpr_x26:
367 case gpr_x27:
368 case gpr_x28:
369 m_context.X[reg - gpr_x0] = reg_value.GetAsUInt64();
370 break;
371
372 case gpr_fp:
373 m_context.Fp = reg_value.GetAsUInt64();
374 break;
375 case gpr_sp:
376 m_context.Sp = reg_value.GetAsUInt64();
377 break;
378 case gpr_lr:
379 m_context.Lr = reg_value.GetAsUInt64();
380 break;
381 case gpr_pc:
382 m_context.Pc = reg_value.GetAsUInt64();
383 break;
384 case gpr_cpsr:
385 m_context.Cpsr = reg_value.GetAsUInt32();
386 break;
387
388 case fpu_v0:
389 case fpu_v1:
390 case fpu_v2:
391 case fpu_v3:
392 case fpu_v4:
393 case fpu_v5:
394 case fpu_v6:
395 case fpu_v7:
396 case fpu_v8:
397 case fpu_v9:
398 case fpu_v10:
399 case fpu_v11:
400 case fpu_v12:
401 case fpu_v13:
402 case fpu_v14:
403 case fpu_v15:
404 case fpu_v16:
405 case fpu_v17:
406 case fpu_v18:
407 case fpu_v19:
408 case fpu_v20:
409 case fpu_v21:
410 case fpu_v22:
411 case fpu_v23:
412 case fpu_v24:
413 case fpu_v25:
414 case fpu_v26:
415 case fpu_v27:
416 case fpu_v28:
417 case fpu_v29:
418 case fpu_v30:
419 case fpu_v31:
420 memcpy(m_context.V[reg - fpu_v0].B, reg_value.GetBytes(), 16);
421 break;
422
423 case fpu_fpsr:
424 m_context.Fpsr = reg_value.GetAsUInt32();
425 break;
426
427 case fpu_fpcr:
428 m_context.Fpcr = reg_value.GetAsUInt32();
429 break;
430
431 default:
432 return false;
433 }
434
435 // Physically update the registers in the target process.
436 return ApplyAllRegisterValues();
437}
438
439#endif // defined(__aarch64__) || defined(_M_ARM64)
static const uint32_t k_num_register_infos
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
const void * GetBytes() const
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
Registers are grouped into register sets.