• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- EmulationStateARM.cpp -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "EmulationStateARM.h"
11 
12 #include "lldb/Core/RegisterValue.h"
13 #include "lldb/Core/Scalar.h"
14 #include "lldb/Interpreter/OptionValueArray.h"
15 #include "lldb/Interpreter/OptionValueDictionary.h"
16 #include "lldb/Target/StackFrame.h"
17 #include "lldb/Target/RegisterContext.h"
18 
19 #include "Utility/ARM_DWARF_Registers.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
EmulationStateARM()24 EmulationStateARM::EmulationStateARM () :
25     m_gpr (),
26     m_vfp_regs (),
27     m_memory ()
28 {
29     ClearPseudoRegisters();
30 }
31 
~EmulationStateARM()32 EmulationStateARM::~EmulationStateARM ()
33 {
34 }
35 
36 bool
LoadPseudoRegistersFromFrame(StackFrame & frame)37 EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame)
38 {
39     RegisterContext *reg_ctx = frame.GetRegisterContext().get();
40     bool success = true;
41     uint32_t reg_num;
42 
43     for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i)
44     {
45         reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i);
46         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
47         RegisterValue reg_value;
48         if (reg_ctx->ReadRegister (reg_info, reg_value))
49         {
50             m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
51         }
52         else
53             success = false;
54     }
55 
56     for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i)
57     {
58         reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i);
59         RegisterValue reg_value;
60         const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
61 
62         if (reg_ctx->ReadRegister (reg_info, reg_value))
63         {
64             uint32_t idx = i - dwarf_d0;
65             if (i < 16)
66                 m_vfp_regs.sd_regs[idx].d_reg = reg_value.GetAsUInt64();
67             else
68                 m_vfp_regs.d_regs[idx - 16] = reg_value.GetAsUInt64();
69         }
70         else
71             success = false;
72     }
73 
74     return success;
75 }
76 
77 bool
StorePseudoRegisterValue(uint32_t reg_num,uint64_t value)78 EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value)
79 {
80     if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr))
81         m_gpr[reg_num  - dwarf_r0] = (uint32_t) value;
82     else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31))
83     {
84         uint32_t idx = reg_num - dwarf_s0;
85         m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2] = (uint32_t) value;
86     }
87     else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31))
88     {
89         if ((reg_num - dwarf_d0) < 16)
90         {
91             m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg = value;
92         }
93         else
94             m_vfp_regs.d_regs[reg_num - dwarf_d16] = value;
95     }
96     else
97         return false;
98 
99     return true;
100 }
101 
102 uint64_t
ReadPseudoRegisterValue(uint32_t reg_num,bool & success)103 EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success)
104 {
105     uint64_t value = 0;
106     success = true;
107 
108     if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr))
109         value = m_gpr[reg_num  - dwarf_r0];
110     else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31))
111     {
112         uint32_t idx = reg_num - dwarf_s0;
113         value = m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2];
114     }
115     else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31))
116     {
117         if ((reg_num - dwarf_d0) < 16)
118             value = m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg;
119         else
120             value = m_vfp_regs.d_regs[reg_num - dwarf_d16];
121     }
122     else
123         success = false;
124 
125     return value;
126 }
127 
128 void
ClearPseudoRegisters()129 EmulationStateARM::ClearPseudoRegisters ()
130 {
131     for (int i = 0; i < 17; ++i)
132         m_gpr[i] = 0;
133 
134     for (int i = 0; i < 16; ++i)
135         m_vfp_regs.sd_regs[i].d_reg = 0;
136 
137     for (int i = 0; i < 16; ++i)
138         m_vfp_regs.d_regs[i] = 0;
139 }
140 
141 void
ClearPseudoMemory()142 EmulationStateARM::ClearPseudoMemory ()
143 {
144     m_memory.clear();
145 }
146 
147 bool
StoreToPseudoAddress(lldb::addr_t p_address,uint64_t value,uint32_t size)148 EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size)
149 {
150     if (size > 8)
151         return false;
152 
153     if (size <= 4)
154         m_memory[p_address] = value;
155     else if (size == 8)
156     {
157         m_memory[p_address] = (value << 32) >> 32;
158         m_memory[p_address + 4] = value << 32;
159     }
160     return true;
161 }
162 
163 uint32_t
ReadFromPseudoAddress(lldb::addr_t p_address,uint32_t size,bool & success)164 EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success)
165 {
166     std::map<lldb::addr_t,uint32_t>::iterator pos;
167     uint32_t ret_val = 0;
168 
169     success = true;
170     pos = m_memory.find(p_address);
171     if (pos != m_memory.end())
172         ret_val = pos->second;
173     else
174         success = false;
175 
176     return ret_val;
177 }
178 
179 size_t
ReadPseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,void * dst,size_t length)180 EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction,
181                                      void *baton,
182                                      const EmulateInstruction::Context &context,
183                                      lldb::addr_t addr,
184                                      void *dst,
185                                      size_t length)
186 {
187     if (!baton)
188         return 0;
189 
190     bool success = true;
191     EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
192     if (length <= 4)
193     {
194         uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, length, success);
195         if (!success)
196             return 0;
197 
198         *((uint32_t *) dst) = value;
199     }
200     else if (length == 8)
201     {
202         uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, 4, success);
203         if (!success)
204             return 0;
205 
206         uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, 4, success);
207         if (!success)
208             return 0;
209 
210         uint64_t value64 = value2;
211         value64 = (value64 << 32) | value1;
212         *((uint64_t *) dst) = value64;
213     }
214     else
215         success = false;
216 
217     if (success)
218         return length;
219 
220     return 0;
221 }
222 
223 size_t
WritePseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,const void * dst,size_t length)224 EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction,
225                                       void *baton,
226                                       const EmulateInstruction::Context &context,
227                                       lldb::addr_t addr,
228                                       const void *dst,
229                                       size_t length)
230 {
231     if (!baton)
232         return 0;
233 
234     bool success;
235     EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
236     uint64_t value = *((uint64_t *) dst);
237     success = pseudo_state->StoreToPseudoAddress (addr, value, length);
238     if (success)
239         return length;
240 
241     return 0;
242 }
243 
244 bool
ReadPseudoRegister(EmulateInstruction * instruction,void * baton,const lldb_private::RegisterInfo * reg_info,lldb_private::RegisterValue & reg_value)245 EmulationStateARM::ReadPseudoRegister (EmulateInstruction *instruction,
246                                        void *baton,
247                                        const lldb_private::RegisterInfo *reg_info,
248                                        lldb_private::RegisterValue &reg_value)
249 {
250     if (!baton || !reg_info)
251         return false;
252 
253     bool success = true;
254     EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
255     const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
256     assert (dwarf_reg_num != LLDB_INVALID_REGNUM);
257     uint64_t reg_uval = pseudo_state->ReadPseudoRegisterValue (dwarf_reg_num, success);
258 
259     if (success)
260         success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
261     return success;
262 
263 }
264 
265 bool
WritePseudoRegister(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,const lldb_private::RegisterInfo * reg_info,const lldb_private::RegisterValue & reg_value)266 EmulationStateARM::WritePseudoRegister (EmulateInstruction *instruction,
267                                         void *baton,
268                                         const EmulateInstruction::Context &context,
269                                         const lldb_private::RegisterInfo *reg_info,
270                                         const lldb_private::RegisterValue &reg_value)
271 {
272     if (!baton || !reg_info)
273         return false;
274 
275     EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
276     const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
277     assert (dwarf_reg_num != LLDB_INVALID_REGNUM);
278     return pseudo_state->StorePseudoRegisterValue (dwarf_reg_num, reg_value.GetAsUInt64());
279 }
280 
281 bool
CompareState(EmulationStateARM & other_state)282 EmulationStateARM::CompareState (EmulationStateARM &other_state)
283 {
284     bool match = true;
285 
286     for (int i = 0; match && i < 17; ++i)
287     {
288         if (m_gpr[i] != other_state.m_gpr[i])
289             match = false;
290     }
291 
292     for (int i = 0; match && i < 16; ++i)
293     {
294         if (m_vfp_regs.sd_regs[i].s_reg[0] != other_state.m_vfp_regs.sd_regs[i].s_reg[0])
295             match = false;
296 
297         if (m_vfp_regs.sd_regs[i].s_reg[1] != other_state.m_vfp_regs.sd_regs[i].s_reg[1])
298             match = false;
299     }
300 
301     for (int i = 0; match && i < 32; ++i)
302     {
303         if (i < 16)
304         {
305             if (m_vfp_regs.sd_regs[i].d_reg != other_state.m_vfp_regs.sd_regs[i].d_reg)
306                 match = false;
307         }
308         else
309         {
310             if (m_vfp_regs.d_regs[i - 16] != other_state.m_vfp_regs.d_regs[i - 16])
311                 match = false;
312         }
313     }
314 
315     return match;
316 }
317 
318 bool
LoadStateFromDictionary(OptionValueDictionary * test_data)319 EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
320 {
321     static ConstString memory_key ("memory");
322     static ConstString registers_key ("registers");
323 
324     if (!test_data)
325         return false;
326 
327     OptionValueSP value_sp = test_data->GetValueForKey (memory_key);
328 
329     // Load memory, if present.
330 
331     if (value_sp.get() != NULL)
332     {
333         static ConstString address_key ("address");
334         static ConstString data_key ("data");
335         uint64_t start_address = 0;
336 
337         OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
338         value_sp = mem_dict->GetValueForKey (address_key);
339         if (value_sp.get() == NULL)
340             return false;
341         else
342             start_address = value_sp->GetUInt64Value ();
343 
344         value_sp = mem_dict->GetValueForKey (data_key);
345         OptionValueArray *mem_array = value_sp->GetAsArray();
346         if (!mem_array)
347             return false;
348 
349         uint32_t num_elts = mem_array->GetSize();
350         uint32_t address = (uint32_t) start_address;
351 
352         for (uint32_t i = 0; i < num_elts; ++i)
353         {
354             value_sp = mem_array->GetValueAtIndex (i);
355             if (value_sp.get() == NULL)
356                 return false;
357             uint64_t value = value_sp->GetUInt64Value();
358             StoreToPseudoAddress (address, value, 4);
359             address = address + 4;
360         }
361     }
362 
363     value_sp = test_data->GetValueForKey (registers_key);
364     if (value_sp.get() == NULL)
365         return false;
366 
367 
368     // Load General Registers
369 
370     OptionValueDictionary *reg_dict = value_sp->GetAsDictionary ();
371 
372     StreamString sstr;
373     for (int i = 0; i < 16; ++i)
374     {
375         sstr.Clear();
376         sstr.Printf ("r%d", i);
377         ConstString reg_name (sstr.GetData());
378         value_sp = reg_dict->GetValueForKey (reg_name);
379         if (value_sp.get() == NULL)
380             return false;
381         uint64_t reg_value = value_sp->GetUInt64Value();
382         StorePseudoRegisterValue (dwarf_r0 + i, reg_value);
383     }
384 
385     static ConstString cpsr_name ("cpsr");
386     value_sp = reg_dict->GetValueForKey (cpsr_name);
387     if (value_sp.get() == NULL)
388         return false;
389     StorePseudoRegisterValue (dwarf_cpsr, value_sp->GetUInt64Value());
390 
391     // Load s/d Registers
392     for (int i = 0; i < 32; ++i)
393     {
394         sstr.Clear();
395         sstr.Printf ("s%d", i);
396         ConstString reg_name (sstr.GetData());
397         value_sp = reg_dict->GetValueForKey (reg_name);
398         if (value_sp.get() == NULL)
399             return false;
400         uint64_t reg_value = value_sp->GetUInt64Value();
401         StorePseudoRegisterValue (dwarf_s0 + i, reg_value);
402     }
403 
404     return true;
405 }
406 
407