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