blob: 953dc75637dcc60671fc2f4857e2f77c1049f9aa [file] [log] [blame]
Christopher Ferris53a3c9b2017-05-10 18:34:15 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
Christopher Ferrisd226a512017-07-14 10:37:19 -070022#include <unwindstack/DwarfSection.h>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070023
24#include "MemoryFake.h"
25
Christopher Ferrisd226a512017-07-14 10:37:19 -070026namespace unwindstack {
27
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070028class MockDwarfSection : public DwarfSection {
29 public:
30 MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
31 virtual ~MockDwarfSection() = default;
32
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070033 MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070034
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070035 MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
36 (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070037
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070038 MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*), (override));
Christopher Ferris92acaac2018-06-21 10:44:02 -070039
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070040 MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
Christopher Ferris92acaac2018-06-21 10:44:02 -070041
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070042 MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
Christopher Ferris92acaac2018-06-21 10:44:02 -070043
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070044 MOCK_METHOD(bool, GetCfaLocationInfo, (uint64_t, const DwarfFde*, dwarf_loc_regs_t*), (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070045
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070046 MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070047
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070048 MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070049
Christopher Ferrisbaf058b2019-10-11 14:26:55 -070050 MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070051};
52
53class DwarfSectionTest : public ::testing::Test {
54 protected:
Christopher Ferris92acaac2018-06-21 10:44:02 -070055 void SetUp() override { section_.reset(new MockDwarfSection(&memory_)); }
56
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070057 MemoryFake memory_;
Christopher Ferris92acaac2018-06-21 10:44:02 -070058 std::unique_ptr<MockDwarfSection> section_;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070059};
60
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070061TEST_F(DwarfSectionTest, Step_fail_fde) {
Christopher Ferris92acaac2018-06-21 10:44:02 -070062 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070063
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070064 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -070065 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070066}
67
68TEST_F(DwarfSectionTest, Step_fail_cie_null) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070069 DwarfFde fde{};
70 fde.pc_end = 0x2000;
71 fde.cie = nullptr;
72
Christopher Ferris92acaac2018-06-21 10:44:02 -070073 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070074
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070075 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -070076 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070077}
78
79TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070080 DwarfCie cie{};
81 DwarfFde fde{};
82 fde.pc_end = 0x2000;
83 fde.cie = &cie;
84
Christopher Ferris92acaac2018-06-21 10:44:02 -070085 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
86 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070087 .WillOnce(::testing::Return(false));
88
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070089 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -070090 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070091}
92
93TEST_F(DwarfSectionTest, Step_pass) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070094 DwarfCie cie{};
95 DwarfFde fde{};
96 fde.pc_end = 0x2000;
97 fde.cie = &cie;
98
Christopher Ferris92acaac2018-06-21 10:44:02 -070099 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
100 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700101 .WillOnce(::testing::Return(true));
102
103 MemoryFake process;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700104 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700105 .WillOnce(::testing::Return(true));
106
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700107 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700108 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700109}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700110
David Srbecky3386eba2018-03-14 21:30:25 +0000111static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
112 dwarf_loc_regs_t* loc_regs) {
113 loc_regs->pc_start = fde->pc_start;
114 loc_regs->pc_end = fde->pc_end;
115 return true;
116}
117
118TEST_F(DwarfSectionTest, Step_cache) {
David Srbecky3386eba2018-03-14 21:30:25 +0000119 DwarfCie cie{};
120 DwarfFde fde{};
121 fde.pc_start = 0x500;
122 fde.pc_end = 0x2000;
123 fde.cie = &cie;
124
Christopher Ferris92acaac2018-06-21 10:44:02 -0700125 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
126 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
David Srbecky3386eba2018-03-14 21:30:25 +0000127 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
128
129 MemoryFake process;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700130 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
David Srbecky3386eba2018-03-14 21:30:25 +0000131 .WillRepeatedly(::testing::Return(true));
132
133 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700134 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
135 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
136 ASSERT_TRUE(section_->Step(0x1500, nullptr, &process, &finished));
David Srbecky3386eba2018-03-14 21:30:25 +0000137}
138
139TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
David Srbecky3386eba2018-03-14 21:30:25 +0000140 DwarfCie cie{};
141 DwarfFde fde0{};
142 fde0.pc_start = 0x1000;
143 fde0.pc_end = 0x2000;
144 fde0.cie = &cie;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700145 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0));
146 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
David Srbecky3386eba2018-03-14 21:30:25 +0000147 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
148
149 MemoryFake process;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700150 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
David Srbecky3386eba2018-03-14 21:30:25 +0000151 .WillRepeatedly(::testing::Return(true));
152
153 bool finished;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700154 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
David Srbecky3386eba2018-03-14 21:30:25 +0000155
156 DwarfFde fde1{};
157 fde1.pc_start = 0x500;
158 fde1.pc_end = 0x800;
159 fde1.cie = &cie;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700160 EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1));
161 EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
David Srbecky3386eba2018-03-14 21:30:25 +0000162 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
163
Christopher Ferris92acaac2018-06-21 10:44:02 -0700164 ASSERT_TRUE(section_->Step(0x600, nullptr, &process, &finished));
165 ASSERT_TRUE(section_->Step(0x700, nullptr, &process, &finished));
David Srbecky3386eba2018-03-14 21:30:25 +0000166}
167
Christopher Ferrisd226a512017-07-14 10:37:19 -0700168} // namespace unwindstack