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 <memory>
27*eb293b8fSAndroid Build Coastguard Worker #include <vector>
28*eb293b8fSAndroid Build Coastguard Worker
29*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
31*eb293b8fSAndroid Build Coastguard Worker
32*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
34*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
35*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
36*eb293b8fSAndroid Build Coastguard Worker
37*eb293b8fSAndroid Build Coastguard Worker #include "ElfTestUtils.h"
38*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
39*eb293b8fSAndroid Build Coastguard Worker
40*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
41*eb293b8fSAndroid Build Coastguard Worker
42*eb293b8fSAndroid Build Coastguard Worker class MapInfoCreateMemoryTest : public ::testing::Test {
43*eb293b8fSAndroid Build Coastguard Worker protected:
44*eb293b8fSAndroid Build Coastguard Worker template <typename Ehdr, typename Shdr>
InitElf(int fd,uint64_t file_offset,uint64_t sh_offset,uint8_t class_type)45*eb293b8fSAndroid Build Coastguard Worker static void InitElf(int fd, uint64_t file_offset, uint64_t sh_offset, uint8_t class_type) {
46*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(20000);
47*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
48*eb293b8fSAndroid Build Coastguard Worker
49*eb293b8fSAndroid Build Coastguard Worker Ehdr ehdr;
50*eb293b8fSAndroid Build Coastguard Worker memset(&ehdr, 0, sizeof(ehdr));
51*eb293b8fSAndroid Build Coastguard Worker memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
52*eb293b8fSAndroid Build Coastguard Worker ehdr.e_ident[EI_CLASS] = class_type;
53*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = sh_offset;
54*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = sizeof(Shdr) + 100;
55*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 4;
56*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[file_offset], &ehdr, sizeof(ehdr));
57*eb293b8fSAndroid Build Coastguard Worker
58*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size()));
59*eb293b8fSAndroid Build Coastguard Worker }
60*eb293b8fSAndroid Build Coastguard Worker
SetUp()61*eb293b8fSAndroid Build Coastguard Worker void SetUp() override {
62*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(12288, 0);
63*eb293b8fSAndroid Build Coastguard Worker memcpy(buffer.data(), ELFMAG, SELFMAG);
64*eb293b8fSAndroid Build Coastguard Worker buffer[EI_CLASS] = ELFCLASS32;
65*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), 1024));
66*eb293b8fSAndroid Build Coastguard Worker
67*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
68*eb293b8fSAndroid Build Coastguard Worker memcpy(&buffer[0x1000], ELFMAG, SELFMAG);
69*eb293b8fSAndroid Build Coastguard Worker buffer[0x1000 + EI_CLASS] = ELFCLASS64;
70*eb293b8fSAndroid Build Coastguard Worker buffer[0x2000] = 0xff;
71*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, buffer.data(), buffer.size()));
72*eb293b8fSAndroid Build Coastguard Worker
73*eb293b8fSAndroid Build Coastguard Worker InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32);
74*eb293b8fSAndroid Build Coastguard Worker InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64);
75*eb293b8fSAndroid Build Coastguard Worker
76*eb293b8fSAndroid Build Coastguard Worker memory_ = new MemoryFake;
77*eb293b8fSAndroid Build Coastguard Worker process_memory_.reset(memory_);
78*eb293b8fSAndroid Build Coastguard Worker }
79*eb293b8fSAndroid Build Coastguard Worker
80*eb293b8fSAndroid Build Coastguard Worker MemoryFake* memory_;
81*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> process_memory_;
82*eb293b8fSAndroid Build Coastguard Worker
83*eb293b8fSAndroid Build Coastguard Worker TemporaryFile elf_;
84*eb293b8fSAndroid Build Coastguard Worker
85*eb293b8fSAndroid Build Coastguard Worker TemporaryFile elf_at_1000_;
86*eb293b8fSAndroid Build Coastguard Worker
87*eb293b8fSAndroid Build Coastguard Worker TemporaryFile elf32_at_map_;
88*eb293b8fSAndroid Build Coastguard Worker TemporaryFile elf64_at_map_;
89*eb293b8fSAndroid Build Coastguard Worker };
90*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,end_le_start)91*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, end_le_start) {
92*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x100, 0x100, 0, 0, elf_.path);
93*eb293b8fSAndroid Build Coastguard Worker
94*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
95*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() == nullptr);
96*eb293b8fSAndroid Build Coastguard Worker
97*eb293b8fSAndroid Build Coastguard Worker info->set_end(0xff);
98*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
99*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() == nullptr);
100*eb293b8fSAndroid Build Coastguard Worker
101*eb293b8fSAndroid Build Coastguard Worker // Make sure this test is valid.
102*eb293b8fSAndroid Build Coastguard Worker info->set_end(0x101);
103*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
104*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
105*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
106*eb293b8fSAndroid Build Coastguard Worker }
107*eb293b8fSAndroid Build Coastguard Worker
108*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero but there is no elf at the offset,
109*eb293b8fSAndroid Build Coastguard Worker // that the full file is used.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_full_file)110*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
111*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x100, 0x200, 0x100, 0, elf_.path);
112*eb293b8fSAndroid Build Coastguard Worker
113*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
114*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
115*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
116*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
117*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, info->elf_start_offset());
118*eb293b8fSAndroid Build Coastguard Worker
119*eb293b8fSAndroid Build Coastguard Worker // Read the entire file.
120*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(1024);
121*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 1024));
122*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
123*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]);
124*eb293b8fSAndroid Build Coastguard Worker for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
125*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
126*eb293b8fSAndroid Build Coastguard Worker }
127*eb293b8fSAndroid Build Coastguard Worker
128*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1));
129*eb293b8fSAndroid Build Coastguard Worker
130*eb293b8fSAndroid Build Coastguard Worker // Now verify the elf start offset is set correctly based on the previous
131*eb293b8fSAndroid Build Coastguard Worker // info.
132*eb293b8fSAndroid Build Coastguard Worker auto prev_info = MapInfo::Create(0, 0x100, 0x10, 0, "");
133*eb293b8fSAndroid Build Coastguard Worker info->set_prev_map(prev_info);
134*eb293b8fSAndroid Build Coastguard Worker
135*eb293b8fSAndroid Build Coastguard Worker // No preconditions met, change each one until it should set the elf start
136*eb293b8fSAndroid Build Coastguard Worker // offset to zero.
137*eb293b8fSAndroid Build Coastguard Worker info->set_elf_offset(0);
138*eb293b8fSAndroid Build Coastguard Worker info->set_elf_start_offset(0);
139*eb293b8fSAndroid Build Coastguard Worker info->set_memory_backed_elf(false);
140*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
141*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
142*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
143*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
144*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, info->elf_start_offset());
145*eb293b8fSAndroid Build Coastguard Worker
146*eb293b8fSAndroid Build Coastguard Worker prev_info->set_offset(0);
147*eb293b8fSAndroid Build Coastguard Worker info->set_elf_offset(0);
148*eb293b8fSAndroid Build Coastguard Worker info->set_elf_start_offset(0);
149*eb293b8fSAndroid Build Coastguard Worker info->set_memory_backed_elf(false);
150*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
151*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
152*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
153*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
154*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, info->elf_start_offset());
155*eb293b8fSAndroid Build Coastguard Worker
156*eb293b8fSAndroid Build Coastguard Worker prev_info->set_flags(PROT_READ);
157*eb293b8fSAndroid Build Coastguard Worker info->set_elf_offset(0);
158*eb293b8fSAndroid Build Coastguard Worker info->set_elf_start_offset(0);
159*eb293b8fSAndroid Build Coastguard Worker info->set_memory_backed_elf(false);
160*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
161*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
162*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
163*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
164*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, info->elf_start_offset());
165*eb293b8fSAndroid Build Coastguard Worker
166*eb293b8fSAndroid Build Coastguard Worker prev_info->set_name(info->name());
167*eb293b8fSAndroid Build Coastguard Worker info->set_elf_offset(0);
168*eb293b8fSAndroid Build Coastguard Worker info->set_elf_start_offset(0);
169*eb293b8fSAndroid Build Coastguard Worker info->set_memory_backed_elf(false);
170*eb293b8fSAndroid Build Coastguard Worker memory = info->CreateMemory(process_memory_);
171*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
172*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
173*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x100U, info->elf_offset());
174*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, info->elf_start_offset());
175*eb293b8fSAndroid Build Coastguard Worker }
176*eb293b8fSAndroid Build Coastguard Worker
177*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero and there is an elf at that
178*eb293b8fSAndroid Build Coastguard Worker // offset, that only part of the file is used.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file)179*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
180*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
181*eb293b8fSAndroid Build Coastguard Worker
182*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
183*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
184*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
185*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
186*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1000U, info->elf_start_offset());
187*eb293b8fSAndroid Build Coastguard Worker
188*eb293b8fSAndroid Build Coastguard Worker // Read the valid part of the file.
189*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x100);
190*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
191*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
192*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
193*eb293b8fSAndroid Build Coastguard Worker for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
194*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
195*eb293b8fSAndroid Build Coastguard Worker }
196*eb293b8fSAndroid Build Coastguard Worker
197*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1));
198*eb293b8fSAndroid Build Coastguard Worker }
199*eb293b8fSAndroid Build Coastguard Worker
200*eb293b8fSAndroid Build Coastguard Worker // Verify that if the offset is non-zero and there is an elf at that
201*eb293b8fSAndroid Build Coastguard Worker // offset, that only part of the file is used. Further verify that if the
202*eb293b8fSAndroid Build Coastguard Worker // embedded elf is bigger than the initial map, the new object is larger
203*eb293b8fSAndroid Build Coastguard Worker // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file_whole_elf32)204*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
205*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
206*eb293b8fSAndroid Build Coastguard Worker
207*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
208*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
209*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
210*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
211*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1000U, info->elf_start_offset());
212*eb293b8fSAndroid Build Coastguard Worker
213*eb293b8fSAndroid Build Coastguard Worker // Verify the memory is a valid elf.
214*eb293b8fSAndroid Build Coastguard Worker uint8_t e_ident[SELFMAG + 1];
215*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
216*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
217*eb293b8fSAndroid Build Coastguard Worker
218*eb293b8fSAndroid Build Coastguard Worker // Read past the end of what would normally be the size of the map.
219*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
220*eb293b8fSAndroid Build Coastguard Worker }
221*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file_whole_elf64)222*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
223*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
224*eb293b8fSAndroid Build Coastguard Worker
225*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
226*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
227*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(info->memory_backed_elf());
228*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0U, info->elf_offset());
229*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x2000U, info->elf_start_offset());
230*eb293b8fSAndroid Build Coastguard Worker
231*eb293b8fSAndroid Build Coastguard Worker // Verify the memory is a valid elf.
232*eb293b8fSAndroid Build Coastguard Worker uint8_t e_ident[SELFMAG + 1];
233*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
234*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
235*eb293b8fSAndroid Build Coastguard Worker
236*eb293b8fSAndroid Build Coastguard Worker // Read past the end of what would normally be the size of the map.
237*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
238*eb293b8fSAndroid Build Coastguard Worker }
239*eb293b8fSAndroid Build Coastguard Worker
240*eb293b8fSAndroid Build Coastguard Worker // Verify that device file names will never result in Memory object creation.
TEST_F(MapInfoCreateMemoryTest,check_device_maps)241*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
242*eb293b8fSAndroid Build Coastguard Worker // Set up some memory so that a valid local memory object would
243*eb293b8fSAndroid Build Coastguard Worker // be returned if the file mapping fails, but the device check is incorrect.
244*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(1024);
245*eb293b8fSAndroid Build Coastguard Worker uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
246*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(start, start + buffer.size(), 0, 0x8000, "/dev/something");
247*eb293b8fSAndroid Build Coastguard Worker
248*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
249*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() == nullptr);
250*eb293b8fSAndroid Build Coastguard Worker }
251*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,process_memory)252*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, process_memory) {
253*eb293b8fSAndroid Build Coastguard Worker auto info = MapInfo::Create(0x2000, 0x3000, 0, PROT_READ, "");
254*eb293b8fSAndroid Build Coastguard Worker
255*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr = {};
256*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
257*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(1024);
258*eb293b8fSAndroid Build Coastguard Worker memcpy(buffer.data(), &ehdr, sizeof(ehdr));
259*eb293b8fSAndroid Build Coastguard Worker
260*eb293b8fSAndroid Build Coastguard Worker // Verify that the the process_memory object is used, so seed it
261*eb293b8fSAndroid Build Coastguard Worker // with memory.
262*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
263*eb293b8fSAndroid Build Coastguard Worker buffer[i] = i % 256;
264*eb293b8fSAndroid Build Coastguard Worker }
265*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(info->start(), buffer.data(), buffer.size());
266*eb293b8fSAndroid Build Coastguard Worker
267*eb293b8fSAndroid Build Coastguard Worker auto memory = info->CreateMemory(process_memory_);
268*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
269*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(info->memory_backed_elf());
270*eb293b8fSAndroid Build Coastguard Worker
271*eb293b8fSAndroid Build Coastguard Worker memset(buffer.data(), 0, buffer.size());
272*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
273*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
274*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
275*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
276*eb293b8fSAndroid Build Coastguard Worker }
277*eb293b8fSAndroid Build Coastguard Worker
278*eb293b8fSAndroid Build Coastguard Worker // Try to read outside of the map size.
279*eb293b8fSAndroid Build Coastguard Worker ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
280*eb293b8fSAndroid Build Coastguard Worker }
281*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_zero_offset)282*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
283*eb293b8fSAndroid Build Coastguard Worker Maps maps;
284*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
285*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
286*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
287*eb293b8fSAndroid Build Coastguard Worker
288*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr = {};
289*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
290*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
291*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
292*eb293b8fSAndroid Build Coastguard Worker
293*eb293b8fSAndroid Build Coastguard Worker // Set the memory in the r-x map.
294*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
295*eb293b8fSAndroid Build Coastguard Worker
296*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps.Find(0x3000).get();
297*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
298*eb293b8fSAndroid Build Coastguard Worker
299*eb293b8fSAndroid Build Coastguard Worker auto mem = map_info->CreateMemory(process_memory_);
300*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(mem.get() != nullptr);
301*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(map_info->memory_backed_elf());
302*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x4000UL, map_info->elf_offset());
303*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x4000UL, map_info->offset());
304*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, map_info->elf_start_offset());
305*eb293b8fSAndroid Build Coastguard Worker
306*eb293b8fSAndroid Build Coastguard Worker // Verify that reading values from this memory works properly.
307*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
308*eb293b8fSAndroid Build Coastguard Worker size_t bytes = mem->Read(0, buffer.data(), buffer.size());
309*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1600UL, bytes);
310*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
311*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < bytes; i++) {
312*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
313*eb293b8fSAndroid Build Coastguard Worker }
314*eb293b8fSAndroid Build Coastguard Worker
315*eb293b8fSAndroid Build Coastguard Worker bytes = mem->Read(0x4000, buffer.data(), buffer.size());
316*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x2000UL, bytes);
317*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < bytes; i++) {
318*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
319*eb293b8fSAndroid Build Coastguard Worker }
320*eb293b8fSAndroid Build Coastguard Worker }
321*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_non_zero_offset)322*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
323*eb293b8fSAndroid Build Coastguard Worker Maps maps;
324*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
325*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
326*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
327*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
328*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
329*eb293b8fSAndroid Build Coastguard Worker
330*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr = {};
331*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
332*eb293b8fSAndroid Build Coastguard Worker
333*eb293b8fSAndroid Build Coastguard Worker // Setup an elf at offset 0x1000 in memory.
334*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
335*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
336*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
337*eb293b8fSAndroid Build Coastguard Worker
338*eb293b8fSAndroid Build Coastguard Worker // Setup an elf at offset 0x3000 in memory..
339*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
340*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
341*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
342*eb293b8fSAndroid Build Coastguard Worker
343*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps.Find(0x4000).get();
344*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
345*eb293b8fSAndroid Build Coastguard Worker
346*eb293b8fSAndroid Build Coastguard Worker auto mem = map_info->CreateMemory(process_memory_);
347*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(mem.get() != nullptr);
348*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(map_info->memory_backed_elf());
349*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1000UL, map_info->elf_offset());
350*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xb000UL, map_info->offset());
351*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xa000UL, map_info->elf_start_offset());
352*eb293b8fSAndroid Build Coastguard Worker
353*eb293b8fSAndroid Build Coastguard Worker // Verify that reading values from this memory works properly.
354*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x4000);
355*eb293b8fSAndroid Build Coastguard Worker size_t bytes = mem->Read(0, buffer.data(), buffer.size());
356*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000UL, bytes);
357*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
358*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < bytes; i++) {
359*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
360*eb293b8fSAndroid Build Coastguard Worker }
361*eb293b8fSAndroid Build Coastguard Worker
362*eb293b8fSAndroid Build Coastguard Worker bytes = mem->Read(0x1000, buffer.data(), buffer.size());
363*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000UL, bytes);
364*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < bytes; i++) {
365*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
366*eb293b8fSAndroid Build Coastguard Worker }
367*eb293b8fSAndroid Build Coastguard Worker }
368*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,valid_single_rx_non_zero_offset)369*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, valid_single_rx_non_zero_offset) {
370*eb293b8fSAndroid Build Coastguard Worker Maps maps;
371*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x3000, 0x5000, 0xa000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
372*eb293b8fSAndroid Build Coastguard Worker
373*eb293b8fSAndroid Build Coastguard Worker Elf32_Ehdr ehdr = {};
374*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
375*eb293b8fSAndroid Build Coastguard Worker
376*eb293b8fSAndroid Build Coastguard Worker // Setup an elf at offset 0x3000 in memory..
377*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
378*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x5000 - sizeof(ehdr), 0x34);
379*eb293b8fSAndroid Build Coastguard Worker
380*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps.Find(0x3000);
381*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
382*eb293b8fSAndroid Build Coastguard Worker
383*eb293b8fSAndroid Build Coastguard Worker auto mem = map_info->CreateMemory(process_memory_);
384*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(mem.get() != nullptr);
385*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(map_info->memory_backed_elf());
386*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0UL, map_info->elf_offset());
387*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xa000UL, map_info->offset());
388*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xa000UL, map_info->elf_start_offset());
389*eb293b8fSAndroid Build Coastguard Worker
390*eb293b8fSAndroid Build Coastguard Worker // Verify that reading values from this memory works properly.
391*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x3000);
392*eb293b8fSAndroid Build Coastguard Worker size_t bytes = mem->Read(0, buffer.data(), buffer.size());
393*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x2000UL, bytes);
394*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
395*eb293b8fSAndroid Build Coastguard Worker for (size_t i = sizeof(ehdr); i < bytes; i++) {
396*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
397*eb293b8fSAndroid Build Coastguard Worker }
398*eb293b8fSAndroid Build Coastguard Worker }
399*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,rosegment_from_file)400*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
401*eb293b8fSAndroid Build Coastguard Worker Maps maps;
402*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
403*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
404*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
405*eb293b8fSAndroid Build Coastguard Worker
406*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps.Find(0x2000).get();
407*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
408*eb293b8fSAndroid Build Coastguard Worker
409*eb293b8fSAndroid Build Coastguard Worker // Set up the size
410*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr;
411*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
412*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
413*eb293b8fSAndroid Build Coastguard Worker
414*eb293b8fSAndroid Build Coastguard Worker // Will not give the elf memory, because the read-only entry does not
415*eb293b8fSAndroid Build Coastguard Worker // extend over the executable segment.
416*eb293b8fSAndroid Build Coastguard Worker auto memory = map_info->CreateMemory(process_memory_);
417*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory.get() != nullptr);
418*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(map_info->memory_backed_elf());
419*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x100);
420*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x2000U, map_info->offset());
421*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, map_info->elf_offset());
422*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, map_info->elf_start_offset());
423*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
424*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xffU, buffer[0]);
425*eb293b8fSAndroid Build Coastguard Worker
426*eb293b8fSAndroid Build Coastguard Worker // Now init the elf data enough so that the file memory object will be used.
427*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shoff = 0x4000;
428*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shnum = 1;
429*eb293b8fSAndroid Build Coastguard Worker ehdr.e_shentsize = 0x100;
430*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
431*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
432*eb293b8fSAndroid Build Coastguard Worker
433*eb293b8fSAndroid Build Coastguard Worker map_info->set_memory_backed_elf(false);
434*eb293b8fSAndroid Build Coastguard Worker memory = map_info->CreateMemory(process_memory_);
435*eb293b8fSAndroid Build Coastguard Worker EXPECT_FALSE(map_info->memory_backed_elf());
436*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x2000U, map_info->offset());
437*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1000U, map_info->elf_offset());
438*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x1000U, map_info->elf_start_offset());
439*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr_mem;
440*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem)));
441*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0);
442*eb293b8fSAndroid Build Coastguard Worker }
443*eb293b8fSAndroid Build Coastguard Worker
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_offset_overflow)444*eb293b8fSAndroid Build Coastguard Worker TEST_F(MapInfoCreateMemoryTest, valid_rosegment_offset_overflow) {
445*eb293b8fSAndroid Build Coastguard Worker Maps maps;
446*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
447*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.so", 0);
448*eb293b8fSAndroid Build Coastguard Worker maps.Add(0x3000, 0x4000, 0xfffffffffffff000UL, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
449*eb293b8fSAndroid Build Coastguard Worker
450*eb293b8fSAndroid Build Coastguard Worker Elf64_Ehdr ehdr = {};
451*eb293b8fSAndroid Build Coastguard Worker TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
452*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
453*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1000 - sizeof(ehdr), 0xab);
454*eb293b8fSAndroid Build Coastguard Worker
455*eb293b8fSAndroid Build Coastguard Worker // Set the memory in the r-x map.
456*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
457*eb293b8fSAndroid Build Coastguard Worker
458*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps.Find(0x3000).get();
459*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
460*eb293b8fSAndroid Build Coastguard Worker
461*eb293b8fSAndroid Build Coastguard Worker auto mem = map_info->CreateMemory(process_memory_);
462*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(mem.get() != nullptr);
463*eb293b8fSAndroid Build Coastguard Worker EXPECT_TRUE(map_info->memory_backed_elf());
464*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xfffffffffffff000UL, map_info->elf_offset());
465*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0xfffffffffffff000UL, map_info->offset());
466*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, map_info->elf_start_offset());
467*eb293b8fSAndroid Build Coastguard Worker
468*eb293b8fSAndroid Build Coastguard Worker // Verify that reading values from this memory works properly.
469*eb293b8fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer(0x2000);
470*eb293b8fSAndroid Build Coastguard Worker size_t bytes = mem->Read(0xfffffffffffff000UL, buffer.data(), buffer.size());
471*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x1000UL, bytes);
472*eb293b8fSAndroid Build Coastguard Worker for (size_t i = 0; i < bytes; i++) {
473*eb293b8fSAndroid Build Coastguard Worker ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
474*eb293b8fSAndroid Build Coastguard Worker }
475*eb293b8fSAndroid Build Coastguard Worker }
476*eb293b8fSAndroid Build Coastguard Worker
477*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
478