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)
67 struct lldb_reg_info reginfo;
93 struct lldb_reg_info reginfo;
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--)
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)
912 addr_t current_func_text_offset = 0;
913 int current_sp_bytes_offset_from_fa = 0;
914 bool is_aligned =
false;
923 row->SetOffset(current_func_text_offset);
939 *newrow = *row.get();
946 std::vector<bool> saved_registers(32,
false);
954 int prologue_completed_sp_bytes_offset_from_cfa = 0;
956 bool prologue_completed_is_aligned =
false;
957 std::vector<bool> prologue_completed_saved_registers;
959 while (current_func_text_offset < size) {
960 int stack_offset, insn_len;
965 bool in_epilogue =
false;
966 bool row_updated =
false;
976 auto &cfa_value = row->GetCFAValue();
977 auto &afa_value = row->GetAFAValue();
978 auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
982 fa_value_ptr->SetIsRegisterPlusOffset(
990 fa_value_ptr->SetIsRegisterPlusOffset(
997 current_sp_bytes_offset_from_fa = 0;
998 afa_value.SetIsRegisterPlusOffset(
1000 fa_value_ptr = &afa_value;
1009 fa_value_ptr = &cfa_value;
1010 afa_value.SetUnspecified();
1014 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1021 fa_value_ptr = &cfa_value;
1022 afa_value.SetUnspecified();
1026 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1038 current_sp_bytes_offset_from_fa +=
m_wordsize;
1043 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1050 !saved_registers[machine_regno]) {
1056 row->SetRegisterInfo(lldb_regno, regloc);
1057 saved_registers[machine_regno] =
true;
1063 current_sp_bytes_offset_from_fa -=
m_wordsize;
1067 saved_registers[machine_regno]) {
1068 saved_registers[machine_regno] =
false;
1069 row->RemoveRegisterInfo(lldb_regno);
1071 if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
1072 fa_value_ptr->SetIsRegisterPlusOffset(
1083 fa_value_ptr->SetIsRegisterPlusOffset(
1090 current_sp_bytes_offset_from_fa -=
m_wordsize;
1092 fa_value_ptr->SetIsRegisterPlusOffset(
1112 fa_value_ptr = &cfa_value;
1113 afa_value.SetUnspecified();
1119 fa_value_ptr->SetIsRegisterPlusOffset(
1122 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
1125 current_sp_bytes_offset_from_fa -=
m_wordsize;
1128 fa_value_ptr->SetIsRegisterPlusOffset(
1139 !saved_registers[machine_regno]) {
1140 saved_registers[machine_regno] =
true;
1154 row->SetRegisterInfo(lldb_regno, regloc);
1160 current_sp_bytes_offset_from_fa += stack_offset;
1162 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1168 current_sp_bytes_offset_from_fa -= stack_offset;
1170 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1178 current_sp_bytes_offset_from_fa +=
m_wordsize;
1180 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1186 current_sp_bytes_offset_from_fa -= stack_offset;
1188 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1191 if (stack_offset > 0)
1199 fa_value_ptr = &cfa_value;
1200 afa_value.SetUnspecified();
1204 current_sp_bytes_offset_from_fa =
1205 fa_value_ptr->GetOffset() - stack_offset;
1213 fa_value_ptr = &cfa_value;
1214 afa_value.SetUnspecified();
1218 current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
1222 else if (prologue_completed_row.get() &&
1241 (
sp.IsCFAPlusOffset() &&
sp.GetOffset() == 0 &&
1247 *newrow = *prologue_completed_row.get();
1249 current_sp_bytes_offset_from_fa =
1250 prologue_completed_sp_bytes_offset_from_cfa;
1251 is_aligned = prologue_completed_is_aligned;
1253 saved_registers.clear();
1254 saved_registers.resize(prologue_completed_saved_registers.size(),
false);
1255 for (
size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) {
1256 saved_registers[i] = prologue_completed_saved_registers[i];
1271 current_sp_bytes_offset_from_fa +=
m_wordsize;
1273 fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
1279 if (current_func_text_offset + insn_len < size) {
1280 row->SetOffset(current_func_text_offset + insn_len);
1284 *newrow = *row.get();
1289 if (!in_epilogue && row_updated) {
1292 *newrow = *row.get();
1293 prologue_completed_row.reset(newrow);
1295 prologue_completed_saved_registers.clear();
1296 prologue_completed_saved_registers.resize(saved_registers.size(),
false);
1297 for (
size_t i = 0; i < saved_registers.size(); ++i) {
1298 prologue_completed_saved_registers[i] = saved_registers[i];
1305 prologue_completed_sp_bytes_offset_from_cfa =
1306 current_sp_bytes_offset_from_fa;
1307 prologue_completed_is_aligned = is_aligned;
1311 current_func_text_offset += insn_len;
1324 UnwindPlan &unwind_plan, RegisterContextSP ®_ctx) {
1331 if (reg_ctx.get() ==
nullptr &&
1342 if (first_row->GetOffset() != 0)
1344 uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber();
1346 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1348 first_row->GetCFAValue().GetRegisterNumber());
1351 first_row->GetCFAValue().GetOffset() !=
m_wordsize)
1358 bool unwind_plan_updated =
false;
1364 bool reinstate_unwind_state =
false;
1366 while (offset < size) {
1382 if (reinstate_unwind_state) {
1384 *new_row = *original_last_row;
1385 new_row->SetOffset(offset);
1387 row = std::make_shared<UnwindPlan::Row>();
1389 reinstate_unwind_state =
false;
1390 unwind_plan_updated =
true;
1400 if (original_row->GetOffset() == offset) {
1401 *row = *original_row;
1412 cfa_reg = row->GetCFAValue().GetRegisterNumber();
1414 cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
1416 row->GetCFAValue().GetRegisterNumber());
1425 row->SetOffset(offset);
1430 unwind_plan_updated =
true;
1437 row->SetOffset(offset);
1442 unwind_plan_updated =
true;
1451 row->SetOffset(offset);
1456 unwind_plan_updated =
true;
1461 row->SetOffset(offset);
1466 unwind_plan_updated =
true;
1472 row->SetOffset(offset);
1476 unwind_plan_updated =
true;
1482 row->SetOffset(offset);
1486 unwind_plan_updated =
true;
1493 row->SetOffset(offset);
1494 row->GetCFAValue().IncOffset(-amount);
1498 unwind_plan_updated =
true;
1502 row->SetOffset(offset);
1503 row->GetCFAValue().IncOffset(amount);
1507 unwind_plan_updated =
true;
1513 row->SetOffset(offset);
1514 row->GetCFAValue().IncOffset(-amount);
1518 unwind_plan_updated =
true;
1523 reinstate_unwind_state =
true;
1535 row->SetOffset(offset);
1536 row->GetCFAValue().SetIsRegisterPlusOffset(
1537 first_row->GetCFAValue().GetRegisterNumber(),
m_wordsize);
1541 unwind_plan_updated =
true;
1542 reinstate_unwind_state =
true;
1556 if (unwind_plan_updated) {
1558 unwind_plan_source +=
" plus augmentation from assembly parsing";
1567 uint8_t *data,
size_t size,
size_t &offset) {
1573 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)
::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)
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.
@ kMaxInstructionByteSize
uint16_t extract_2(uint8_t *b)
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...
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.
@ eRegisterKindLLDB
lldb's internal register numbers
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)