Add the rest of the mechanisms to make ARM instruction emulation usable/possible.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@128907 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index 2d64c64..e2de734 100644
--- a/source/Core/Disassembler.cpp
+++ b/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/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp
index eb20d08..f67e350 100644
--- a/source/Core/EmulateInstruction.cpp
+++ b/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 @@
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 @@
(
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 @@
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
+(
+ 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 @@
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 ®_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 ®_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();
+ }
+}
+
+
+
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
index 59e6d9a..74d4575 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
@@ -404,7 +404,7 @@
{
std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
- if (disasm_ap->IsValid())
+ if (disasm_ap.get() && disasm_ap->IsValid())
return disasm_ap.release();
return NULL;
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 9db4871..dbe3212 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -11,7 +11,9 @@
#include "EmulateInstructionARM.h"
#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Address.h"
#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
#include "Plugins/Process/Utility/ARMDefines.h"
#include "Plugins/Process/Utility/ARMUtils.h"
@@ -153,13 +155,61 @@
void
EmulateInstructionARM::Initialize ()
{
+ PluginManager::RegisterPlugin (GetPluginNameStatic (),
+ GetPluginDescriptionStatic (),
+ CreateInstance);
}
void
EmulateInstructionARM::Terminate ()
{
+ PluginManager::UnregisterPlugin (CreateInstance);
}
+const char *
+EmulateInstructionARM::GetPluginNameStatic ()
+{
+ return "lldb.emulate-instruction.arm";
+}
+
+const char *
+EmulateInstructionARM::GetPluginDescriptionStatic ()
+{
+ return "Emulate instructions for the ARM architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionARM::CreateInstance (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ {
+ std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+ {
+ std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch () == llvm::Triple::arm)
+ return true;
+ else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
+ return true;
+
+ return false;
+}
+
// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
bool
EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
@@ -503,7 +553,7 @@
addr_t addr = sp + sp_offset; // a pointer to the stack area
EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextRegisterPlusOffset;
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
Register sp_reg;
sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
context.SetRegisterPlusOffset (sp_reg, sp_offset);
@@ -1191,7 +1241,9 @@
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextAdjustStackPointer;
- context.SetImmediateSigned (sp_offset);
+ Register sp_reg;
+ sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ context.SetRegisterPlusOffset (sp_reg, sp_offset);
if (d == 15)
{
@@ -1253,8 +1305,12 @@
addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextAdjustStackPointer;
- context.SetImmediateSigned (reg_value);
+ context.type = EmulateInstruction::eContextAddition;
+ Register sp_reg;
+ sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
+ Register other_reg;
+ other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
+ context.SetRegisterRegisterOperands (sp_reg, other_reg);
if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
return false;
@@ -2431,8 +2487,10 @@
AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextImmediate;
- context.SetNoArgs ();
+ context.type = EmulateInstruction::eContextAddition;
+ Register dwarf_reg;
+ dwarf_reg.SetRegister (eRegisterKindDWARF, Rn);
+ context.SetRegisterPlusOffset (dwarf_reg, imm32);
if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
return false;
@@ -12247,7 +12305,16 @@
{ 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
// mul
{ 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
+
+
+ //----------------------------------------------------------------------
+ // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
+ // otherwise the wrong instructions will be selected.
+ //----------------------------------------------------------------------
+ { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
+ { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
+
//----------------------------------------------------------------------
// Load instructions
//----------------------------------------------------------------------
@@ -12330,9 +12397,6 @@
{ 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
{ 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
{ 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
- { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
- { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
-
};
const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
@@ -12347,6 +12411,7 @@
bool
EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
{
+ m_arch = arch;
m_arm_isa = 0;
const char *arch_cstr = arch.GetArchitectureName ();
if (arch_cstr)
@@ -12365,6 +12430,26 @@
return m_arm_isa != 0;
}
+bool
+EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr)
+{
+ m_opcode = insn_opcode;
+
+ if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
+ m_opcode_mode = eModeThumb;
+ else
+ {
+ AddressClass addr_class = inst_addr.GetAddressClass();
+
+ if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
+ m_opcode_mode = eModeARM;
+ else if (addr_class == eAddressClassCodeAlternateISA)
+ m_opcode_mode = eModeThumb;
+ else
+ return false;
+ }
+ return true;
+}
bool
EmulateInstructionARM::ReadInstruction ()
@@ -12421,8 +12506,6 @@
bool
EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
{
- if (m_opcode_cpsr == 0)
- return false;
const uint32_t cond = CurrentCond (opcode);
@@ -12432,20 +12515,46 @@
bool result = false;
switch (UnsignedBits(cond, 3, 1))
{
- case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
- case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
- case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
- case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
- case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break;
+ case 0:
+ if (m_opcode_cpsr == 0)
+ return true;
+ result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
+ break;
+ case 1:
+ if (m_opcode_cpsr == 0)
+ return true;
+ result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
+ break;
+ case 2:
+ if (m_opcode_cpsr == 0)
+ return true;
+ result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
+ break;
+ case 3:
+ if (m_opcode_cpsr == 0)
+ return true;
+ result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
+ break;
+ case 4:
+ if (m_opcode_cpsr == 0)
+ return true;
+ result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
+ break;
case 5:
- {
+ if (m_opcode_cpsr == 0)
+ return true;
+ else
+ {
bool n = (m_opcode_cpsr & MASK_CPSR_N);
bool v = (m_opcode_cpsr & MASK_CPSR_V);
result = n == v;
}
break;
case 6:
- {
+ if (m_opcode_cpsr == 0)
+ return true;
+ else
+ {
bool n = (m_opcode_cpsr & MASK_CPSR_N);
bool v = (m_opcode_cpsr & MASK_CPSR_V);
result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
@@ -12875,5 +12984,79 @@
if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
m_it_session.ITAdvance();
- return false;
+
+ ARMOpcode *opcode_data;
+
+ if (m_opcode_mode == eModeThumb)
+ opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32());
+ else if (m_opcode_mode == eModeARM)
+ opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32());
+ else
+ return false;
+
+ if (!opcode_data)
+ return false;
+ // Verify that we're the right arch for this opcode
+
+ switch (m_arm_isa)
+ {
+ case ARMv4:
+ if (opcode_data->variants != ARMvAll)
+ return false;
+ break;
+
+ case ARMv4T:
+ if ((opcode_data->variants!= ARMvAll)
+ && (opcode_data->variants != ARMV4T_ABOVE))
+ return false;
+ break;
+
+ case ARMv5T:
+ case ARMv5TE:
+ if ((opcode_data->variants != ARMvAll)
+ && (opcode_data->variants != ARMV4T_ABOVE)
+ && (opcode_data->variants != ARMV5_ABOVE))
+ return false;
+ break;
+
+ case ARMv5TEJ:
+ if ((opcode_data->variants != ARMvAll)
+ && (opcode_data->variants != ARMV4T_ABOVE)
+ && (opcode_data->variants != ARMV5_ABOVE)
+ && (opcode_data->variants != ARMV5J_ABOVE))
+ return false;
+ break;
+
+ case ARMv6:
+ case ARMv6K:
+ if ((opcode_data->variants != ARMvAll)
+ && (opcode_data->variants != ARMV4T_ABOVE)
+ && (opcode_data->variants != ARMV5_ABOVE)
+ && (opcode_data->variants != ARMV5J_ABOVE)
+ && (opcode_data->variants != ARMV6_ABOVE))
+ return false;
+ break;
+
+ case ARMv6T2:
+ case ARMv7:
+ case ARMv8:
+ if ((opcode_data->variants != ARMvAll)
+ && (opcode_data->variants != ARMV4T_ABOVE)
+ && (opcode_data->variants != ARMV5_ABOVE)
+ && (opcode_data->variants != ARMV5J_ABOVE)
+ && (opcode_data->variants != ARMV6_ABOVE)
+ && (opcode_data->variants != ARMV6T2_ABOVE))
+ return false;
+ break;
+
+ default:
+// if (opcode_data->variants != ARMvAll)
+// return false;
+ break;
+ }
+
+ // Just for now, for testing purposes.
+ //fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(), opcode_data->name);
+
+ return (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
}
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index 501b6cd..c1dd193 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -67,6 +67,15 @@
static void
Terminate ();
+ static const char *
+ GetPluginNameStatic ();
+
+ static const char *
+ GetPluginDescriptionStatic ();
+
+ static lldb_private::EmulateInstruction *
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
virtual const char *
GetPluginName()
{
@@ -76,7 +85,7 @@
virtual const char *
GetShortPluginName()
{
- return "lldb.emulate-instruction.arm";
+ return GetPluginNameStatic();
}
virtual uint32_t
@@ -85,20 +94,36 @@
return 1;
}
+ bool
+ SetTargetTriple (const ArchSpec &arch);
+
enum Mode
{
eModeInvalid,
eModeARM,
eModeThumb
};
+
+ EmulateInstructionARM (const ArchSpec &arch) :
+ EmulateInstruction (lldb::eByteOrderLittle,
+ 4,
+ arch),
+ m_arm_isa (0),
+ m_opcode_mode (eModeInvalid),
+ m_opcode_cpsr (0),
+ m_it_session ()
+ {
+ }
- EmulateInstructionARM (void *baton,
+ EmulateInstructionARM (const ArchSpec &arch,
+ void *baton,
ReadMemory read_mem_callback,
WriteMemory write_mem_callback,
ReadRegister read_reg_callback,
WriteRegister write_reg_callback) :
EmulateInstruction (lldb::eByteOrderLittle, // Byte order for ARM
4, // Address size in byte
+ arch,
baton,
read_mem_callback,
write_mem_callback,
@@ -117,6 +142,9 @@
virtual bool
ReadInstruction ();
+
+ virtual bool
+ SetInstruction (const Opcode &insn_opcode, const Address &inst_addr);
virtual bool
EvaluateInstruction ();
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 7fd5cfb..00f2f00 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -70,6 +70,8 @@
break;
}
}
+ parent_arg_die = parent_arg_die->GetParent();
+ parend_pos_die = parend_pos_die->GetParent();
}
if (match)
diff --git a/source/lldb.cpp b/source/lldb.cpp
index b6473c6..1705c3f 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/StringRef.h"
#include "Plugins/Disassembler/llvm/DisassemblerLLVM.h"
+#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
@@ -85,6 +86,7 @@
ArchDefaultUnwindPlan_x86_64::Initialize();
ArchDefaultUnwindPlan_i386::Initialize();
ArchVolatileRegs_x86::Initialize();
+ EmulateInstructionARM::Initialize ();
#if defined (__APPLE__)
//----------------------------------------------------------------------
@@ -152,6 +154,7 @@
ArchDefaultUnwindPlan_i386::Terminate();
ArchDefaultUnwindPlan_x86_64::Terminate();
ArchVolatileRegs_x86::Terminate();
+ EmulateInstructionARM::Terminate ();
#if defined (__APPLE__)
DynamicLoaderMacOSXDYLD::Terminate();