diff options
Diffstat (limited to 'lldb/source/Plugins/UnwindAssembly')
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 ®_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_ 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_ |