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