1 //===-- EmulationStateARM.cpp -----------------------------------*- C++ -*-===//
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_gpr(), m_vfp_regs(), m_memory() {
24   ClearPseudoRegisters();
25 }
26 
27 EmulationStateARM::~EmulationStateARM() {}
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   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 
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