diff options
Diffstat (limited to 'lldb/source/Plugins/UnwindAssembly/InstEmulation')
-rw-r--r-- | lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp | 224 | ||||
-rw-r--r-- | lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h | 78 |
2 files changed, 290 insertions, 12 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 ®_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 ®_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_ |