From 56f0497bb869338dc1e4868b634f98be83ace483 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Sat, 1 Oct 2016 04:50:25 +0000 Subject: [PATCH] Add unit tests for specific instruction patterns that the x86 assembly inspection class is designed to detect. This is only about half of the instructions that it needs to recognize - I'll complete this in a separate checkin. The larger full-function style test cases I'd checked in previously covered nearly all of these already, but I wanted simpler test cases too, so if they fail in the future, it will be easier to spot the issue. llvm-svn: 283010 --- .../x86/Testx86AssemblyInspectionEngine.cpp | 519 ++++++++++++++++++ 1 file changed, 519 insertions(+) diff --git a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp index 17c1dde19831..2f610e98bfb8 100644 --- a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp +++ b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp @@ -952,3 +952,522 @@ TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessSmallStackFrame) { EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); } + +TEST_F(Testx86AssemblyInspectionEngine, TestPushRBP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x55, // pushq $rbp + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(1); + + EXPECT_EQ(1, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); + + std::unique_ptr engine32 = Geti386Inspector(); + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(1); + + EXPECT_EQ(1, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-8, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushImm) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x68, 0xff, 0xff, 0x01, 0x69, // pushq $0x6901ffff + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(5); + + EXPECT_EQ(5, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + std::unique_ptr engine32 = Geti386Inspector(); + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(5); + + EXPECT_EQ(5, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); +} + +// We treat 'pushq $0' / 'pushl $0' specially - this shows up +// in the first function called in a new thread and it needs to +// put a 0 as the saved pc. We pretend it didn't change the CFA. +TEST_F(Testx86AssemblyInspectionEngine, TestPush0) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x6a, 0x00, // pushq $0 + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + // We're verifying that no row was created for the 'pushq $0' + EXPECT_EQ(0, row_sp->GetOffset()); + + std::unique_ptr engine32 = Geti386Inspector(); + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + // We're verifying that no row was created for the 'pushq $0' + EXPECT_EQ(0, row_sp->GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushExtended) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0xff, 0x74, 0x24, 0x20, // pushl 0x20(%esp) + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(4); + + EXPECT_EQ(4, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + std::unique_ptr engine32 = Geti386Inspector(); + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(4); + + EXPECT_EQ(4, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushR15) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x41, 0x57, // pushq %r15 + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushR14) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x41, 0x56, // pushq %r14 + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushR13) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x41, 0x55, // pushq %r13 + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushR12) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x41, 0x54, // pushq %r13 + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestPushRBX) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data[] = { + 0x53, // pushq %rbx + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(1); + + EXPECT_EQ(1, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestMovRSPtoRBP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + + uint8_t data64_1[] = { + 0x48, 0x8b, 0xec, // movq %rsp, %rbp + 0x90 // nop + }; + + AddressRange sample_range(0x1000, sizeof(data64_1)); + UnwindPlan unwind_plan(eRegisterKindLLDB); + + std::unique_ptr engine64 = Getx86_64Inspector(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data64_1, sizeof(data64_1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(3); + + EXPECT_EQ(3, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); + + uint8_t data64_2[] = { + 0x48, 0x89, 0xe5, // movq %rsp, %rbp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data64_2)); + unwind_plan.Clear(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data64_2, sizeof(data64_2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(3); + EXPECT_EQ(3, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); + + uint8_t data32_1[] = { + 0x8b, 0xec, // movl %rsp, %rbp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data32_1)); + unwind_plan.Clear(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data32_1, sizeof(data32_1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); + + uint8_t data32_2[] = { + 0x89, 0xe5, // movl %rsp, %rbp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data32_2)); + unwind_plan.Clear(); + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data32_2, sizeof(data32_2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(2); + EXPECT_EQ(2, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestSubRSP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr engine64 = Getx86_64Inspector(); + + uint8_t data1[] = { + 0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $0x100, $rsp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data1)); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data1, sizeof(data1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(7); + EXPECT_EQ(7, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(264, row_sp->GetCFAValue().GetOffset()); + + uint8_t data2[] = { + 0x48, 0x83, 0xec, 0x10, // subq $0x10, %rsp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data2)); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data2, sizeof(data2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(4); + EXPECT_EQ(4, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(24, row_sp->GetCFAValue().GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestSubESP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr engine32 = Geti386Inspector(); + + uint8_t data1[] = { + 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $0x100, $esp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data1)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data1, sizeof(data1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(6); + EXPECT_EQ(6, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(260, row_sp->GetCFAValue().GetOffset()); + + uint8_t data2[] = { + 0x83, 0xec, 0x10, // subq $0x10, %esp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data2)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data2, sizeof(data2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(3); + EXPECT_EQ(3, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestAddRSP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr engine64 = Getx86_64Inspector(); + + uint8_t data1[] = { + 0x48, 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addq $0x100, %rsp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data1)); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data1, sizeof(data1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(7); + EXPECT_EQ(7, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8 - 256, row_sp->GetCFAValue().GetOffset()); + + uint8_t data2[] = { + 0x48, 0x83, 0xc4, 0x10, // addq $0x10, %rsp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data2)); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data2, sizeof(data2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(4); + EXPECT_EQ(4, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(8 - 16, row_sp->GetCFAValue().GetOffset()); +} + +TEST_F(Testx86AssemblyInspectionEngine, TestAddESP) { + UnwindPlan::Row::RegisterLocation regloc; + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr engine32 = Geti386Inspector(); + + uint8_t data1[] = { + 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addq $0x100, %esp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data1)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data1, sizeof(data1), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(6); + EXPECT_EQ(6, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(4 - 256, row_sp->GetCFAValue().GetOffset()); + + uint8_t data2[] = { + 0x83, 0xc4, 0x10, // addq $0x10, %esp + 0x90 // nop + }; + + sample_range = AddressRange(0x1000, sizeof(data2)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data2, sizeof(data2), sample_range, unwind_plan)); + + row_sp = unwind_plan.GetRowForFunctionOffset(3); + EXPECT_EQ(3, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(4 - 16, row_sp->GetCFAValue().GetOffset()); +}