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