• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
22 #include <memory>
23 #include <string>
24 #include <vector>
25 
26 #include <unwindstack/Elf.h>
27 #include <unwindstack/Global.h>
28 #include <unwindstack/MapInfo.h>
29 #include <unwindstack/Maps.h>
30 
31 #include "ElfFake.h"
32 
33 using ::testing::_;
34 using ::testing::DoAll;
35 using ::testing::Return;
36 using ::testing::SetArgPointee;
37 
38 namespace unwindstack {
39 
40 class GlobalMock : public Global {
41  public:
GlobalMock(std::shared_ptr<Memory> & memory)42   explicit GlobalMock(std::shared_ptr<Memory>& memory) : Global(memory) {}
GlobalMock(std::shared_ptr<Memory> & memory,std::vector<std::string> & search_libs)43   GlobalMock(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
44       : Global(memory, search_libs) {}
45 
46   MOCK_METHOD(bool, ReadVariableData, (uint64_t), (override));
47 
48   MOCK_METHOD(void, ProcessArch, (), (override));
49 
TestFindAndReadVariable(Maps * maps,const char * var_str)50   void TestFindAndReadVariable(Maps* maps, const char* var_str) {
51     FindAndReadVariable(maps, var_str);
52   }
53 };
54 
55 class GlobalTest : public ::testing::Test {
56  protected:
SetUp()57   void SetUp() override {
58     maps_.reset(
59         new BufferMaps("10000-11000 r--p 0000 00:00 0 first.so\n"
60                        "11000-12000 r-xp 1000 00:00 0 first.so\n"
61                        "12000-13000 rw-p 2000 00:00 0 first.so\n"
62 
63                        "20000-22000 r--p 0000 00:00 0 second.so\n"
64                        "22000-23000 rw-p 2000 00:00 0 second.so\n"
65 
66                        "30000-31000 r--p 0000 00:00 0 third.so\n"
67                        "31000-32000 ---p 0000 00:00 0\n"
68                        "32000-33000 r-xp 1000 00:00 0 third.so\n"
69                        "33000-34000 rw-p 2000 00:00 0 third.so\n"
70 
71                        "40000-42000 r--p 0000 00:00 0 fourth.so\n"
72                        "42000-43000 rw-p 0000 00:00 0 fourth.so\n"));
73     ASSERT_TRUE(maps_->Parse());
74     ASSERT_EQ(11U, maps_->Total());
75 
76     elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
77     elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
78     elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
79     elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
80 
81     ElfFake* elf_fake = new ElfFake(nullptr);
82     elf_fake->FakeSetValid(true);
83     elf_fake->FakeSetInterface(elf_fakes_[0]);
84     elf_fakes_[0]->FakeSetDataVaddrStart(0x2000);
85     elf_fakes_[0]->FakeSetDataVaddrEnd(0x3000);
86     elf_fakes_[0]->FakeSetDataOffset(0x2000);
87     auto map_info = maps_->Find(0x10000);
88     map_info->GetElfFields().elf_.reset(elf_fake);
89 
90     elf_fake = new ElfFake(nullptr);
91     elf_fake->FakeSetValid(true);
92     elf_fake->FakeSetInterface(elf_fakes_[1]);
93     elf_fakes_[1]->FakeSetDataVaddrStart(0x2000);
94     elf_fakes_[1]->FakeSetDataVaddrEnd(0x3000);
95     elf_fakes_[1]->FakeSetDataOffset(0x2000);
96     map_info = maps_->Find(0x20000);
97     map_info->GetElfFields().elf_.reset(elf_fake);
98 
99     elf_fake = new ElfFake(nullptr);
100     elf_fake->FakeSetValid(true);
101     elf_fake->FakeSetInterface(elf_fakes_[2]);
102     elf_fakes_[2]->FakeSetDataVaddrStart(0x2000);
103     elf_fakes_[2]->FakeSetDataVaddrEnd(0x3000);
104     elf_fakes_[2]->FakeSetDataOffset(0x2000);
105     map_info = maps_->Find(0x30000);
106     map_info->GetElfFields().elf_.reset(elf_fake);
107 
108     elf_fake = new ElfFake(nullptr);
109     elf_fake->FakeSetValid(true);
110     elf_fake->FakeSetInterface(elf_fakes_[3]);
111     elf_fakes_[3]->FakeSetDataVaddrStart(00);
112     elf_fakes_[3]->FakeSetDataVaddrEnd(0x1000);
113     elf_fakes_[3]->FakeSetDataOffset(0);
114     map_info = maps_->Find(0x40000);
115     map_info->GetElfFields().elf_.reset(elf_fake);
116 
117     global_.reset(new GlobalMock(empty_));
118   }
119 
120   std::shared_ptr<Memory> empty_;
121   std::unique_ptr<BufferMaps> maps_;
122   std::unique_ptr<GlobalMock> global_;
123   std::vector<ElfInterfaceFake*> elf_fakes_;
124 };
125 
TEST_F(GlobalTest,ro_rx_rw)126 TEST_F(GlobalTest, ro_rx_rw) {
127   std::string global_var("fake_global");
128   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
129   EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
130 
131   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
132 }
133 
TEST_F(GlobalTest,ro_rx_rw_searchable)134 TEST_F(GlobalTest, ro_rx_rw_searchable) {
135   std::vector<std::string> search_libs = {"first.so"};
136   global_.reset(new GlobalMock(empty_, search_libs));
137 
138   std::string global_var("fake_global");
139   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
140   EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
141 
142   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
143 }
144 
TEST_F(GlobalTest,ro_rx_rw_not_searchable)145 TEST_F(GlobalTest, ro_rx_rw_not_searchable) {
146   std::vector<std::string> search_libs = {"second.so"};
147   global_.reset(new GlobalMock(empty_, search_libs));
148 
149   std::string global_var("fake_global");
150   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
151 
152   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
153 }
154 
TEST_F(GlobalTest,ro_rw)155 TEST_F(GlobalTest, ro_rw) {
156   std::string global_var("fake_global");
157   elf_fakes_[1]->FakeSetGlobalVariable(global_var, 0x2010);
158   EXPECT_CALL(*global_, ReadVariableData(0x22010)).WillOnce(Return(true));
159 
160   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
161 }
162 
TEST_F(GlobalTest,ro_blank_rx_rw)163 TEST_F(GlobalTest, ro_blank_rx_rw) {
164   std::string global_var("fake_global");
165   elf_fakes_[2]->FakeSetGlobalVariable(global_var, 0x2010);
166   EXPECT_CALL(*global_, ReadVariableData(0x33010)).WillOnce(Return(true));
167 
168   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
169 }
170 
TEST_F(GlobalTest,ro_rw_with_zero_offset)171 TEST_F(GlobalTest, ro_rw_with_zero_offset) {
172   std::string global_var("fake_global");
173   elf_fakes_[3]->FakeSetGlobalVariable(global_var, 0x10);
174   EXPECT_CALL(*global_, ReadVariableData(0x42010)).WillOnce(Return(true));
175 
176   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
177 }
178 
179 }  // namespace unwindstack
180