1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <errno.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <signal.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <sys/mman.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <sys/ptrace.h>
23*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h>
24*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
25*eb293b8fSAndroid Build Coastguard Worker
26*eb293b8fSAndroid Build Coastguard Worker #include <atomic>
27*eb293b8fSAndroid Build Coastguard Worker #include <memory>
28*eb293b8fSAndroid Build Coastguard Worker #include <thread>
29*eb293b8fSAndroid Build Coastguard Worker #include <vector>
30*eb293b8fSAndroid Build Coastguard Worker
31*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
32*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
33*eb293b8fSAndroid Build Coastguard Worker
34*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
35*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
36*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
38*eb293b8fSAndroid Build Coastguard Worker
39*eb293b8fSAndroid Build Coastguard Worker #include "ElfTestUtils.h"
40*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
41*eb293b8fSAndroid Build Coastguard Worker
42*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
43*eb293b8fSAndroid Build Coastguard Worker
44*eb293b8fSAndroid Build Coastguard Worker class MapInfoGetElfTest : public ::testing::Test {
45*eb293b8fSAndroid Build Coastguard Worker protected:
SetUp()46*eb293b8fSAndroid Build Coastguard Worker void SetUp() override {
47*eb293b8fSAndroid Build Coastguard Worker memory_ = new MemoryFake;
48*eb293b8fSAndroid Build Coastguard Worker process_memory_.reset(memory_);
49*eb293b8fSAndroid Build Coastguard Worker }
50*eb293b8fSAndroid Build Coastguard Worker
51*eb293b8fSAndroid Build Coastguard Worker template <typename Ehdr, typename Shdr>
InitElf(uint64_t sh_offset,Ehdr * ehdr,uint8_t class_type,uint8_t machine_type)52*eb293b8fSAndroid Build Coastguard Worker static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
53*eb293b8fSAndroid Build Coastguard Worker memset(ehdr, 0, sizeof(*ehdr));
54*eb293b8fSAndroid Build Coastguard Worker memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
55*eb293b8fSAndroid Build Coastguard Worker ehdr->e_ident[EI_CLASS] = class_type;
56*eb293b8fSAndroid Build Coastguard Worker ehdr->e_machine = machine_type;
57*eb293b8fSAndroid Build Coastguard Worker ehdr->e_shoff = sh_offset;
58*eb293b8fSAndroid Build Coastguard Worker ehdr->e_shentsize = sizeof(Shdr) + 100;
59*eb293b8fSAndroid Build Coastguard Worker ehdr->e_shnum = 4;
60*eb293b8fSAndroid Build Coastguard Worker }
61*eb293b8fSAndroid Build Coastguard Worker
62*eb293b8fSAndroid Build Coastguard Worker void InitMapInfo(std::vector<std::shared_ptr<MapInfo>>& maps, bool in_memory);
63*eb293b8fSAndroid Build Coastguard Worker
64*eb293b8fSAndroid Build Coastguard Worker const size_t kMapSize = 4096;
65*eb293b8fSAndroid Build Coastguard Worker
66*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> process_memory_;
67*eb293b8fSAndroid Build Coastguard Worker MemoryFake* memory_;
68*eb293b8fSAndroid Build Coastguard Worker
69*eb293b8fSAndroid Build Coastguard Worker TemporaryFile elf_;
70*eb293b8fSAndroid Build Coastguard Worker };
71*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,invalid)72*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, invalid) {
73*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "");
74*eb293b8fSAndroid Build Coastguard Worker
75*eb293b8fSAndroid Build Coastguard Worker // The map is empty, but this should still create an invalid elf object.
76*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
77*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
78*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
79*eb293b8fSAndroid Build Coastguard Worker }
80*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,valid32)81*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, valid32) {
82*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
83*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
84*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
85*eb293b8fSAndroid Build Coastguard Worker
86*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x3000, 0x4000, 0, PROT_READ, "");
87*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
88*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
89*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
90*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
91*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ELFCLASS32, elf->class_type());
92*eb293b8fSAndroid Build Coastguard Worker
93*eb293b8fSAndroid Build Coastguard Worker // Now verify that an empty process memory returns an invalid elf object.
94*eb293b8fSAndroid Build Coastguard Worker info->set_elf(nullptr);
95*eb293b8fSAndroid Build Coastguard Worker elf = info->GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
96*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
97*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
98*eb293b8fSAndroid Build Coastguard Worker }
99*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,valid64)100*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, valid64) {
101*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
102*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
103*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
104*eb293b8fSAndroid Build Coastguard Worker
105*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x8000, 0x9000, 0, PROT_READ, "");
106*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
107*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
108*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
109*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
110*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ELFCLASS64, elf->class_type());
111*eb293b8fSAndroid Build Coastguard Worker }
112*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,invalid_arch_mismatch)113*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) {
114*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
115*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
116*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
117*eb293b8fSAndroid Build Coastguard Worker
118*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x3000, 0x4000, 0, PROT_READ, "");
119*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_X86);
120*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
121*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
122*eb293b8fSAndroid Build Coastguard Worker }
123*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,gnu_debugdata_init32)124*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
125*eb293b8fSAndroid Build Coastguard Worker TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
126*eb293b8fSAndroid Build Coastguard Worker [&](uint64_t offset, const void* ptr, size_t size) {
127*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x2000 + offset, ptr, size);
128*eb293b8fSAndroid Build Coastguard Worker });
129*eb293b8fSAndroid Build Coastguard Worker
130*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x2000, 0x3000, 0, PROT_READ, "");
131*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
132*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
133*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
134*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
135*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ELFCLASS32, elf->class_type());
136*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
137*eb293b8fSAndroid Build Coastguard Worker }
138*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,gnu_debugdata_init64)139*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
140*eb293b8fSAndroid Build Coastguard Worker TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
141*eb293b8fSAndroid Build Coastguard Worker [&](uint64_t offset, const void* ptr, size_t size) {
142*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x5000 + offset, ptr, size);
143*eb293b8fSAndroid Build Coastguard Worker });
144*eb293b8fSAndroid Build Coastguard Worker
145*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x5000, 0x8000, 0, PROT_READ, "");
146*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
147*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
148*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
149*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
150*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(ELFCLASS64, elf->class_type());
151*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
152*eb293b8fSAndroid Build Coastguard Worker }
153*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,end_le_start)154*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, end_le_start) {
155*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
156*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
157*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
158*eb293b8fSAndroid Build Coastguard Worker
159*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x1000, 0x1000, 0, PROT_READ, elf_.path);
160*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
161*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
162*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
163*eb293b8fSAndroid Build Coastguard Worker
164*eb293b8fSAndroid Build Coastguard Worker info->set_elf(nullptr);
165*eb293b8fSAndroid Build Coastguard Worker info->set_end(0xfff);
166*eb293b8fSAndroid Build Coastguard Worker elf = info->GetElf(process_memory_, ARCH_ARM);
167*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
168*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
169*eb293b8fSAndroid Build Coastguard Worker
170*eb293b8fSAndroid Build Coastguard Worker // Make sure this test is valid.
171*eb293b8fSAndroid Build Coastguard Worker info->set_elf(nullptr);
172*eb293b8fSAndroid Build Coastguard Worker info->set_end(0x2000);
173*eb293b8fSAndroid Build Coastguard Worker elf = info->GetElf(process_memory_, ARCH_ARM);
174*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
175*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
176*eb293b8fSAndroid Build Coastguard Worker }
177*eb293b8fSAndroid Build Coastguard Worker
178*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero but there is no elf at the offset,
179*eb293b8fSAndroid Build Coastguard Worker // that the full file is used.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_full_file)180*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
181*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x1000);
182*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
183*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
184*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
185*eb293b8fSAndroid Build Coastguard Worker memcpy(buffer.data(), &ehdr, sizeof(ehdr));
186*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
187*eb293b8fSAndroid Build Coastguard Worker
188*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
189*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
190*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
191*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
192*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory() != nullptr);
193*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
194*eb293b8fSAndroid Build Coastguard Worker
195*eb293b8fSAndroid Build Coastguard Worker // Read the entire file.
196*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
197*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
198*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
199*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
200*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
201*eb293b8fSAndroid Build Coastguard Worker }
202*eb293b8fSAndroid Build Coastguard Worker
203*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
204*eb293b8fSAndroid Build Coastguard Worker }
205*eb293b8fSAndroid Build Coastguard Worker
206*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero and there is an elf at that
207*eb293b8fSAndroid Build Coastguard Worker // offset, that only part of the file is used.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file)208*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
209*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
210*eb293b8fSAndroid Build Coastguard Worker
211*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
212*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
213*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
214*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
215*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
216*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
217*eb293b8fSAndroid Build Coastguard Worker
218*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
219*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
220*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
221*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory() != nullptr);
222*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
223*eb293b8fSAndroid Build Coastguard Worker
224*eb293b8fSAndroid Build Coastguard Worker // Read the valid part of the file.
225*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
226*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
227*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
228*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
229*eb293b8fSAndroid Build Coastguard Worker }
230*eb293b8fSAndroid Build Coastguard Worker
231*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
232*eb293b8fSAndroid Build Coastguard Worker }
233*eb293b8fSAndroid Build Coastguard Worker
234*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero and there is an elf at that
235*eb293b8fSAndroid Build Coastguard Worker // offset, that only part of the file is used. Further verify that if the
236*eb293b8fSAndroid Build Coastguard Worker // embedded elf is bigger than the initial map, the new object is larger
237*eb293b8fSAndroid Build Coastguard Worker // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file_whole_elf32)238*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
239*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
240*eb293b8fSAndroid Build Coastguard Worker
241*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
242*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
243*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
244*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
245*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x2000;
246*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
247*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 4;
248*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
249*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
250*eb293b8fSAndroid Build Coastguard Worker
251*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
252*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
253*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
254*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory() != nullptr);
255*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
256*eb293b8fSAndroid Build Coastguard Worker
257*eb293b8fSAndroid Build Coastguard Worker // Verify the memory is a valid elf.
258*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
259*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
260*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
261*eb293b8fSAndroid Build Coastguard Worker
262*eb293b8fSAndroid Build Coastguard Worker // Read past the end of what would normally be the size of the map.
263*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
264*eb293b8fSAndroid Build Coastguard Worker }
265*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file_whole_elf64)266*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
267*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
268*eb293b8fSAndroid Build Coastguard Worker
269*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
270*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
271*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
272*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
273*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x2000;
274*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
275*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 4;
276*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
277*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
278*eb293b8fSAndroid Build Coastguard Worker
279*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
280*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
281*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
282*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory() != nullptr);
283*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
284*eb293b8fSAndroid Build Coastguard Worker
285*eb293b8fSAndroid Build Coastguard Worker // Verify the memory is a valid elf.
286*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
287*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
288*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
289*eb293b8fSAndroid Build Coastguard Worker
290*eb293b8fSAndroid Build Coastguard Worker // Read past the end of what would normally be the size of the map.
291*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
292*eb293b8fSAndroid Build Coastguard Worker }
293*eb293b8fSAndroid Build Coastguard Worker
294*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero and there is an elf at that
295*eb293b8fSAndroid Build Coastguard Worker // offset, that only part of the file is used. Further verify that if the
296*eb293b8fSAndroid Build Coastguard Worker // the initial map is smaller than elf header size, we can still read the elf.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file_whole_elf64_small_map_range)297*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64_small_map_range) {
298*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x7000, 0x7004, 0x1000, PROT_READ, elf_.path);
299*eb293b8fSAndroid Build Coastguard Worker
300*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
301*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
302*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
303*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
304*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x2000;
305*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
306*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 4;
307*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
308*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
309*eb293b8fSAndroid Build Coastguard Worker
310*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
311*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
312*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
313*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory() != nullptr);
314*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
315*eb293b8fSAndroid Build Coastguard Worker
316*eb293b8fSAndroid Build Coastguard Worker // Verify the memory is a valid elf.
317*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
318*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
319*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
320*eb293b8fSAndroid Build Coastguard Worker
321*eb293b8fSAndroid Build Coastguard Worker // Read past the end of what would normally be the size of the map.
322*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
323*eb293b8fSAndroid Build Coastguard Worker }
324*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,check_device_maps)325*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, check_device_maps) {
326*eb293b8fSAndroid Build Coastguard Worker // Create valid elf data in process memory for this to verify that only
327*eb293b8fSAndroid Build Coastguard Worker // the name is causing invalid elf data.
328*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
329*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
330*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x2000;
331*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
332*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 0;
333*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
334*eb293b8fSAndroid Build Coastguard Worker
335*eb293b8fSAndroid Build Coastguard Worker auto info =
336*eb293b8fSAndroid Build Coastguard Worker MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
337*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_X86_64);
338*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
339*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
340*eb293b8fSAndroid Build Coastguard Worker
341*eb293b8fSAndroid Build Coastguard Worker // Set the name to nothing to verify that it still fails.
342*eb293b8fSAndroid Build Coastguard Worker info->set_elf(nullptr);
343*eb293b8fSAndroid Build Coastguard Worker info->set_name("");
344*eb293b8fSAndroid Build Coastguard Worker elf = info->GetElf(process_memory_, ARCH_X86_64);
345*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(elf->valid());
346*eb293b8fSAndroid Build Coastguard Worker
347*eb293b8fSAndroid Build Coastguard Worker // Change the flags and verify the elf is valid now.
348*eb293b8fSAndroid Build Coastguard Worker info->set_elf(nullptr);
349*eb293b8fSAndroid Build Coastguard Worker info->set_flags(PROT_READ);
350*eb293b8fSAndroid Build Coastguard Worker elf = info->GetElf(process_memory_, ARCH_X86_64);
351*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
352*eb293b8fSAndroid Build Coastguard Worker }
353*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoGetElfTest,multiple_thread_get_elf)354*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
355*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kNumConcurrentThreads = 100;
356*eb293b8fSAndroid Build Coastguard Worker
357*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
358*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
359*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x2000;
360*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
361*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 0;
362*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
363*eb293b8fSAndroid Build Coastguard Worker
364*eb293b8fSAndroid Build Coastguard Worker Elf* elf_in_threads[kNumConcurrentThreads];
365*eb293b8fSAndroid Build Coastguard Worker std::vector<std::thread*> threads;
366*eb293b8fSAndroid Build Coastguard Worker
367*eb293b8fSAndroid Build Coastguard Worker std::atomic_bool wait;
368*eb293b8fSAndroid Build Coastguard Worker wait = true;
369*eb293b8fSAndroid Build Coastguard Worker // Create all of the threads and have them do the GetElf at the same time
370*eb293b8fSAndroid Build Coastguard Worker // to make it likely that a race will occur.
371*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ, "");
372*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumConcurrentThreads; i++) {
373*eb293b8fSAndroid Build Coastguard Worker std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
374*eb293b8fSAndroid Build Coastguard Worker while (wait)
375*eb293b8fSAndroid Build Coastguard Worker ;
376*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->GetElf(process_memory_, ARCH_X86_64);
377*eb293b8fSAndroid Build Coastguard Worker elf_in_threads[i] = elf;
378*eb293b8fSAndroid Build Coastguard Worker });
379*eb293b8fSAndroid Build Coastguard Worker threads.push_back(thread);
380*eb293b8fSAndroid Build Coastguard Worker }
381*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(info->elf() == nullptr);
382*eb293b8fSAndroid Build Coastguard Worker
383*eb293b8fSAndroid Build Coastguard Worker // Set them all going and wait for the threads to finish.
384*eb293b8fSAndroid Build Coastguard Worker wait = false;
385*eb293b8fSAndroid Build Coastguard Worker for (auto thread : threads) {
386*eb293b8fSAndroid Build Coastguard Worker thread->join();
387*eb293b8fSAndroid Build Coastguard Worker delete thread;
388*eb293b8fSAndroid Build Coastguard Worker }
389*eb293b8fSAndroid Build Coastguard Worker
390*eb293b8fSAndroid Build Coastguard Worker // Now verify that all of the elf files are exactly the same and valid.
391*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info->elf().get();
392*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
393*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(elf->valid());
394*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumConcurrentThreads; i++) {
395*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched.";
396*eb293b8fSAndroid Build Coastguard Worker }
397*eb293b8fSAndroid Build Coastguard Worker }
398*eb293b8fSAndroid Build Coastguard Worker
399*eb293b8fSAndroid Build Coastguard Worker // Verify that previous maps don't automatically get the same elf object.
TEST_F(MapInfoGetElfTest,prev_map_elf_not_set)400*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) {
401*eb293b8fSAndroid Build Coastguard Worker auto info1 = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "/not/present");
402*eb293b8fSAndroid Build Coastguard Worker auto info2 = MapInfo::Create(info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path);
403*eb293b8fSAndroid Build Coastguard Worker
404*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
405*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
406*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr));
407*eb293b8fSAndroid Build Coastguard Worker Elf* elf = info2->GetElf(process_memory_, ARCH_ARM);
408*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
409*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
410*eb293b8fSAndroid Build Coastguard Worker
411*eb293b8fSAndroid Build Coastguard Worker ASSERT_NE(elf, info1->GetElf(process_memory_, ARCH_ARM));
412*eb293b8fSAndroid Build Coastguard Worker }
413*eb293b8fSAndroid Build Coastguard Worker
InitMapInfo(std::vector<std::shared_ptr<MapInfo>> & maps,bool in_memory)414*eb293b8fSAndroid Build Coastguard Worker void MapInfoGetElfTest::InitMapInfo(std::vector<std::shared_ptr<MapInfo>>& maps, bool in_memory) {
415*eb293b8fSAndroid Build Coastguard Worker maps.resize(2);
416*eb293b8fSAndroid Build Coastguard Worker maps[0] = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, elf_.path);
417*eb293b8fSAndroid Build Coastguard Worker maps[1] = MapInfo::Create(maps[0], 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path);
418*eb293b8fSAndroid Build Coastguard Worker
419*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
420*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
421*eb293b8fSAndroid Build Coastguard Worker if (in_memory) {
422*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
423*eb293b8fSAndroid Build Coastguard Worker } else {
424*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
425*eb293b8fSAndroid Build Coastguard Worker }
426*eb293b8fSAndroid Build Coastguard Worker }
427*eb293b8fSAndroid Build Coastguard Worker
428*eb293b8fSAndroid Build Coastguard Worker // Verify that a read-only map followed by a read-execute map will result
429*eb293b8fSAndroid Build Coastguard Worker // in the same elf object in both maps.
TEST_F(MapInfoGetElfTest,read_only_followed_by_read_exec_share_elf_exec_first)430*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf_exec_first) {
431*eb293b8fSAndroid Build Coastguard Worker std::vector<std::shared_ptr<MapInfo>> maps;
432*eb293b8fSAndroid Build Coastguard Worker
433*eb293b8fSAndroid Build Coastguard Worker // First use in memory maps.
434*eb293b8fSAndroid Build Coastguard Worker InitMapInfo(maps, true);
435*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(2U, maps.size());
436*eb293b8fSAndroid Build Coastguard Worker MapInfo* r_map_info = maps[0].get();
437*eb293b8fSAndroid Build Coastguard Worker MapInfo* rx_map_info = maps[1].get();
438*eb293b8fSAndroid Build Coastguard Worker
439*eb293b8fSAndroid Build Coastguard Worker // Get the elf from the read-exec map first.
440*eb293b8fSAndroid Build Coastguard Worker Elf* elf = rx_map_info->GetElf(process_memory_, ARCH_ARM);
441*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
442*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
443*eb293b8fSAndroid Build Coastguard Worker
444*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(elf, r_map_info->GetElf(process_memory_, ARCH_ARM));
445*eb293b8fSAndroid Build Coastguard Worker
446*eb293b8fSAndroid Build Coastguard Worker // Now use file maps.
447*eb293b8fSAndroid Build Coastguard Worker maps.clear();
448*eb293b8fSAndroid Build Coastguard Worker InitMapInfo(maps, false);
449*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(2U, maps.size());
450*eb293b8fSAndroid Build Coastguard Worker r_map_info = maps[0].get();
451*eb293b8fSAndroid Build Coastguard Worker rx_map_info = maps[1].get();
452*eb293b8fSAndroid Build Coastguard Worker
453*eb293b8fSAndroid Build Coastguard Worker // Get the elf from the read-exec map first.
454*eb293b8fSAndroid Build Coastguard Worker elf = rx_map_info->GetElf(process_memory_, ARCH_ARM);
455*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
456*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
457*eb293b8fSAndroid Build Coastguard Worker
458*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(elf, r_map_info->GetElf(process_memory_, ARCH_ARM));
459*eb293b8fSAndroid Build Coastguard Worker }
460*eb293b8fSAndroid Build Coastguard Worker
461*eb293b8fSAndroid Build Coastguard Worker // Verify that a read-only map followed by a read-execute map will result
462*eb293b8fSAndroid Build Coastguard Worker // in the same elf object in both maps.
TEST_F(MapInfoGetElfTest,read_only_followed_by_read_exec_share_elf_read_only_first)463*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf_read_only_first) {
464*eb293b8fSAndroid Build Coastguard Worker std::vector<std::shared_ptr<MapInfo>> maps;
465*eb293b8fSAndroid Build Coastguard Worker
466*eb293b8fSAndroid Build Coastguard Worker // First use in memory maps.
467*eb293b8fSAndroid Build Coastguard Worker InitMapInfo(maps, true);
468*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(2U, maps.size());
469*eb293b8fSAndroid Build Coastguard Worker MapInfo* r_map_info = maps[0].get();
470*eb293b8fSAndroid Build Coastguard Worker MapInfo* rx_map_info = maps[1].get();
471*eb293b8fSAndroid Build Coastguard Worker
472*eb293b8fSAndroid Build Coastguard Worker // Get the elf from the read-only map first.
473*eb293b8fSAndroid Build Coastguard Worker Elf* elf = r_map_info->GetElf(process_memory_, ARCH_ARM);
474*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
475*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
476*eb293b8fSAndroid Build Coastguard Worker
477*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(elf, rx_map_info->GetElf(process_memory_, ARCH_ARM));
478*eb293b8fSAndroid Build Coastguard Worker
479*eb293b8fSAndroid Build Coastguard Worker // Now use file maps.
480*eb293b8fSAndroid Build Coastguard Worker maps.clear();
481*eb293b8fSAndroid Build Coastguard Worker InitMapInfo(maps, false);
482*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(2U, maps.size());
483*eb293b8fSAndroid Build Coastguard Worker r_map_info = maps[0].get();
484*eb293b8fSAndroid Build Coastguard Worker rx_map_info = maps[1].get();
485*eb293b8fSAndroid Build Coastguard Worker
486*eb293b8fSAndroid Build Coastguard Worker // Get the elf from the read-only map first.
487*eb293b8fSAndroid Build Coastguard Worker elf = r_map_info->GetElf(process_memory_, ARCH_ARM);
488*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
489*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
490*eb293b8fSAndroid Build Coastguard Worker
491*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(elf, rx_map_info->GetElf(process_memory_, ARCH_ARM));
492*eb293b8fSAndroid Build Coastguard Worker }
493*eb293b8fSAndroid Build Coastguard Worker
494*eb293b8fSAndroid Build Coastguard Worker // Verify that a read-only map followed by an empty map, then followed by
495*eb293b8fSAndroid Build Coastguard Worker // a read-execute map will result in the same elf object in both maps.
TEST_F(MapInfoGetElfTest,read_only_followed_by_empty_then_read_exec_share_elf)496*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoGetElfTest, read_only_followed_by_empty_then_read_exec_share_elf) {
497*eb293b8fSAndroid Build Coastguard Worker auto r_info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, elf_.path);
498*eb293b8fSAndroid Build Coastguard Worker auto empty = MapInfo::Create(r_info, 0x2000, 0x3000, 0, 0, "");
499*eb293b8fSAndroid Build Coastguard Worker auto rw_info = MapInfo::Create(empty, 0x3000, 0x4000, 0x2000, PROT_READ | PROT_EXEC, elf_.path);
500*eb293b8fSAndroid Build Coastguard Worker
501*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr;
502*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
503*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
504*eb293b8fSAndroid Build Coastguard Worker Elf* elf = rw_info->GetElf(process_memory_, ARCH_ARM);
505*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf != nullptr);
506*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(elf->valid());
507*eb293b8fSAndroid Build Coastguard Worker
508*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(elf, r_info->GetElf(process_memory_, ARCH_ARM));
509*eb293b8fSAndroid Build Coastguard Worker }
510*eb293b8fSAndroid Build Coastguard Worker
511*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
512