Add a second, more complicated, arm64 example program to

the arm64 assembly unwind tests.

llvm-svn: 283849
This commit is contained in:
Jason Molenda 2016-10-11 03:44:48 +00:00
parent 74ad41c7cd
commit 086a78cf23
1 changed files with 169 additions and 11 deletions
lldb/unittests/UnwindAssembly/InstEmulation

View File

@ -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, TestSimpleFunction) {
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, TestSimpleFunction) {
// 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, TestSimpleFunction) {
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();
}