summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/Disassembler.cpp1
-rw-r--r--lldb/source/Core/EmulateInstruction.cpp529
2 files changed, 523 insertions, 7 deletions
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index 2d64c644262..e2de734d5d7 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -18,6 +18,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Timer.h"
diff --git a/lldb/source/Core/EmulateInstruction.cpp b/lldb/source/Core/EmulateInstruction.cpp
index eb20d087e5a..f67e3505981 100644
--- a/lldb/source/Core/EmulateInstruction.cpp
+++ b/lldb/source/Core/EmulateInstruction.cpp
@@ -9,10 +9,18 @@
#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Endian.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+
+#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -25,18 +33,18 @@ EmulateInstruction::FindPlugin (const ArchSpec &arch, const char *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();
+ EmulateInstruction *emulate_insn_ptr = create_callback(arch);
+ if (emulate_insn_ptr)
+ return emulate_insn_ptr;
}
}
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();
+ EmulateInstruction *emulate_insn_ptr = create_callback(arch);
+ if (emulate_insn_ptr)
+ return emulate_insn_ptr;
}
}
return NULL;
@@ -46,6 +54,7 @@ EmulateInstruction::EmulateInstruction
(
lldb::ByteOrder byte_order,
uint32_t addr_byte_size,
+ const ArchSpec &arch,
void *baton,
ReadMemory read_mem_callback,
WriteMemory write_mem_callback,
@@ -53,7 +62,8 @@ EmulateInstruction::EmulateInstruction
WriteRegister write_reg_callback
) :
m_byte_order (endian::InlHostByteOrder()),
- m_addr_byte_size (sizeof (void *)),
+ m_addr_byte_size (addr_byte_size),
+ m_arch (arch),
m_baton (baton),
m_read_mem_callback (read_mem_callback),
m_write_mem_callback (write_mem_callback),
@@ -64,6 +74,25 @@ EmulateInstruction::EmulateInstruction
{
}
+EmulateInstruction::EmulateInstruction
+(
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size,
+ const ArchSpec &arch
+) :
+ m_byte_order (endian::InlHostByteOrder()),
+ m_addr_byte_size (addr_byte_size),
+ m_arch (arch),
+ m_baton (NULL),
+ m_read_mem_callback (&ReadMemoryDefault),
+ m_write_mem_callback (&WriteMemoryDefault),
+ m_read_reg_callback (&ReadRegisterDefault),
+ m_write_reg_callback (&WriteRegisterDefault),
+ m_opcode_pc (LLDB_INVALID_ADDRESS)
+{
+ ::memset (&m_opcode, 0, sizeof (m_opcode));
+}
+
uint64_t
EmulateInstruction::ReadRegisterUnsigned (uint32_t reg_kind, uint32_t reg_num, uint64_t fail_value, bool *success_ptr)
{
@@ -123,3 +152,489 @@ EmulateInstruction::WriteMemoryUnsigned (const Context &context,
return true;
return false;
}
+
+
+void
+EmulateInstruction::SetBaton (void *baton)
+{
+ m_baton = baton;
+}
+
+void
+EmulateInstruction::SetCallbacks (ReadMemory read_mem_callback,
+ WriteMemory write_mem_callback,
+ ReadRegister read_reg_callback,
+ WriteRegister write_reg_callback)
+{
+ 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;
+}
+
+void
+EmulateInstruction::SetReadMemCallback (ReadMemory read_mem_callback)
+{
+ m_read_mem_callback = read_mem_callback;
+}
+
+
+void
+EmulateInstruction::SetWriteMemCallback (WriteMemory write_mem_callback)
+{
+ m_write_mem_callback = write_mem_callback;
+}
+
+
+void
+EmulateInstruction::SetReadRegCallback (ReadRegister read_reg_callback)
+{
+ m_read_reg_callback = read_reg_callback;
+}
+
+
+void
+EmulateInstruction::SetWriteRegCallback (WriteRegister write_reg_callback)
+{
+ m_write_reg_callback = write_reg_callback;
+}
+
+
+
+//
+// Read & Write Memory and Registers callback functions.
+//
+
+size_t
+EmulateInstruction::ReadMemoryProcess (void *baton,
+ const Context &context,
+ lldb::addr_t addr,
+ void *dst,
+ size_t length)
+{
+ Process *process = (Process *) baton;
+
+ if (!process)
+ return 0;
+
+ DataBufferSP data_sp (new DataBufferHeap (length, '\0'));
+ Error error;
+
+ size_t bytes_read = process->ReadMemory (addr, data_sp->GetBytes(), data_sp->GetByteSize(), error);
+
+ if (bytes_read > 0)
+ ((DataBufferHeap *) data_sp.get())->CopyData (dst, length);
+
+ return bytes_read;
+}
+
+size_t
+EmulateInstruction::WriteMemoryProcess (void *baton,
+ const Context &context,
+ lldb::addr_t addr,
+ const void *dst,
+ size_t length)
+{
+ Process *process = (Process *) baton;
+
+ if (!process)
+ return 0;
+
+ lldb::DataBufferSP data_sp (new DataBufferHeap (dst, length));
+ if (data_sp)
+ {
+ length = data_sp->GetByteSize();
+ if (length > 0)
+ {
+ Error error;
+ size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
+
+ return bytes_written;
+ }
+ }
+
+ return 0;
+}
+
+bool
+EmulateInstruction::ReadRegisterProcess (void *baton,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t &reg_value)
+{
+ Process *process = (Process *) baton;
+ if (!process)
+ return false;
+
+ Thread *thread = process->CalculateThread ();
+ RegisterContext *reg_context = thread->GetRegisterContext().get();
+ Scalar value;
+
+
+ if (reg_context->ReadRegisterValue (reg_num, value))
+ {
+ reg_value = value.GetRawBits64 (0);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstruction::WriteRegisterProcess (void *baton,
+ const Context &context,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t reg_value)
+{
+ Process *process = (Process *) baton;
+ Thread *thread = process->CalculateThread ();
+ RegisterContext *reg_context = thread->GetRegisterContext().get();
+ Scalar value (reg_value);
+
+ return reg_context->WriteRegisterValue (reg_num, value);
+}
+
+size_t
+EmulateInstruction::ReadMemoryDefault (void *baton,
+ const Context &context,
+ lldb::addr_t addr,
+ void *dst,
+ size_t length)
+{
+ PrintContext ("Read from memory", context);
+ fprintf (stdout, " Read from Memory (address = %p, length = %d)\n",(void *) addr, (uint) length);
+
+ *((uint64_t *) dst) = 0xdeadbeef;
+ return length;
+}
+
+size_t
+EmulateInstruction::WriteMemoryDefault (void *baton,
+ const Context &context,
+ lldb::addr_t addr,
+ const void *dst,
+ size_t length)
+{
+ PrintContext ("Write to memory", context);
+ fprintf (stdout, " Write to Memory (address = %p, length = %d)\n", (void *) addr, (uint) length);
+ return length;
+}
+
+bool
+EmulateInstruction::ReadRegisterDefault (void *baton,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t &reg_value)
+{
+ std::string reg_name;
+ TranslateRegister (reg_kind, reg_num, reg_name);
+ fprintf (stdout, " Read Register (%s)\n", reg_name.c_str());
+
+ reg_value = 24;
+ return true;
+}
+
+bool
+EmulateInstruction::WriteRegisterDefault (void *baton,
+ const Context &context,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t reg_value)
+{
+ PrintContext ("Write to register", context);
+ std::string reg_name;
+ TranslateRegister (reg_kind, reg_num, reg_name);
+ fprintf (stdout, " Write to Register (%s), value = 0x%llx\n", reg_name.c_str(), reg_value);
+ return true;
+}
+
+void
+EmulateInstruction::PrintContext (const char *context_type, const Context &context)
+{
+ switch (context.type)
+ {
+ case eContextReadOpcode:
+ fprintf (stdout, " %s context: Reading an Opcode\n", context_type);
+ break;
+
+ case eContextImmediate:
+ fprintf (stdout, " %s context: Immediate\n", context_type);
+ break;
+
+ case eContextPushRegisterOnStack:
+ fprintf (stdout, " %s context: Pushing a register onto the stack.\n", context_type);
+ break;
+
+ case eContextPopRegisterOffStack:
+ fprintf (stdout, " %s context: Popping a register off the stack.\n", context_type);
+ break;
+
+ case eContextAdjustStackPointer:
+ fprintf (stdout, " %s context: Adjusting the stack pointer.\n", context_type);
+ break;
+
+ case eContextAdjustBaseRegister:
+ fprintf (stdout, " %s context: Adjusting (writing value back to) a base register.\n", context_type);
+ break;
+
+ case eContextRegisterPlusOffset:
+ fprintf (stdout, " %s context: Register plus offset\n", context_type);
+ break;
+
+ case eContextRegisterStore:
+ fprintf (stdout, " %s context: Storing a register.\n", context_type);
+ break;
+
+ case eContextRegisterLoad:
+ fprintf (stdout, " %s context: Loading a register.\n", context_type);
+ break;
+
+ case eContextRelativeBranchImmediate:
+ fprintf (stdout, " %s context: Relative branch immediate\n", context_type);
+ break;
+
+ case eContextAbsoluteBranchRegister:
+ fprintf (stdout, " %s context: Absolute branch register\n", context_type);
+ break;
+
+ case eContextSupervisorCall:
+ fprintf (stdout, " %s context: Performing a supervisor call.\n", context_type);
+ break;
+
+ case eContextTableBranchReadMemory:
+ fprintf (stdout, " %s context: Table branch read memory\n", context_type);
+ break;
+
+ case eContextWriteRegisterRandomBits:
+ fprintf (stdout, " %s context: Write random bits to a register\n", context_type);
+ break;
+
+ case eContextWriteMemoryRandomBits:
+ fprintf (stdout, " %s context: Write random bits to a memory address\n", context_type);
+ break;
+
+ case eContextMultiplication:
+ fprintf (stdout, " %s context: Performing a multiplication\n", context_type);
+ break;
+
+ case eContextAddition:
+ fprintf (stdout, " %s context: Performing an addition\n", context_type);
+ break;
+
+ case eContextReturnFromException:
+ fprintf (stdout, " %s context: Returning from an exception\n", context_type);
+ break;
+
+ default:
+ fprintf (stdout, " %s context: Unrecognized context.\n", context_type);
+ break;
+ }
+
+ switch (context.info_type)
+ {
+ case eInfoTypeRegisterPlusOffset:
+ {
+ std::string reg_name;
+ TranslateRegister (context.info.RegisterPlusOffset.reg.kind,
+ context.info.RegisterPlusOffset.reg.num,
+ reg_name);
+ fprintf (stdout, " Info type: Register plus offset (%s +/- %lld)\n", reg_name.c_str(),
+ context.info.RegisterPlusOffset.signed_offset);
+ }
+ break;
+ case eInfoTypeRegisterPlusIndirectOffset:
+ {
+ std::string base_reg_name;
+ std::string offset_reg_name;
+ TranslateRegister (context.info.RegisterPlusIndirectOffset.base_reg.kind,
+ context.info.RegisterPlusIndirectOffset.base_reg.num,
+ base_reg_name);
+ TranslateRegister (context.info.RegisterPlusIndirectOffset.offset_reg.kind,
+ context.info.RegisterPlusIndirectOffset.offset_reg.num,
+ offset_reg_name);
+ fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s)\n",
+ base_reg_name.c_str(),
+ offset_reg_name.c_str());
+ }
+ break;
+ case eInfoTypeRegisterToRegisterPlusOffset:
+ {
+ std::string base_reg_name;
+ std::string data_reg_name;
+ TranslateRegister (context.info.RegisterToRegisterPlusOffset.base_reg.kind,
+ context.info.RegisterToRegisterPlusOffset.base_reg.num,
+ base_reg_name);
+ TranslateRegister (context.info.RegisterToRegisterPlusOffset.data_reg.kind,
+ context.info.RegisterToRegisterPlusOffset.data_reg.num,
+ data_reg_name);
+ fprintf (stdout, " Info type: Register plus offset (%s +/- %lld) and data register (%s)\n",
+ base_reg_name.c_str(), context.info.RegisterToRegisterPlusOffset.offset,
+ data_reg_name.c_str());
+ }
+ break;
+ case eInfoTypeRegisterToRegisterPlusIndirectOffset:
+ {
+ std::string base_reg_name;
+ std::string offset_reg_name;
+ std::string data_reg_name;
+ TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.base_reg.kind,
+ context.info.RegisterToRegisterPlusIndirectOffset.base_reg.num,
+ base_reg_name);
+ TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.kind,
+ context.info.RegisterToRegisterPlusIndirectOffset.offset_reg.num,
+ offset_reg_name);
+ TranslateRegister (context.info.RegisterToRegisterPlusIndirectOffset.data_reg.kind,
+ context.info.RegisterToRegisterPlusIndirectOffset.data_reg.num,
+ data_reg_name);
+ fprintf (stdout, " Info type: Register plus indirect offset (%s +/- %s) and data register (%s)\n",
+ base_reg_name.c_str(), offset_reg_name.c_str(), data_reg_name.c_str());
+ }
+ break;
+
+ case eInfoTypeRegisterRegisterOperands:
+ {
+ std::string op1_reg_name;
+ std::string op2_reg_name;
+ TranslateRegister (context.info.RegisterRegisterOperands.operand1.kind,
+ context.info.RegisterRegisterOperands.operand1.num,
+ op1_reg_name);
+ TranslateRegister (context.info.RegisterRegisterOperands.operand2.kind,
+ context.info.RegisterRegisterOperands.operand2.num,
+ op2_reg_name);
+ fprintf (stdout, " Info type: Register operands for binary op (%s, %s)\n",
+ op1_reg_name.c_str(),
+ op2_reg_name.c_str());
+ }
+ break;
+ case eInfoTypeOffset:
+ fprintf (stdout, " Info type: signed offset (%lld)\n", context.info.signed_offset);
+ break;
+
+ case eInfoTypeRegister:
+ {
+ std::string reg_name;
+ TranslateRegister (context.info.reg.kind, context.info.reg.num, reg_name);
+ fprintf (stdout, " Info type: Register (%s)\n", reg_name.c_str());
+ }
+ break;
+
+ case eInfoTypeImmediate:
+ fprintf (stdout, " Info type: Immediate (%lld)\n", context.info.immediate);
+ break;
+
+ case eInfoTypeImmediateSigned:
+ fprintf (stdout, " Info type: Signed immediate (%lld)\n", context.info.signed_immediate);
+ break;
+
+ case eInfoTypeAddress:
+ fprintf (stdout, " Info type: Address (%p)\n", (void *) context.info.address);
+ break;
+
+ case eInfoTypeModeAndImmediate:
+ {
+ std::string mode_name;
+
+ if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeARM)
+ mode_name = "ARM";
+ else if (context.info.ModeAndImmediate.mode == EmulateInstructionARM::eModeThumb)
+ mode_name = "Thumb";
+ else
+ mode_name = "Unknown mode";
+
+ fprintf (stdout, " Info type: Mode (%s) and immediate (%d)\n", mode_name.c_str(),
+ context.info.ModeAndImmediate.data_value);
+ }
+ break;
+
+ case eInfoTypeModeAndImmediateSigned:
+ {
+ std::string mode_name;
+
+ if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeARM)
+ mode_name = "ARM";
+ else if (context.info.ModeAndImmediateSigned.mode == EmulateInstructionARM::eModeThumb)
+ mode_name = "Thumb";
+ else
+ mode_name = "Unknown mode";
+
+ fprintf (stdout, " Info type: Mode (%s) and signed immediate (%d)\n", mode_name.c_str(),
+ context.info.ModeAndImmediateSigned.signed_data_value);
+ }
+ break;
+
+ case eInfoTypeMode:
+ {
+ std::string mode_name;
+
+ if (context.info.mode == EmulateInstructionARM::eModeARM)
+ mode_name = "ARM";
+ else if (context.info.mode == EmulateInstructionARM::eModeThumb)
+ mode_name = "Thumb";
+ else
+ mode_name = "Unknown mode";
+
+ fprintf (stdout, " Info type: Mode (%s)\n", mode_name.c_str());
+ }
+ break;
+
+ case eInfoTypeNoArgs:
+ fprintf (stdout, " Info type: no arguments\n");
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+EmulateInstruction::TranslateRegister (uint32_t kind, uint32_t num, std::string &name)
+{
+ if (kind == eRegisterKindDWARF)
+ {
+ if (num == 13) //dwarf_sp NOTE: This is ARM-SPECIFIC
+ name = "sp";
+ else if (num == 14) //dwarf_lr NOTE: This is ARM-SPECIFIC
+ name = "lr";
+ else if (num == 15) //dwarf_pc NOTE: This is ARM-SPECIFIC
+ name = "pc";
+ else if (num == 16) //dwarf_cpsr NOTE: This is ARM-SPECIFIC
+ name = "cpsr";
+ else
+ {
+ StreamString sstr;
+
+ sstr.Printf ("r%d", num);
+ name = sstr.GetData();
+ }
+
+ }
+ else if (kind == eRegisterKindGeneric)
+ {
+ if (num == LLDB_REGNUM_GENERIC_SP)
+ name = "sp";
+ else if (num == LLDB_REGNUM_GENERIC_FLAGS)
+ name = "cpsr";
+ else if (num == LLDB_REGNUM_GENERIC_PC)
+ name = "pc";
+ else if (num == LLDB_REGNUM_GENERIC_RA)
+ name = "lr";
+ else
+ {
+ StreamString sstr;
+
+ sstr.Printf ("r%d", num);
+ name = sstr.GetData();
+ }
+ }
+ else
+ {
+ StreamString sstr;
+
+ sstr.Printf ("r%d", num);
+ name = sstr.GetData();
+ }
+}
+
+
+
OpenPOWER on IntegriCloud