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