summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/UnwindAssembly
diff options
context:
space:
mode:
authorAleksandr Urakov <aleksandr.urakov@jetbrains.com>2018-10-30 10:07:08 +0000
committerAleksandr Urakov <aleksandr.urakov@jetbrains.com>2018-10-30 10:07:08 +0000
commit4538ed3b85b1b77a1ca4cec1c1dc57a9a0d38fee (patch)
treef877beaa47a7988b191122369dea7b815e0e0784 /lldb/source/Plugins/UnwindAssembly
parentd62afe0063b0f98b40f60d2d1ccfae5efc4c99b0 (diff)
downloadbcm5719-llvm-4538ed3b85b1b77a1ca4cec1c1dc57a9a0d38fee.tar.gz
bcm5719-llvm-4538ed3b85b1b77a1ca4cec1c1dc57a9a0d38fee.zip
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary: This patch fixes issues with a stack realignment. MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one is used for access to function parameters, while another is used for access to locals. To support this the patch: - adds an alternative frame pointer (`ebx`); - considers stack realignment instructions (e.g. `and esp, -32`); - along with CFA (Canonical Frame Address) which point to the position next to the saved return address (or to the first parameter on the stack) introduces AFA (Aligned Frame Address) which points to the position of the stack pointer right after realignment. AFA is used for access to registers saved after the realignment (see the test); Here is an example of the code with the realignment: ``` struct __declspec(align(256)) OverAligned { char c; }; void foo(int foo_arg) { OverAligned oa_foo = { 1 }; auto aaa_foo = 1234; } void bar(int bar_arg) { OverAligned oa_bar = { 2 }; auto aaa_bar = 5678; foo(1111); } int main() { bar(2222); return 0; } ``` and here is the `bar` disassembly: ``` push ebx mov ebx, esp sub esp, 8 and esp, -100h add esp, 4 push ebp mov ebp, [ebx+4] mov [esp+4], ebp mov ebp, esp sub esp, 200h mov byte ptr [ebp-200h], 2 mov dword ptr [ebp-4], 5678 push 1111 ; foo_arg call j_?foo@@YAXH@Z ; foo(int) add esp, 4 mov esp, ebp pop ebp mov esp, ebx pop ebx retn ``` Reviewers: labath, zturner, jasonmolenda, stella.stamenova Reviewed By: jasonmolenda Subscribers: abidh, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D53435 llvm-svn: 345577
Diffstat (limited to 'lldb/source/Plugins/UnwindAssembly')
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp2
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp314
-rw-r--r--lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h7
3 files changed, 249 insertions, 74 deletions
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 327d0b0e4f7..9295a095353 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -92,7 +92,7 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
// assembly parsing instead.
if (first_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::isRegisterPlusOffset ||
+ UnwindPlan::Row::FAValue::isRegisterPlusOffset ||
RegisterNumber(thread, unwind_plan.GetRegisterKind(),
first_row->GetCFAValue().GetRegisterNumber()) !=
sp_regnum ||
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 10a56980594..eb1989895af 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -59,6 +59,7 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_machine_ip_regnum = k_machine_eip;
m_machine_sp_regnum = k_machine_esp;
m_machine_fp_regnum = k_machine_ebp;
+ m_machine_alt_fp_regnum = k_machine_ebx;
m_wordsize = 4;
struct lldb_reg_info reginfo;
@@ -84,6 +85,7 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_machine_ip_regnum = k_machine_rip;
m_machine_sp_regnum = k_machine_rsp;
m_machine_fp_regnum = k_machine_rbp;
+ m_machine_alt_fp_regnum = k_machine_rbx;
m_wordsize = 8;
struct lldb_reg_info reginfo;
@@ -135,6 +137,8 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_lldb_sp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
m_lldb_fp_regnum = lldb_regno;
+ if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+ m_lldb_alt_fp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
m_lldb_ip_regnum = lldb_regno;
@@ -160,6 +164,7 @@ void x86AssemblyInspectionEngine::Initialize(
m_machine_ip_regnum = k_machine_eip;
m_machine_sp_regnum = k_machine_esp;
m_machine_fp_regnum = k_machine_ebp;
+ m_machine_alt_fp_regnum = k_machine_ebx;
m_wordsize = 4;
struct lldb_reg_info reginfo;
@@ -185,6 +190,7 @@ void x86AssemblyInspectionEngine::Initialize(
m_machine_ip_regnum = k_machine_rip;
m_machine_sp_regnum = k_machine_rsp;
m_machine_fp_regnum = k_machine_rbp;
+ m_machine_alt_fp_regnum = k_machine_rbx;
m_wordsize = 8;
struct lldb_reg_info reginfo;
@@ -239,6 +245,8 @@ void x86AssemblyInspectionEngine::Initialize(
m_lldb_sp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
m_lldb_fp_regnum = lldb_regno;
+ if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+ m_lldb_alt_fp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
m_lldb_ip_regnum = lldb_regno;
@@ -387,6 +395,45 @@ bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
return false;
}
+// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
+// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
+bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xdc)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xe3)
+ return true;
+ return false;
+}
+
+// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
+// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
+bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xe5)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xec)
+ return true;
+ return false;
+}
+
+// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
+// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
+bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xe3)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xdc)
+ return true;
+ return false;
+}
+
// subq $0x20, %rsp
bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
uint8_t *p = m_cur_insn;
@@ -476,6 +523,46 @@ bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
return false;
}
+// lea -0x28(%ebx), %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+
+ // Check opcode
+ if (*p != 0x8d)
+ return false;
+ ++p;
+
+ // 8 bit displacement
+ if (*p == 0x63) {
+ amount = (int8_t)p[1];
+ return true;
+ }
+
+ // 32 bit displacement
+ if (*p == 0xa3) {
+ amount = (int32_t)extract_4(p + 1);
+ return true;
+ }
+
+ return false;
+}
+
+// and -0xfffffff0, %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+
+ if (*p != 0x81 && *p != 0x83)
+ return false;
+
+ return *++p == 0xe4;
+}
+
// popq %rbx
// popl %ebx
bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
@@ -640,7 +727,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
return false;
addr_t current_func_text_offset = 0;
- int current_sp_bytes_offset_from_cfa = 0;
+ int current_sp_bytes_offset_from_fa = 0;
+ bool is_aligned = false;
UnwindPlan::Row::RegisterLocation initial_regloc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -657,8 +745,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
// saved instruction pointer can be found at CFA - wordsize.
- current_sp_bytes_offset_from_cfa = m_wordsize;
- initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa = m_wordsize;
+ initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
unwind_plan.AppendRow(row);
@@ -682,6 +770,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
// epilogue started executed
+ bool prologue_completed_is_aligned;
std::vector<bool> prologue_completed_saved_registers;
while (current_func_text_offset < size) {
@@ -701,22 +790,59 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
break;
}
- if (push_rbp_pattern_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
- UnwindPlan::Row::RegisterLocation regloc;
- regloc.SetAtCFAPlusOffset(-row->GetCFAValue().GetOffset());
- row->SetRegisterInfo(m_lldb_fp_regnum, regloc);
- saved_registers[m_machine_fp_regnum] = true;
- row_updated = true;
+ auto &cfa_value = row->GetCFAValue();
+ auto &afa_value = row->GetAFAValue();
+ auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
+
+ if (mov_rsp_rbp_pattern_p()) {
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_fp_regnum, fa_value_ptr->GetOffset());
+ row_updated = true;
+ }
}
- else if (mov_rsp_rbp_pattern_p()) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_fp_regnum, row->GetCFAValue().GetOffset());
+ else if (mov_rsp_rbx_pattern_p()) {
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
+ row_updated = true;
+ }
+ }
+
+ else if (and_rsp_pattern_p()) {
+ current_sp_bytes_offset_from_fa = 0;
+ afa_value.SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+ fa_value_ptr = &afa_value;
+ is_aligned = true;
row_updated = true;
}
+ else if (mov_rbp_rsp_pattern_p()) {
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
+ else if (mov_rbx_rsp_pattern_p()) {
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
// This is the start() function (or a pthread equivalent), it starts with a
// pushl $0x0 which puts the saved pc value of 0 on the stack. In this
// case we want to pretend we didn't see a stack movement at all --
@@ -726,12 +852,12 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (push_reg_p(machine_regno)) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- // the PUSH instruction has moved the stack pointer - if the CFA is set
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ // the PUSH instruction has moved the stack pointer - if the FA is set
// in terms of the stack pointer, we need to add a new row of
// instructions.
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
// record where non-volatile (callee-saved, spilled) registers are saved
@@ -740,7 +866,10 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
saved_registers[machine_regno] == false) {
UnwindPlan::Row::RegisterLocation regloc;
- regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+ if (is_aligned)
+ regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
+ else
+ regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
row->SetRegisterInfo(lldb_regno, regloc);
saved_registers[machine_regno] = true;
row_updated = true;
@@ -748,7 +877,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (pop_reg_p(machine_regno)) {
- current_sp_bytes_offset_from_cfa -= m_wordsize;
+ current_sp_bytes_offset_from_fa -= m_wordsize;
if (nonvolatile_reg_p(machine_regno) &&
machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
@@ -756,29 +885,29 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
saved_registers[machine_regno] = false;
row->RemoveRegisterInfo(lldb_regno);
- if (machine_regno == (int)m_machine_fp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
+ if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, fa_value_ptr->GetOffset());
}
in_epilogue = true;
row_updated = true;
}
- // the POP instruction has moved the stack pointer - if the CFA is set in
+ // the POP instruction has moved the stack pointer - if the FA is set in
// terms of the stack pointer, we need to add a new row of instructions.
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (pop_misc_reg_p()) {
- current_sp_bytes_offset_from_cfa -= m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
@@ -787,24 +916,38 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// off the stack into rbp (restoring the caller's rbp value). It is the
// opposite of ENTER, or 'push rbp, mov rsp rbp'.
else if (leave_pattern_p()) {
- // We're going to copy the value in rbp into rsp, so re-set the sp offset
- // based on the CFAValue. Also, adjust it to recognize that we're
- // popping the saved rbp value off the stack.
- current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
- current_sp_bytes_offset_from_cfa -= m_wordsize;
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
-
- // rbp is restored to the caller's value
- saved_registers[m_machine_fp_regnum] = false;
- row->RemoveRegisterInfo(m_lldb_fp_regnum);
-
- // cfa is now in terms of rsp again.
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ if (saved_registers[m_machine_fp_regnum]) {
+ saved_registers[m_machine_fp_regnum] = false;
+ row->RemoveRegisterInfo(m_lldb_fp_regnum);
+
+ row_updated = true;
+ }
+
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, fa_value_ptr->GetOffset());
+
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
+ current_sp_bytes_offset_from_fa -= m_wordsize;
+
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+ row_updated = true;
+ }
in_epilogue = true;
- row_updated = true;
}
else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
@@ -816,12 +959,14 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::Row::RegisterLocation regloc;
// stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
- // want to express this as the offset from the CFA. If the frame base is
- // rbp (like the above instruction), the CFA offset for rbp is probably
- // 16. So we want to say that the value is stored at the CFA address -
+ // want to express this as the offset from the FA. If the frame base is
+ // rbp (like the above instruction), the FA offset for rbp is probably
+ // 16. So we want to say that the value is stored at the FA address -
// 96.
- regloc.SetAtCFAPlusOffset(
- -(stack_offset + row->GetCFAValue().GetOffset()));
+ if (is_aligned)
+ regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
+ else
+ regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
row->SetRegisterInfo(lldb_regno, regloc);
@@ -829,17 +974,17 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (sub_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa += stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (add_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa -= stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
in_epilogue = true;
@@ -847,27 +992,48 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
else if (push_extended_pattern_p() || push_imm_pattern_p() ||
push_misc_reg_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (lea_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa -= stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
if (stack_offset > 0)
in_epilogue = true;
}
- else if (lea_rbp_rsp_pattern_p(stack_offset) &&
- row->GetCFAValue().GetRegisterNumber() == m_lldb_fp_regnum) {
- current_sp_bytes_offset_from_cfa =
- row->GetCFAValue().GetOffset() - stack_offset;
+ else if (lea_rbp_rsp_pattern_p(stack_offset)) {
+ if (is_aligned &&
+ cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
+ current_sp_bytes_offset_from_fa =
+ fa_value_ptr->GetOffset() - stack_offset;
+ }
+ }
+
+ else if (lea_rbx_rsp_pattern_p(stack_offset)) {
+ if (is_aligned &&
+ cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
+ }
}
else if (ret_pattern_p() && prologue_completed_row.get()) {
@@ -877,8 +1043,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *prologue_completed_row.get();
row.reset(newrow);
- current_sp_bytes_offset_from_cfa =
+ current_sp_bytes_offset_from_fa =
prologue_completed_sp_bytes_offset_from_cfa;
+ is_aligned = prologue_completed_is_aligned;
saved_registers.clear();
saved_registers.resize(prologue_completed_saved_registers.size(), false);
@@ -896,9 +1063,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// This is used in i386 programs to get the PIC base address for finding
// global data
else if (call_next_insn_pattern_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
@@ -931,7 +1098,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// track of it either way.
if (in_epilogue == false) {
prologue_completed_sp_bytes_offset_from_cfa =
- current_sp_bytes_offset_from_cfa;
+ current_sp_bytes_offset_from_fa;
+ prologue_completed_is_aligned = is_aligned;
}
m_cur_insn = m_cur_insn + insn_len;
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index cec9803c8a4..e02b510ba1f 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -98,10 +98,15 @@ private:
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();
@@ -157,9 +162,11 @@ private:
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;
OpenPOWER on IntegriCloud