[Lldb-commits] [lldb] r282991 - Add support for some extended push instructions in i386/x86_64 like
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Fri Sep 30 17:19:27 PDT 2016
Author: jmolenda
Date: Fri Sep 30 19:19:26 2016
New Revision: 282991
URL: http://llvm.org/viewvc/llvm-project?rev=282991&view=rev
Log:
Add support for some extended push instructions in i386/x86_64 like
'push 0x20(%esp)' which clang can generate when emitting
-fomit-frame-pointer code for 32-bit.
Add a unit test program which includes this instruction.
Also fix a bug in the refactoring/rewrite of the x86 assembly
instruction profiler where I'd hard coded it as a 64-bit disassembler
instead of using the ArchSpec to pick a 32-bit or 64-bit disassembler
from llvm. When the disassembler would hit an instruction
that is invalid in 64-bit mode, it would stop disassembling the function.
This likely led to the TestSBData testsuite failure on linux with 32-bit
i386 and gcc-4.9; I'll test that in a bit.
The newly added unit test program is 32-bit i386 code and it includes
an instruction which is invalid in 64-bit mode so it will catch this.
<rdar://problem/28557876>
Modified:
lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp?rev=282991&r1=282990&r2=282991&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp Fri Sep 30 19:19:26 2016
@@ -29,10 +29,9 @@ x86AssemblyInspectionEngine::x86Assembly
m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1),
m_register_map_initialized(false), m_disasm_context() {
- m_disasm_context = ::LLVMCreateDisasm("x86_64-apple-macosx", nullptr,
- /*TagType=*/1, nullptr, nullptr);
- // ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr,
- // /*TagType=*/1, nullptr, nullptr);
+ m_disasm_context =
+ ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr,
+ /*TagType=*/1, nullptr, nullptr);
}
x86AssemblyInspectionEngine::~x86AssemblyInspectionEngine() {
@@ -320,6 +319,50 @@ bool x86AssemblyInspectionEngine::push_i
return false;
}
+// pushl imm8(%esp)
+//
+// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)'
+// (same byte pattern for 'pushq 0x20(%rsp)' in an x86_64 program)
+//
+// 0xff (with opcode bits '6' in next byte, PUSH r/m32)
+// 0x74 (ModR/M byte with three bits used to specify the opcode)
+// mod == b01, opcode == b110, R/M == b100
+// "+disp8"
+// 0x24 (SIB byte - scaled index = 0, r32 == esp)
+// 0x20 imm8 value
+
+bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
+ if (*m_cur_insn == 0xff) {
+ // Get the 3 opcode bits from the ModR/M byte
+ uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
+ if (opcode == 6) {
+ // I'm only looking for 0xff /6 here - I
+ // don't really care what value is being pushed,
+ // just that we're pushing a 32/64 bit value on
+ // to the stack is enough.
+ return true;
+ }
+ }
+ return false;
+}
+
+// pushq %rbx
+// pushl %ebx
+bool x86AssemblyInspectionEngine::push_reg_p(int ®no) {
+ uint8_t *p = m_cur_insn;
+ int regno_prefix_bit = 0;
+ // If we have a rex prefix byte, check to see if a B bit is set
+ if (m_wordsize == 8 && *p == 0x41) {
+ regno_prefix_bit = 1 << 3;
+ p++;
+ }
+ if (*p >= 0x50 && *p <= 0x57) {
+ regno = (*p - 0x50) | regno_prefix_bit;
+ return true;
+ }
+ return false;
+}
+
// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
@@ -395,23 +438,6 @@ bool x86AssemblyInspectionEngine::lea_rs
return false;
}
-// pushq %rbx
-// pushl %ebx
-bool x86AssemblyInspectionEngine::push_reg_p(int ®no) {
- uint8_t *p = m_cur_insn;
- int regno_prefix_bit = 0;
- // If we have a rex prefix byte, check to see if a B bit is set
- if (m_wordsize == 8 && *p == 0x41) {
- regno_prefix_bit = 1 << 3;
- p++;
- }
- if (*p >= 0x50 && *p <= 0x57) {
- regno = (*p - 0x50) | regno_prefix_bit;
- return true;
- }
- return false;
-}
-
// popq %rbx
// popl %ebx
bool x86AssemblyInspectionEngine::pop_reg_p(int ®no) {
@@ -762,6 +788,14 @@ bool x86AssemblyInspectionEngine::GetNon
in_epilogue = true;
}
+ else if (push_extended_pattern_p() || push_imm_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);
+ 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) {
@@ -1002,6 +1036,16 @@ bool x86AssemblyInspectionEngine::Augmen
continue;
}
+ // push extended
+ if (push_extended_pattern_p()) {
+ row->SetOffset(offset);
+ row->GetCFAValue().IncOffset(m_wordsize);
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow(new_row);
+ unwind_plan_updated = true;
+ continue;
+ }
+
// add/sub %rsp/%esp
int amount;
if (add_rsp_pattern_p(amount)) {
@@ -1045,16 +1089,16 @@ bool x86AssemblyInspectionEngine::Augmen
// [0x5d] pop %rbp/%ebp
// => [0xc3] ret
if (pop_rbp_pattern_p() || leave_pattern_p()) {
- offset += 1;
- row->SetOffset(offset);
- row->GetCFAValue().SetIsRegisterPlusOffset(
- first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
+ offset += 1;
+ row->SetOffset(offset);
+ row->GetCFAValue().SetIsRegisterPlusOffset(
+ first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
- UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
- unwind_plan.InsertRow(new_row);
- unwind_plan_updated = true;
- reinstate_unwind_state = true;
- continue;
+ UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
+ unwind_plan.InsertRow(new_row);
+ unwind_plan_updated = true;
+ reinstate_unwind_state = true;
+ continue;
}
} else {
// CFA register is not sp or fp.
Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h?rev=282991&r1=282990&r2=282991&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h Fri Sep 30 19:19:26 2016
@@ -96,6 +96,7 @@ private:
bool push_rbp_pattern_p();
bool push_0_pattern_p();
bool push_imm_pattern_p();
+ bool push_extended_pattern_p();
bool mov_rsp_rbp_pattern_p();
bool sub_rsp_pattern_p(int &amount);
bool add_rsp_pattern_p(int &amount);
Modified: lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp?rev=282991&r1=282990&r2=282991&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp (original)
+++ lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp Fri Sep 30 19:19:26 2016
@@ -447,9 +447,304 @@ TEST_F(Testx86AssemblyInspectionEngine,
EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc));
EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc));
-
}
+TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessBigStackFrame) {
+ std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
+
+ // this source file:
+ //
+ // #include <stdio.h>
+ // int main (int argc, char **argv)
+ // {
+ //
+ // const int arrsize = 60;
+ // int buf[arrsize * arrsize];
+ // int accum = argc;
+ // for (int i = 0; i < arrsize; i++)
+ // for (int j = 0; j < arrsize; j++)
+ // {
+ // if (i > 0 && j > 0)
+ // {
+ // int n = buf[(i-1) * (j-1)] * 2;
+ // int m = buf[(i-1) * (j-1)] / 2;
+ // int j = buf[(i-1) * (j-1)] + 2;
+ // int k = buf[(i-1) * (j-1)] - 2;
+ // printf ("%d ", n + m + j + k);
+ // buf[(i-1) * (j-1)] += n - m + j - k;
+ // }
+ // buf[i*j] = accum++;
+ // }
+ //
+ // return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *
+ // arrsize) - 3]);
+ // }
+ //
+ // compiled 'clang -arch i386 -fomit-frame-pointer -Os' for i386-apple-macosx
+
+ // simplified assembly version of the above function, which is used as the
+ // input
+ // data:
+ //
+ // .section __TEXT,__text,regular,pure_instructions
+ // .macosx_version_min 10, 12
+ // .globl _main
+ // .align 4, 0x90
+ // _main: ## @main
+ // ## BB#0:
+ // pushl %ebp
+ // pushl %ebx
+ // pushl %edi
+ // pushl %esi
+ // L0$pb:
+ // subl $0x386c, %esp
+ // calll L1
+ // L1:
+ // popl %ecx
+ // movl %ecx, 0x8(%esp)
+ // subl $0x8, %esp
+ // pushl %eax
+ // pushl 0x20(%esp)
+ // calll _puts
+ // addl $0x10, %esp
+ // incl %ebx
+ // addl $0x386c, %esp
+ // popl %esi
+ // popl %edi
+ // popl %ebx
+ // popl %ebp
+ // retl
+ //
+ // .section __TEXT,__cstring,cstring_literals
+ // L_.str: ## @.str
+ // .asciz "HI"
+ //
+ //
+ // .subsections_via_symbols
+
+ uint8_t data[] = {
+ 0x55,
+ // offset 0 -- pushl %ebp
+
+ 0x53,
+ // offset 1 -- pushl %ebx
+
+ 0x57,
+ // offset 2 -- pushl %edi
+
+ 0x56,
+ // offset 3 -- pushl %esi
+
+ 0x81, 0xec, 0x6c, 0x38, 0x00, 0x00,
+ // offset 4 -- subl $0x386c, %esp
+
+ 0xe8, 0x00, 0x00, 0x00, 0x00,
+ // offset 10 -- calll 0
+ // call the next instruction, to put the pc on the stack
+
+ 0x59,
+ // offset 15 -- popl %ecx
+ // pop the saved pc address into ecx
+
+ 0x89, 0x4c, 0x24, 0x08,
+ // offset 16 -- movl %ecx, 0x8(%esp)
+
+ // ....
+
+ 0x83, 0xec, 0x08,
+ // offset 20 -- subl $0x8, %esp
+
+ 0x50,
+ // offset 23 -- pushl %eax
+
+ 0xff, 0x74, 0x24, 0x20,
+ // offset 24 -- pushl 0x20(%esp)
+
+ 0xe8, 0x8c, 0x00, 0x00, 0x00,
+ // offset 28 -- calll puts
+
+ 0x83, 0xc4, 0x10,
+ // offset 33 -- addl $0x10, %esp
+ // get esp back to the value it was before the
+ // alignment & argument saves for the puts call
+
+ 0x43,
+ // offset 36 -- incl %ebx
+
+ // ....
+
+ 0x81, 0xc4, 0x6c, 0x38, 0x00, 0x00,
+ // offset 37 -- addl $0x386c, %esp
+
+ 0x5e,
+ // offset 43 -- popl %esi
+
+ 0x5f,
+ // offset 44 -- popl %edi
+
+ 0x5b,
+ // offset 45 -- popl %ebx
+
+ 0x5d,
+ // offset 46 -- popl %ebp
+
+ 0xc3,
+ // offset 47 -- retl
+
+ 0xe8, 0x12, 0x34, 0x56, 0x78,
+ // offset 48 -- calll __stack_chk_fail
+ };
+
+ AddressRange sample_range(0x1000, sizeof(data));
+
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+
+ // Unwind rules should look like
+ //
+ // 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
+ // 2: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
+ // 3: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0
+ // eip=[CFA-4]
+ // 4: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 10: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ //
+ // ....
+ //
+ // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ //
+ // .....
+ //
+ // 37: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 43: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ // 44: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0
+ // eip=[CFA-4]
+ // 45: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
+ // 46: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
+ // 47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ // 48: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+
+ UnwindPlan::Row::RegisterLocation regloc;
+ UnwindPlan::RowSP row_sp;
+
+ // Check that we get the CFA correct for the pic base setup sequence
+
+ // CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(10);
+ EXPECT_EQ(10, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
+
+ // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(15);
+ EXPECT_EQ(15, row_sp->GetOffset());
+ EXPECT_EQ(14468, row_sp->GetCFAValue().GetOffset());
+
+ // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(16);
+ EXPECT_EQ(16, row_sp->GetOffset());
+ EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
+
+ // Check that the row for offset 16 has the registers saved that we expect
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-4, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-12, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_edi, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-16, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-20, regloc.GetOffset());
+
+ //
+ // Check the pushing & popping around the call printf instruction
+
+ // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(23);
+ EXPECT_EQ(23, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(14472, row_sp->GetCFAValue().GetOffset());
+
+ // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(24);
+ EXPECT_EQ(24, row_sp->GetOffset());
+ EXPECT_EQ(14476, row_sp->GetCFAValue().GetOffset());
+
+ // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(28);
+ EXPECT_EQ(28, row_sp->GetOffset());
+ EXPECT_EQ(14480, row_sp->GetCFAValue().GetOffset());
+
+ // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8]
+ // esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(36);
+ EXPECT_EQ(36, row_sp->GetOffset());
+ EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset());
+
+ // Check that the epilogue gets us back to the original unwind state
+
+ // 47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ row_sp = unwind_plan.GetRowForFunctionOffset(47);
+ EXPECT_EQ(47, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-4, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(k_esp, regloc));
+ EXPECT_TRUE(regloc.IsCFAPlusOffset());
+ EXPECT_EQ(0, regloc.GetOffset());
+
+ // Check that no unexpected registers were saved
+
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
+}
TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessSmallStackFrame) {
std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
@@ -463,18 +758,18 @@ TEST_F(Testx86AssemblyInspectionEngine,
// compiled 'clang -fomit-frame-pointer' for x86_64-apple-macosx
uint8_t data[] = {
- 0x50,
+ 0x50,
// offset 0 -- pushq %rax
- 0x48, 0x8d, 0x3d, 0x32, 0x00, 0x00, 0x00,
+ 0x48, 0x8d, 0x3d, 0x32, 0x00, 0x00, 0x00,
// offset 1 -- leaq 0x32(%rip), %rdi ; "HI"
- 0xe8, 0x0b, 0x00, 0x00, 0x00,
+ 0xe8, 0x0b, 0x00, 0x00, 0x00,
// offset 8 -- callq 0x100000f58 ; puts
0x31, 0xc9,
// offset 13 -- xorl %ecx, %ecx
-
+
0x89, 0x44, 0x24, 0x04,
// offset 15 -- movl %eax, 0x4(%rsp)
@@ -495,14 +790,14 @@ TEST_F(Testx86AssemblyInspectionEngine,
data, sizeof(data), sample_range, unwind_plan));
// Unwind rules should look like
- // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
- // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
- // 22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
+ // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
+ // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
+ // 22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
UnwindPlan::Row::RegisterLocation regloc;
// grab the Row for when the prologue has finished executing:
- // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
+ // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8]
UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(13);
@@ -548,7 +843,6 @@ TEST_F(Testx86AssemblyInspectionEngine,
EXPECT_EQ(-8, regloc.GetOffset());
}
-
TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessSmallStackFrame) {
std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
@@ -563,7 +857,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
uint8_t data[] = {
0x83, 0xec, 0x0c,
// offset 0 -- subl $0xc, %esp
-
+
0xe8, 0x00, 0x00, 0x00, 0x00,
// offset 3 -- calll 0 {call the next instruction, to put the pc on
// the stack}
@@ -603,11 +897,11 @@ TEST_F(Testx86AssemblyInspectionEngine,
data, sizeof(data), sample_range, unwind_plan));
// Unwind rules should look like
- // row[0]: 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
- // row[1]: 3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
- // row[2]: 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]
- // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
- // row[4]: 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ // row[0]: 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ // row[1]: 3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
+ // row[2]: 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4]
+ // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
+ // row[4]: 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
UnwindPlan::Row::RegisterLocation regloc;
@@ -631,7 +925,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset());
// Check unwind state after we pop the pic base value off the stack
- // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
+ // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4]
row_sp = unwind_plan.GetRowForFunctionOffset(9);
EXPECT_EQ(9, row_sp->GetOffset());
@@ -650,7 +944,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc));
// verify that we get back to the original unwind state before the ret
- // 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
+ // 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
row_sp = unwind_plan.GetRowForFunctionOffset(34);
EXPECT_EQ(34, row_sp->GetOffset());
More information about the lldb-commits
mailing list