| //===-- EmulateInstruction.h ------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/Core/EmulateInstruction.h" |
| |
| #include "lldb/Core/DataExtractor.h" |
| #include "lldb/Core/PluginManager.h" |
| #include "lldb/Core/StreamString.h" |
| #include "lldb/Host/Endian.h" |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| EmulateInstruction* |
| EmulateInstruction::FindPlugin (const ArchSpec &arch, const char *plugin_name) |
| { |
| EmulateInstructionCreateInstance create_callback = NULL; |
| if (plugin_name) |
| { |
| create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (plugin_name); |
| if (create_callback) |
| { |
| std::auto_ptr<EmulateInstruction> instance_ap(create_callback(arch)); |
| if (instance_ap.get()) |
| return instance_ap.release(); |
| } |
| } |
| else |
| { |
| for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != NULL; ++idx) |
| { |
| std::auto_ptr<EmulateInstruction> instance_ap(create_callback(arch)); |
| if (instance_ap.get()) |
| return instance_ap.release(); |
| } |
| } |
| return NULL; |
| } |
| |
| EmulateInstruction::EmulateInstruction |
| ( |
| lldb::ByteOrder byte_order, |
| uint32_t addr_byte_size, |
| void *baton, |
| ReadMemory read_mem_callback, |
| WriteMemory write_mem_callback, |
| ReadRegister read_reg_callback, |
| WriteRegister write_reg_callback |
| ) : |
| m_byte_order (endian::InlHostByteOrder()), |
| m_addr_byte_size (sizeof (void *)), |
| m_baton (baton), |
| m_read_mem_callback (read_mem_callback), |
| m_write_mem_callback (write_mem_callback), |
| m_read_reg_callback (read_reg_callback), |
| m_write_reg_callback (write_reg_callback), |
| m_inst_pc (LLDB_INVALID_ADDRESS) |
| { |
| ::memset (&m_inst, 0, sizeof (m_inst)); |
| } |
| |
| uint64_t |
| EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr) |
| { |
| uint64_t uval64 = 0; |
| bool success = m_read_reg_callback (m_baton, reg_kind, reg_num, uval64); |
| if (success_ptr) |
| *success_ptr = success; |
| if (!success) |
| uval64 = fail_value; |
| return uval64; |
| } |
| |
| bool |
| EmulateInstruction::WriteRegisterUnsigned (const Context &context, uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value) |
| { |
| return m_write_reg_callback (m_baton, context, reg_kind, reg_num, reg_value); |
| } |
| |
| uint64_t |
| EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr) |
| { |
| uint64_t uval64 = 0; |
| bool success = false; |
| if (byte_size <= 8) |
| { |
| uint8_t buf[sizeof(uint64_t)]; |
| size_t bytes_read = m_read_mem_callback (m_baton, context, addr, buf, byte_size); |
| if (bytes_read == byte_size) |
| { |
| uint32_t offset = 0; |
| DataExtractor data (buf, byte_size, m_byte_order, m_addr_byte_size); |
| uval64 = data.GetMaxU64 (&offset, byte_size); |
| success = true; |
| } |
| } |
| |
| if (success_ptr) |
| *success_ptr = success; |
| |
| if (!success) |
| uval64 = fail_value; |
| return uval64; |
| } |
| |
| |
| bool |
| EmulateInstruction::WriteMemoryUnsigned (const Context &context, |
| lldb::addr_t addr, |
| uint64_t uval, |
| size_t uval_byte_size) |
| { |
| StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder()); |
| strm.PutMaxHex64 (uval, uval_byte_size); |
| |
| size_t bytes_written = m_write_mem_callback (m_baton, context, addr, strm.GetData(), uval_byte_size); |
| if (bytes_written == uval_byte_size) |
| return true; |
| return false; |
| } |