xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/MapInfoCreateMemoryTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
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 "utils/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   auto info = MapInfo::Create(0x100, 0x100, 0, 0, elf_.path);
93 
94   auto memory = info->CreateMemory(process_memory_);
95   ASSERT_TRUE(memory.get() == nullptr);
96 
97   info->set_end(0xff);
98   memory = 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 = 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   auto info = MapInfo::Create(0x100, 0x200, 0x100, 0, elf_.path);
112 
113   auto 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(0U, 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   auto prev_info = MapInfo::Create(0, 0x100, 0x10, 0, "");
133   info->set_prev_map(prev_info);
134 
135   // No preconditions met, change each one until it should set the elf start
136   // offset to zero.
137   info->set_elf_offset(0);
138   info->set_elf_start_offset(0);
139   info->set_memory_backed_elf(false);
140   memory = info->CreateMemory(process_memory_);
141   ASSERT_TRUE(memory.get() != nullptr);
142   EXPECT_FALSE(info->memory_backed_elf());
143   ASSERT_EQ(0x100U, info->elf_offset());
144   EXPECT_EQ(0U, info->elf_start_offset());
145 
146   prev_info->set_offset(0);
147   info->set_elf_offset(0);
148   info->set_elf_start_offset(0);
149   info->set_memory_backed_elf(false);
150   memory = info->CreateMemory(process_memory_);
151   ASSERT_TRUE(memory.get() != nullptr);
152   EXPECT_FALSE(info->memory_backed_elf());
153   ASSERT_EQ(0x100U, info->elf_offset());
154   EXPECT_EQ(0U, info->elf_start_offset());
155 
156   prev_info->set_flags(PROT_READ);
157   info->set_elf_offset(0);
158   info->set_elf_start_offset(0);
159   info->set_memory_backed_elf(false);
160   memory = info->CreateMemory(process_memory_);
161   ASSERT_TRUE(memory.get() != nullptr);
162   EXPECT_FALSE(info->memory_backed_elf());
163   ASSERT_EQ(0x100U, info->elf_offset());
164   EXPECT_EQ(0U, info->elf_start_offset());
165 
166   prev_info->set_name(info->name());
167   info->set_elf_offset(0);
168   info->set_elf_start_offset(0);
169   info->set_memory_backed_elf(false);
170   memory = info->CreateMemory(process_memory_);
171   ASSERT_TRUE(memory.get() != nullptr);
172   EXPECT_FALSE(info->memory_backed_elf());
173   ASSERT_EQ(0x100U, info->elf_offset());
174   EXPECT_EQ(0U, info->elf_start_offset());
175 }
176 
177 // Verify that if the offset is non-zero and there is an elf at that
178 // offset, that only part of the file is used.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file)179 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
180   auto info = MapInfo::Create(0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
181 
182   auto memory = info->CreateMemory(process_memory_);
183   ASSERT_TRUE(memory.get() != nullptr);
184   EXPECT_FALSE(info->memory_backed_elf());
185   ASSERT_EQ(0U, info->elf_offset());
186   EXPECT_EQ(0x1000U, info->elf_start_offset());
187 
188   // Read the valid part of the file.
189   std::vector<uint8_t> buffer(0x100);
190   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
191   ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
192   ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
193   for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
194     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
195   }
196 
197   ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1));
198 }
199 
200 // Verify that if the offset is non-zero and there is an elf at that
201 // offset, that only part of the file is used. Further verify that if the
202 // embedded elf is bigger than the initial map, the new object is larger
203 // 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 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
205   auto info = MapInfo::Create(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
206 
207   auto memory = info->CreateMemory(process_memory_);
208   ASSERT_TRUE(memory.get() != nullptr);
209   EXPECT_FALSE(info->memory_backed_elf());
210   ASSERT_EQ(0U, info->elf_offset());
211   EXPECT_EQ(0x1000U, info->elf_start_offset());
212 
213   // Verify the memory is a valid elf.
214   uint8_t e_ident[SELFMAG + 1];
215   ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
216   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
217 
218   // Read past the end of what would normally be the size of the map.
219   ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
220 }
221 
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file_whole_elf64)222 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
223   auto info = MapInfo::Create(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
224 
225   auto memory = info->CreateMemory(process_memory_);
226   ASSERT_TRUE(memory.get() != nullptr);
227   EXPECT_FALSE(info->memory_backed_elf());
228   ASSERT_EQ(0U, info->elf_offset());
229   EXPECT_EQ(0x2000U, info->elf_start_offset());
230 
231   // Verify the memory is a valid elf.
232   uint8_t e_ident[SELFMAG + 1];
233   ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
234   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
235 
236   // Read past the end of what would normally be the size of the map.
237   ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
238 }
239 
240 // Verify that device file names will never result in Memory object creation.
TEST_F(MapInfoCreateMemoryTest,check_device_maps)241 TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
242   // Set up some memory so that a valid local memory object would
243   // be returned if the file mapping fails, but the device check is incorrect.
244   std::vector<uint8_t> buffer(1024);
245   uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
246   auto info = MapInfo::Create(start, start + buffer.size(), 0, 0x8000, "/dev/something");
247 
248   auto memory = info->CreateMemory(process_memory_);
249   ASSERT_TRUE(memory.get() == nullptr);
250 }
251 
TEST_F(MapInfoCreateMemoryTest,process_memory)252 TEST_F(MapInfoCreateMemoryTest, process_memory) {
253   auto info = MapInfo::Create(0x2000, 0x3000, 0, PROT_READ, "");
254 
255   Elf32_Ehdr ehdr = {};
256   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
257   std::vector<uint8_t> buffer(1024);
258   memcpy(buffer.data(), &ehdr, sizeof(ehdr));
259 
260   // Verify that the the process_memory object is used, so seed it
261   // with memory.
262   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
263     buffer[i] = i % 256;
264   }
265   memory_->SetMemory(info->start(), buffer.data(), buffer.size());
266 
267   auto memory = info->CreateMemory(process_memory_);
268   ASSERT_TRUE(memory.get() != nullptr);
269   EXPECT_TRUE(info->memory_backed_elf());
270 
271   memset(buffer.data(), 0, buffer.size());
272   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
273   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
274   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
275     ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
276   }
277 
278   // Try to read outside of the map size.
279   ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
280 }
281 
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_zero_offset)282 TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
283   Maps maps;
284   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
285   maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
286   maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
287 
288   Elf32_Ehdr ehdr = {};
289   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
290   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
291   memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
292 
293   // Set the memory in the r-x map.
294   memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
295 
296   auto map_info = maps.Find(0x3000).get();
297   ASSERT_TRUE(map_info != nullptr);
298 
299   auto mem = map_info->CreateMemory(process_memory_);
300   ASSERT_TRUE(mem.get() != nullptr);
301   EXPECT_TRUE(map_info->memory_backed_elf());
302   EXPECT_EQ(0x4000UL, map_info->elf_offset());
303   EXPECT_EQ(0x4000UL, map_info->offset());
304   EXPECT_EQ(0U, map_info->elf_start_offset());
305 
306   // Verify that reading values from this memory works properly.
307   std::vector<uint8_t> buffer(0x4000);
308   size_t bytes = mem->Read(0, buffer.data(), buffer.size());
309   ASSERT_EQ(0x1600UL, bytes);
310   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
311   for (size_t i = sizeof(ehdr); i < bytes; i++) {
312     ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
313   }
314 
315   bytes = mem->Read(0x4000, buffer.data(), buffer.size());
316   ASSERT_EQ(0x2000UL, bytes);
317   for (size_t i = 0; i < bytes; i++) {
318     ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
319   }
320 }
321 
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_non_zero_offset)322 TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
323   Maps maps;
324   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
325   maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
326   maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
327   maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
328   maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
329 
330   Elf32_Ehdr ehdr = {};
331   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
332 
333   // Setup an elf at offset 0x1000 in memory.
334   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
335   memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
336   memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
337 
338   // Setup an elf at offset 0x3000 in memory..
339   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
340   memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
341   memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
342 
343   auto map_info = maps.Find(0x4000).get();
344   ASSERT_TRUE(map_info != nullptr);
345 
346   auto mem = map_info->CreateMemory(process_memory_);
347   ASSERT_TRUE(mem.get() != nullptr);
348   EXPECT_TRUE(map_info->memory_backed_elf());
349   EXPECT_EQ(0x1000UL, map_info->elf_offset());
350   EXPECT_EQ(0xb000UL, map_info->offset());
351   EXPECT_EQ(0xa000UL, map_info->elf_start_offset());
352 
353   // Verify that reading values from this memory works properly.
354   std::vector<uint8_t> buffer(0x4000);
355   size_t bytes = mem->Read(0, buffer.data(), buffer.size());
356   ASSERT_EQ(0x1000UL, bytes);
357   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
358   for (size_t i = sizeof(ehdr); i < bytes; i++) {
359     ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
360   }
361 
362   bytes = mem->Read(0x1000, buffer.data(), buffer.size());
363   ASSERT_EQ(0x1000UL, bytes);
364   for (size_t i = 0; i < bytes; i++) {
365     ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
366   }
367 }
368 
TEST_F(MapInfoCreateMemoryTest,valid_single_rx_non_zero_offset)369 TEST_F(MapInfoCreateMemoryTest, valid_single_rx_non_zero_offset) {
370   Maps maps;
371   maps.Add(0x3000, 0x5000, 0xa000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
372 
373   Elf32_Ehdr ehdr = {};
374   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
375 
376   // Setup an elf at offset 0x3000 in memory..
377   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
378   memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x5000 - sizeof(ehdr), 0x34);
379 
380   auto map_info = maps.Find(0x3000);
381   ASSERT_TRUE(map_info != nullptr);
382 
383   auto mem = map_info->CreateMemory(process_memory_);
384   ASSERT_TRUE(mem.get() != nullptr);
385   EXPECT_TRUE(map_info->memory_backed_elf());
386   EXPECT_EQ(0UL, map_info->elf_offset());
387   EXPECT_EQ(0xa000UL, map_info->offset());
388   EXPECT_EQ(0xa000UL, map_info->elf_start_offset());
389 
390   // Verify that reading values from this memory works properly.
391   std::vector<uint8_t> buffer(0x3000);
392   size_t bytes = mem->Read(0, buffer.data(), buffer.size());
393   ASSERT_EQ(0x2000UL, bytes);
394   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
395   for (size_t i = sizeof(ehdr); i < bytes; i++) {
396     ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
397   }
398 }
399 
TEST_F(MapInfoCreateMemoryTest,rosegment_from_file)400 TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
401   Maps maps;
402   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
403   maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
404   maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
405 
406   auto map_info = maps.Find(0x2000).get();
407   ASSERT_TRUE(map_info != nullptr);
408 
409   // Set up the size
410   Elf64_Ehdr ehdr;
411   ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
412   ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
413 
414   // Will not give the elf memory, because the read-only entry does not
415   // extend over the executable segment.
416   auto memory = map_info->CreateMemory(process_memory_);
417   ASSERT_TRUE(memory.get() != nullptr);
418   EXPECT_FALSE(map_info->memory_backed_elf());
419   std::vector<uint8_t> buffer(0x100);
420   EXPECT_EQ(0x2000U, map_info->offset());
421   EXPECT_EQ(0U, map_info->elf_offset());
422   EXPECT_EQ(0U, map_info->elf_start_offset());
423   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
424   EXPECT_EQ(0xffU, buffer[0]);
425 
426   // Now init the elf data enough so that the file memory object will be used.
427   ehdr.e_shoff = 0x4000;
428   ehdr.e_shnum = 1;
429   ehdr.e_shentsize = 0x100;
430   ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
431   ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
432 
433   map_info->set_memory_backed_elf(false);
434   memory = map_info->CreateMemory(process_memory_);
435   EXPECT_FALSE(map_info->memory_backed_elf());
436   EXPECT_EQ(0x2000U, map_info->offset());
437   EXPECT_EQ(0x1000U, map_info->elf_offset());
438   EXPECT_EQ(0x1000U, map_info->elf_start_offset());
439   Elf64_Ehdr ehdr_mem;
440   ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem)));
441   EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0);
442 }
443 
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_offset_overflow)444 TEST_F(MapInfoCreateMemoryTest, valid_rosegment_offset_overflow) {
445   Maps maps;
446   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
447   maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.so", 0);
448   maps.Add(0x3000, 0x4000, 0xfffffffffffff000UL, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
449 
450   Elf64_Ehdr ehdr = {};
451   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
452   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
453   memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1000 - sizeof(ehdr), 0xab);
454 
455   // Set the memory in the r-x map.
456   memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
457 
458   auto map_info = maps.Find(0x3000).get();
459   ASSERT_TRUE(map_info != nullptr);
460 
461   auto mem = map_info->CreateMemory(process_memory_);
462   ASSERT_TRUE(mem.get() != nullptr);
463   EXPECT_TRUE(map_info->memory_backed_elf());
464   EXPECT_EQ(0xfffffffffffff000UL, map_info->elf_offset());
465   EXPECT_EQ(0xfffffffffffff000UL, map_info->offset());
466   EXPECT_EQ(0U, map_info->elf_start_offset());
467 
468   // Verify that reading values from this memory works properly.
469   std::vector<uint8_t> buffer(0x2000);
470   size_t bytes = mem->Read(0xfffffffffffff000UL, buffer.data(), buffer.size());
471   ASSERT_EQ(0x1000UL, bytes);
472   for (size_t i = 0; i < bytes; i++) {
473     ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
474   }
475 }
476 
477 }  // namespace unwindstack
478