xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/GlobalTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
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     std::shared_ptr<Memory> empty;
77     elf_fakes_.push_back(new ElfInterfaceFake(empty));
78     elf_fakes_.push_back(new ElfInterfaceFake(empty));
79     elf_fakes_.push_back(new ElfInterfaceFake(empty));
80     elf_fakes_.push_back(new ElfInterfaceFake(empty));
81 
82     ElfFake* elf_fake = new ElfFake(empty);
83     elf_fake->FakeSetValid(true);
84     elf_fake->FakeSetInterface(elf_fakes_[0]);
85     elf_fakes_[0]->FakeSetDataVaddrStart(0x2000);
86     elf_fakes_[0]->FakeSetDataVaddrEnd(0x3000);
87     elf_fakes_[0]->FakeSetDataOffset(0x2000);
88     auto map_info = maps_->Find(0x10000);
89     map_info->GetElfFields().elf_.reset(elf_fake);
90 
91     elf_fake = new ElfFake(empty);
92     elf_fake->FakeSetValid(true);
93     elf_fake->FakeSetInterface(elf_fakes_[1]);
94     elf_fakes_[1]->FakeSetDataVaddrStart(0x2000);
95     elf_fakes_[1]->FakeSetDataVaddrEnd(0x3000);
96     elf_fakes_[1]->FakeSetDataOffset(0x2000);
97     map_info = maps_->Find(0x20000);
98     map_info->GetElfFields().elf_.reset(elf_fake);
99 
100     elf_fake = new ElfFake(empty);
101     elf_fake->FakeSetValid(true);
102     elf_fake->FakeSetInterface(elf_fakes_[2]);
103     elf_fakes_[2]->FakeSetDataVaddrStart(0x2000);
104     elf_fakes_[2]->FakeSetDataVaddrEnd(0x3000);
105     elf_fakes_[2]->FakeSetDataOffset(0x2000);
106     map_info = maps_->Find(0x30000);
107     map_info->GetElfFields().elf_.reset(elf_fake);
108 
109     elf_fake = new ElfFake(empty);
110     elf_fake->FakeSetValid(true);
111     elf_fake->FakeSetInterface(elf_fakes_[3]);
112     elf_fakes_[3]->FakeSetDataVaddrStart(00);
113     elf_fakes_[3]->FakeSetDataVaddrEnd(0x1000);
114     elf_fakes_[3]->FakeSetDataOffset(0);
115     map_info = maps_->Find(0x40000);
116     map_info->GetElfFields().elf_.reset(elf_fake);
117 
118     global_.reset(new GlobalMock(empty_));
119   }
120 
121   std::shared_ptr<Memory> empty_;
122   std::unique_ptr<BufferMaps> maps_;
123   std::unique_ptr<GlobalMock> global_;
124   std::vector<ElfInterfaceFake*> elf_fakes_;
125 };
126 
TEST_F(GlobalTest,ro_rx_rw)127 TEST_F(GlobalTest, ro_rx_rw) {
128   std::string global_var("fake_global");
129   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
130   EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
131 
132   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
133 }
134 
TEST_F(GlobalTest,ro_rx_rw_searchable)135 TEST_F(GlobalTest, ro_rx_rw_searchable) {
136   std::vector<std::string> search_libs = {"first.so"};
137   global_.reset(new GlobalMock(empty_, search_libs));
138 
139   std::string global_var("fake_global");
140   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
141   EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
142 
143   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
144 }
145 
TEST_F(GlobalTest,ro_rx_rw_not_searchable)146 TEST_F(GlobalTest, ro_rx_rw_not_searchable) {
147   std::vector<std::string> search_libs = {"second.so"};
148   global_.reset(new GlobalMock(empty_, search_libs));
149 
150   std::string global_var("fake_global");
151   elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
152 
153   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
154 }
155 
TEST_F(GlobalTest,ro_rw)156 TEST_F(GlobalTest, ro_rw) {
157   std::string global_var("fake_global");
158   elf_fakes_[1]->FakeSetGlobalVariable(global_var, 0x2010);
159   EXPECT_CALL(*global_, ReadVariableData(0x22010)).WillOnce(Return(true));
160 
161   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
162 }
163 
TEST_F(GlobalTest,ro_blank_rx_rw)164 TEST_F(GlobalTest, ro_blank_rx_rw) {
165   std::string global_var("fake_global");
166   elf_fakes_[2]->FakeSetGlobalVariable(global_var, 0x2010);
167   EXPECT_CALL(*global_, ReadVariableData(0x33010)).WillOnce(Return(true));
168 
169   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
170 }
171 
TEST_F(GlobalTest,ro_rw_with_zero_offset)172 TEST_F(GlobalTest, ro_rw_with_zero_offset) {
173   std::string global_var("fake_global");
174   elf_fakes_[3]->FakeSetGlobalVariable(global_var, 0x10);
175   EXPECT_CALL(*global_, ReadVariableData(0x42010)).WillOnce(Return(true));
176 
177   global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
178 }
179 
180 }  // namespace unwindstack
181