1 //===-- EmulationStateARM.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 #include "EmulationStateARM.h"
10
11 #include "lldb/Interpreter/OptionValueArray.h"
12 #include "lldb/Interpreter/OptionValueDictionary.h"
13 #include "lldb/Target/RegisterContext.h"
14 #include "lldb/Target/StackFrame.h"
15 #include "lldb/Utility/RegisterValue.h"
16 #include "lldb/Utility/Scalar.h"
17
18 #include "Utility/ARM_DWARF_Registers.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
EmulationStateARM()23 EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24 ClearPseudoRegisters();
25 }
26
27 EmulationStateARM::~EmulationStateARM() = default;
28
LoadPseudoRegistersFromFrame(StackFrame & frame)29 bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
30 RegisterContext *reg_ctx = frame.GetRegisterContext().get();
31 bool success = true;
32 uint32_t reg_num;
33
34 for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) {
35 reg_num =
36 reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
37 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
38 RegisterValue reg_value;
39 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
40 m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
41 } else
42 success = false;
43 }
44
45 for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) {
46 reg_num =
47 reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
48 RegisterValue reg_value;
49 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
50
51 if (reg_ctx->ReadRegister(reg_info, reg_value)) {
52 uint64_t value = reg_value.GetAsUInt64();
53 uint32_t idx = i - dwarf_d0;
54 if (i < 16) {
55 m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
56 m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
57 } else
58 m_vfp_regs.d_regs[idx - 16] = value;
59 } else
60 success = false;
61 }
62
63 return success;
64 }
65
StorePseudoRegisterValue(uint32_t reg_num,uint64_t value)66 bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
67 uint64_t value) {
68 if (reg_num <= dwarf_cpsr)
69 m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
70 else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
71 uint32_t idx = reg_num - dwarf_s0;
72 m_vfp_regs.s_regs[idx] = (uint32_t)value;
73 } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
74 uint32_t idx = reg_num - dwarf_d0;
75 if (idx < 16) {
76 m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
77 m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
78 } else
79 m_vfp_regs.d_regs[idx - 16] = value;
80 } else
81 return false;
82
83 return true;
84 }
85
ReadPseudoRegisterValue(uint32_t reg_num,bool & success)86 uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
87 bool &success) {
88 uint64_t value = 0;
89 success = true;
90
91 if (reg_num <= dwarf_cpsr)
92 value = m_gpr[reg_num - dwarf_r0];
93 else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
94 uint32_t idx = reg_num - dwarf_s0;
95 value = m_vfp_regs.d_regs[idx];
96 } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
97 uint32_t idx = reg_num - dwarf_d0;
98 if (idx < 16)
99 value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
100 ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32);
101 else
102 value = m_vfp_regs.d_regs[idx - 16];
103 } else
104 success = false;
105
106 return value;
107 }
108
ClearPseudoRegisters()109 void EmulationStateARM::ClearPseudoRegisters() {
110 for (int i = 0; i < 17; ++i)
111 m_gpr[i] = 0;
112
113 for (int i = 0; i < 32; ++i)
114 m_vfp_regs.s_regs[i] = 0;
115
116 for (int i = 0; i < 16; ++i)
117 m_vfp_regs.d_regs[i] = 0;
118 }
119
ClearPseudoMemory()120 void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
121
StoreToPseudoAddress(lldb::addr_t p_address,uint32_t value)122 bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
123 uint32_t value) {
124 m_memory[p_address] = value;
125 return true;
126 }
127
ReadFromPseudoAddress(lldb::addr_t p_address,bool & success)128 uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
129 bool &success) {
130 std::map<lldb::addr_t, uint32_t>::iterator pos;
131 uint32_t ret_val = 0;
132
133 success = true;
134 pos = m_memory.find(p_address);
135 if (pos != m_memory.end())
136 ret_val = pos->second;
137 else
138 success = false;
139
140 return ret_val;
141 }
142
ReadPseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,void * dst,size_t length)143 size_t EmulationStateARM::ReadPseudoMemory(
144 EmulateInstruction *instruction, void *baton,
145 const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
146 size_t length) {
147 if (!baton)
148 return 0;
149
150 bool success = true;
151 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
152 if (length <= 4) {
153 uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
154 if (!success)
155 return 0;
156
157 if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
158 value = llvm::ByteSwap_32(value);
159 *((uint32_t *)dst) = value;
160 } else if (length == 8) {
161 uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
162 if (!success)
163 return 0;
164
165 uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
166 if (!success)
167 return 0;
168
169 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
170 value1 = llvm::ByteSwap_32(value1);
171 value2 = llvm::ByteSwap_32(value2);
172 }
173 ((uint32_t *)dst)[0] = value1;
174 ((uint32_t *)dst)[1] = value2;
175 } else
176 success = false;
177
178 if (success)
179 return length;
180
181 return 0;
182 }
183
WritePseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,const void * dst,size_t length)184 size_t EmulationStateARM::WritePseudoMemory(
185 EmulateInstruction *instruction, void *baton,
186 const EmulateInstruction::Context &context, lldb::addr_t addr,
187 const void *dst, size_t length) {
188 if (!baton)
189 return 0;
190
191 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
192
193 if (length <= 4) {
194 uint32_t value;
195 memcpy (&value, dst, sizeof (uint32_t));
196 if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
197 value = llvm::ByteSwap_32(value);
198
199 pseudo_state->StoreToPseudoAddress(addr, value);
200 return length;
201 } else if (length == 8) {
202 uint32_t value1;
203 uint32_t value2;
204 memcpy (&value1, dst, sizeof (uint32_t));
205 memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
206 sizeof(uint32_t));
207 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
208 value1 = llvm::ByteSwap_32(value1);
209 value2 = llvm::ByteSwap_32(value2);
210 }
211
212 pseudo_state->StoreToPseudoAddress(addr, value1);
213 pseudo_state->StoreToPseudoAddress(addr + 4, value2);
214 return length;
215 }
216
217 return 0;
218 }
219
ReadPseudoRegister(EmulateInstruction * instruction,void * baton,const lldb_private::RegisterInfo * reg_info,lldb_private::RegisterValue & reg_value)220 bool EmulationStateARM::ReadPseudoRegister(
221 EmulateInstruction *instruction, void *baton,
222 const lldb_private::RegisterInfo *reg_info,
223 lldb_private::RegisterValue ®_value) {
224 if (!baton || !reg_info)
225 return false;
226
227 bool success = true;
228 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
229 const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
230 assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
231 uint64_t reg_uval =
232 pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
233
234 if (success)
235 success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
236 return success;
237 }
238
WritePseudoRegister(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,const lldb_private::RegisterInfo * reg_info,const lldb_private::RegisterValue & reg_value)239 bool EmulationStateARM::WritePseudoRegister(
240 EmulateInstruction *instruction, void *baton,
241 const EmulateInstruction::Context &context,
242 const lldb_private::RegisterInfo *reg_info,
243 const lldb_private::RegisterValue ®_value) {
244 if (!baton || !reg_info)
245 return false;
246
247 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
248 const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
249 assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
250 return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
251 reg_value.GetAsUInt64());
252 }
253
CompareState(EmulationStateARM & other_state,Stream * out_stream)254 bool EmulationStateARM::CompareState(EmulationStateARM &other_state,
255 Stream *out_stream) {
256 bool match = true;
257
258 for (int i = 0; match && i < 17; ++i) {
259 if (m_gpr[i] != other_state.m_gpr[i]) {
260 match = false;
261 out_stream->Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i],
262 other_state.m_gpr[i]);
263 }
264 }
265
266 for (int i = 0; match && i < 32; ++i) {
267 if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) {
268 match = false;
269 out_stream->Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i],
270 other_state.m_vfp_regs.s_regs[i]);
271 }
272 }
273
274 for (int i = 0; match && i < 16; ++i) {
275 if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) {
276 match = false;
277 out_stream->Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16,
278 m_vfp_regs.d_regs[i],
279 other_state.m_vfp_regs.d_regs[i]);
280 }
281 }
282
283 // other_state is the expected state. If it has memory, check it.
284 if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) {
285 match = false;
286 out_stream->Printf("memory does not match\n");
287 out_stream->Printf("got memory:\n");
288 for (auto p : m_memory)
289 out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
290 out_stream->Printf("expected memory:\n");
291 for (auto p : other_state.m_memory)
292 out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
293 }
294
295 return match;
296 }
297
LoadRegistersStateFromDictionary(OptionValueDictionary * reg_dict,char kind,int first_reg,int num)298 bool EmulationStateARM::LoadRegistersStateFromDictionary(
299 OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {
300 StreamString sstr;
301 for (int i = 0; i < num; ++i) {
302 sstr.Clear();
303 sstr.Printf("%c%d", kind, i);
304 OptionValueSP value_sp =
305 reg_dict->GetValueForKey(ConstString(sstr.GetString()));
306 if (value_sp.get() == nullptr)
307 return false;
308 uint64_t reg_value = value_sp->GetUInt64Value();
309 StorePseudoRegisterValue(first_reg + i, reg_value);
310 }
311
312 return true;
313 }
314
LoadStateFromDictionary(OptionValueDictionary * test_data)315 bool EmulationStateARM::LoadStateFromDictionary(
316 OptionValueDictionary *test_data) {
317 static ConstString memory_key("memory");
318 static ConstString registers_key("registers");
319
320 if (!test_data)
321 return false;
322
323 OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
324
325 // Load memory, if present.
326
327 if (value_sp.get() != nullptr) {
328 static ConstString address_key("address");
329 static ConstString data_key("data");
330 uint64_t start_address = 0;
331
332 OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
333 value_sp = mem_dict->GetValueForKey(address_key);
334 if (value_sp.get() == nullptr)
335 return false;
336 else
337 start_address = value_sp->GetUInt64Value();
338
339 value_sp = mem_dict->GetValueForKey(data_key);
340 OptionValueArray *mem_array = value_sp->GetAsArray();
341 if (!mem_array)
342 return false;
343
344 uint32_t num_elts = mem_array->GetSize();
345 uint32_t address = (uint32_t)start_address;
346
347 for (uint32_t i = 0; i < num_elts; ++i) {
348 value_sp = mem_array->GetValueAtIndex(i);
349 if (value_sp.get() == nullptr)
350 return false;
351 uint64_t value = value_sp->GetUInt64Value();
352 StoreToPseudoAddress(address, value);
353 address = address + 4;
354 }
355 }
356
357 value_sp = test_data->GetValueForKey(registers_key);
358 if (value_sp.get() == nullptr)
359 return false;
360
361 // Load General Registers
362
363 OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
364 if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))
365 return false;
366
367 static ConstString cpsr_name("cpsr");
368 value_sp = reg_dict->GetValueForKey(cpsr_name);
369 if (value_sp.get() == nullptr)
370 return false;
371 StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
372
373 // Load s/d Registers
374 // To prevent you giving both types in a state and overwriting
375 // one or the other, we'll expect to get either all S registers,
376 // or all D registers. Not a mix of the two.
377 bool found_s_registers =
378 LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);
379 bool found_d_registers =
380 LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);
381
382 return found_s_registers != found_d_registers;
383 }
384