summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/UnwindAssembly
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/UnwindAssembly')
-rw-r--r--lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp224
-rw-r--r--lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h78
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp15
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h23
4 files changed, 315 insertions, 25 deletions
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 1379cd4ce12..d9855b7c788 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -12,16 +12,16 @@
#include "llvm-c/EnhancedDisassembly.h"
#include "lldb/Core/Address.h"
-#include "lldb/Core/Error.h"
#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Error.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/UnwindAssembly.h"
using namespace lldb;
using namespace lldb_private;
@@ -33,19 +33,108 @@ using namespace lldb_private;
//-----------------------------------------------------------------------------------------------
bool
-UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
+UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range,
+ Thread& thread,
+ UnwindPlan& unwind_plan)
{
+#if 0
+ UnwindPlan::Row row;
+ UnwindPlan::Row::RegisterLocation regloc;
+
+ m_unwind_plan_sp->SetRegisterKind (eRegisterKindGeneric);
+ row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
+ row.SetCFAOffset (2 * 8);
+ row.SetOffset (0);
+
+ regloc.SetAtCFAPlusOffset (2 * -8);
+ row.SetRegisterInfo (LLDB_REGNUM_GENERIC_FP, regloc);
+ regloc.SetAtCFAPlusOffset (1 * -8);
+ row.SetRegisterInfo (LLDB_REGNUM_GENERIC_PC, regloc);
+ regloc.SetIsCFAPlusOffset (0);
+ row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
+
+ m_unwind_plan_sp->AppendRow (row);
+ m_unwind_plan_sp->SetSourceName ("x86_64 architectural default");
+#endif
+
+ if (range.GetByteSize() > 0 &&
+ range.GetBaseAddress().IsValid() &&
+ m_inst_emulator_ap.get())
+ {
+#if 0
+ Target &target = thread.GetProcess().GetTarget();
+ const ArchSpec &target_arch = target.GetArchitecture();
+ bool prefer_file_cache = true;
+ Error error;
+ DataBufferHeap data_buffer (range.GetByteSize(), 0);
+ if (target.ReadMemory (range.GetBaseAddress(),
+ prefer_file_cache,
+ data_buffer.GetBytes(),
+ data_buffer.GetByteSize(),
+ error) == data_buffer.GetByteSize())
+ {
+ DataExtractor data (data_buffer.GetBytes(),
+ data_buffer.GetByteSize(),
+ target_arch.GetByteOrder(),
+ target_arch.GetAddressByteSize());
+ }
+#endif
+ StreamFile strm (stdout, false);
+
+ ExecutionContext exe_ctx;
+ thread.CalculateExecutionContext(exe_ctx);
+ DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
+ NULL,
+ exe_ctx,
+ range));
+ if (disasm_sp)
+ {
+
+ m_range_ptr = ⦥
+ m_thread_ptr = &thread;
+ m_unwind_plan_ptr = &unwind_plan;
+
+ const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
+ const bool show_address = true;
+ const bool show_bytes = true;
+ const bool raw = false;
+ // Initialize the stack pointer with a known value. In the 32 bit case
+ // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
+ // We use the address byte size to be safe for any future addresss sizes
+ SetRegisterValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (1ull << ((addr_byte_size * 8) - 1)));
+
+ const InstructionList &inst_list = disasm_sp->GetInstructionList ();
+ const size_t num_instructions = inst_list.GetSize();
+ for (size_t idx=0; idx<num_instructions; ++idx)
+ {
+ Instruction *inst = inst_list.GetInstructionAtIndex (idx).get();
+ if (inst)
+ {
+ inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, &exe_ctx, raw);
+ strm.EOL();
+
+ m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), inst->GetAddress(), exe_ctx.target);
+ m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
+ }
+ }
+ }
+ }
return false;
}
bool
-UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
+UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func,
+ Thread& thread,
+ UnwindPlan &unwind_plan)
{
return false;
}
bool
-UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func, Target& target, Thread* thread, Address& first_non_prologue_insn)
+UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func,
+ Target& target,
+ Thread* thread,
+ Address& first_non_prologue_insn)
{
return false;
}
@@ -53,6 +142,10 @@ UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func, Target& t
UnwindAssembly *
UnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
{
+ std::auto_ptr<lldb_private::EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
+ // Make sure that all prologue instructions are handled
+ if (inst_emulator_ap.get())
+ return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
return NULL;
}
@@ -106,3 +199,120 @@ UnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
{
return "Instruction emulation based unwind information.";
}
+
+
+
+size_t
+UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
+ void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr,
+ void *dst,
+ size_t dst_len)
+{
+ //UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
+ printf ("UnwindAssemblyInstEmulation::ReadMemory (context.type = %i, context.info_type = %i, addr = 0x%16.16llx, dst = %p, dst_len = %zu)\n",
+ context.type,
+ context.info_type,
+ addr,
+ dst,
+ dst_len);
+ return dst_len;
+}
+
+size_t
+UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
+ void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr,
+ const void *dst,
+ size_t dst_len)
+{
+ // UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
+
+ DataExtractor data (dst,
+ dst_len,
+ instruction->GetArchitecture ().GetByteOrder(),
+ instruction->GetArchitecture ().GetAddressByteSize());
+ StreamFile strm(stdout, false);
+
+ strm.Printf ("UnwindAssemblyInstEmulation::WriteMemory (context.type = %i, context.info_type = %i, ",
+ context.type,
+ context.info_type);
+ data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
+ strm.EOL();
+ return dst_len;
+}
+
+bool
+UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
+ void *baton,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t &reg_value)
+{
+ UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
+ const char *reg_name = instruction->GetRegisterName (reg_kind, reg_num);
+
+ reg_value = inst_emulator->GetRegisterValue (reg_kind, reg_num);
+
+ printf ("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => value = 0x%16.16llx\n", reg_name, reg_value);
+
+ return true;
+}
+
+bool
+UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
+ void *baton,
+ const EmulateInstruction::Context &context,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t reg_value)
+{
+ UnwindAssemblyInstEmulation *inst_emulator = (UnwindAssemblyInstEmulation *)baton;
+ const char *reg_name = instruction->GetRegisterName (reg_kind, reg_num);
+
+ printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = 0x%16.16llx, context.type = %i, context.info_type = %i)\n",
+ reg_name,
+ reg_value,
+ context.type,
+ context.info_type);
+
+ inst_emulator->SetRegisterValue (reg_kind, reg_num, reg_value);
+
+ switch (context.type)
+ {
+ case EmulateInstruction::eContextInvalid:
+ case EmulateInstruction::eContextReadOpcode:
+ case EmulateInstruction::eContextImmediate:
+ case EmulateInstruction::eContextAdjustBaseRegister:
+ case EmulateInstruction::eContextRegisterPlusOffset:
+ case EmulateInstruction::eContextAdjustPC:
+ case EmulateInstruction::eContextRegisterStore:
+ case EmulateInstruction::eContextRegisterLoad:
+ case EmulateInstruction::eContextRelativeBranchImmediate:
+ case EmulateInstruction::eContextAbsoluteBranchRegister:
+ case EmulateInstruction::eContextSupervisorCall:
+ case EmulateInstruction::eContextTableBranchReadMemory:
+ case EmulateInstruction::eContextWriteRegisterRandomBits:
+ case EmulateInstruction::eContextWriteMemoryRandomBits:
+ case EmulateInstruction::eContextMultiplication:
+ case EmulateInstruction::eContextAddition:
+ case EmulateInstruction::eContextSubtraction:
+ case EmulateInstruction::eContextAdvancePC:
+ case EmulateInstruction::eContextReturnFromException:
+ break;
+
+ case EmulateInstruction::eContextPushRegisterOnStack:
+ break;
+
+ case EmulateInstruction::eContextPopRegisterOffStack:
+ break;
+
+ case EmulateInstruction::eContextAdjustStackPointer:
+ break;
+ }
+ return true;
+}
+
+
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index f6137389c95..c18cbabdfa7 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -11,8 +11,8 @@
#define liblldb_UnwindAssemblyInstEmulation_h_
#include "lldb/lldb-private.h"
+#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Target/UnwindAssembly.h"
-#include "lldb/Target/Thread.h"
class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly
{
@@ -43,7 +43,6 @@ public:
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -69,14 +68,83 @@ public:
GetPluginVersion();
private:
+
+ static size_t
+ ReadMemory (lldb_private::EmulateInstruction *instruction,
+ void *baton,
+ const lldb_private::EmulateInstruction::Context &context,
+ lldb::addr_t addr,
+ void *dst,
+ size_t length);
+
+ static size_t
+ WriteMemory (lldb_private::EmulateInstruction *instruction,
+ void *baton,
+ const lldb_private::EmulateInstruction::Context &context,
+ lldb::addr_t addr,
+ const void *dst,
+ size_t length);
+
+ static bool
+ ReadRegister (lldb_private::EmulateInstruction *instruction,
+ void *baton,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t &reg_value);
+
+ static bool
+ WriteRegister (lldb_private::EmulateInstruction *instruction,
+ void *baton,
+ const lldb_private::EmulateInstruction::Context &context,
+ uint32_t reg_kind,
+ uint32_t reg_num,
+ uint64_t reg_value);
+
// Call CreateInstance to get an instance of this class
- UnwindAssemblyInstEmulation(int cpu) :
- lldb_private::UnwindAssembly(), m_cpu(cpu)
+ UnwindAssemblyInstEmulation (const lldb_private::ArchSpec &arch,
+ lldb_private::EmulateInstruction *inst_emulator) :
+ UnwindAssembly (arch),
+ m_inst_emulator_ap (inst_emulator),
+ m_range_ptr (NULL),
+ m_thread_ptr (NULL),
+ m_unwind_plan_ptr (NULL)
+ {
+ if (m_inst_emulator_ap.get())
+ {
+ m_inst_emulator_ap->SetBaton (this);
+ m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
+ }
+ }
+
+ static uint64_t
+ MakeRegisterKindValuePair (uint32_t reg_kind, uint32_t reg_num)
+ {
+ return (uint64_t)reg_kind << 32 | reg_num;
+ }
+
+ void
+ SetRegisterValue (uint32_t reg_kind, uint32_t reg_num, uint64_t reg_value)
+ {
+ m_register_values[MakeRegisterKindValuePair (reg_kind, reg_num)] = reg_value;
+ }
+
+ uint64_t
+ GetRegisterValue (uint32_t reg_kind, uint32_t reg_num)
{
+ const uint64_t reg_id = MakeRegisterKindValuePair (reg_kind, reg_num);
+ RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
+ if (pos != m_register_values.end())
+ return pos->second;
+ return (uint64_t)reg_kind << 24 | (uint64_t)reg_num;
}
- int m_cpu;
+ std::auto_ptr<lldb_private::EmulateInstruction> m_inst_emulator_ap;
+ lldb_private::AddressRange* m_range_ptr;
+ lldb_private::Thread* m_thread_ptr;
+ lldb_private::UnwindPlan* m_unwind_plan_ptr;
+ typedef std::map<uint64_t, uint64_t> RegisterValueMap;
+ RegisterValueMap m_register_values;
};
#endif // liblldb_UnwindAssemblyInstEmulation_h_
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 28bb3364243..8382e3ea26f 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -818,6 +818,17 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
// UnwindAssemblyParser_x86 method definitions
//-----------------------------------------------------------------------------------------------
+UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) :
+ lldb_private::UnwindAssembly(arch),
+ m_cpu(cpu)
+{
+}
+
+
+UnwindAssembly_x86::~UnwindAssembly_x86 ()
+{
+}
+
bool
UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
{
@@ -844,9 +855,9 @@ UnwindAssembly_x86::CreateInstance (const ArchSpec &arch)
{
const llvm::Triple::ArchType cpu = arch.GetMachine ();
if (cpu == llvm::Triple::x86)
- return new UnwindAssembly_x86 (k_i386);
+ return new UnwindAssembly_x86 (arch, k_i386);
else if (cpu == llvm::Triple::x86_64)
- return new UnwindAssembly_x86 (k_x86_64);
+ return new UnwindAssembly_x86 (arch, k_x86_64);
return NULL;
}
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
index 4c29dcf7b28..f5d039141b2 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
+++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -12,25 +12,29 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/UnwindAssembly.h"
-#include "lldb/Target/Thread.h"
-namespace lldb_private {
-
class UnwindAssembly_x86 : public lldb_private::UnwindAssembly
{
public:
- ~UnwindAssembly_x86 () { }
+ ~UnwindAssembly_x86 ();
virtual bool
- GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, lldb_private::Thread& thread, UnwindPlan& unwind_plan);
+ GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan);
virtual bool
- GetFastUnwindPlan (AddressRange& func, lldb_private::Thread& thread, UnwindPlan &unwind_plan);
+ GetFastUnwindPlan (lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan &unwind_plan);
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
virtual bool
- FirstNonPrologueInsn (AddressRange& func, lldb_private::Target& target, lldb_private::Thread* thread, Address& first_non_prologue_insn);
+ FirstNonPrologueInsn (lldb_private::AddressRange& func,
+ lldb_private::Target& target,
+ lldb_private::Thread* thread,
+ lldb_private::Address& first_non_prologue_insn);
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
@@ -61,13 +65,10 @@ public:
GetPluginVersion();
private:
- UnwindAssembly_x86(int cpu) :
- lldb_private::UnwindAssembly(), m_cpu(cpu) { } // Call CreateInstance instead.
+ UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu);
int m_cpu;
};
-} // namespace lldb_private
-
#endif // liblldb_UnwindAssembly_x86_h_
OpenPOWER on IntegriCloud