1061da546Spatrick //===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 11061da546Spatrick 12061da546Spatrick #include "lldb/Core/EmulateInstruction.h" 13061da546Spatrick #include "lldb/Symbol/UnwindPlan.h" 14061da546Spatrick #include "lldb/Target/UnwindAssembly.h" 15061da546Spatrick #include "lldb/Utility/RegisterValue.h" 16061da546Spatrick #include "lldb/lldb-private.h" 17061da546Spatrick 18061da546Spatrick class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly { 19061da546Spatrick public: 20061da546Spatrick ~UnwindAssemblyInstEmulation() override = default; 21061da546Spatrick 22061da546Spatrick bool GetNonCallSiteUnwindPlanFromAssembly( 23061da546Spatrick lldb_private::AddressRange &func, lldb_private::Thread &thread, 24061da546Spatrick lldb_private::UnwindPlan &unwind_plan) override; 25061da546Spatrick 26061da546Spatrick bool 27061da546Spatrick GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func, 28061da546Spatrick uint8_t *opcode_data, size_t opcode_size, 29061da546Spatrick lldb_private::UnwindPlan &unwind_plan); 30061da546Spatrick 31061da546Spatrick bool 32061da546Spatrick AugmentUnwindPlanFromCallSite(lldb_private::AddressRange &func, 33061da546Spatrick lldb_private::Thread &thread, 34061da546Spatrick lldb_private::UnwindPlan &unwind_plan) override; 35061da546Spatrick 36061da546Spatrick bool GetFastUnwindPlan(lldb_private::AddressRange &func, 37061da546Spatrick lldb_private::Thread &thread, 38061da546Spatrick lldb_private::UnwindPlan &unwind_plan) override; 39061da546Spatrick 40061da546Spatrick // thread may be NULL in which case we only use the Target (e.g. if this is 41061da546Spatrick // called pre-process-launch). 42061da546Spatrick bool 43061da546Spatrick FirstNonPrologueInsn(lldb_private::AddressRange &func, 44061da546Spatrick const lldb_private::ExecutionContext &exe_ctx, 45061da546Spatrick lldb_private::Address &first_non_prologue_insn) override; 46061da546Spatrick 47061da546Spatrick static lldb_private::UnwindAssembly * 48061da546Spatrick CreateInstance(const lldb_private::ArchSpec &arch); 49061da546Spatrick 50061da546Spatrick // PluginInterface protocol 51061da546Spatrick static void Initialize(); 52061da546Spatrick 53061da546Spatrick static void Terminate(); 54061da546Spatrick GetPluginNameStatic()55*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "inst-emulation"; } 56061da546Spatrick 57*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic(); 58061da546Spatrick GetPluginName()59*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 60061da546Spatrick 61061da546Spatrick private: 62061da546Spatrick // Call CreateInstance to get an instance of this class UnwindAssemblyInstEmulation(const lldb_private::ArchSpec & arch,lldb_private::EmulateInstruction * inst_emulator)63061da546Spatrick UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch, 64061da546Spatrick lldb_private::EmulateInstruction *inst_emulator) 65061da546Spatrick : UnwindAssembly(arch), m_inst_emulator_up(inst_emulator), 66061da546Spatrick m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_curr_row(), 67*f6aab3d8Srobert m_initial_sp(0), m_cfa_reg_info(), m_fp_is_cfa(false), 68*f6aab3d8Srobert m_register_values(), m_pushed_regs(), m_curr_row_modified(false), 69061da546Spatrick m_forward_branch_offset(0) { 70*f6aab3d8Srobert if (m_inst_emulator_up) { 71061da546Spatrick m_inst_emulator_up->SetBaton(this); 72061da546Spatrick m_inst_emulator_up->SetCallbacks(ReadMemory, WriteMemory, ReadRegister, 73061da546Spatrick WriteRegister); 74061da546Spatrick } 75061da546Spatrick } 76061da546Spatrick 77061da546Spatrick static size_t 78061da546Spatrick ReadMemory(lldb_private::EmulateInstruction *instruction, void *baton, 79061da546Spatrick const lldb_private::EmulateInstruction::Context &context, 80061da546Spatrick lldb::addr_t addr, void *dst, size_t length); 81061da546Spatrick 82061da546Spatrick static size_t 83061da546Spatrick WriteMemory(lldb_private::EmulateInstruction *instruction, void *baton, 84061da546Spatrick const lldb_private::EmulateInstruction::Context &context, 85061da546Spatrick lldb::addr_t addr, const void *dst, size_t length); 86061da546Spatrick 87061da546Spatrick static bool ReadRegister(lldb_private::EmulateInstruction *instruction, 88061da546Spatrick void *baton, 89061da546Spatrick const lldb_private::RegisterInfo *reg_info, 90061da546Spatrick lldb_private::RegisterValue ®_value); 91061da546Spatrick 92061da546Spatrick static bool 93061da546Spatrick WriteRegister(lldb_private::EmulateInstruction *instruction, void *baton, 94061da546Spatrick const lldb_private::EmulateInstruction::Context &context, 95061da546Spatrick const lldb_private::RegisterInfo *reg_info, 96061da546Spatrick const lldb_private::RegisterValue ®_value); 97061da546Spatrick 98061da546Spatrick // size_t 99061da546Spatrick // ReadMemory (lldb_private::EmulateInstruction *instruction, 100061da546Spatrick // const lldb_private::EmulateInstruction::Context &context, 101061da546Spatrick // lldb::addr_t addr, 102061da546Spatrick // void *dst, 103061da546Spatrick // size_t length); 104061da546Spatrick 105061da546Spatrick size_t WriteMemory(lldb_private::EmulateInstruction *instruction, 106061da546Spatrick const lldb_private::EmulateInstruction::Context &context, 107061da546Spatrick lldb::addr_t addr, const void *dst, size_t length); 108061da546Spatrick 109061da546Spatrick bool ReadRegister(lldb_private::EmulateInstruction *instruction, 110061da546Spatrick const lldb_private::RegisterInfo *reg_info, 111061da546Spatrick lldb_private::RegisterValue ®_value); 112061da546Spatrick 113061da546Spatrick bool WriteRegister(lldb_private::EmulateInstruction *instruction, 114061da546Spatrick const lldb_private::EmulateInstruction::Context &context, 115061da546Spatrick const lldb_private::RegisterInfo *reg_info, 116061da546Spatrick const lldb_private::RegisterValue ®_value); 117061da546Spatrick 118061da546Spatrick static uint64_t 119061da546Spatrick MakeRegisterKindValuePair(const lldb_private::RegisterInfo ®_info); 120061da546Spatrick 121061da546Spatrick void SetRegisterValue(const lldb_private::RegisterInfo ®_info, 122061da546Spatrick const lldb_private::RegisterValue ®_value); 123061da546Spatrick 124061da546Spatrick bool GetRegisterValue(const lldb_private::RegisterInfo ®_info, 125061da546Spatrick lldb_private::RegisterValue ®_value); 126061da546Spatrick 127061da546Spatrick std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_up; 128061da546Spatrick lldb_private::AddressRange *m_range_ptr; 129061da546Spatrick lldb_private::UnwindPlan *m_unwind_plan_ptr; 130061da546Spatrick lldb_private::UnwindPlan::RowSP m_curr_row; 131061da546Spatrick typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap; 132061da546Spatrick uint64_t m_initial_sp; 133061da546Spatrick lldb_private::RegisterInfo m_cfa_reg_info; 134061da546Spatrick bool m_fp_is_cfa; 135061da546Spatrick typedef std::map<uint64_t, lldb_private::RegisterValue> RegisterValueMap; 136061da546Spatrick RegisterValueMap m_register_values; 137061da546Spatrick PushedRegisterToAddrMap m_pushed_regs; 138061da546Spatrick 139061da546Spatrick // While processing the instruction stream, we need to communicate some state 140061da546Spatrick // change 141061da546Spatrick // information up to the higher level loop that makes decisions about how to 142061da546Spatrick // push 143061da546Spatrick // the unwind instructions for the UnwindPlan we're constructing. 144061da546Spatrick 145061da546Spatrick // The instruction we're processing updated the UnwindPlan::Row contents 146061da546Spatrick bool m_curr_row_modified; 147061da546Spatrick // The instruction is branching forward with the given offset. 0 value means 148061da546Spatrick // no branching. 149061da546Spatrick uint32_t m_forward_branch_offset; 150061da546Spatrick }; 151061da546Spatrick 152dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 153