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
|
//===-- x86AssemblyInspectionEngine.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#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 ®_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> ®_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 ®_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 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 push_reg_p(int ®no);
bool pop_reg_p(int ®no);
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 ®no, int &rbp_offset);
bool ret_pattern_p();
uint32_t extract_4(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_lldb_ip_regnum;
uint32_t m_lldb_sp_regnum;
uint32_t m_lldb_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_
|