/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include "ElfFake.h" using ::testing::_; using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; namespace unwindstack { class GlobalMock : public Global { public: explicit GlobalMock(std::shared_ptr& memory) : Global(memory) {} GlobalMock(std::shared_ptr& memory, std::vector& search_libs) : Global(memory, search_libs) {} MOCK_METHOD(bool, ReadVariableData, (uint64_t), (override)); MOCK_METHOD(void, ProcessArch, (), (override)); void TestFindAndReadVariable(Maps* maps, const char* var_str) { FindAndReadVariable(maps, var_str); } }; class GlobalTest : public ::testing::Test { protected: void SetUp() override { maps_.reset( new BufferMaps("10000-11000 r--p 0000 00:00 0 first.so\n" "11000-12000 r-xp 1000 00:00 0 first.so\n" "12000-13000 rw-p 2000 00:00 0 first.so\n" "20000-22000 r--p 0000 00:00 0 second.so\n" "22000-23000 rw-p 2000 00:00 0 second.so\n" "30000-31000 r--p 0000 00:00 0 third.so\n" "31000-32000 ---p 0000 00:00 0\n" "32000-33000 r-xp 1000 00:00 0 third.so\n" "33000-34000 rw-p 2000 00:00 0 third.so\n" "40000-42000 r--p 0000 00:00 0 fourth.so\n" "42000-43000 rw-p 0000 00:00 0 fourth.so\n")); ASSERT_TRUE(maps_->Parse()); ASSERT_EQ(11U, maps_->Total()); elf_fakes_.push_back(new ElfInterfaceFake(nullptr)); elf_fakes_.push_back(new ElfInterfaceFake(nullptr)); elf_fakes_.push_back(new ElfInterfaceFake(nullptr)); elf_fakes_.push_back(new ElfInterfaceFake(nullptr)); ElfFake* elf_fake = new ElfFake(nullptr); elf_fake->FakeSetValid(true); elf_fake->FakeSetInterface(elf_fakes_[0]); elf_fakes_[0]->FakeSetDataVaddrStart(0x2000); elf_fakes_[0]->FakeSetDataVaddrEnd(0x3000); elf_fakes_[0]->FakeSetDataOffset(0x2000); auto map_info = maps_->Find(0x10000); map_info->GetElfFields().elf_.reset(elf_fake); elf_fake = new ElfFake(nullptr); elf_fake->FakeSetValid(true); elf_fake->FakeSetInterface(elf_fakes_[1]); elf_fakes_[1]->FakeSetDataVaddrStart(0x2000); elf_fakes_[1]->FakeSetDataVaddrEnd(0x3000); elf_fakes_[1]->FakeSetDataOffset(0x2000); map_info = maps_->Find(0x20000); map_info->GetElfFields().elf_.reset(elf_fake); elf_fake = new ElfFake(nullptr); elf_fake->FakeSetValid(true); elf_fake->FakeSetInterface(elf_fakes_[2]); elf_fakes_[2]->FakeSetDataVaddrStart(0x2000); elf_fakes_[2]->FakeSetDataVaddrEnd(0x3000); elf_fakes_[2]->FakeSetDataOffset(0x2000); map_info = maps_->Find(0x30000); map_info->GetElfFields().elf_.reset(elf_fake); elf_fake = new ElfFake(nullptr); elf_fake->FakeSetValid(true); elf_fake->FakeSetInterface(elf_fakes_[3]); elf_fakes_[3]->FakeSetDataVaddrStart(00); elf_fakes_[3]->FakeSetDataVaddrEnd(0x1000); elf_fakes_[3]->FakeSetDataOffset(0); map_info = maps_->Find(0x40000); map_info->GetElfFields().elf_.reset(elf_fake); global_.reset(new GlobalMock(empty_)); } std::shared_ptr empty_; std::unique_ptr maps_; std::unique_ptr global_; std::vector elf_fakes_; }; TEST_F(GlobalTest, ro_rx_rw) { std::string global_var("fake_global"); elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010); EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true)); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } TEST_F(GlobalTest, ro_rx_rw_searchable) { std::vector search_libs = {"first.so"}; global_.reset(new GlobalMock(empty_, search_libs)); std::string global_var("fake_global"); elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010); EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true)); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } TEST_F(GlobalTest, ro_rx_rw_not_searchable) { std::vector search_libs = {"second.so"}; global_.reset(new GlobalMock(empty_, search_libs)); std::string global_var("fake_global"); elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } TEST_F(GlobalTest, ro_rw) { std::string global_var("fake_global"); elf_fakes_[1]->FakeSetGlobalVariable(global_var, 0x2010); EXPECT_CALL(*global_, ReadVariableData(0x22010)).WillOnce(Return(true)); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } TEST_F(GlobalTest, ro_blank_rx_rw) { std::string global_var("fake_global"); elf_fakes_[2]->FakeSetGlobalVariable(global_var, 0x2010); EXPECT_CALL(*global_, ReadVariableData(0x33010)).WillOnce(Return(true)); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } TEST_F(GlobalTest, ro_rw_with_zero_offset) { std::string global_var("fake_global"); elf_fakes_[3]->FakeSetGlobalVariable(global_var, 0x10); EXPECT_CALL(*global_, ReadVariableData(0x42010)).WillOnce(Return(true)); global_->TestFindAndReadVariable(maps_.get(), global_var.c_str()); } } // namespace unwindstack