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
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
//===-- x86AssemblyInspectionEngine.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_x86AssemblyInspectionEngine_h_
#define liblldb_x86AssemblyInspectionEngine_h_

#include "llvm-c/Disassembler.h"

#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"

#include <map>
#include <vector>

namespace lldb_private {

// x86AssemblyInspectionEngine - a class which will take a buffer of bytes
// of i386/x86_64 instructions and create an UnwindPlan based on those
// assembly instructions.
class x86AssemblyInspectionEngine {

public:
  /// default ctor
  x86AssemblyInspectionEngine(const lldb_private::ArchSpec &arch);

  /// default dtor
  ~x86AssemblyInspectionEngine();

  /// One of the two initialize methods that can be called on this object;
  /// they must be called before any of the assembly inspection methods
  /// are called.  This one should be used if the caller has access to a
  /// valid RegisterContext.
  void Initialize(lldb::RegisterContextSP &reg_ctx);

  /// One of the two initialize methods that can be called on this object;
  /// they must be called before any of the assembly inspection methods
  /// are called.  This one takes a vector of register name and lldb
  /// register numbers.
  struct lldb_reg_info {
    const char *name;
    uint32_t lldb_regnum;
    lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {}
  };
  void Initialize(std::vector<lldb_reg_info> &reg_info);

  /// Create an UnwindPlan for a "non-call site" stack frame situation.
  /// This is usually when this function/method is currently executing, and may
  /// be at
  /// a location where exception-handling style unwind information (eh_frame,
  /// compact unwind info, arm unwind info)
  /// are not valid.
  /// \p data is a pointer to the instructions for the function
  /// \p size is the size of the instruction buffer above
  /// \p func_range is the start Address and size of the function, to be
  /// included in the UnwindPlan
  /// \p unwind_plan is the unwind plan that this method creates
  /// \returns true if it was able to create an UnwindPlan; false if not.
  bool
  GetNonCallSiteUnwindPlanFromAssembly(uint8_t *data, size_t size,
                                       lldb_private::AddressRange &func_range,
                                       lldb_private::UnwindPlan &unwind_plan);

  /// Take an existing UnwindPlan, probably from eh_frame which may be missing
  /// description
  /// of the epilogue instructions, and add the epilogue description to it based
  /// on the
  /// instructions in the function.
  ///
  /// The \p unwind_plan 's register numbers must be converted into the lldb
  /// register numbering
  /// scheme OR a RegisterContext must be provided in \p reg_ctx.  If the \p
  /// unwind_plan
  /// register numbers are already in lldb register numbering, \p reg_ctx may be
  /// null.
  /// \returns true if the \p unwind_plan was updated, false if it was not.
  bool AugmentUnwindPlanFromCallSite(uint8_t *data, size_t size,
                                     lldb_private::AddressRange &func_range,
                                     lldb_private::UnwindPlan &unwind_plan,
                                     lldb::RegisterContextSP &reg_ctx);

  bool FindFirstNonPrologueInstruction(uint8_t *data, size_t size,
                                       size_t &offset);

private:
  bool nonvolatile_reg_p(int machine_regno);
  bool push_rbp_pattern_p();
  bool push_0_pattern_p();
  bool push_imm_pattern_p();
  bool push_extended_pattern_p();
  bool push_misc_reg_p();
  bool mov_rsp_rbp_pattern_p();
  bool mov_rsp_rbx_pattern_p();
  bool mov_rbp_rsp_pattern_p();
  bool mov_rbx_rsp_pattern_p();
  bool sub_rsp_pattern_p(int &amount);
  bool add_rsp_pattern_p(int &amount);
  bool lea_rsp_pattern_p(int &amount);
  bool lea_rbp_rsp_pattern_p(int &amount);
  bool lea_rbx_rsp_pattern_p(int &amount);
  bool and_rsp_pattern_p();
  bool push_reg_p(int &regno);
  bool pop_reg_p(int &regno);
  bool pop_rbp_pattern_p();
  bool pop_misc_reg_p();
  bool leave_pattern_p();
  bool call_next_insn_pattern_p();
  bool mov_reg_to_local_stack_frame_p(int &regno, int &rbp_offset);
  bool ret_pattern_p();
  bool jmp_to_reg_p();
  bool pc_rel_branch_or_jump_p (const int instruction_length, int &offset);
  bool non_local_branch_p (const lldb::addr_t current_func_text_offset, 
                           const lldb_private::AddressRange &func_range,
                           const int instruction_length);
  bool local_branch_p (const lldb::addr_t current_func_text_offset, 
                       const lldb_private::AddressRange &func_range,
                       const int instruction_length,
                       lldb::addr_t &target_insn_offset);
  uint16_t extract_2(uint8_t *b);
  int16_t extract_2_signed(uint8_t *b);
  uint32_t extract_4(uint8_t *b);
  int32_t extract_4_signed(uint8_t *b);

  bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes);

  bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno);

  enum CPU { k_i386, k_x86_64, k_cpu_unspecified };

  enum i386_register_numbers {
    k_machine_eax = 0,
    k_machine_ecx = 1,
    k_machine_edx = 2,
    k_machine_ebx = 3,
    k_machine_esp = 4,
    k_machine_ebp = 5,
    k_machine_esi = 6,
    k_machine_edi = 7,
    k_machine_eip = 8
  };

  enum x86_64_register_numbers {
    k_machine_rax = 0,
    k_machine_rcx = 1,
    k_machine_rdx = 2,
    k_machine_rbx = 3,
    k_machine_rsp = 4,
    k_machine_rbp = 5,
    k_machine_rsi = 6,
    k_machine_rdi = 7,
    k_machine_r8 = 8,
    k_machine_r9 = 9,
    k_machine_r10 = 10,
    k_machine_r11 = 11,
    k_machine_r12 = 12,
    k_machine_r13 = 13,
    k_machine_r14 = 14,
    k_machine_r15 = 15,
    k_machine_rip = 16
  };

  enum { kMaxInstructionByteSize = 32 };

  uint8_t *m_cur_insn;

  uint32_t m_machine_ip_regnum;
  uint32_t m_machine_sp_regnum;
  uint32_t m_machine_fp_regnum;
  uint32_t m_machine_alt_fp_regnum;
  uint32_t m_lldb_ip_regnum;
  uint32_t m_lldb_sp_regnum;
  uint32_t m_lldb_fp_regnum;
  uint32_t m_lldb_alt_fp_regnum;

  typedef std::map<uint32_t, lldb_reg_info> MachineRegnumToNameAndLLDBRegnum;

  MachineRegnumToNameAndLLDBRegnum m_reg_map;

  lldb_private::ArchSpec m_arch;
  CPU m_cpu;
  int m_wordsize;

  bool m_register_map_initialized;

  ::LLVMDisasmContextRef m_disasm_context;

  DISALLOW_COPY_AND_ASSIGN(x86AssemblyInspectionEngine);
};

} // namespace lldb_private

#endif // liblldb_x86AssemblyInspectionEngine_h_