1 //===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 10 #define LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 11 12 #include "lldb/Core/EmulateInstruction.h" 13 #include "lldb/Symbol/UnwindPlan.h" 14 #include "lldb/Target/UnwindAssembly.h" 15 #include "lldb/Utility/RegisterValue.h" 16 #include "lldb/lldb-private.h" 17 18 class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly { 19 public: 20 ~UnwindAssemblyInstEmulation() override = default; 21 22 bool GetNonCallSiteUnwindPlanFromAssembly( 23 lldb_private::AddressRange &func, lldb_private::Thread &thread, 24 lldb_private::UnwindPlan &unwind_plan) override; 25 26 bool 27 GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func, 28 uint8_t *opcode_data, size_t opcode_size, 29 lldb_private::UnwindPlan &unwind_plan); 30 31 bool 32 AugmentUnwindPlanFromCallSite(lldb_private::AddressRange &func, 33 lldb_private::Thread &thread, 34 lldb_private::UnwindPlan &unwind_plan) override; 35 36 bool GetFastUnwindPlan(lldb_private::AddressRange &func, 37 lldb_private::Thread &thread, 38 lldb_private::UnwindPlan &unwind_plan) override; 39 40 // thread may be NULL in which case we only use the Target (e.g. if this is 41 // called pre-process-launch). 42 bool 43 FirstNonPrologueInsn(lldb_private::AddressRange &func, 44 const lldb_private::ExecutionContext &exe_ctx, 45 lldb_private::Address &first_non_prologue_insn) override; 46 47 static lldb_private::UnwindAssembly * 48 CreateInstance(const lldb_private::ArchSpec &arch); 49 50 // PluginInterface protocol 51 static void Initialize(); 52 53 static void Terminate(); 54 55 static llvm::StringRef GetPluginNameStatic() { return "inst-emulation"; } 56 57 static llvm::StringRef GetPluginDescriptionStatic(); 58 59 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 60 61 private: 62 // Call CreateInstance to get an instance of this class 63 UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch, 64 lldb_private::EmulateInstruction *inst_emulator) 65 : UnwindAssembly(arch), m_inst_emulator_up(inst_emulator), 66 m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_curr_row(), 67 m_initial_sp(0), m_cfa_reg_info(), m_fp_is_cfa(false), 68 m_register_values(), m_pushed_regs(), m_curr_row_modified(false), 69 m_forward_branch_offset(0) { 70 if (m_inst_emulator_up.get()) { 71 m_inst_emulator_up->SetBaton(this); 72 m_inst_emulator_up->SetCallbacks(ReadMemory, WriteMemory, ReadRegister, 73 WriteRegister); 74 } 75 } 76 77 static size_t 78 ReadMemory(lldb_private::EmulateInstruction *instruction, void *baton, 79 const lldb_private::EmulateInstruction::Context &context, 80 lldb::addr_t addr, void *dst, size_t length); 81 82 static size_t 83 WriteMemory(lldb_private::EmulateInstruction *instruction, void *baton, 84 const lldb_private::EmulateInstruction::Context &context, 85 lldb::addr_t addr, const void *dst, size_t length); 86 87 static bool ReadRegister(lldb_private::EmulateInstruction *instruction, 88 void *baton, 89 const lldb_private::RegisterInfo *reg_info, 90 lldb_private::RegisterValue ®_value); 91 92 static bool 93 WriteRegister(lldb_private::EmulateInstruction *instruction, void *baton, 94 const lldb_private::EmulateInstruction::Context &context, 95 const lldb_private::RegisterInfo *reg_info, 96 const lldb_private::RegisterValue ®_value); 97 98 // size_t 99 // ReadMemory (lldb_private::EmulateInstruction *instruction, 100 // const lldb_private::EmulateInstruction::Context &context, 101 // lldb::addr_t addr, 102 // void *dst, 103 // size_t length); 104 105 size_t WriteMemory(lldb_private::EmulateInstruction *instruction, 106 const lldb_private::EmulateInstruction::Context &context, 107 lldb::addr_t addr, const void *dst, size_t length); 108 109 bool ReadRegister(lldb_private::EmulateInstruction *instruction, 110 const lldb_private::RegisterInfo *reg_info, 111 lldb_private::RegisterValue ®_value); 112 113 bool WriteRegister(lldb_private::EmulateInstruction *instruction, 114 const lldb_private::EmulateInstruction::Context &context, 115 const lldb_private::RegisterInfo *reg_info, 116 const lldb_private::RegisterValue ®_value); 117 118 static uint64_t 119 MakeRegisterKindValuePair(const lldb_private::RegisterInfo ®_info); 120 121 void SetRegisterValue(const lldb_private::RegisterInfo ®_info, 122 const lldb_private::RegisterValue ®_value); 123 124 bool GetRegisterValue(const lldb_private::RegisterInfo ®_info, 125 lldb_private::RegisterValue ®_value); 126 127 std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_up; 128 lldb_private::AddressRange *m_range_ptr; 129 lldb_private::UnwindPlan *m_unwind_plan_ptr; 130 lldb_private::UnwindPlan::RowSP m_curr_row; 131 typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap; 132 uint64_t m_initial_sp; 133 lldb_private::RegisterInfo m_cfa_reg_info; 134 bool m_fp_is_cfa; 135 typedef std::map<uint64_t, lldb_private::RegisterValue> RegisterValueMap; 136 RegisterValueMap m_register_values; 137 PushedRegisterToAddrMap m_pushed_regs; 138 139 // While processing the instruction stream, we need to communicate some state 140 // change 141 // information up to the higher level loop that makes decisions about how to 142 // push 143 // the unwind instructions for the UnwindPlan we're constructing. 144 145 // The instruction we're processing updated the UnwindPlan::Row contents 146 bool m_curr_row_modified; 147 // The instruction is branching forward with the given offset. 0 value means 148 // no branching. 149 uint32_t m_forward_branch_offset; 150 }; 151 152 #endif // LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H 153