1 | //===-- UnwindPlanTest.cpp ------------------------------------------------===// |
2 | // |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #include "lldb/Symbol/UnwindPlan.h" |
11 | #include "gmock/gmock.h" |
12 | #include "gtest/gtest.h" |
13 | |
14 | using namespace lldb_private; |
15 | using namespace lldb; |
16 | |
17 | static UnwindPlan::Row make_simple_row(addr_t offset, uint64_t cfa_value) { |
18 | UnwindPlan::Row row; |
19 | row.SetOffset(offset); |
20 | row.GetCFAValue().SetIsConstant(cfa_value); |
21 | return row; |
22 | } |
23 | |
24 | TEST(UnwindPlan, InsertRow) { |
25 | UnwindPlan::Row row1 = make_simple_row(offset: 0, cfa_value: 42); |
26 | UnwindPlan::Row row2 = make_simple_row(offset: 0, cfa_value: 47); |
27 | UnwindPlan::Row row3 = make_simple_row(offset: -1, cfa_value: 4242); |
28 | |
29 | UnwindPlan plan(eRegisterKindGeneric); |
30 | plan.InsertRow(row: row1); |
31 | EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(row1)); |
32 | |
33 | plan.InsertRow(row: row2, /*replace_existing=*/false); |
34 | EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(row1)); |
35 | |
36 | plan.InsertRow(row: row2, /*replace_existing=*/true); |
37 | EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(row2)); |
38 | |
39 | EXPECT_THAT(plan.GetRowForFunctionOffset(-1), nullptr); |
40 | plan.InsertRow(row: row3); |
41 | EXPECT_THAT(plan.GetRowForFunctionOffset(-1), testing::Pointee(row3)); |
42 | } |
43 | |
44 | TEST(UnwindPlan, GetRowForFunctionOffset) { |
45 | UnwindPlan::Row row1 = make_simple_row(offset: 10, cfa_value: 42); |
46 | UnwindPlan::Row row2 = make_simple_row(offset: 20, cfa_value: 47); |
47 | |
48 | UnwindPlan plan(eRegisterKindGeneric); |
49 | plan.InsertRow(row: row1); |
50 | plan.InsertRow(row: row2); |
51 | |
52 | EXPECT_THAT(plan.GetRowForFunctionOffset(0), nullptr); |
53 | EXPECT_THAT(plan.GetRowForFunctionOffset(9), nullptr); |
54 | EXPECT_THAT(plan.GetRowForFunctionOffset(10), testing::Pointee(row1)); |
55 | EXPECT_THAT(plan.GetRowForFunctionOffset(19), testing::Pointee(row1)); |
56 | EXPECT_THAT(plan.GetRowForFunctionOffset(20), testing::Pointee(row2)); |
57 | EXPECT_THAT(plan.GetRowForFunctionOffset(99), testing::Pointee(row2)); |
58 | } |
59 | |
60 | TEST(UnwindPlan, PlanValidAtAddress) { |
61 | UnwindPlan::Row row1 = make_simple_row(offset: 0, cfa_value: 42); |
62 | UnwindPlan::Row row2 = make_simple_row(offset: 10, cfa_value: 47); |
63 | |
64 | UnwindPlan plan(eRegisterKindGeneric); |
65 | // When valid address range is not set, plans are valid as long as they have a |
66 | // row that sets the CFA. |
67 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(0))); |
68 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(10))); |
69 | |
70 | plan.InsertRow(row: row2); |
71 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(0))); |
72 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(10))); |
73 | |
74 | plan.InsertRow(row: row1); |
75 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(0))); |
76 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(10))); |
77 | |
78 | // With an address range, they're only valid within that range. |
79 | plan.SetPlanValidAddressRanges({AddressRange(0, 5), AddressRange(15, 5)}); |
80 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(0))); |
81 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(5))); |
82 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(10))); |
83 | EXPECT_TRUE(plan.PlanValidAtAddress(Address(15))); |
84 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(20))); |
85 | EXPECT_FALSE(plan.PlanValidAtAddress(Address(25))); |
86 | } |
87 | |