10b57cec5SDimitry Andric //===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H
105ffd83dbSDimitry Andric #define LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "lldb/Core/EmulateInstruction.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/UnwindPlan.h"
140b57cec5SDimitry Andric #include "lldb/Target/UnwindAssembly.h"
150b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
160b57cec5SDimitry Andric #include "lldb/lldb-private.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly {
190b57cec5SDimitry Andric public:
200b57cec5SDimitry Andric   ~UnwindAssemblyInstEmulation() override = default;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric   bool GetNonCallSiteUnwindPlanFromAssembly(
230b57cec5SDimitry Andric       lldb_private::AddressRange &func, lldb_private::Thread &thread,
240b57cec5SDimitry Andric       lldb_private::UnwindPlan &unwind_plan) override;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   bool
270b57cec5SDimitry Andric   GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func,
280b57cec5SDimitry Andric                                        uint8_t *opcode_data, size_t opcode_size,
290b57cec5SDimitry Andric                                        lldb_private::UnwindPlan &unwind_plan);
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   bool
320b57cec5SDimitry Andric   AugmentUnwindPlanFromCallSite(lldb_private::AddressRange &func,
330b57cec5SDimitry Andric                                 lldb_private::Thread &thread,
340b57cec5SDimitry Andric                                 lldb_private::UnwindPlan &unwind_plan) override;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   bool GetFastUnwindPlan(lldb_private::AddressRange &func,
370b57cec5SDimitry Andric                          lldb_private::Thread &thread,
380b57cec5SDimitry Andric                          lldb_private::UnwindPlan &unwind_plan) override;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   // thread may be NULL in which case we only use the Target (e.g. if this is
410b57cec5SDimitry Andric   // called pre-process-launch).
420b57cec5SDimitry Andric   bool
430b57cec5SDimitry Andric   FirstNonPrologueInsn(lldb_private::AddressRange &func,
440b57cec5SDimitry Andric                        const lldb_private::ExecutionContext &exe_ctx,
450b57cec5SDimitry Andric                        lldb_private::Address &first_non_prologue_insn) override;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   static lldb_private::UnwindAssembly *
480b57cec5SDimitry Andric   CreateInstance(const lldb_private::ArchSpec &arch);
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   // PluginInterface protocol
510b57cec5SDimitry Andric   static void Initialize();
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   static void Terminate();
540b57cec5SDimitry Andric 
GetPluginNameStatic()55349cc55cSDimitry Andric   static llvm::StringRef GetPluginNameStatic() { return "inst-emulation"; }
560b57cec5SDimitry Andric 
57349cc55cSDimitry Andric   static llvm::StringRef GetPluginDescriptionStatic();
580b57cec5SDimitry Andric 
GetPluginName()59349cc55cSDimitry Andric   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric private:
620b57cec5SDimitry Andric   // Call CreateInstance to get an instance of this class
UnwindAssemblyInstEmulation(const lldb_private::ArchSpec & arch,lldb_private::EmulateInstruction * inst_emulator)630b57cec5SDimitry Andric   UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch,
640b57cec5SDimitry Andric                               lldb_private::EmulateInstruction *inst_emulator)
650b57cec5SDimitry Andric       : UnwindAssembly(arch), m_inst_emulator_up(inst_emulator),
660b57cec5SDimitry Andric         m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_curr_row(),
67fcaf7f86SDimitry Andric         m_initial_sp(0), m_cfa_reg_info(), m_fp_is_cfa(false),
68fcaf7f86SDimitry Andric         m_register_values(), m_pushed_regs(), m_curr_row_modified(false),
690b57cec5SDimitry Andric         m_forward_branch_offset(0) {
70*bdd1243dSDimitry Andric     if (m_inst_emulator_up) {
710b57cec5SDimitry Andric       m_inst_emulator_up->SetBaton(this);
720b57cec5SDimitry Andric       m_inst_emulator_up->SetCallbacks(ReadMemory, WriteMemory, ReadRegister,
730b57cec5SDimitry Andric                                        WriteRegister);
740b57cec5SDimitry Andric     }
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   static size_t
780b57cec5SDimitry Andric   ReadMemory(lldb_private::EmulateInstruction *instruction, void *baton,
790b57cec5SDimitry Andric              const lldb_private::EmulateInstruction::Context &context,
800b57cec5SDimitry Andric              lldb::addr_t addr, void *dst, size_t length);
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   static size_t
830b57cec5SDimitry Andric   WriteMemory(lldb_private::EmulateInstruction *instruction, void *baton,
840b57cec5SDimitry Andric               const lldb_private::EmulateInstruction::Context &context,
850b57cec5SDimitry Andric               lldb::addr_t addr, const void *dst, size_t length);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   static bool ReadRegister(lldb_private::EmulateInstruction *instruction,
880b57cec5SDimitry Andric                            void *baton,
890b57cec5SDimitry Andric                            const lldb_private::RegisterInfo *reg_info,
900b57cec5SDimitry Andric                            lldb_private::RegisterValue &reg_value);
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   static bool
930b57cec5SDimitry Andric   WriteRegister(lldb_private::EmulateInstruction *instruction, void *baton,
940b57cec5SDimitry Andric                 const lldb_private::EmulateInstruction::Context &context,
950b57cec5SDimitry Andric                 const lldb_private::RegisterInfo *reg_info,
960b57cec5SDimitry Andric                 const lldb_private::RegisterValue &reg_value);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   //    size_t
990b57cec5SDimitry Andric   //    ReadMemory (lldb_private::EmulateInstruction *instruction,
1000b57cec5SDimitry Andric   //                const lldb_private::EmulateInstruction::Context &context,
1010b57cec5SDimitry Andric   //                lldb::addr_t addr,
1020b57cec5SDimitry Andric   //                void *dst,
1030b57cec5SDimitry Andric   //                size_t length);
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   size_t WriteMemory(lldb_private::EmulateInstruction *instruction,
1060b57cec5SDimitry Andric                      const lldb_private::EmulateInstruction::Context &context,
1070b57cec5SDimitry Andric                      lldb::addr_t addr, const void *dst, size_t length);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   bool ReadRegister(lldb_private::EmulateInstruction *instruction,
1100b57cec5SDimitry Andric                     const lldb_private::RegisterInfo *reg_info,
1110b57cec5SDimitry Andric                     lldb_private::RegisterValue &reg_value);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   bool WriteRegister(lldb_private::EmulateInstruction *instruction,
1140b57cec5SDimitry Andric                      const lldb_private::EmulateInstruction::Context &context,
1150b57cec5SDimitry Andric                      const lldb_private::RegisterInfo *reg_info,
1160b57cec5SDimitry Andric                      const lldb_private::RegisterValue &reg_value);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   static uint64_t
1190b57cec5SDimitry Andric   MakeRegisterKindValuePair(const lldb_private::RegisterInfo &reg_info);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   void SetRegisterValue(const lldb_private::RegisterInfo &reg_info,
1220b57cec5SDimitry Andric                         const lldb_private::RegisterValue &reg_value);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   bool GetRegisterValue(const lldb_private::RegisterInfo &reg_info,
1250b57cec5SDimitry Andric                         lldb_private::RegisterValue &reg_value);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_up;
1280b57cec5SDimitry Andric   lldb_private::AddressRange *m_range_ptr;
1290b57cec5SDimitry Andric   lldb_private::UnwindPlan *m_unwind_plan_ptr;
1300b57cec5SDimitry Andric   lldb_private::UnwindPlan::RowSP m_curr_row;
1310b57cec5SDimitry Andric   typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap;
1320b57cec5SDimitry Andric   uint64_t m_initial_sp;
1330b57cec5SDimitry Andric   lldb_private::RegisterInfo m_cfa_reg_info;
1340b57cec5SDimitry Andric   bool m_fp_is_cfa;
1350b57cec5SDimitry Andric   typedef std::map<uint64_t, lldb_private::RegisterValue> RegisterValueMap;
1360b57cec5SDimitry Andric   RegisterValueMap m_register_values;
1370b57cec5SDimitry Andric   PushedRegisterToAddrMap m_pushed_regs;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // While processing the instruction stream, we need to communicate some state
1400b57cec5SDimitry Andric   // change
1410b57cec5SDimitry Andric   // information up to the higher level loop that makes decisions about how to
1420b57cec5SDimitry Andric   // push
1430b57cec5SDimitry Andric   // the unwind instructions for the UnwindPlan we're constructing.
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // The instruction we're processing updated the UnwindPlan::Row contents
1460b57cec5SDimitry Andric   bool m_curr_row_modified;
1470b57cec5SDimitry Andric   // The instruction is branching forward with the given offset. 0 value means
1480b57cec5SDimitry Andric   // no branching.
1490b57cec5SDimitry Andric   uint32_t m_forward_branch_offset;
1500b57cec5SDimitry Andric };
1510b57cec5SDimitry Andric 
1525ffd83dbSDimitry Andric #endif // LLDB_SOURCE_PLUGINS_UNWINDASSEMBLY_INSTEMULATION_UNWINDASSEMBLYINSTEMULATION_H
153