• 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 <atomic>
27 #include <memory>
28 #include <thread>
29 #include <vector>
30 
31 #include <android-base/file.h>
32 #include <gtest/gtest.h>
33 
34 #include <unwindstack/Elf.h>
35 #include <unwindstack/MapInfo.h>
36 #include <unwindstack/Maps.h>
37 #include <unwindstack/Memory.h>
38 
39 #include "ElfTestUtils.h"
40 #include "MemoryFake.h"
41 
42 namespace unwindstack {
43 
44 class MapInfoGetElfTest : public ::testing::Test {
45  protected:
SetUp()46   void SetUp() override {
47     memory_ = new MemoryFake;
48     process_memory_.reset(memory_);
49   }
50 
51   template <typename Ehdr, typename Shdr>
InitElf(uint64_t sh_offset,Ehdr * ehdr,uint8_t class_type,uint8_t machine_type)52   static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
53     memset(ehdr, 0, sizeof(*ehdr));
54     memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
55     ehdr->e_ident[EI_CLASS] = class_type;
56     ehdr->e_machine = machine_type;
57     ehdr->e_shoff = sh_offset;
58     ehdr->e_shentsize = sizeof(Shdr) + 100;
59     ehdr->e_shnum = 4;
60   }
61 
62   const size_t kMapSize = 4096;
63 
64   std::shared_ptr<Memory> process_memory_;
65   MemoryFake* memory_;
66 
67   TemporaryFile elf_;
68 };
69 
TEST_F(MapInfoGetElfTest,invalid)70 TEST_F(MapInfoGetElfTest, invalid) {
71   MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
72 
73   // The map is empty, but this should still create an invalid elf object.
74   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
75   ASSERT_TRUE(elf != nullptr);
76   ASSERT_FALSE(elf->valid());
77 }
78 
TEST_F(MapInfoGetElfTest,valid32)79 TEST_F(MapInfoGetElfTest, valid32) {
80   MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
81 
82   Elf32_Ehdr ehdr;
83   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
84   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
85 
86   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
87   ASSERT_TRUE(elf != nullptr);
88   ASSERT_TRUE(elf->valid());
89   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
90   EXPECT_EQ(ELFCLASS32, elf->class_type());
91 
92   // Now verify that an empty process memory returns an invalid elf object.
93   info.elf.reset();
94   elf = info.GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
95   ASSERT_TRUE(elf != nullptr);
96   ASSERT_FALSE(elf->valid());
97 }
98 
TEST_F(MapInfoGetElfTest,valid64)99 TEST_F(MapInfoGetElfTest, valid64) {
100   MapInfo info(nullptr, 0x8000, 0x9000, 0, PROT_READ, "");
101 
102   Elf64_Ehdr ehdr;
103   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
104   memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
105 
106   Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
107   ASSERT_TRUE(elf != nullptr);
108   ASSERT_TRUE(elf->valid());
109   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
110   EXPECT_EQ(ELFCLASS64, elf->class_type());
111 }
112 
TEST_F(MapInfoGetElfTest,invalid_arch_mismatch)113 TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) {
114   MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
115 
116   Elf32_Ehdr ehdr;
117   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
118   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
119 
120   Elf* elf = info.GetElf(process_memory_, ARCH_X86);
121   ASSERT_TRUE(elf != nullptr);
122   ASSERT_FALSE(elf->valid());
123 }
124 
TEST_F(MapInfoGetElfTest,gnu_debugdata_init32)125 TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
126   MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
127 
128   TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
129                                                [&](uint64_t offset, const void* ptr, size_t size) {
130                                                  memory_->SetMemory(0x2000 + offset, ptr, size);
131                                                });
132 
133   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
134   ASSERT_TRUE(elf != nullptr);
135   ASSERT_TRUE(elf->valid());
136   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
137   EXPECT_EQ(ELFCLASS32, elf->class_type());
138   EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
139 }
140 
TEST_F(MapInfoGetElfTest,gnu_debugdata_init64)141 TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
142   MapInfo info(nullptr, 0x5000, 0x8000, 0, PROT_READ, "");
143 
144   TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
145                                                [&](uint64_t offset, const void* ptr, size_t size) {
146                                                  memory_->SetMemory(0x5000 + offset, ptr, size);
147                                                });
148 
149   Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
150   ASSERT_TRUE(elf != nullptr);
151   ASSERT_TRUE(elf->valid());
152   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
153   EXPECT_EQ(ELFCLASS64, elf->class_type());
154   EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
155 }
156 
TEST_F(MapInfoGetElfTest,end_le_start)157 TEST_F(MapInfoGetElfTest, end_le_start) {
158   MapInfo info(nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path);
159 
160   Elf32_Ehdr ehdr;
161   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
162   ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
163 
164   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
165   ASSERT_TRUE(elf != nullptr);
166   ASSERT_FALSE(elf->valid());
167 
168   info.elf.reset();
169   info.end = 0xfff;
170   elf = info.GetElf(process_memory_, ARCH_ARM);
171   ASSERT_TRUE(elf != nullptr);
172   ASSERT_FALSE(elf->valid());
173 
174   // Make sure this test is valid.
175   info.elf.reset();
176   info.end = 0x2000;
177   elf = info.GetElf(process_memory_, ARCH_ARM);
178   ASSERT_TRUE(elf != nullptr);
179   ASSERT_TRUE(elf->valid());
180 }
181 
182 // Verify that if the offset is non-zero but there is no elf at the offset,
183 // that the full file is used.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_full_file)184 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
185   MapInfo info(nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
186 
187   std::vector<uint8_t> buffer(0x1000);
188   memset(buffer.data(), 0, buffer.size());
189   Elf32_Ehdr ehdr;
190   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
191   memcpy(buffer.data(), &ehdr, sizeof(ehdr));
192   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
193 
194   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
195   ASSERT_TRUE(elf != nullptr);
196   ASSERT_TRUE(elf->valid());
197   ASSERT_TRUE(elf->memory() != nullptr);
198   ASSERT_EQ(0x100U, info.elf_offset);
199 
200   // Read the entire file.
201   memset(buffer.data(), 0, buffer.size());
202   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
203   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
204   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
205     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
206   }
207 
208   ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
209 }
210 
211 // Verify that if the offset is non-zero and there is an elf at that
212 // offset, that only part of the file is used.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file)213 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
214   MapInfo info(nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
215 
216   std::vector<uint8_t> buffer(0x4000);
217   memset(buffer.data(), 0, buffer.size());
218   Elf32_Ehdr ehdr;
219   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
220   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
221   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
222 
223   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
224   ASSERT_TRUE(elf != nullptr);
225   ASSERT_TRUE(elf->valid());
226   ASSERT_TRUE(elf->memory() != nullptr);
227   ASSERT_EQ(0U, info.elf_offset);
228 
229   // Read the valid part of the file.
230   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
231   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
232   for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
233     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
234   }
235 
236   ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
237 }
238 
239 // Verify that if the offset is non-zero and there is an elf at that
240 // offset, that only part of the file is used. Further verify that if the
241 // embedded elf is bigger than the initial map, the new object is larger
242 // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file_whole_elf32)243 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
244   MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
245 
246   std::vector<uint8_t> buffer(0x4000);
247   memset(buffer.data(), 0, buffer.size());
248   Elf32_Ehdr ehdr;
249   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
250   ehdr.e_shoff = 0x2000;
251   ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
252   ehdr.e_shnum = 4;
253   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
254   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
255 
256   Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
257   ASSERT_TRUE(elf != nullptr);
258   ASSERT_TRUE(elf->valid());
259   ASSERT_TRUE(elf->memory() != nullptr);
260   ASSERT_EQ(0U, info.elf_offset);
261 
262   // Verify the memory is a valid elf.
263   memset(buffer.data(), 0, buffer.size());
264   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
265   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
266 
267   // Read past the end of what would normally be the size of the map.
268   ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
269 }
270 
TEST_F(MapInfoGetElfTest,file_backed_non_zero_offset_partial_file_whole_elf64)271 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
272   MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
273 
274   std::vector<uint8_t> buffer(0x4000);
275   memset(buffer.data(), 0, buffer.size());
276   Elf64_Ehdr ehdr;
277   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
278   ehdr.e_shoff = 0x2000;
279   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
280   ehdr.e_shnum = 4;
281   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
282   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
283 
284   Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
285   ASSERT_TRUE(elf != nullptr);
286   ASSERT_TRUE(elf->valid());
287   ASSERT_TRUE(elf->memory() != nullptr);
288   ASSERT_EQ(0U, info.elf_offset);
289 
290   // Verify the memory is a valid elf.
291   memset(buffer.data(), 0, buffer.size());
292   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
293   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
294 
295   // Read past the end of what would normally be the size of the map.
296   ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
297 }
298 
TEST_F(MapInfoGetElfTest,check_device_maps)299 TEST_F(MapInfoGetElfTest, check_device_maps) {
300   MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP,
301                "/dev/something");
302 
303   // Create valid elf data in process memory for this to verify that only
304   // the name is causing invalid elf data.
305   Elf64_Ehdr ehdr;
306   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
307   ehdr.e_shoff = 0x2000;
308   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
309   ehdr.e_shnum = 0;
310   memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
311 
312   Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
313   ASSERT_TRUE(elf != nullptr);
314   ASSERT_FALSE(elf->valid());
315 
316   // Set the name to nothing to verify that it still fails.
317   info.elf.reset();
318   info.name = "";
319   elf = info.GetElf(process_memory_, ARCH_X86_64);
320   ASSERT_FALSE(elf->valid());
321 
322   // Change the flags and verify the elf is valid now.
323   info.elf.reset();
324   info.flags = PROT_READ;
325   elf = info.GetElf(process_memory_, ARCH_X86_64);
326   ASSERT_TRUE(elf->valid());
327 }
328 
TEST_F(MapInfoGetElfTest,multiple_thread_get_elf)329 TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
330   static constexpr size_t kNumConcurrentThreads = 100;
331 
332   Elf64_Ehdr ehdr;
333   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
334   ehdr.e_shoff = 0x2000;
335   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
336   ehdr.e_shnum = 0;
337   memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
338 
339   Elf* elf_in_threads[kNumConcurrentThreads];
340   std::vector<std::thread*> threads;
341 
342   std::atomic_bool wait;
343   wait = true;
344   // Create all of the threads and have them do the GetElf at the same time
345   // to make it likely that a race will occur.
346   MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, "");
347   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
348     std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
349       while (wait)
350         ;
351       Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
352       elf_in_threads[i] = elf;
353     });
354     threads.push_back(thread);
355   }
356   ASSERT_TRUE(info.elf == nullptr);
357 
358   // Set them all going and wait for the threads to finish.
359   wait = false;
360   for (auto thread : threads) {
361     thread->join();
362     delete thread;
363   }
364 
365   // Now verify that all of the elf files are exactly the same and valid.
366   Elf* elf = info.elf.get();
367   ASSERT_TRUE(elf != nullptr);
368   EXPECT_TRUE(elf->valid());
369   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
370     EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched.";
371   }
372 }
373 
374 // Verify that previous maps don't automatically get the same elf object.
TEST_F(MapInfoGetElfTest,prev_map_elf_not_set)375 TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) {
376   MapInfo info1(nullptr, 0x1000, 0x2000, 0, PROT_READ, "/not/present");
377   MapInfo info2(&info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path);
378 
379   Elf32_Ehdr ehdr;
380   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
381   memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr));
382   Elf* elf = info2.GetElf(process_memory_, ARCH_ARM);
383   ASSERT_TRUE(elf != nullptr);
384   ASSERT_TRUE(elf->valid());
385 
386   ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM));
387 }
388 
389 // Verify that a read-only map followed by a read-execute map will result
390 // in the same elf object in both maps.
TEST_F(MapInfoGetElfTest,read_only_followed_by_read_exec_share_elf)391 TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf) {
392   MapInfo r_info(nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path);
393   MapInfo rw_info(&r_info, 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path);
394 
395   Elf32_Ehdr ehdr;
396   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
397   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
398   Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM);
399   ASSERT_TRUE(elf != nullptr);
400   ASSERT_TRUE(elf->valid());
401 
402   ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM));
403 }
404 
405 }  // namespace unwindstack
406