diff options
author | emaste <emaste@FreeBSD.org> | 2013-08-23 18:06:42 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2013-08-23 18:06:42 +0000 |
commit | 424d4dadd208e2a1e9a43c3d55f47f03ba0c4509 (patch) | |
tree | 05d762b98a499804ce690e6ce04033f1ddf4dee6 /contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp | |
parent | cde487f27a84e02a560384f75178fddca68740f6 (diff) | |
parent | dcd15f81789e389c1cb27d264fcdddfd0a6002bd (diff) | |
download | FreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.zip FreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.tar.gz |
Merge lldb r188801 to contrib/llvm/tools/lldb/
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp new file mode 100644 index 0000000..bad4118 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -0,0 +1,406 @@ +//===-- EmulationStateARM.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "EmulationStateARM.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Interpreter/OptionValueArray.h" +#include "lldb/Interpreter/OptionValueDictionary.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/RegisterContext.h" + +#include "Utility/ARM_DWARF_Registers.h" + +using namespace lldb; +using namespace lldb_private; + +EmulationStateARM::EmulationStateARM () : + m_gpr (), + m_vfp_regs (), + m_memory () +{ + ClearPseudoRegisters(); +} + +EmulationStateARM::~EmulationStateARM () +{ +} + +bool +EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame) +{ + RegisterContext *reg_ctx = frame.GetRegisterContext().get(); + bool success = true; + uint32_t reg_num; + + for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) + { + reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i); + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); + RegisterValue reg_value; + if (reg_ctx->ReadRegister (reg_info, reg_value)) + { + m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32(); + } + else + success = false; + } + + for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) + { + reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i); + RegisterValue reg_value; + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); + + if (reg_ctx->ReadRegister (reg_info, reg_value)) + { + uint32_t idx = i - dwarf_d0; + if (i < 16) + m_vfp_regs.sd_regs[idx].d_reg = reg_value.GetAsUInt64(); + else + m_vfp_regs.d_regs[idx - 16] = reg_value.GetAsUInt64(); + } + else + success = false; + } + + return success; +} + +bool +EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value) +{ + if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) + m_gpr[reg_num - dwarf_r0] = (uint32_t) value; + else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) + { + uint32_t idx = reg_num - dwarf_s0; + m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2] = (uint32_t) value; + } + else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) + { + if ((reg_num - dwarf_d0) < 16) + { + m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg = value; + } + else + m_vfp_regs.d_regs[reg_num - dwarf_d16] = value; + } + else + return false; + + return true; +} + +uint64_t +EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success) +{ + uint64_t value = 0; + success = true; + + if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) + value = m_gpr[reg_num - dwarf_r0]; + else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) + { + uint32_t idx = reg_num - dwarf_s0; + value = m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2]; + } + else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) + { + if ((reg_num - dwarf_d0) < 16) + value = m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg; + else + value = m_vfp_regs.d_regs[reg_num - dwarf_d16]; + } + else + success = false; + + return value; +} + +void +EmulationStateARM::ClearPseudoRegisters () +{ + for (int i = 0; i < 17; ++i) + m_gpr[i] = 0; + + for (int i = 0; i < 16; ++i) + m_vfp_regs.sd_regs[i].d_reg = 0; + + for (int i = 0; i < 16; ++i) + m_vfp_regs.d_regs[i] = 0; +} + +void +EmulationStateARM::ClearPseudoMemory () +{ + m_memory.clear(); +} + +bool +EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size) +{ + if (size > 8) + return false; + + if (size <= 4) + m_memory[p_address] = value; + else if (size == 8) + { + m_memory[p_address] = (value << 32) >> 32; + m_memory[p_address + 4] = value << 32; + } + return true; +} + +uint32_t +EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success) +{ + std::map<lldb::addr_t,uint32_t>::iterator pos; + uint32_t ret_val = 0; + + success = true; + pos = m_memory.find(p_address); + if (pos != m_memory.end()) + ret_val = pos->second; + else + success = false; + + return ret_val; +} + +size_t +EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, + void *dst, + size_t length) +{ + if (!baton) + return 0; + + bool success = true; + EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; + if (length <= 4) + { + uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, length, success); + if (!success) + return 0; + + *((uint32_t *) dst) = value; + } + else if (length == 8) + { + uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, 4, success); + if (!success) + return 0; + + uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, 4, success); + if (!success) + return 0; + + uint64_t value64 = value2; + value64 = (value64 << 32) | value1; + *((uint64_t *) dst) = value64; + } + else + success = false; + + if (success) + return length; + + return 0; +} + +size_t +EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, + const void *dst, + size_t length) +{ + if (!baton) + return 0; + + bool success; + EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; + uint64_t value = *((uint64_t *) dst); + success = pseudo_state->StoreToPseudoAddress (addr, value, length); + if (success) + return length; + + return 0; +} + +bool +EmulationStateARM::ReadPseudoRegister (EmulateInstruction *instruction, + void *baton, + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value) +{ + if (!baton || !reg_info) + return false; + + bool success = true; + EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; + const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; + assert (dwarf_reg_num != LLDB_INVALID_REGNUM); + uint64_t reg_uval = pseudo_state->ReadPseudoRegisterValue (dwarf_reg_num, success); + + if (success) + success = reg_value.SetUInt(reg_uval, reg_info->byte_size); + return success; + +} + +bool +EmulationStateARM::WritePseudoRegister (EmulateInstruction *instruction, + void *baton, + const EmulateInstruction::Context &context, + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value) +{ + if (!baton || !reg_info) + return false; + + EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; + const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; + assert (dwarf_reg_num != LLDB_INVALID_REGNUM); + return pseudo_state->StorePseudoRegisterValue (dwarf_reg_num, reg_value.GetAsUInt64()); +} + +bool +EmulationStateARM::CompareState (EmulationStateARM &other_state) +{ + bool match = true; + + for (int i = 0; match && i < 17; ++i) + { + if (m_gpr[i] != other_state.m_gpr[i]) + match = false; + } + + for (int i = 0; match && i < 16; ++i) + { + if (m_vfp_regs.sd_regs[i].s_reg[0] != other_state.m_vfp_regs.sd_regs[i].s_reg[0]) + match = false; + + if (m_vfp_regs.sd_regs[i].s_reg[1] != other_state.m_vfp_regs.sd_regs[i].s_reg[1]) + match = false; + } + + for (int i = 0; match && i < 32; ++i) + { + if (i < 16) + { + if (m_vfp_regs.sd_regs[i].d_reg != other_state.m_vfp_regs.sd_regs[i].d_reg) + match = false; + } + else + { + if (m_vfp_regs.d_regs[i - 16] != other_state.m_vfp_regs.d_regs[i - 16]) + match = false; + } + } + + return match; +} + +bool +EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data) +{ + static ConstString memory_key ("memory"); + static ConstString registers_key ("registers"); + + if (!test_data) + return false; + + OptionValueSP value_sp = test_data->GetValueForKey (memory_key); + + // Load memory, if present. + + if (value_sp.get() != NULL) + { + static ConstString address_key ("address"); + static ConstString data_key ("data"); + uint64_t start_address = 0; + + OptionValueDictionary *mem_dict = value_sp->GetAsDictionary(); + value_sp = mem_dict->GetValueForKey (address_key); + if (value_sp.get() == NULL) + return false; + else + start_address = value_sp->GetUInt64Value (); + + value_sp = mem_dict->GetValueForKey (data_key); + OptionValueArray *mem_array = value_sp->GetAsArray(); + if (!mem_array) + return false; + + uint32_t num_elts = mem_array->GetSize(); + uint32_t address = (uint32_t) start_address; + + for (uint32_t i = 0; i < num_elts; ++i) + { + value_sp = mem_array->GetValueAtIndex (i); + if (value_sp.get() == NULL) + return false; + uint64_t value = value_sp->GetUInt64Value(); + StoreToPseudoAddress (address, value, 4); + address = address + 4; + } + } + + value_sp = test_data->GetValueForKey (registers_key); + if (value_sp.get() == NULL) + return false; + + + // Load General Registers + + OptionValueDictionary *reg_dict = value_sp->GetAsDictionary (); + + StreamString sstr; + for (int i = 0; i < 16; ++i) + { + sstr.Clear(); + sstr.Printf ("r%d", i); + ConstString reg_name (sstr.GetData()); + value_sp = reg_dict->GetValueForKey (reg_name); + if (value_sp.get() == NULL) + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue (dwarf_r0 + i, reg_value); + } + + static ConstString cpsr_name ("cpsr"); + value_sp = reg_dict->GetValueForKey (cpsr_name); + if (value_sp.get() == NULL) + return false; + StorePseudoRegisterValue (dwarf_cpsr, value_sp->GetUInt64Value()); + + // Load s/d Registers + for (int i = 0; i < 32; ++i) + { + sstr.Clear(); + sstr.Printf ("s%d", i); + ConstString reg_name (sstr.GetData()); + value_sp = reg_dict->GetValueForKey (reg_name); + if (value_sp.get() == NULL) + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue (dwarf_s0 + i, reg_value); + } + + return true; +} + |