• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SetUpTestCase()61   static void SetUpTestCase() {
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 
SetUp()77   void SetUp() override {
78     memory_ = new MemoryFake;
79     process_memory_.reset(memory_);
80   }
81 
82   MemoryFake* memory_;
83   std::shared_ptr<Memory> process_memory_;
84 
85   static TemporaryFile elf_;
86 
87   static TemporaryFile elf_at_1000_;
88 
89   static TemporaryFile elf32_at_map_;
90   static TemporaryFile elf64_at_map_;
91 };
92 TemporaryFile MapInfoCreateMemoryTest::elf_;
93 TemporaryFile MapInfoCreateMemoryTest::elf_at_1000_;
94 TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_;
95 TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
96 
TEST_F(MapInfoCreateMemoryTest,end_le_start)97 TEST_F(MapInfoCreateMemoryTest, end_le_start) {
98   MapInfo info(nullptr, 0x100, 0x100, 0, 0, elf_.path);
99 
100   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
101   ASSERT_TRUE(memory.get() == nullptr);
102 
103   info.end = 0xff;
104   memory.reset(info.CreateMemory(process_memory_));
105   ASSERT_TRUE(memory.get() == nullptr);
106 
107   // Make sure this test is valid.
108   info.end = 0x101;
109   memory.reset(info.CreateMemory(process_memory_));
110   ASSERT_TRUE(memory.get() != nullptr);
111   EXPECT_FALSE(info.memory_backed_elf);
112 }
113 
114 // Verify that if the offset is non-zero but there is no elf at the offset,
115 // that the full file is used.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_full_file)116 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
117   MapInfo info(nullptr, 0x100, 0x200, 0x100, 0, elf_.path);
118 
119   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
120   ASSERT_TRUE(memory.get() != nullptr);
121   EXPECT_FALSE(info.memory_backed_elf);
122   ASSERT_EQ(0x100U, info.elf_offset);
123   EXPECT_EQ(0x100U, info.elf_start_offset);
124 
125   // Read the entire file.
126   std::vector<uint8_t> buffer(1024);
127   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 1024));
128   ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
129   ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]);
130   for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
131     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
132   }
133 
134   ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1));
135 
136   // Now verify the elf start offset is set correctly based on the previous
137   // info.
138   MapInfo prev_info(nullptr, 0, 0x100, 0x10, 0, "");
139   info.prev_map = &prev_info;
140 
141   // No preconditions met, change each one until it should set the elf start
142   // offset to zero.
143   info.elf_offset = 0;
144   info.elf_start_offset = 0;
145   info.memory_backed_elf = false;
146   memory.reset(info.CreateMemory(process_memory_));
147   ASSERT_TRUE(memory.get() != nullptr);
148   EXPECT_FALSE(info.memory_backed_elf);
149   ASSERT_EQ(0x100U, info.elf_offset);
150   EXPECT_EQ(0x100U, info.elf_start_offset);
151 
152   prev_info.offset = 0;
153   info.elf_offset = 0;
154   info.elf_start_offset = 0;
155   info.memory_backed_elf = false;
156   memory.reset(info.CreateMemory(process_memory_));
157   ASSERT_TRUE(memory.get() != nullptr);
158   EXPECT_FALSE(info.memory_backed_elf);
159   ASSERT_EQ(0x100U, info.elf_offset);
160   EXPECT_EQ(0x100U, info.elf_start_offset);
161 
162   prev_info.flags = PROT_READ;
163   info.elf_offset = 0;
164   info.elf_start_offset = 0;
165   info.memory_backed_elf = false;
166   memory.reset(info.CreateMemory(process_memory_));
167   ASSERT_TRUE(memory.get() != nullptr);
168   EXPECT_FALSE(info.memory_backed_elf);
169   ASSERT_EQ(0x100U, info.elf_offset);
170   EXPECT_EQ(0x100U, info.elf_start_offset);
171 
172   prev_info.name = info.name;
173   info.elf_offset = 0;
174   info.elf_start_offset = 0;
175   info.memory_backed_elf = false;
176   memory.reset(info.CreateMemory(process_memory_));
177   ASSERT_TRUE(memory.get() != nullptr);
178   EXPECT_FALSE(info.memory_backed_elf);
179   ASSERT_EQ(0x100U, info.elf_offset);
180   EXPECT_EQ(0U, info.elf_start_offset);
181 }
182 
183 // Verify that if the offset is non-zero and there is an elf at that
184 // offset, that only part of the file is used.
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file)185 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
186   MapInfo info(nullptr, 0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
187 
188   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
189   ASSERT_TRUE(memory.get() != nullptr);
190   EXPECT_FALSE(info.memory_backed_elf);
191   ASSERT_EQ(0U, info.elf_offset);
192   EXPECT_EQ(0x1000U, info.elf_start_offset);
193 
194   // Read the valid part of the file.
195   std::vector<uint8_t> buffer(0x100);
196   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
197   ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
198   ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
199   for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
200     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
201   }
202 
203   ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1));
204 }
205 
206 // Verify that if the offset is non-zero and there is an elf at that
207 // offset, that only part of the file is used. Further verify that if the
208 // embedded elf is bigger than the initial map, the new object is larger
209 // 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)210 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
211   MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
212 
213   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
214   ASSERT_TRUE(memory.get() != nullptr);
215   EXPECT_FALSE(info.memory_backed_elf);
216   ASSERT_EQ(0U, info.elf_offset);
217   EXPECT_EQ(0x1000U, info.elf_start_offset);
218 
219   // Verify the memory is a valid elf.
220   uint8_t e_ident[SELFMAG + 1];
221   ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
222   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
223 
224   // Read past the end of what would normally be the size of the map.
225   ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
226 }
227 
TEST_F(MapInfoCreateMemoryTest,file_backed_non_zero_offset_partial_file_whole_elf64)228 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
229   MapInfo info(nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
230 
231   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
232   ASSERT_TRUE(memory.get() != nullptr);
233   EXPECT_FALSE(info.memory_backed_elf);
234   ASSERT_EQ(0U, info.elf_offset);
235   EXPECT_EQ(0x2000U, info.elf_start_offset);
236 
237   // Verify the memory is a valid elf.
238   uint8_t e_ident[SELFMAG + 1];
239   ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG));
240   ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
241 
242   // Read past the end of what would normally be the size of the map.
243   ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1));
244 }
245 
246 // Verify that device file names will never result in Memory object creation.
TEST_F(MapInfoCreateMemoryTest,check_device_maps)247 TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
248   // Set up some memory so that a valid local memory object would
249   // be returned if the file mapping fails, but the device check is incorrect.
250   std::vector<uint8_t> buffer(1024);
251   uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
252   MapInfo info(nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something");
253 
254   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
255   ASSERT_TRUE(memory.get() == nullptr);
256 }
257 
TEST_F(MapInfoCreateMemoryTest,process_memory)258 TEST_F(MapInfoCreateMemoryTest, process_memory) {
259   MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
260 
261   Elf32_Ehdr ehdr = {};
262   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
263   std::vector<uint8_t> buffer(1024);
264   memcpy(buffer.data(), &ehdr, sizeof(ehdr));
265 
266   // Verify that the the process_memory object is used, so seed it
267   // with memory.
268   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
269     buffer[i] = i % 256;
270   }
271   memory_->SetMemory(info.start, buffer.data(), buffer.size());
272 
273   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
274   ASSERT_TRUE(memory.get() != nullptr);
275   EXPECT_TRUE(info.memory_backed_elf);
276 
277   memset(buffer.data(), 0, buffer.size());
278   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
279   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
280   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
281     ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
282   }
283 
284   // Try to read outside of the map size.
285   ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
286 }
287 
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_zero_offset)288 TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
289   Maps maps;
290   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
291   maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
292   maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
293 
294   Elf32_Ehdr ehdr = {};
295   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
296   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
297   memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
298 
299   // Set the memory in the r-x map.
300   memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
301 
302   MapInfo* map_info = maps.Find(0x3000);
303   ASSERT_TRUE(map_info != nullptr);
304 
305   std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
306   ASSERT_TRUE(mem.get() != nullptr);
307   EXPECT_TRUE(map_info->memory_backed_elf);
308   EXPECT_EQ(0x4000UL, map_info->elf_offset);
309   EXPECT_EQ(0x4000UL, map_info->offset);
310   EXPECT_EQ(0U, map_info->elf_start_offset);
311 
312   // Verify that reading values from this memory works properly.
313   std::vector<uint8_t> buffer(0x4000);
314   size_t bytes = mem->Read(0, buffer.data(), buffer.size());
315   ASSERT_EQ(0x1600UL, bytes);
316   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
317   for (size_t i = sizeof(ehdr); i < bytes; i++) {
318     ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
319   }
320 
321   bytes = mem->Read(0x4000, buffer.data(), buffer.size());
322   ASSERT_EQ(0x2000UL, bytes);
323   for (size_t i = 0; i < bytes; i++) {
324     ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
325   }
326 }
327 
TEST_F(MapInfoCreateMemoryTest,valid_rosegment_non_zero_offset)328 TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
329   Maps maps;
330   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
331   maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
332   maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
333   maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
334   maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
335 
336   Elf32_Ehdr ehdr = {};
337   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
338 
339   // Setup an elf at offset 0x1000 in memory.
340   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
341   memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
342   memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
343 
344   // Setup an elf at offset 0x3000 in memory..
345   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
346   memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
347   memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
348 
349   MapInfo* map_info = maps.Find(0x4000);
350   ASSERT_TRUE(map_info != nullptr);
351 
352   std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
353   ASSERT_TRUE(mem.get() != nullptr);
354   EXPECT_TRUE(map_info->memory_backed_elf);
355   EXPECT_EQ(0x1000UL, map_info->elf_offset);
356   EXPECT_EQ(0xb000UL, map_info->offset);
357   EXPECT_EQ(0xa000UL, map_info->elf_start_offset);
358 
359   // Verify that reading values from this memory works properly.
360   std::vector<uint8_t> buffer(0x4000);
361   size_t bytes = mem->Read(0, buffer.data(), buffer.size());
362   ASSERT_EQ(0x1000UL, bytes);
363   ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
364   for (size_t i = sizeof(ehdr); i < bytes; i++) {
365     ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
366   }
367 
368   bytes = mem->Read(0x1000, buffer.data(), buffer.size());
369   ASSERT_EQ(0x1000UL, bytes);
370   for (size_t i = 0; i < bytes; i++) {
371     ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
372   }
373 }
374 
TEST_F(MapInfoCreateMemoryTest,rosegment_from_file)375 TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
376   Maps maps;
377   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
378   maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
379   maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
380 
381   MapInfo* map_info = maps.Find(0x2000);
382   ASSERT_TRUE(map_info != nullptr);
383 
384   // Set up the size
385   Elf64_Ehdr ehdr;
386   ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
387   ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
388 
389   // Will not give the elf memory, because the read-only entry does not
390   // extend over the executable segment.
391   std::unique_ptr<Memory> memory(map_info->CreateMemory(process_memory_));
392   ASSERT_TRUE(memory.get() != nullptr);
393   EXPECT_FALSE(map_info->memory_backed_elf);
394   std::vector<uint8_t> buffer(0x100);
395   EXPECT_EQ(0x2000U, map_info->offset);
396   EXPECT_EQ(0U, map_info->elf_offset);
397   EXPECT_EQ(0U, map_info->elf_start_offset);
398   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
399   EXPECT_EQ(0xffU, buffer[0]);
400 
401   // Now init the elf data enough so that the file memory object will be used.
402   ehdr.e_shoff = 0x4000;
403   ehdr.e_shnum = 1;
404   ehdr.e_shentsize = 0x100;
405   ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
406   ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
407 
408   map_info->memory_backed_elf = false;
409   memory.reset(map_info->CreateMemory(process_memory_));
410   EXPECT_FALSE(map_info->memory_backed_elf);
411   EXPECT_EQ(0x2000U, map_info->offset);
412   EXPECT_EQ(0x1000U, map_info->elf_offset);
413   EXPECT_EQ(0x1000U, map_info->elf_start_offset);
414   Elf64_Ehdr ehdr_mem;
415   ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem)));
416   EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0);
417 }
418 
419 }  // namespace unwindstack
420