diff options
| author | Jason Molenda <jmolenda@apple.com> | 2016-11-01 01:26:54 +0000 |
|---|---|---|
| committer | Jason Molenda <jmolenda@apple.com> | 2016-11-01 01:26:54 +0000 |
| commit | e322332a096aa2c1862a1c25239e3ec2dfc9346a (patch) | |
| tree | 683a7832863063bbe60830f2104b40c9b4eb7750 /lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp | |
| parent | a1a77f3a21f8d94300fb6c9df503cb45279a8fb3 (diff) | |
| download | bcm5719-llvm-e322332a096aa2c1862a1c25239e3ec2dfc9346a.tar.gz bcm5719-llvm-e322332a096aa2c1862a1c25239e3ec2dfc9346a.zip | |
Fix a bug where the EmulateInstructionARM64 handling of STP/LDP instructions
for floating point registers was not recording them correctly. I needed to
change the EmulateInstructionARM64 unwind plans from using the DWARF
register numbering scheme to using the LLDB register numbering scheme
(because dwarf doesn't define register numbers for the 64-bit "d" registers).
Updated the EmulateInstructionARM64 unit tests to work with the LLDB
register numbering scheme and added a unit test to check the floating
point register spills & restores are correctly recorded.
https://reviews.llvm.org/D25864
<rdar://problem/28745483>
llvm-svn: 285662
Diffstat (limited to 'lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp')
| -rw-r--r-- | lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp | 268 |
1 files changed, 215 insertions, 53 deletions
diff --git a/lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp b/lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp index 7f8c301315d..d7caf4281d5 100644 --- a/lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp +++ b/lldb/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp @@ -14,7 +14,6 @@ #include <vector> #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h" -#include "Utility/ARM64_DWARF_Registers.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" @@ -24,6 +23,7 @@ #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" #include "llvm/Support/TargetSelect.h" using namespace lldb; @@ -93,59 +93,59 @@ TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) { // CFA=sp +0 row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // CFA=fp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(8); EXPECT_EQ(8ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(16); EXPECT_EQ(16ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // CFA=sp +0 => fp= <same> lr= <same> row_sp = unwind_plan.GetRowForFunctionOffset(20); EXPECT_EQ(20ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); } @@ -210,35 +210,35 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { // 0: CFA=sp +0 => row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); 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(4ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-40, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, 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(8ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-24, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); @@ -246,14 +246,14 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(12); EXPECT_EQ(12ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); @@ -261,7 +261,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(16); EXPECT_EQ(16ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); @@ -269,7 +269,7 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(28); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); @@ -280,10 +280,10 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { // 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(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp= @@ -291,24 +291,24 @@ TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) { row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_EQ(36ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, 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(40ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); 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(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); } @@ -364,45 +364,45 @@ TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) { // 0: CFA=sp +0 => row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); 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().GetRegisterNumber() == gpr_sp_arm64); 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)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x23_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x24_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x25_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); row_sp = unwind_plan.GetRowForFunctionOffset(36); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); 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().GetRegisterNumber() == gpr_sp_arm64); 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().GetRegisterNumber() == gpr_sp_arm64); 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().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); } @@ -490,21 +490,183 @@ TEST_F(TestArm64InstEmulation, TestRegisterSavedTwice) { row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(40); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); } + +TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) { + 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; + + // this file built with clang for iOS arch arm64 optimization -Os + // #include <stdio.h> + // double foo(double in) { + // double arr[32]; + // for (int i = 0; i < 32; i++) + // arr[i] = in + i; + // for (int i = 2; i < 30; i++) + // arr[i] = ((((arr[i - 1] * arr[i - 2] * 0.2) + (0.7 * arr[i])) / + // ((((arr[i] * 0.73) + 0.65) * (arr[i - 1] + 0.2)) - ((arr[i + 1] + (arr[i] + // * 0.32) + 0.52) / 0.3) + (0.531 * arr[i - 2]))) + ((arr[i - 1] + 5) / + // ((arr[i + 2] + 0.4) / arr[i])) + (arr[5] * (0.17 + arr[7] * arr[i])) + + // ((i > 5 ? (arr[i - 3]) : arr[i - 1]) * 0.263) + (((arr[i - 2] + arr[i - + // 1]) * 0.3252) + 3.56) - (arr[i + 1] * 0.852311)) * ((arr[i] * 85234.1345) + // + (77342.451324 / (arr[i - 2] + arr[i - 1] - 73425341.33455))) + (arr[i] + // * 875712013.55) - (arr[i - 1] * 0.5555) - ((arr[i] * (arr[i + 1] + + // 17342834.44) / 8688200123.555)) + (arr[i - 2] + 8888.888); + // return arr[16]; + //} + // int main(int argc, char **argv) { printf("%g\n", foo(argc)); } + + // so function foo() uses enough registers that it spills the callee-saved + // floating point registers. + uint8_t data[] = { + // prologue + 0xef, 0x3b, 0xba, 0x6d, // 0: 0x6dba3bef stp d15, d14, [sp, #-0x60]! + 0xed, 0x33, 0x01, 0x6d, // 4: 0x6d0133ed stp d13, d12, [sp, #0x10] + 0xeb, 0x2b, 0x02, 0x6d, // 8: 0x6d022beb stp d11, d10, [sp, #0x20] + 0xe9, 0x23, 0x03, 0x6d, // 12: 0x6d0323e9 stp d9, d8, [sp, #0x30] + 0xfc, 0x6f, 0x04, 0xa9, // 16: 0xa9046ffc stp x28, x27, [sp, #0x40] + 0xfd, 0x7b, 0x05, 0xa9, // 20: 0xa9057bfd stp x29, x30, [sp, #0x50] + 0xfd, 0x43, 0x01, 0x91, // 24: 0x910143fd add x29, sp, #0x50 + 0xff, 0x43, 0x04, 0xd1, // 28: 0xd10443ff sub sp, sp, #0x110 + + // epilogue + 0xbf, 0x43, 0x01, 0xd1, // 32: 0xd10143bf sub sp, x29, #0x50 + 0xfd, 0x7b, 0x45, 0xa9, // 36: 0xa9457bfd ldp x29, x30, [sp, #0x50] + 0xfc, 0x6f, 0x44, 0xa9, // 40: 0xa9446ffc ldp x28, x27, [sp, #0x40] + 0xe9, 0x23, 0x43, 0x6d, // 44: 0x6d4323e9 ldp d9, d8, [sp, #0x30] + 0xeb, 0x2b, 0x42, 0x6d, // 48: 0x6d422beb ldp d11, d10, [sp, #0x20] + 0xed, 0x33, 0x41, 0x6d, // 52: 0x6d4133ed ldp d13, d12, [sp, #0x10] + 0xef, 0x3b, 0xc6, 0x6c, // 56: 0x6cc63bef ldp d15, d14, [sp], #0x60 + 0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0 ret + }; + + // UnwindPlan we expect: + // 0: CFA=sp +0 => + // 4: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96] + // 8: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 12: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] + // d14=[CFA-88] d15=[CFA-96] + // 16: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] + // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 20: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48] + // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] + // d15=[CFA-96] + // 24: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 36: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 40: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48] + // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] + // d15=[CFA-96] + // 44: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] + // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 48: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] + // d14=[CFA-88] d15=[CFA-96] + // 52: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 56: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96] + // 60: CFA=sp +0 => + + sample_range = AddressRange(0x1000, sizeof(data)); + + EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( + sample_range, data, sizeof(data), unwind_plan)); + + // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + row_sp = unwind_plan.GetRowForFunctionOffset(28); + EXPECT_EQ(28ull, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d15_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-96, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d14_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-88, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d13_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-80, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d12_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-72, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d11_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-64, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d10_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-56, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d9_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-48, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d8_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-40, regloc.GetOffset()); + + // 60: CFA=sp +0 => + row_sp = unwind_plan.GetRowForFunctionOffset(60); + EXPECT_EQ(60ull, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); + + if (row_sp->GetRegisterInfo(fpu_d8_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d9_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d10_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d11_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d12_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d13_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d14_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d15_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(gpr_x27_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(gpr_x28_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); +} |

