Author: jmolenda Date: Mon Oct 10 22:44:48 2016 New Revision: 283849 URL: http://llvm.org/viewvc/llvm-project?rev=283849&view=rev Log: Add a second, more complicated, arm64 example program to the arm64 assembly unwind tests.
Modified: lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp Modified: lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp?rev=283849&r1=283848&r2=283849&view=diff ============================================================================== --- lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp (original) +++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp Mon Oct 10 22:44:48 2016 @@ -56,7 +56,7 @@ static void terminate() { EmulateInstructionARM64::Terminate(); } -TEST_F(TestArm64InstEmulation, TestSimpleFunction) { +TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) { init(); @@ -64,16 +64,14 @@ TEST_F(TestArm64InstEmulation, TestSimpl UnwindAssemblyInstEmulation *engine = static_cast<UnwindAssemblyInstEmulation *>( UnwindAssemblyInstEmulation::CreateInstance(arch)); - EXPECT_TRUE(engine != nullptr); - if (engine == nullptr) - return; + ASSERT_NE(engine, nullptr); UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); UnwindPlan::Row::RegisterLocation regloc; - // 'int main() { }' compiled for arm64-apple-macosx with clang + // 'int main() { }' compiled for arm64-apple-ios with clang uint8_t data[] = { 0xfd, 0x7b, 0xbf, 0xa9, // 0xa9bf7bfd : stp x29, x30, [sp, #-0x10]! 0xfd, 0x03, 0x00, 0x91, // 0x910003fd : mov x29, sp @@ -92,12 +90,6 @@ TEST_F(TestArm64InstEmulation, TestSimpl // row[2]: 16: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] // row[3]: 20: CFA=sp +0 => fp= <same> lr= <same> - // But this is missing the setup of the frame pointer register (x29) and - // restore of the same. This is a bug in the instruction profiler -- - // it won't work if we have a stack frame with a variable length array, or - // an alloca style call where the stack frame size is not fixed. We need - // to recognize the setup of the frame pointer register. - sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( @@ -164,3 +156,169 @@ TEST_F(TestArm64InstEmulation, TestSimpl terminate(); } + +TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { + init(); + + ArchSpec arch("arm64-apple-ios10", nullptr); + UnwindAssemblyInstEmulation *engine = + static_cast<UnwindAssemblyInstEmulation *>( + UnwindAssemblyInstEmulation::CreateInstance(arch)); + ASSERT_NE(engine, nullptr); + + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + UnwindPlan::Row::RegisterLocation regloc; + + // disassembly of -[NSPlaceholderString initWithBytes:length:encoding:] + // from Foundation for iOS. + uint8_t data[] = { + 0xf6, 0x57, 0xbd, 0xa9, // 0: 0xa9bd57f6 stp x22, x21, [sp, #-48]! + 0xf4, 0x4f, 0x01, 0xa9, // 4: 0xa9014ff4 stp x20, x19, [sp, #16] + 0xfd, 0x7b, 0x02, 0xa9, // 8: 0xa9027bfd stp x29, x30, [sp, #32] + 0xfd, 0x83, 0x00, 0x91, // 12: 0x910083fd add x29, sp, #32 + 0xff, 0x43, 0x00, 0xd1, // 16: 0xd10043ff sub sp, sp, #16 + + // [... function body ...] + 0x1f, 0x20, 0x03, 0xd5, // 20: 0xd503201f nop + + 0xbf, 0x83, 0x00, 0xd1, // 24: 0xd10083bf sub sp, x29, #32 + 0xfd, 0x7b, 0x42, 0xa9, // 28: 0xa9427bfd ldp x29, x30, [sp, #32] + 0xf4, 0x4f, 0x41, 0xa9, // 32: 0xa9414ff4 ldp x20, x19, [sp, #16] + 0xf6, 0x57, 0xc3, 0xa8, // 36: 0xa8c357f6 ldp x22, x21, [sp], #48 + 0x01, 0x16, 0x09, 0x14, // 40: 0x14091601 b 0x18f640524 ; symbol stub + // for: CFStringCreateWithBytes + }; + + // UnwindPlan we expect: + // 0: CFA=sp +0 => + // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48] + // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // 12: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + // 16: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + + // [... function body ...] + + // 28: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + // 32: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] fp= + // <same> lr= <same> + // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp= + // <same> lr= <same> + // 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same> + // lr= <same> + + sample_range = AddressRange(0x1000, sizeof(data)); + + EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( + sample_range, data, sizeof(data), unwind_plan)); + + // 0: CFA=sp +0 => + row_sp = unwind_plan.GetRowForFunctionOffset(0); + EXPECT_EQ(0, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); + + // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48] + row_sp = unwind_plan.GetRowForFunctionOffset(4); + EXPECT_EQ(4, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-40, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-48, regloc.GetOffset()); + + // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + row_sp = unwind_plan.GetRowForFunctionOffset(8); + EXPECT_EQ(8, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-24, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-32, regloc.GetOffset()); + + // 12: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + row_sp = unwind_plan.GetRowForFunctionOffset(12); + EXPECT_EQ(12, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-16, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-8, regloc.GetOffset()); + + // 16: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + row_sp = unwind_plan.GetRowForFunctionOffset(16); + EXPECT_EQ(16, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + // 28: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] + // fp=[CFA-16] lr=[CFA-8] + row_sp = unwind_plan.GetRowForFunctionOffset(28); + EXPECT_EQ(28, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); + + // 32: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] fp= + // <same> lr= <same> + row_sp = unwind_plan.GetRowForFunctionOffset(32); + EXPECT_EQ(32, row_sp->GetOffset()); + + // I'd prefer if these restored registers were cleared entirely instead of set + // to IsSame... + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp= + // <same> lr= <same> + row_sp = unwind_plan.GetRowForFunctionOffset(36); + EXPECT_EQ(36, row_sp->GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + // 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same> + // lr= <same> + row_sp = unwind_plan.GetRowForFunctionOffset(40); + EXPECT_EQ(40, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(regloc.IsSame()); + + terminate(); +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits