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_gpr(), m_vfp_regs(), m_memory() {
24 ClearPseudoRegisters();
25 }
26
~EmulationStateARM()27 EmulationStateARM::~EmulationStateARM() {}
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)254 bool EmulationStateARM::CompareState(EmulationStateARM &other_state) {
255 bool match = true;
256
257 for (int i = 0; match && i < 17; ++i) {
258 if (m_gpr[i] != other_state.m_gpr[i])
259 match = false;
260 }
261
262 for (int i = 0; match && i < 32; ++i) {
263 if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i])
264 match = false;
265 }
266
267 for (int i = 0; match && i < 16; ++i) {
268 if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i])
269 match = false;
270 }
271
272 return match;
273 }
274
LoadStateFromDictionary(OptionValueDictionary * test_data)275 bool EmulationStateARM::LoadStateFromDictionary(
276 OptionValueDictionary *test_data) {
277 static ConstString memory_key("memory");
278 static ConstString registers_key("registers");
279
280 if (!test_data)
281 return false;
282
283 OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
284
285 // Load memory, if present.
286
287 if (value_sp.get() != nullptr) {
288 static ConstString address_key("address");
289 static ConstString data_key("data");
290 uint64_t start_address = 0;
291
292 OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
293 value_sp = mem_dict->GetValueForKey(address_key);
294 if (value_sp.get() == nullptr)
295 return false;
296 else
297 start_address = value_sp->GetUInt64Value();
298
299 value_sp = mem_dict->GetValueForKey(data_key);
300 OptionValueArray *mem_array = value_sp->GetAsArray();
301 if (!mem_array)
302 return false;
303
304 uint32_t num_elts = mem_array->GetSize();
305 uint32_t address = (uint32_t)start_address;
306
307 for (uint32_t i = 0; i < num_elts; ++i) {
308 value_sp = mem_array->GetValueAtIndex(i);
309 if (value_sp.get() == nullptr)
310 return false;
311 uint64_t value = value_sp->GetUInt64Value();
312 StoreToPseudoAddress(address, value);
313 address = address + 4;
314 }
315 }
316
317 value_sp = test_data->GetValueForKey(registers_key);
318 if (value_sp.get() == nullptr)
319 return false;
320
321 // Load General Registers
322
323 OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
324
325 StreamString sstr;
326 for (int i = 0; i < 16; ++i) {
327 sstr.Clear();
328 sstr.Printf("r%d", i);
329 ConstString reg_name(sstr.GetString());
330 value_sp = reg_dict->GetValueForKey(reg_name);
331 if (value_sp.get() == nullptr)
332 return false;
333 uint64_t reg_value = value_sp->GetUInt64Value();
334 StorePseudoRegisterValue(dwarf_r0 + i, reg_value);
335 }
336
337 static ConstString cpsr_name("cpsr");
338 value_sp = reg_dict->GetValueForKey(cpsr_name);
339 if (value_sp.get() == nullptr)
340 return false;
341 StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
342
343 // Load s/d Registers
344 for (int i = 0; i < 32; ++i) {
345 sstr.Clear();
346 sstr.Printf("s%d", i);
347 ConstString reg_name(sstr.GetString());
348 value_sp = reg_dict->GetValueForKey(reg_name);
349 if (value_sp.get() == nullptr)
350 return false;
351 uint64_t reg_value = value_sp->GetUInt64Value();
352 StorePseudoRegisterValue(dwarf_s0 + i, reg_value);
353 }
354
355 return true;
356 }
357