LLDB  mainline
EmulationStateARM.cpp
Go to the documentation of this file.
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 
14 #include "lldb/Target/StackFrame.h"
16 #include "lldb/Utility/Scalar.h"
17 
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
25 }
26 
28 
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 
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 
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 
84 
86  uint32_t value) {
87  m_memory[p_address] = value;
88  return true;
89 }
90 
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 
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 
121  value = llvm::ByteSwap_32(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 
133  value1 = llvm::ByteSwap_32(value1);
134  value2 = llvm::ByteSwap_32(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 
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));
160  value = llvm::ByteSwap_32(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));
171  value1 = llvm::ByteSwap_32(value1);
172  value2 = llvm::ByteSwap_32(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 
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 
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 
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],
242  other_state.m_vfp_regs.d_regs[i]);
243  }
244  }
245 
246  // other_state is the expected state. If it has memory, check it.
247  if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) {
248  match = false;
249  out_stream->Printf("memory does not match\n");
250  out_stream->Printf("got memory:\n");
251  for (auto p : m_memory)
252  out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
253  out_stream->Printf("expected memory:\n");
254  for (auto p : other_state.m_memory)
255  out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
256  }
257 
258  return match;
259 }
260 
262  OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {
263  StreamString sstr;
264  for (int i = 0; i < num; ++i) {
265  sstr.Clear();
266  sstr.Printf("%c%d", kind, i);
267  OptionValueSP value_sp =
268  reg_dict->GetValueForKey(ConstString(sstr.GetString()));
269  if (value_sp.get() == nullptr)
270  return false;
271  uint64_t reg_value = value_sp->GetUInt64Value();
272  StorePseudoRegisterValue(first_reg + i, reg_value);
273  }
274 
275  return true;
276 }
277 
279  OptionValueDictionary *test_data) {
280  static ConstString memory_key("memory");
281  static ConstString registers_key("registers");
282 
283  if (!test_data)
284  return false;
285 
286  OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
287 
288  // Load memory, if present.
289 
290  if (value_sp.get() != nullptr) {
291  static ConstString address_key("address");
292  static ConstString data_key("data");
293  uint64_t start_address = 0;
294 
295  OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
296  value_sp = mem_dict->GetValueForKey(address_key);
297  if (value_sp.get() == nullptr)
298  return false;
299  else
300  start_address = value_sp->GetUInt64Value();
301 
302  value_sp = mem_dict->GetValueForKey(data_key);
303  OptionValueArray *mem_array = value_sp->GetAsArray();
304  if (!mem_array)
305  return false;
306 
307  uint32_t num_elts = mem_array->GetSize();
308  uint32_t address = (uint32_t)start_address;
309 
310  for (uint32_t i = 0; i < num_elts; ++i) {
311  value_sp = mem_array->GetValueAtIndex(i);
312  if (value_sp.get() == nullptr)
313  return false;
314  uint64_t value = value_sp->GetUInt64Value();
315  StoreToPseudoAddress(address, value);
316  address = address + 4;
317  }
318  }
319 
320  value_sp = test_data->GetValueForKey(registers_key);
321  if (value_sp.get() == nullptr)
322  return false;
323 
324  // Load General Registers
325 
326  OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
327  if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))
328  return false;
329 
330  static ConstString cpsr_name("cpsr");
331  value_sp = reg_dict->GetValueForKey(cpsr_name);
332  if (value_sp.get() == nullptr)
333  return false;
334  StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
335 
336  // Load s/d Registers
337  // To prevent you giving both types in a state and overwriting
338  // one or the other, we'll expect to get either all S registers,
339  // or all D registers. Not a mix of the two.
340  bool found_s_registers =
341  LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);
342  bool found_d_registers =
343  LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);
344 
345  return found_s_registers != found_d_registers;
346 }
lldb_private::OptionValueDictionary::GetValueForKey
lldb::OptionValueSP GetValueForKey(ConstString key) const
Definition: OptionValueDictionary.cpp:300
lldb_private::OptionValue::GetAsDictionary
OptionValueDictionary * GetAsDictionary()
Definition: OptionValue.cpp:130
Scalar.h
LLDB_INVALID_REGNUM
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
dwarf_s0
@ dwarf_s0
Definition: ARM_DWARF_Registers.h:33
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb::eRegisterKindDWARF
@ eRegisterKindDWARF
the register numbers seen DWARF
Definition: lldb-enumerations.h:230
dwarf_d31
@ dwarf_d31
Definition: ARM_DWARF_Registers.h:186
lldb_private::EmulateInstruction::Context
Definition: EmulateInstruction.h:184
EmulationStateARM::LoadRegistersStateFromDictionary
bool LoadRegistersStateFromDictionary(lldb_private::OptionValueDictionary *reg_dict, char kind, int first_reg, int num)
Definition: EmulationStateARM.cpp:261
lldb_private::OptionValueArray::GetValueAtIndex
lldb::OptionValueSP GetValueAtIndex(size_t idx) const
Definition: OptionValueArray.h:63
EmulationStateARM::m_memory
std::map< lldb::addr_t, uint32_t > m_memory
Definition: EmulationStateARM.h:75
EmulationStateARM::LoadStateFromDictionary
bool LoadStateFromDictionary(lldb_private::OptionValueDictionary *test_data)
Definition: EmulationStateARM.cpp:278
EmulationStateARM::ReadPseudoMemory
static size_t ReadPseudoMemory(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, size_t length)
Definition: EmulationStateARM.cpp:106
RegisterValue.h
EmulationStateARM::StoreToPseudoAddress
bool StoreToPseudoAddress(lldb::addr_t p_address, uint32_t value)
Definition: EmulationStateARM.cpp:85
StackFrame.h
EmulationStateARM::ClearPseudoMemory
void ClearPseudoMemory()
Definition: EmulationStateARM.cpp:83
EmulationStateARM::ReadPseudoRegister
static bool ReadPseudoRegister(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &reg_value)
Definition: EmulationStateARM.cpp:183
lldb_private::Stream
Definition: Stream.h:28
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
OptionValueDictionary.h
lldb_private::OptionValue::GetAsArray
OptionValueArray * GetAsArray()
Definition: OptionValue.cpp:106
EmulationStateARM::ClearPseudoRegisters
void ClearPseudoRegisters()
Definition: EmulationStateARM.cpp:72
EmulationStateARM::ReadFromPseudoAddress
uint32_t ReadFromPseudoAddress(lldb::addr_t p_address, bool &success)
Definition: EmulationStateARM.cpp:91
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
EmulationStateARM::CompareState
bool CompareState(EmulationStateARM &other_state, lldb_private::Stream *out_stream)
Definition: EmulationStateARM.cpp:217
EmulationStateARM::m_gpr
uint32_t m_gpr[17]
Definition: EmulationStateARM.h:67
lldb_private::RegisterValue::GetAsUInt64
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:556
lldb_private::OptionValueArray::GetSize
size_t GetSize() const
Definition: OptionValueArray.h:54
EmulationStateARM::m_vfp_regs
struct EmulationStateARM::_sd_regs m_vfp_regs
lldb_private::StreamString::Clear
void Clear()
Definition: StreamString.cpp:31
EmulationStateARM.h
EmulationStateARM::StorePseudoRegisterValue
bool StorePseudoRegisterValue(uint32_t reg_num, uint64_t value)
Definition: EmulationStateARM.cpp:29
lldb_private::ConstString
Definition: ConstString.h:39
dwarf_d0
@ dwarf_d0
Definition: ARM_DWARF_Registers.h:155
lldb_private::StreamString
Definition: StreamString.h:23
OptionValueArray.h
dwarf_s31
@ dwarf_s31
Definition: ARM_DWARF_Registers.h:64
EmulationStateARM::WritePseudoMemory
static size_t WritePseudoMemory(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length)
Definition: EmulationStateARM.cpp:147
ARM_DWARF_Registers.h
dwarf_r0
@ dwarf_r0
Definition: ABISysV_mips.cpp:39
EmulationStateARM
Definition: EmulationStateARM.h:17
dwarf_cpsr
@ dwarf_cpsr
Definition: ARM_DWARF_Registers.h:31
uint32_t
lldb_private::EmulateInstruction
Definition: EmulateInstruction.h:93
lldb_private::RegisterValue::SetUInt
bool SetUInt(uint64_t uint, uint32_t byte_size)
Definition: RegisterValue.cpp:727
lldb_private::endian::InlHostByteOrder
lldb::ByteOrder InlHostByteOrder()
Definition: Endian.h:25
EmulationStateARM::~EmulationStateARM
virtual ~EmulationStateARM()
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb::eByteOrderBig
@ eByteOrderBig
Definition: lldb-enumerations.h:141
lldb_private::OptionValueDictionary
Definition: OptionValueDictionary.h:19
EmulationStateARM::EmulationStateARM
EmulationStateARM()
Definition: EmulationStateARM.cpp:23
lldb
Definition: SBAddress.h:15
EmulationStateARM::_sd_regs::d_regs
uint64_t d_regs[16]
Definition: EmulationStateARM.h:71
EmulationStateARM::_sd_regs::s_regs
uint32_t s_regs[32]
Definition: EmulationStateARM.h:69
RegisterContext.h
EmulationStateARM::WritePseudoRegister
static bool WritePseudoRegister(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &reg_value)
Definition: EmulationStateARM.cpp:202
EmulationStateARM::ReadPseudoRegisterValue
uint64_t ReadPseudoRegisterValue(uint32_t reg_num, bool &success)
Definition: EmulationStateARM.cpp:49
lldb_private::OptionValueArray
Definition: OptionValueArray.h:18