@@ -856,3 +856,111 @@ TEST_F(TestArm64InstEmulation, TestCFAResetToSP) {
856856 EXPECT_TRUE (row->GetCFAValue ().GetRegisterNumber () == gpr_sp_arm64);
857857 EXPECT_TRUE (row->GetCFAValue ().IsRegisterPlusOffset () == true );
858858}
859+
860+ TEST_F (TestArm64InstEmulation, TestPrologueStartsWithStrD8) {
861+ ArchSpec arch (" aarch64" );
862+ std::unique_ptr<UnwindAssemblyInstEmulation> engine (
863+ static_cast <UnwindAssemblyInstEmulation *>(
864+ UnwindAssemblyInstEmulation::CreateInstance (arch)));
865+ ASSERT_NE (nullptr , engine);
866+
867+ const UnwindPlan::Row *row;
868+ AddressRange sample_range;
869+ UnwindPlan unwind_plan (eRegisterKindLLDB);
870+ UnwindPlan::Row::AbstractRegisterLocation regloc;
871+
872+ // The sample function is built with 'clang --target aarch64 -O1':
873+ //
874+ // int bar(float x);
875+ // int foo(float x) {
876+ // return bar(x) + bar(x);
877+ // }
878+ //
879+ // The function uses one floating point register and spills it with
880+ // 'str d8, [sp, #-0x20]!'.
881+
882+ // clang-format off
883+ uint8_t data[] = {
884+ // prologue
885+ 0xe8 , 0x0f , 0x1e , 0xfc , // 0: fc1e0fe8 str d8, [sp, #-0x20]!
886+ 0xfd , 0xfb , 0x00 , 0xa9 , // 4: a900fbfd stp x29, x30, [sp, #0x8]
887+ 0xf3 , 0x0f , 0x00 , 0xf9 , // 8: f9000ff3 str x19, [sp, #0x18]
888+ 0xfd , 0x23 , 0x00 , 0x91 , // 12: 910023fd add x29, sp, #0x8
889+
890+ // epilogue
891+ 0xfd , 0xfb , 0x40 , 0xa9 , // 16: a940fbfd ldp x29, x30, [sp, #0x8]
892+ 0xf3 , 0x0f , 0x40 , 0xf9 , // 20: f9400ff3 ldr x19, [sp, #0x18]
893+ 0xe8 , 0x07 , 0x42 , 0xfc , // 24: fc4207e8 ldr d8, [sp], #0x20
894+ 0xc0 , 0x03 , 0x5f , 0xd6 , // 28: d65f03c0 ret
895+ };
896+ // clang-format on
897+
898+ // UnwindPlan we expect:
899+ // 0: CFA=sp +0 =>
900+ // 4: CFA=sp+32 => d8=[CFA-32]
901+ // 8: CFA=sp+32 => fp=[CFA-24] lr=[CFA-16] d8=[CFA-32]
902+ // 12: CFA=sp+32 => x19=[CFA-8] fp=[CFA-24] lr=[CFA-16] d8=[CFA-32]
903+ // 16: CFA=fp+24 => x19=[CFA-8] fp=[CFA-24] lr=[CFA-16] d8=[CFA-32]
904+ // 20: CFA=sp+32 => x19=[CFA-8] fp=<same> lr=<same> d8=[CFA-32]
905+ // 24: CFA=sp+32 => x19=<same> fp=<same> lr=<same> d8=[CFA-32]
906+ // 28: CFA=sp +0 => x19=<same> fp=<same> lr=<same> d8=<same>
907+
908+ sample_range = AddressRange (0x1000 , sizeof (data));
909+
910+ EXPECT_TRUE (engine->GetNonCallSiteUnwindPlanFromAssembly (
911+ sample_range, data, sizeof (data), unwind_plan));
912+
913+ // 4: CFA=sp+32 => d8=[CFA-32]
914+ row = unwind_plan.GetRowForFunctionOffset (4 );
915+ EXPECT_EQ (4 , row->GetOffset ());
916+ EXPECT_TRUE (row->GetCFAValue ().GetRegisterNumber () == gpr_sp_arm64);
917+ EXPECT_TRUE (row->GetCFAValue ().IsRegisterPlusOffset () == true );
918+ EXPECT_EQ (32 , row->GetCFAValue ().GetOffset ());
919+
920+ EXPECT_TRUE (row->GetRegisterInfo (fpu_d8_arm64, regloc));
921+ EXPECT_TRUE (regloc.IsAtCFAPlusOffset ());
922+ EXPECT_EQ (-32 , regloc.GetOffset ());
923+
924+ // 16: CFA=fp+24 => x19=[CFA-8] fp=[CFA-24] lr=[CFA-16] d8=[CFA-32]
925+ row = unwind_plan.GetRowForFunctionOffset (16 );
926+ EXPECT_EQ (16 , row->GetOffset ());
927+ EXPECT_TRUE (row->GetCFAValue ().GetRegisterNumber () == gpr_fp_arm64);
928+ EXPECT_TRUE (row->GetCFAValue ().IsRegisterPlusOffset () == true );
929+ EXPECT_EQ (24 , row->GetCFAValue ().GetOffset ());
930+
931+ EXPECT_TRUE (row->GetRegisterInfo (gpr_x19_arm64, regloc));
932+ EXPECT_TRUE (regloc.IsAtCFAPlusOffset ());
933+ EXPECT_EQ (-8 , regloc.GetOffset ());
934+
935+ EXPECT_TRUE (row->GetRegisterInfo (gpr_fp_arm64, regloc));
936+ EXPECT_TRUE (regloc.IsAtCFAPlusOffset ());
937+ EXPECT_EQ (-24 , regloc.GetOffset ());
938+
939+ EXPECT_TRUE (row->GetRegisterInfo (gpr_lr_arm64, regloc));
940+ EXPECT_TRUE (regloc.IsAtCFAPlusOffset ());
941+ EXPECT_EQ (-16 , regloc.GetOffset ());
942+
943+ EXPECT_TRUE (row->GetRegisterInfo (fpu_d8_arm64, regloc));
944+ EXPECT_TRUE (regloc.IsAtCFAPlusOffset ());
945+ EXPECT_EQ (-32 , regloc.GetOffset ());
946+
947+ // 28: CFA=sp +0 => x19=<same> fp=<same> lr=<same> d8=<same>
948+ row = unwind_plan.GetRowForFunctionOffset (28 );
949+ EXPECT_EQ (28 , row->GetOffset ());
950+ EXPECT_TRUE (row->GetCFAValue ().GetRegisterNumber () == gpr_sp_arm64);
951+ EXPECT_TRUE (row->GetCFAValue ().IsRegisterPlusOffset () == true );
952+ EXPECT_EQ (0 , row->GetCFAValue ().GetOffset ());
953+
954+ if (row->GetRegisterInfo (gpr_x19_arm64, regloc)) {
955+ EXPECT_TRUE (regloc.IsSame ());
956+ }
957+ if (row->GetRegisterInfo (gpr_fp_arm64, regloc)) {
958+ EXPECT_TRUE (regloc.IsSame ());
959+ }
960+ if (row->GetRegisterInfo (gpr_lr_arm64, regloc)) {
961+ EXPECT_TRUE (regloc.IsSame ());
962+ }
963+ if (row->GetRegisterInfo (fpu_d8_arm64, regloc)) {
964+ EXPECT_TRUE (regloc.IsSame ());
965+ }
966+ }
0 commit comments