13#include "llvm-c/Disassembler.h"
32 m_cpu(k_cpu_unspecified), m_wordsize(-1),
33 m_register_map_initialized(false), m_disasm_context() {
35 ::LLVMCreateDisasm(arch.
GetTriple().getTriple().c_str(),
nullptr,
49 if (cpu == llvm::Triple::x86)
51 else if (cpu == llvm::Triple::x86_64)
57 if (reg_ctx.get() ==
nullptr)
100 reginfo.
name =
"rsi";
104 reginfo.
name =
"r10";
106 reginfo.
name =
"r12";
108 reginfo.
name =
"r14";
110 reginfo.
name =
"rip";
112 reginfo.
name =
"rcx";
114 reginfo.
name =
"rbx";
116 reginfo.
name =
"rbp";
118 reginfo.
name =
"rdi";
122 reginfo.
name =
"r11";
124 reginfo.
name =
"r13";
126 reginfo.
name =
"r15";
130 for (MachineRegnumToNameAndLLDBRegnum::iterator it =
m_reg_map.begin();
132 const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName(it->second.name);
151 std::vector<lldb_reg_info> ®_info) {
157 if (cpu == llvm::Triple::x86)
159 else if (cpu == llvm::Triple::x86_64)
173 reginfo.
name =
"eax";
175 reginfo.
name =
"edx";
177 reginfo.
name =
"esp";
179 reginfo.
name =
"esi";
181 reginfo.
name =
"eip";
183 reginfo.
name =
"ecx";
185 reginfo.
name =
"ebx";
187 reginfo.
name =
"ebp";
189 reginfo.
name =
"edi";
199 reginfo.
name =
"rax";
201 reginfo.
name =
"rdx";
203 reginfo.
name =
"rsp";
205 reginfo.
name =
"rsi";
209 reginfo.
name =
"r10";
211 reginfo.
name =
"r12";
213 reginfo.
name =
"r14";
215 reginfo.
name =
"rip";
217 reginfo.
name =
"rcx";
219 reginfo.
name =
"rbx";
221 reginfo.
name =
"rbp";
223 reginfo.
name =
"rdi";
227 reginfo.
name =
"r11";
229 reginfo.
name =
"r13";
231 reginfo.
name =
"r15";
235 for (MachineRegnumToNameAndLLDBRegnum::iterator it =
m_reg_map.begin();
237 for (
size_t i = 0; i < reg_info.size(); ++i) {
238 if (::strcmp(reg_info[i].name, it->second.name) == 0) {
265 switch (machine_regno) {
278 switch (machine_regno) {
296#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
300#define REX_W_SRCREG(opcode) (((opcode)&0x4) >> 2)
304#define REX_W_DSTREG(opcode) ((opcode)&0x1)
315 return *p == 0x6a && *(p + 1) == 0x0;
322 return *p == 0x68 || *p == 0x6a;
339 uint8_t opcode = (*(
m_cur_insn + 1) >> 3) & 7;
358 if (p == 0x0e || p == 0x16 || p == 0x1e || p == 0x06)
368 int regno_prefix_bit = 0;
371 regno_prefix_bit = (*p & 1) << 3;
374 if (*p >= 0x50 && *p <= 0x57) {
375 regno = (*p - 0x50) | regno_prefix_bit;
387 if (*(p) == 0x8b && *(p + 1) == 0xec)
389 if (*(p) == 0x89 && *(p + 1) == 0xe5)
400 if (*(p) == 0x8b && *(p + 1) == 0xdc)
402 if (*(p) == 0x89 && *(p + 1) == 0xe3)
413 if (*(p) == 0x8b && *(p + 1) == 0xe5)
415 if (*(p) == 0x89 && *(p + 1) == 0xec)
426 if (*(p) == 0x8b && *(p + 1) == 0xe3)
428 if (*(p) == 0x89 && *(p + 1) == 0xdc)
439 if (*p == 0x83 && *(p + 1) == 0xec) {
440 amount = (int8_t) * (p + 2);
444 if (*p == 0x81 && *(p + 1) == 0xec) {
457 if (*p == 0x83 && *(p + 1) == 0xc4) {
458 amount = (int8_t) * (p + 2);
462 if (*p == 0x81 && *(p + 1) == 0xc4) {
481 if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) {
482 amount = (int8_t) * (p + 3);
487 if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) {
509 amount = (int8_t)p[1];
536 amount = (int8_t)p[1];
556 if (*p != 0x81 && *p != 0x83)
566 int regno_prefix_bit = 0;
569 regno_prefix_bit = (*p & 1) << 3;
572 if (*p >= 0x58 && *p <= 0x5f) {
573 regno = (*p - 0x58) | regno_prefix_bit;
593 if (p == 0x1f || p == 0x07 || p == 0x17)
608 return (*p == 0xe8) && (*(p + 1) == 0x0) && (*(p + 2) == 0x0) &&
609 (*(p + 3) == 0x0) && (*(p + 4) == 0x0);
624 int ®no,
int &rbp_offset) {
626 int src_reg_prefix_bit = 0;
627 int target_reg_prefix_bit = 0;
632 if (target_reg_prefix_bit == 1) {
643 int opcode_destreg_masked_out = *(p + 1) & (~0x38);
649 if (opcode_destreg_masked_out == 0x45)
651 else if (opcode_destreg_masked_out == 0x85)
658 offset = (int8_t) * (p + 2);
664 regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
665 rbp_offset = offset > 0 ? offset : -offset;
683 uint8_t second_byte_sans_reg = *(
m_cur_insn + 1) & ~7;
686 if (second_byte_sans_reg == 0x20)
690 if (second_byte_sans_reg == 0x60)
694 if (second_byte_sans_reg == 0xa0)
698 if (second_byte_sans_reg == 0xe0)
720 const int instruction_length,
int &offset)
751 if (b1 == 0x0f && opcode_size == 0) {
777 if (opcode_size == 0)
782 int8_t rel8 = (int8_t) *(
m_cur_insn + opcode_size);
801 const addr_t current_func_text_offset,
803 const int instruction_length,
804 addr_t &target_insn_offset) {
808 if (offset < 0 &&
addr_t(-offset) > current_func_text_offset) {
812 if (offset + next_pc_value > func_range.
GetByteSize()) {
817 target_insn_offset = next_pc_value + offset;
828 const addr_t current_func_text_offset,
830 const int instruction_length) {
832 addr_t target_insn_offset;
842 return *p == 0xc3 || *p == 0xc2 || *p == 0xca || *p == 0xcb;
847 for (
int i = 1; i >= 0; i--)
854 for (
int i = 1; i >= 0; i--)
861 for (
int i = 3; i >= 0; i--)
868 for (
int i = 3; i >= 0; i--)
876 uint32_t buffer_remaining_bytes) {
879 llvm::SmallVector<uint8_t, 32> opcode_data;
880 opcode_data.resize(max_op_byte_size);
882 char out_string[512];
883 const size_t inst_size =
885 out_string,
sizeof(out_string));
892 int machine_regno, uint32_t &lldb_regno) {
893 MachineRegnumToNameAndLLDBRegnum::iterator it =
m_reg_map.find(machine_regno);
895 lldb_regno = it->second.lldb_regnum;
906 if (data ==
nullptr || size == 0)
915 addr_t current_func_text_offset = 0;
916 int current_sp_bytes_offset_from_fa = 0;
917 bool is_aligned =
false;
926 row->SetOffset(current_func_text_offset);
942 *newrow = *row.get();
949 std::vector<bool> saved_registers(32,
false);
957 int prologue_completed_sp_bytes_offset_from_cfa = 0;
959 bool prologue_completed_is_aligned =
false;
960 std::vector<bool> prologue_completed_saved_registers;
962 while (current_func_text_offset < size) {
963 int stack_offset, insn_len;
968 bool in_epilogue =
false;
969 bool row_updated =
false;
979 auto &cfa_value = row->GetCFAValue();
980 auto &afa_value = row->GetAFAValue();
981 auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
985 fa_value_ptr->SetIsRegisterPlusOffset(
993 fa_value_ptr->SetIsRegisterPlusOffset(
1000 current_sp_bytes_offset_from_fa = 0;
1001 afa_value.SetIsRegisterPlusOffset(
1003 fa_value_ptr = &afa_value;
1012 fa_value_ptr = &cfa_value;
1013 afa_value.SetUnspecified();
1017 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1024 fa_value_ptr = &cfa_value;
1025 afa_value.SetUnspecified();
1029 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1041 current_sp_bytes_offset_from_fa +=
m_wordsize;
1046 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1053 !saved_registers[machine_regno]) {
1059 row->SetRegisterInfo(lldb_regno, regloc);
1060 saved_registers[machine_regno] =
true;
1066 current_sp_bytes_offset_from_fa -=
m_wordsize;
1070 saved_registers[machine_regno]) {
1071 saved_registers[machine_regno] =
false;
1072 row->RemoveRegisterInfo(lldb_regno);
1074 if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
1075 fa_value_ptr->SetIsRegisterPlusOffset(
1086 fa_value_ptr->SetIsRegisterPlusOffset(
1093 current_sp_bytes_offset_from_fa -=
m_wordsize;
1095 fa_value_ptr->SetIsRegisterPlusOffset(
1115 fa_value_ptr = &cfa_value;
1116 afa_value.SetUnspecified();
1122 fa_value_ptr->SetIsRegisterPlusOffset(
1125 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1128 current_sp_bytes_offset_from_fa -=
m_wordsize;
1131 fa_value_ptr->SetIsRegisterPlusOffset(
1142 !saved_registers[machine_regno]) {
1143 saved_registers[machine_regno] =
true;
1157 row->SetRegisterInfo(lldb_regno, regloc);
1163 current_sp_bytes_offset_from_fa += stack_offset;
1165 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1171 current_sp_bytes_offset_from_fa -= stack_offset;
1173 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1181 current_sp_bytes_offset_from_fa +=
m_wordsize;
1183 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1189 current_sp_bytes_offset_from_fa -= stack_offset;
1191 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1194 if (stack_offset > 0)
1202 fa_value_ptr = &cfa_value;
1203 afa_value.SetUnspecified();
1207 current_sp_bytes_offset_from_fa =
1208 fa_value_ptr->GetOffset() - stack_offset;
1216 fa_value_ptr = &cfa_value;
1217 afa_value.SetUnspecified();
1221 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1225 else if (prologue_completed_row.get() &&
1244 (
sp.IsCFAPlusOffset() &&
sp.GetOffset() == 0 &&
1250 *newrow = *prologue_completed_row.get();
1252 current_sp_bytes_offset_from_fa =
1253 prologue_completed_sp_bytes_offset_from_cfa;
1254 is_aligned = prologue_completed_is_aligned;
1256 saved_registers.clear();
1257 saved_registers.resize(prologue_completed_saved_registers.size(),
false);
1258 for (
size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) {
1259 saved_registers[i] = prologue_completed_saved_registers[i];
1274 current_sp_bytes_offset_from_fa +=
m_wordsize;
1276 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1282 if (current_func_text_offset + insn_len < size) {
1283 row->SetOffset(current_func_text_offset + insn_len);
1287 *newrow = *row.get();
1292 if (!in_epilogue && row_updated) {
1295 *newrow = *row.get();
1296 prologue_completed_row.reset(newrow);
1298 prologue_completed_saved_registers.clear();
1299 prologue_completed_saved_registers.resize(saved_registers.size(),
false);
1300 for (
size_t i = 0; i < saved_registers.size(); ++i) {
1301 prologue_completed_saved_registers[i] = saved_registers[i];
1308 prologue_completed_sp_bytes_offset_from_cfa =
1309 current_sp_bytes_offset_from_fa;
1310 prologue_completed_is_aligned = is_aligned;
1314 current_func_text_offset += insn_len;
1334 if (reg_ctx.get() ==
nullptr &&
1345 if (first_row->GetOffset() != 0)
1347 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1349 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1351 first_row->GetCFAValue().GetRegisterNumber());
1354 first_row->GetCFAValue().GetOffset() !=
m_wordsize)
1361 bool unwind_plan_updated =
false;
1367 bool reinstate_unwind_state =
false;
1369 while (offset < size) {
1385 if (reinstate_unwind_state) {
1387 *new_row = *original_last_row;
1388 new_row->SetOffset(offset);
1390 row = std::make_shared<UnwindPlan::Row>();
1392 reinstate_unwind_state =
false;
1393 unwind_plan_updated =
true;
1403 if (original_row->GetOffset() == offset) {
1404 *row = *original_row;
1415 cfa_reg = row->GetCFAValue().GetRegisterNumber();
1417 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1419 row->GetCFAValue().GetRegisterNumber());
1428 row->SetOffset(offset);
1433 unwind_plan_updated =
true;
1440 row->SetOffset(offset);
1445 unwind_plan_updated =
true;
1454 row->SetOffset(offset);
1459 unwind_plan_updated =
true;
1464 row->SetOffset(offset);
1469 unwind_plan_updated =
true;
1475 row->SetOffset(offset);
1479 unwind_plan_updated =
true;
1485 row->SetOffset(offset);
1489 unwind_plan_updated =
true;
1496 row->SetOffset(offset);
1497 row->GetCFAValue().IncOffset(-amount);
1501 unwind_plan_updated =
true;
1505 row->SetOffset(offset);
1506 row->GetCFAValue().IncOffset(amount);
1510 unwind_plan_updated =
true;
1516 row->SetOffset(offset);
1517 row->GetCFAValue().IncOffset(-amount);
1521 unwind_plan_updated =
true;
1526 reinstate_unwind_state =
true;
1538 row->SetOffset(offset);
1539 row->GetCFAValue().SetIsRegisterPlusOffset(
1540 first_row->GetCFAValue().GetRegisterNumber(),
m_wordsize);
1544 unwind_plan_updated =
true;
1545 reinstate_unwind_state =
true;
1559 if (unwind_plan_updated) {
1561 unwind_plan_source +=
" plus augmentation from assembly parsing";
1570 uint8_t *data,
size_t size,
size_t &offset) {
1579 while (offset < size) {
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
A section + offset based address class.
bool IsValid() const
Check if the object state is valid.
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
uint32_t GetMaximumOpcodeByteSize() const
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
void SetAtAFAPlusOffset(int32_t offset)
void SetIsCFAPlusOffset(int32_t offset)
void SetAtCFAPlusOffset(int32_t offset)
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
void SetRegisterKind(lldb::RegisterKind kind)
void SetPlanValidAddressRange(const AddressRange &range)
void AppendRow(const RowSP &row_sp)
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
lldb::RegisterKind GetRegisterKind() const
std::shared_ptr< Row > RowSP
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
void SetSourceName(const char *)
lldb_private::ConstString GetSourceName() const
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
bool FindFirstNonPrologueInstruction(uint8_t *data, size_t size, size_t &offset)
@ kMaxInstructionByteSize
::LLVMDisasmContextRef m_disasm_context
bool mov_reg_to_local_stack_frame_p(int ®no, int &rbp_offset)
bool mov_rsp_rbp_pattern_p()
bool mov_rbx_rsp_pattern_p()
bool call_next_insn_pattern_p()
bool non_local_branch_p(const lldb::addr_t current_func_text_offset, const lldb_private::AddressRange &func_range, const int instruction_length)
~x86AssemblyInspectionEngine()
default dtor
bool nonvolatile_reg_p(int machine_regno)
bool lea_rbx_rsp_pattern_p(int &amount)
bool add_rsp_pattern_p(int &amount)
uint32_t m_machine_sp_regnum
bool lea_rsp_pattern_p(int &amount)
int16_t extract_2_signed(uint8_t *b)
bool lea_rbp_rsp_pattern_p(int &amount)
bool mov_rbp_rsp_pattern_p()
uint32_t m_machine_fp_regnum
bool AugmentUnwindPlanFromCallSite(uint8_t *data, size_t size, lldb_private::AddressRange &func_range, lldb_private::UnwindPlan &unwind_plan, lldb::RegisterContextSP ®_ctx)
Take an existing UnwindPlan, probably from eh_frame which may be missing description of the epilogue ...
bool push_rbp_pattern_p()
uint32_t m_machine_alt_fp_regnum
bool pc_rel_branch_or_jump_p(const int instruction_length, int &offset)
void Initialize(lldb::RegisterContextSP ®_ctx)
One of the two initialize methods that can be called on this object; they must be called before any o...
uint32_t m_lldb_alt_fp_regnum
bool GetNonCallSiteUnwindPlanFromAssembly(uint8_t *data, size_t size, lldb_private::AddressRange &func_range, lldb_private::UnwindPlan &unwind_plan)
Create an UnwindPlan for a "non-call site" stack frame situation.
uint16_t extract_2(uint8_t *b)
bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes)
uint32_t m_machine_ip_regnum
uint32_t m_lldb_ip_regnum
bool mov_rsp_rbx_pattern_p()
uint32_t m_lldb_sp_regnum
int32_t extract_4_signed(uint8_t *b)
bool m_register_map_initialized
MachineRegnumToNameAndLLDBRegnum m_reg_map
bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno)
bool push_reg_p(int ®no)
bool pop_reg_p(int ®no)
uint32_t m_lldb_fp_regnum
uint32_t extract_4(uint8_t *b)
bool push_extended_pattern_p()
lldb_private::ArchSpec m_arch
bool sub_rsp_pattern_p(int &amount)
x86AssemblyInspectionEngine(const lldb_private::ArchSpec &arch)
default ctor
bool push_imm_pattern_p()
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)
#define LLDB_INVALID_REGNUM
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
One of the two initialize methods that can be called on this object; they must be called before any o...
#define REX_W_PREFIX_P(opcode)
#define REX_W_DSTREG(opcode)
#define REX_W_SRCREG(opcode)