reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
//===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_UnwindAssemblyInstEmulation_h_
#define liblldb_UnwindAssemblyInstEmulation_h_

#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/UnwindAssembly.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.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
  GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func,
                                       uint8_t *opcode_data, size_t opcode_size,
                                       lldb_private::UnwindPlan &unwind_plan);

  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_up(inst_emulator),
        m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), 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_up.get()) {
      m_inst_emulator_up->SetBaton(this);
      m_inst_emulator_up->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 &reg_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 &reg_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 &reg_value);

  bool WriteRegister(lldb_private::EmulateInstruction *instruction,
                     const lldb_private::EmulateInstruction::Context &context,
                     const lldb_private::RegisterInfo *reg_info,
                     const lldb_private::RegisterValue &reg_value);

  static uint64_t
  MakeRegisterKindValuePair(const lldb_private::RegisterInfo &reg_info);

  void SetRegisterValue(const lldb_private::RegisterInfo &reg_info,
                        const lldb_private::RegisterValue &reg_value);

  bool GetRegisterValue(const lldb_private::RegisterInfo &reg_info,
                        lldb_private::RegisterValue &reg_value);

  std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_up;
  lldb_private::AddressRange *m_range_ptr;
  lldb_private::UnwindPlan *m_unwind_plan_ptr;
  lldb_private::UnwindPlan::RowSP m_curr_row;
  typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap;
  uint64_t m_initial_sp;
  lldb_private::RegisterInfo m_cfa_reg_info;
  bool m_fp_is_cfa;
  typedef std::map<uint64_t, lldb_private::RegisterValue> 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_