LLDB mainline
RegisterContextWindows_arm.cpp
Go to the documentation of this file.
1//===-- RegisterContextWindows_arm.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(__arm__) || defined(_M_ARM)
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 FPU_OFFSET(idx) 0
27#define FPSCR_OFFSET 0
28#define TLS_OFFSET 0
29#define EXC_OFFSET(reg) 0
30#define DBG_OFFSET_NAME(reg) 0
31
32#define DEFINE_DBG(reg, i) \
33 #reg, nullptr, 0, DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \
34 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
35 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \
36 nullptr, nullptr, nullptr
37
38// Include RegisterInfos_arm to declare our g_register_infos_arm structure.
39#define DECLARE_REGISTER_INFOS_ARM_STRUCT
41#undef DECLARE_REGISTER_INFOS_ARM_STRUCT
42
43static size_t k_num_register_infos = std::size(g_register_infos_arm);
44
45// Array of lldb register numbers used to define the set of all General Purpose
46// Registers
47uint32_t g_gpr_reg_indices[] = {
50};
51
52uint32_t g_fpu_reg_indices[] = {
57
58 fpu_d0, fpu_d1, fpu_d2, fpu_d3, fpu_d4, fpu_d5, fpu_d6, fpu_d7,
59 fpu_d8, fpu_d9, fpu_d10, fpu_d11, fpu_d12, fpu_d13, fpu_d14, fpu_d15,
60 fpu_d16, fpu_d17, fpu_d18, fpu_d19, fpu_d20, fpu_d21, fpu_d22, fpu_d23,
61 fpu_d24, fpu_d25, fpu_d26, fpu_d27, fpu_d28, fpu_d29, fpu_d30, fpu_d31,
62
63 fpu_q0, fpu_q1, fpu_q2, fpu_q3, fpu_q4, fpu_q5, fpu_q6, fpu_q7,
64 fpu_q8, fpu_q9, fpu_q10, fpu_q11, fpu_q12, fpu_q13, fpu_q14, fpu_q15,
65
67};
68
69RegisterSet g_register_sets[] = {
70 {"General Purpose Registers", "gpr", std::size(g_gpr_reg_indices),
71 g_gpr_reg_indices},
72 {"Floating Point Registers", "fpu", std::size(g_fpu_reg_indices),
73 g_fpu_reg_indices},
74};
75
76// Constructors and Destructors
77RegisterContextWindows_arm::RegisterContextWindows_arm(
78 Thread &thread, uint32_t concrete_frame_idx)
79 : RegisterContextWindows(thread, concrete_frame_idx) {}
80
81RegisterContextWindows_arm::~RegisterContextWindows_arm() = default;
82
83size_t RegisterContextWindows_arm::GetRegisterCount() {
84 return std::size(g_register_infos_arm);
85}
86
87const RegisterInfo *
88RegisterContextWindows_arm::GetRegisterInfoAtIndex(size_t reg) {
89 if (reg < k_num_register_infos)
90 return &g_register_infos_arm[reg];
91 return nullptr;
92}
93
94size_t RegisterContextWindows_arm::GetRegisterSetCount() {
95 return std::size(g_register_sets);
96}
97
98const RegisterSet *RegisterContextWindows_arm::GetRegisterSet(size_t reg_set) {
99 return &g_register_sets[reg_set];
100}
101
102bool RegisterContextWindows_arm::ReadRegister(const RegisterInfo *reg_info,
103 RegisterValue &reg_value) {
104 if (!CacheAllRegisterValues())
105 return false;
106
107 if (reg_info == nullptr)
108 return false;
109
110 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
111
112 switch (reg) {
113 case gpr_r0:
114 reg_value.SetUInt32(m_context.R0);
115 break;
116 case gpr_r1:
117 reg_value.SetUInt32(m_context.R1);
118 break;
119 case gpr_r2:
120 reg_value.SetUInt32(m_context.R2);
121 break;
122 case gpr_r3:
123 reg_value.SetUInt32(m_context.R3);
124 break;
125 case gpr_r4:
126 reg_value.SetUInt32(m_context.R4);
127 break;
128 case gpr_r5:
129 reg_value.SetUInt32(m_context.R5);
130 break;
131 case gpr_r6:
132 reg_value.SetUInt32(m_context.R6);
133 break;
134 case gpr_r7:
135 reg_value.SetUInt32(m_context.R7);
136 break;
137 case gpr_r8:
138 reg_value.SetUInt32(m_context.R8);
139 break;
140 case gpr_r9:
141 reg_value.SetUInt32(m_context.R9);
142 break;
143 case gpr_r10:
144 reg_value.SetUInt32(m_context.R10);
145 break;
146 case gpr_r11:
147 reg_value.SetUInt32(m_context.R11);
148 break;
149 case gpr_r12:
150 reg_value.SetUInt32(m_context.R12);
151 break;
152 case gpr_sp:
153 reg_value.SetUInt32(m_context.Sp);
154 break;
155 case gpr_lr:
156 reg_value.SetUInt32(m_context.Lr);
157 break;
158 case gpr_pc:
159 reg_value.SetUInt32(m_context.Pc);
160 break;
161 case gpr_cpsr:
162 reg_value.SetUInt32(m_context.Cpsr);
163 break;
164
165 case fpu_s0:
166 case fpu_s1:
167 case fpu_s2:
168 case fpu_s3:
169 case fpu_s4:
170 case fpu_s5:
171 case fpu_s6:
172 case fpu_s7:
173 case fpu_s8:
174 case fpu_s9:
175 case fpu_s10:
176 case fpu_s11:
177 case fpu_s12:
178 case fpu_s13:
179 case fpu_s14:
180 case fpu_s15:
181 case fpu_s16:
182 case fpu_s17:
183 case fpu_s18:
184 case fpu_s19:
185 case fpu_s20:
186 case fpu_s21:
187 case fpu_s22:
188 case fpu_s23:
189 case fpu_s24:
190 case fpu_s25:
191 case fpu_s26:
192 case fpu_s27:
193 case fpu_s28:
194 case fpu_s29:
195 case fpu_s30:
196 case fpu_s31:
197 reg_value.SetUInt32(m_context.S[reg - fpu_s0], RegisterValue::eTypeFloat);
198 break;
199
200 case fpu_d0:
201 case fpu_d1:
202 case fpu_d2:
203 case fpu_d3:
204 case fpu_d4:
205 case fpu_d5:
206 case fpu_d6:
207 case fpu_d7:
208 case fpu_d8:
209 case fpu_d9:
210 case fpu_d10:
211 case fpu_d11:
212 case fpu_d12:
213 case fpu_d13:
214 case fpu_d14:
215 case fpu_d15:
216 case fpu_d16:
217 case fpu_d17:
218 case fpu_d18:
219 case fpu_d19:
220 case fpu_d20:
221 case fpu_d21:
222 case fpu_d22:
223 case fpu_d23:
224 case fpu_d24:
225 case fpu_d25:
226 case fpu_d26:
227 case fpu_d27:
228 case fpu_d28:
229 case fpu_d29:
230 case fpu_d30:
231 case fpu_d31:
232 reg_value.SetUInt64(m_context.D[reg - fpu_d0], RegisterValue::eTypeDouble);
233 break;
234
235 case fpu_q0:
236 case fpu_q1:
237 case fpu_q2:
238 case fpu_q3:
239 case fpu_q4:
240 case fpu_q5:
241 case fpu_q6:
242 case fpu_q7:
243 case fpu_q8:
244 case fpu_q9:
245 case fpu_q10:
246 case fpu_q11:
247 case fpu_q12:
248 case fpu_q13:
249 case fpu_q14:
250 case fpu_q15:
251 reg_value.SetBytes(&m_context.Q[reg - fpu_q0], reg_info->byte_size,
253 break;
254
255 case fpu_fpscr:
256 reg_value.SetUInt32(m_context.Fpscr);
257 break;
258
259 default:
260 reg_value.SetValueToInvalid();
261 return false;
262 }
263 return true;
264}
265
266bool RegisterContextWindows_arm::WriteRegister(const RegisterInfo *reg_info,
267 const RegisterValue &reg_value) {
268 // Since we cannot only write a single register value to the inferior, we
269 // need to make sure our cached copy of the register values are fresh.
270 // Otherwise when writing EAX, for example, we may also overwrite some other
271 // register with a stale value.
272 if (!CacheAllRegisterValues())
273 return false;
274
275 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
276
277 switch (reg) {
278 case gpr_r0:
279 m_context.R0 = reg_value.GetAsUInt32();
280 break;
281 case gpr_r1:
282 m_context.R1 = reg_value.GetAsUInt32();
283 break;
284 case gpr_r2:
285 m_context.R2 = reg_value.GetAsUInt32();
286 break;
287 case gpr_r3:
288 m_context.R3 = reg_value.GetAsUInt32();
289 break;
290 case gpr_r4:
291 m_context.R4 = reg_value.GetAsUInt32();
292 break;
293 case gpr_r5:
294 m_context.R5 = reg_value.GetAsUInt32();
295 break;
296 case gpr_r6:
297 m_context.R6 = reg_value.GetAsUInt32();
298 break;
299 case gpr_r7:
300 m_context.R7 = reg_value.GetAsUInt32();
301 break;
302 case gpr_r8:
303 m_context.R8 = reg_value.GetAsUInt32();
304 break;
305 case gpr_r9:
306 m_context.R9 = reg_value.GetAsUInt32();
307 break;
308 case gpr_r10:
309 m_context.R10 = reg_value.GetAsUInt32();
310 break;
311 case gpr_r11:
312 m_context.R11 = reg_value.GetAsUInt32();
313 break;
314 case gpr_r12:
315 m_context.R12 = reg_value.GetAsUInt32();
316 break;
317 case gpr_sp:
318 m_context.Sp = reg_value.GetAsUInt32();
319 break;
320 case gpr_lr:
321 m_context.Lr = reg_value.GetAsUInt32();
322 break;
323 case gpr_pc:
324 m_context.Pc = reg_value.GetAsUInt32();
325 break;
326 case gpr_cpsr:
327 m_context.Cpsr = reg_value.GetAsUInt32();
328 break;
329
330 case fpu_s0:
331 case fpu_s1:
332 case fpu_s2:
333 case fpu_s3:
334 case fpu_s4:
335 case fpu_s5:
336 case fpu_s6:
337 case fpu_s7:
338 case fpu_s8:
339 case fpu_s9:
340 case fpu_s10:
341 case fpu_s11:
342 case fpu_s12:
343 case fpu_s13:
344 case fpu_s14:
345 case fpu_s15:
346 case fpu_s16:
347 case fpu_s17:
348 case fpu_s18:
349 case fpu_s19:
350 case fpu_s20:
351 case fpu_s21:
352 case fpu_s22:
353 case fpu_s23:
354 case fpu_s24:
355 case fpu_s25:
356 case fpu_s26:
357 case fpu_s27:
358 case fpu_s28:
359 case fpu_s29:
360 case fpu_s30:
361 case fpu_s31:
362 m_context.S[reg - fpu_s0] = reg_value.GetAsUInt32();
363 break;
364
365 case fpu_d0:
366 case fpu_d1:
367 case fpu_d2:
368 case fpu_d3:
369 case fpu_d4:
370 case fpu_d5:
371 case fpu_d6:
372 case fpu_d7:
373 case fpu_d8:
374 case fpu_d9:
375 case fpu_d10:
376 case fpu_d11:
377 case fpu_d12:
378 case fpu_d13:
379 case fpu_d14:
380 case fpu_d15:
381 case fpu_d16:
382 case fpu_d17:
383 case fpu_d18:
384 case fpu_d19:
385 case fpu_d20:
386 case fpu_d21:
387 case fpu_d22:
388 case fpu_d23:
389 case fpu_d24:
390 case fpu_d25:
391 case fpu_d26:
392 case fpu_d27:
393 case fpu_d28:
394 case fpu_d29:
395 case fpu_d30:
396 case fpu_d31:
397 m_context.D[reg - fpu_d0] = reg_value.GetAsUInt64();
398 break;
399
400 case fpu_q0:
401 case fpu_q1:
402 case fpu_q2:
403 case fpu_q3:
404 case fpu_q4:
405 case fpu_q5:
406 case fpu_q6:
407 case fpu_q7:
408 case fpu_q8:
409 case fpu_q9:
410 case fpu_q10:
411 case fpu_q11:
412 case fpu_q12:
413 case fpu_q13:
414 case fpu_q14:
415 case fpu_q15:
416 memcpy(&m_context.Q[reg - fpu_q0], reg_value.GetBytes(), 16);
417 break;
418
419 case fpu_fpscr:
420 m_context.Fpscr = reg_value.GetAsUInt32();
421 break;
422
423 default:
424 return false;
425 }
426
427 // Physically update the registers in the target process.
428 return ApplyAllRegisterValues();
429}
430
431#endif // defined(__arm__) || defined(_M_ARM)
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)
@ eTypeFloat
< This value is used when the (integer) register is larger than 64-bits.
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.