//===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_UnwindAssemblyInstEmulation_h_ #define liblldb_UnwindAssemblyInstEmulation_h_ // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/UnwindAssembly.h" class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly { public: ~UnwindAssemblyInstEmulation() override = default; bool GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func, lldb_private::Thread& thread, lldb_private::UnwindPlan& unwind_plan) override; bool AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func, lldb_private::Thread& thread, lldb_private::UnwindPlan& unwind_plan) override; bool GetFastUnwindPlan(lldb_private::AddressRange& func, lldb_private::Thread& thread, lldb_private::UnwindPlan &unwind_plan) override; // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch). bool FirstNonPrologueInsn(lldb_private::AddressRange& func, const lldb_private::ExecutionContext &exe_ctx, lldb_private::Address& first_non_prologue_insn) override; static lldb_private::UnwindAssembly * CreateInstance (const lldb_private::ArchSpec &arch); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ static void Initialize(); static void Terminate(); static lldb_private::ConstString GetPluginNameStatic(); static const char * GetPluginDescriptionStatic(); lldb_private::ConstString GetPluginName() override; uint32_t GetPluginVersion() override; private: // Call CreateInstance to get an instance of this class 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), m_curr_row (), m_cfa_reg_info (), m_fp_is_cfa (false), m_register_values (), m_pushed_regs(), m_curr_row_modified (false), m_forward_branch_offset (0) { if (m_inst_emulator_ap.get()) { m_inst_emulator_ap->SetBaton (this); m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister); } } 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, const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue ®_value); static bool WriteRegister (lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue ®_value); // size_t // ReadMemory (lldb_private::EmulateInstruction *instruction, // const lldb_private::EmulateInstruction::Context &context, // lldb::addr_t addr, // void *dst, // size_t length); size_t WriteMemory (lldb_private::EmulateInstruction *instruction, const lldb_private::EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length); bool ReadRegister (lldb_private::EmulateInstruction *instruction, const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue ®_value); bool WriteRegister (lldb_private::EmulateInstruction *instruction, const lldb_private::EmulateInstruction::Context &context, const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue ®_value); static uint64_t MakeRegisterKindValuePair (const lldb_private::RegisterInfo ®_info); void SetRegisterValue (const lldb_private::RegisterInfo ®_info, const lldb_private::RegisterValue ®_value); bool GetRegisterValue (const lldb_private::RegisterInfo ®_info, lldb_private::RegisterValue ®_value); std::unique_ptr m_inst_emulator_ap; lldb_private::AddressRange* m_range_ptr; lldb_private::Thread* m_thread_ptr; lldb_private::UnwindPlan* m_unwind_plan_ptr; lldb_private::UnwindPlan::RowSP m_curr_row; typedef std::map PushedRegisterToAddrMap; uint64_t m_initial_sp; lldb_private::RegisterInfo m_cfa_reg_info; bool m_fp_is_cfa; typedef std::map RegisterValueMap; RegisterValueMap m_register_values; PushedRegisterToAddrMap m_pushed_regs; // While processing the instruction stream, we need to communicate some state change // information up to the higher level loop that makes decisions about how to push // the unwind instructions for the UnwindPlan we're constructing. // The instruction we're processing updated the UnwindPlan::Row contents bool m_curr_row_modified; // The instruction is branching forward with the given offset. 0 value means no branching. uint32_t m_forward_branch_offset; }; #endif // liblldb_UnwindAssemblyInstEmulation_h_