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 
23 EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24   ClearPseudoRegisters();
25 }
26 
27 EmulationStateARM::~EmulationStateARM() = default;
28 
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 
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 
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 
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 
120 void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
121 
122 bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
123                                              uint32_t value) {
124   m_memory[p_address] = value;
125   return true;
126 }
127 
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 
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 
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 
220 bool EmulationStateARM::ReadPseudoRegister(
221     EmulateInstruction *instruction, void *baton,
222     const lldb_private::RegisterInfo *reg_info,
223     lldb_private::RegisterValue &reg_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 
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 &reg_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 
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 
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 
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