1 //===-- RegisterContextPOSIX_arm64.cpp --------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include <cstring>
11 #include <errno.h>
12 #include <stdint.h>
13
14 #include "lldb/Core/DataBufferHeap.h"
15 #include "lldb/Core/DataExtractor.h"
16 #include "lldb/Core/RegisterValue.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Target/Thread.h"
20 #include "lldb/Host/Endian.h"
21 #include "llvm/Support/Compiler.h"
22
23 #include "RegisterContextPOSIX_arm64.h"
24 #include "Plugins/Process/elf-core/ProcessElfCore.h"
25
26 using namespace lldb;
27 using namespace lldb_private;
28
29 // ARM64 general purpose registers.
30 const uint32_t g_gpr_regnums_arm64[] =
31 {
32 gpr_x0_arm64,
33 gpr_x1_arm64,
34 gpr_x2_arm64,
35 gpr_x3_arm64,
36 gpr_x4_arm64,
37 gpr_x5_arm64,
38 gpr_x6_arm64,
39 gpr_x7_arm64,
40 gpr_x8_arm64,
41 gpr_x9_arm64,
42 gpr_x10_arm64,
43 gpr_x11_arm64,
44 gpr_x12_arm64,
45 gpr_x13_arm64,
46 gpr_x14_arm64,
47 gpr_x15_arm64,
48 gpr_x16_arm64,
49 gpr_x17_arm64,
50 gpr_x18_arm64,
51 gpr_x19_arm64,
52 gpr_x20_arm64,
53 gpr_x21_arm64,
54 gpr_x22_arm64,
55 gpr_x23_arm64,
56 gpr_x24_arm64,
57 gpr_x25_arm64,
58 gpr_x26_arm64,
59 gpr_x27_arm64,
60 gpr_x28_arm64,
61 gpr_fp_arm64,
62 gpr_lr_arm64,
63 gpr_sp_arm64,
64 gpr_pc_arm64,
65 gpr_cpsr_arm64,
66 LLDB_INVALID_REGNUM // register sets need to end with this flag
67 };
68 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \
69 "g_gpr_regnums_arm64 has wrong number of register infos");
70
71 // ARM64 floating point registers.
72 static const uint32_t g_fpu_regnums_arm64[] =
73 {
74 fpu_v0_arm64,
75 fpu_v1_arm64,
76 fpu_v2_arm64,
77 fpu_v3_arm64,
78 fpu_v4_arm64,
79 fpu_v5_arm64,
80 fpu_v6_arm64,
81 fpu_v7_arm64,
82 fpu_v8_arm64,
83 fpu_v9_arm64,
84 fpu_v10_arm64,
85 fpu_v11_arm64,
86 fpu_v12_arm64,
87 fpu_v13_arm64,
88 fpu_v14_arm64,
89 fpu_v15_arm64,
90 fpu_v16_arm64,
91 fpu_v17_arm64,
92 fpu_v18_arm64,
93 fpu_v19_arm64,
94 fpu_v20_arm64,
95 fpu_v21_arm64,
96 fpu_v22_arm64,
97 fpu_v23_arm64,
98 fpu_v24_arm64,
99 fpu_v25_arm64,
100 fpu_v26_arm64,
101 fpu_v27_arm64,
102 fpu_v28_arm64,
103 fpu_v29_arm64,
104 fpu_v30_arm64,
105 fpu_v31_arm64,
106 fpu_fpsr_arm64,
107 fpu_fpcr_arm64,
108 LLDB_INVALID_REGNUM // register sets need to end with this flag
109 };
110 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \
111 "g_fpu_regnums_arm64 has wrong number of register infos");
112
113 // Number of register sets provided by this context.
114 enum
115 {
116 k_num_register_sets = 2
117 };
118
119 // Register sets for ARM64.
120 static const lldb_private::RegisterSet
121 g_reg_sets_arm64[k_num_register_sets] =
122 {
123 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 },
124 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
125 };
126
IsGPR(unsigned reg)127 bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg)
128 {
129 return reg <= m_reg_info.last_gpr; // GPR's come first.
130 }
131
IsFPR(unsigned reg)132 bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg)
133 {
134 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
135 }
136
RegisterContextPOSIX_arm64(lldb_private::Thread & thread,uint32_t concrete_frame_idx,lldb_private::RegisterInfoInterface * register_info)137 RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(lldb_private::Thread &thread,
138 uint32_t concrete_frame_idx,
139 lldb_private::RegisterInfoInterface *register_info)
140 : lldb_private::RegisterContext(thread, concrete_frame_idx)
141 {
142 m_register_info_ap.reset(register_info);
143
144 switch (register_info->m_target_arch.GetMachine())
145 {
146 case llvm::Triple::aarch64:
147 m_reg_info.num_registers = k_num_registers_arm64;
148 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64;
149 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64;
150 m_reg_info.last_gpr = k_last_gpr_arm64;
151 m_reg_info.first_fpr = k_first_fpr_arm64;
152 m_reg_info.last_fpr = k_last_fpr_arm64;
153 m_reg_info.first_fpr_v = fpu_v0_arm64;
154 m_reg_info.last_fpr_v = fpu_v31_arm64;
155 m_reg_info.gpr_flags = gpr_cpsr_arm64;
156 break;
157 default:
158 assert(false && "Unhandled target architecture.");
159 break;
160 }
161
162 ::memset(&m_fpr, 0, sizeof m_fpr);
163
164 // elf-core yet to support ReadFPR()
165 lldb::ProcessSP base = CalculateProcess();
166 if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
167 return;
168 }
169
~RegisterContextPOSIX_arm64()170 RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64()
171 {
172 }
173
174 void
Invalidate()175 RegisterContextPOSIX_arm64::Invalidate()
176 {
177 }
178
179 void
InvalidateAllRegisters()180 RegisterContextPOSIX_arm64::InvalidateAllRegisters()
181 {
182 }
183
184 unsigned
GetRegisterOffset(unsigned reg)185 RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg)
186 {
187 assert(reg < m_reg_info.num_registers && "Invalid register number.");
188 return GetRegisterInfo()[reg].byte_offset;
189 }
190
191 unsigned
GetRegisterSize(unsigned reg)192 RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg)
193 {
194 assert(reg < m_reg_info.num_registers && "Invalid register number.");
195 return GetRegisterInfo()[reg].byte_size;
196 }
197
198 size_t
GetRegisterCount()199 RegisterContextPOSIX_arm64::GetRegisterCount()
200 {
201 size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers;
202 return num_registers;
203 }
204
205 size_t
GetGPRSize()206 RegisterContextPOSIX_arm64::GetGPRSize()
207 {
208 return m_register_info_ap->GetGPRSize ();
209 }
210
211 const lldb_private::RegisterInfo *
GetRegisterInfo()212 RegisterContextPOSIX_arm64::GetRegisterInfo()
213 {
214 // Commonly, this method is overridden and g_register_infos is copied and specialized.
215 // So, use GetRegisterInfo() rather than g_register_infos in this scope.
216 return m_register_info_ap->GetRegisterInfo ();
217 }
218
219 const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)220 RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg)
221 {
222 if (reg < m_reg_info.num_registers)
223 return &GetRegisterInfo()[reg];
224 else
225 return NULL;
226 }
227
228 size_t
GetRegisterSetCount()229 RegisterContextPOSIX_arm64::GetRegisterSetCount()
230 {
231 size_t sets = 0;
232 for (size_t set = 0; set < k_num_register_sets; ++set)
233 {
234 if (IsRegisterSetAvailable(set))
235 ++sets;
236 }
237
238 return sets;
239 }
240
241 const lldb_private::RegisterSet *
GetRegisterSet(size_t set)242 RegisterContextPOSIX_arm64::GetRegisterSet(size_t set)
243 {
244 if (IsRegisterSetAvailable(set))
245 {
246 switch (m_register_info_ap->m_target_arch.GetMachine())
247 {
248 case llvm::Triple::aarch64:
249 return &g_reg_sets_arm64[set];
250 default:
251 assert(false && "Unhandled target architecture.");
252 return NULL;
253 }
254 }
255 return NULL;
256 }
257
258 const char *
GetRegisterName(unsigned reg)259 RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg)
260 {
261 assert(reg < m_reg_info.num_registers && "Invalid register offset.");
262 return GetRegisterInfo()[reg].name;
263 }
264
265 lldb::ByteOrder
GetByteOrder()266 RegisterContextPOSIX_arm64::GetByteOrder()
267 {
268 // Get the target process whose privileged thread was used for the register read.
269 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
270 lldb_private::Process *process = CalculateProcess().get();
271
272 if (process)
273 byte_order = process->GetByteOrder();
274 return byte_order;
275 }
276
277 bool
IsRegisterSetAvailable(size_t set_index)278 RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index)
279 {
280 return set_index < k_num_register_sets;
281 }
282
283
284 // Used when parsing DWARF and EH frame information and any other
285 // object file sections that contain register numbers in them.
286 uint32_t
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)287 RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
288 uint32_t num)
289 {
290 const uint32_t num_regs = GetRegisterCount();
291
292 assert (kind < lldb::kNumRegisterKinds);
293 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
294 {
295 const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
296
297 if (reg_info->kinds[kind] == num)
298 return reg_idx;
299 }
300
301 return LLDB_INVALID_REGNUM;
302 }
303