UnwindAssemblyInstEmulation *engine =
static_cast<UnwindAssemblyInstEmulation *>(
UnwindAssemblyInstEmulation::CreateInstance(arch));
- ASSERT_NE(engine, nullptr);
+ ASSERT_NE(nullptr, engine);
UnwindPlan::RowSP row_sp;
AddressRange sample_range;
UnwindAssemblyInstEmulation *engine =
static_cast<UnwindAssemblyInstEmulation *>(
UnwindAssemblyInstEmulation::CreateInstance(arch));
- ASSERT_NE(engine, nullptr);
+ ASSERT_NE(nullptr, engine);
UnwindPlan::RowSP row_sp;
AddressRange sample_range;
EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc));
EXPECT_TRUE(regloc.IsSame());
}
+
+TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) {
+ ArchSpec arch("arm64-apple-ios10", nullptr);
+ UnwindAssemblyInstEmulation *engine =
+ static_cast<UnwindAssemblyInstEmulation *>(
+ UnwindAssemblyInstEmulation::CreateInstance(arch));
+ ASSERT_NE(nullptr, engine);
+
+ UnwindPlan::RowSP row_sp;
+ AddressRange sample_range;
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ UnwindPlan::Row::RegisterLocation regloc;
+
+ // disassembly of JSC::ARM64LogicalImmediate::findBitRange<16u>
+ // from JavaScriptcore for iOS.
+ uint8_t data[] = {
+ 0x08, 0x3c, 0x0f, 0x53, // 0: 0x530f3c08 ubfx w8, w0, #15, #1
+ 0x68, 0x00, 0x00, 0x39, // 4: 0x39000068 strb w8, [x3]
+ 0x08, 0x3c, 0x40, 0xd2, // 8: 0xd2403c08 eor x8, x0, #0xffff
+ 0x1f, 0x00, 0x71, 0xf2, // 12: 0xf271001f tst x0, #0x8000
+
+ // [...]
+
+ 0x3f, 0x01, 0x0c, 0xeb, // 16: 0xeb0c013f cmp x9, x12
+ 0x81, 0x00, 0x00, 0x54, // 20: 0x54000081 b.ne +34
+ 0x5f, 0x00, 0x00, 0xb9, // 24: 0xb900005f str wzr, [x2]
+ 0xe0, 0x03, 0x00, 0x32, // 28: 0x320003e0 orr w0, wzr, #0x1
+ 0xc0, 0x03, 0x5f, 0xd6, // 32: 0xd65f03c0 ret
+ 0x89, 0x01, 0x09, 0xca, // 36: 0xca090189 eor x9, x12, x9
+
+ // [...]
+
+ 0x08, 0x05, 0x00, 0x11, // 40: 0x11000508 add w8, w8, #0x1
+ 0x48, 0x00, 0x00, 0xb9, // 44: 0xb9000048 str w8, [x2]
+ 0xe0, 0x03, 0x00, 0x32, // 48: 0x320003e0 orr w0, wzr, #0x1
+ 0xc0, 0x03, 0x5f, 0xd6, // 52: 0xd65f03c0 ret
+ 0x00, 0x00, 0x80, 0x52, // 56: 0x52800000 mov w0, #0x0
+ 0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0 ret
+
+ };
+
+ // UnwindPlan we expect:
+ // 0: CFA=sp +0 =>
+ // (possibly with additional rows at offsets 36 and 56 saying the same thing)
+
+ 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());
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(32);
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x23, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x24, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x25, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x26, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x27, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x28, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+ EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(36);
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(52);
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(56);
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(60);
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+}
+
+