blob: 9f7517b1512474285db22d7a69ca04f93763f04e [file] [log] [blame]
Christopher Ferris570b76f2017-06-30 17:18:16 -07001/*
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 <android-base/test_utils.h>
31#include <gtest/gtest.h>
32
Christopher Ferrisd226a512017-07-14 10:37:19 -070033#include <unwindstack/Elf.h>
34#include <unwindstack/MapInfo.h>
Christopher Ferris5f118512017-09-01 11:17:16 -070035#include <unwindstack/Maps.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070036#include <unwindstack/Memory.h>
37
Christopher Ferris570b76f2017-06-30 17:18:16 -070038#include "ElfTestUtils.h"
Christopher Ferris5f118512017-09-01 11:17:16 -070039#include "MemoryFake.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070040
41namespace unwindstack {
Christopher Ferris570b76f2017-06-30 17:18:16 -070042
43class MapInfoGetElfTest : public ::testing::Test {
44 protected:
45 void SetUp() override {
Christopher Ferris5f118512017-09-01 11:17:16 -070046 memory_ = new MemoryFake;
47 process_memory_.reset(memory_);
Christopher Ferris570b76f2017-06-30 17:18:16 -070048 }
49
Christopher Ferris5f118512017-09-01 11:17:16 -070050 template <typename Ehdr, typename Shdr>
51 static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
52 memset(ehdr, 0, sizeof(*ehdr));
53 memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
54 ehdr->e_ident[EI_CLASS] = class_type;
55 ehdr->e_machine = machine_type;
56 ehdr->e_shoff = sh_offset;
57 ehdr->e_shentsize = sizeof(Shdr) + 100;
58 ehdr->e_shnum = 4;
59 }
Christopher Ferris570b76f2017-06-30 17:18:16 -070060
61 const size_t kMapSize = 4096;
62
Christopher Ferris5f118512017-09-01 11:17:16 -070063 std::shared_ptr<Memory> process_memory_;
64 MemoryFake* memory_;
65
66 TemporaryFile elf_;
Christopher Ferris570b76f2017-06-30 17:18:16 -070067};
68
69TEST_F(MapInfoGetElfTest, invalid) {
Christopher Ferris5f118512017-09-01 11:17:16 -070070 MapInfo info{.start = 0x1000, .end = 0x2000, .offset = 0, .flags = PROT_READ, .name = ""};
71
Christopher Ferris570b76f2017-06-30 17:18:16 -070072 // The map is empty, but this should still create an invalid elf object.
Christopher Ferris5f118512017-09-01 11:17:16 -070073 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
Christopher Ferris570b76f2017-06-30 17:18:16 -070074 ASSERT_TRUE(elf.get() != nullptr);
75 ASSERT_FALSE(elf->valid());
76}
77
78TEST_F(MapInfoGetElfTest, valid32) {
Christopher Ferris5f118512017-09-01 11:17:16 -070079 MapInfo info{.start = 0x3000, .end = 0x4000, .offset = 0, .flags = PROT_READ, .name = ""};
80
Christopher Ferris570b76f2017-06-30 17:18:16 -070081 Elf32_Ehdr ehdr;
82 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
Christopher Ferris5f118512017-09-01 11:17:16 -070083 memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
Christopher Ferris570b76f2017-06-30 17:18:16 -070084
Christopher Ferris5f118512017-09-01 11:17:16 -070085 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
Christopher Ferris570b76f2017-06-30 17:18:16 -070086 ASSERT_TRUE(elf.get() != nullptr);
87 ASSERT_TRUE(elf->valid());
88 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
89 EXPECT_EQ(ELFCLASS32, elf->class_type());
90}
91
92TEST_F(MapInfoGetElfTest, valid64) {
Christopher Ferris5f118512017-09-01 11:17:16 -070093 MapInfo info{.start = 0x8000, .end = 0x9000, .offset = 0, .flags = PROT_READ, .name = ""};
94
Christopher Ferris570b76f2017-06-30 17:18:16 -070095 Elf64_Ehdr ehdr;
96 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
Christopher Ferris5f118512017-09-01 11:17:16 -070097 memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
Christopher Ferris570b76f2017-06-30 17:18:16 -070098
Christopher Ferris5f118512017-09-01 11:17:16 -070099 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
Christopher Ferris570b76f2017-06-30 17:18:16 -0700100 ASSERT_TRUE(elf.get() != nullptr);
101 ASSERT_TRUE(elf->valid());
102 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
103 EXPECT_EQ(ELFCLASS64, elf->class_type());
104}
105
106TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
Christopher Ferris5f118512017-09-01 11:17:16 -0700107 MapInfo info{.start = 0x4000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
Christopher Ferris570b76f2017-06-30 17:18:16 -0700108
Christopher Ferris5f118512017-09-01 11:17:16 -0700109 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
110 [&](uint64_t offset, const void* ptr, size_t size) {
111 memory_->SetMemory(0x4000 + offset, ptr, size);
112 });
113
114 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
Christopher Ferris570b76f2017-06-30 17:18:16 -0700115 ASSERT_TRUE(elf.get() != nullptr);
116 ASSERT_TRUE(elf->valid());
117 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
118 EXPECT_EQ(ELFCLASS32, elf->class_type());
119 EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
120}
121
122TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
Christopher Ferris5f118512017-09-01 11:17:16 -0700123 MapInfo info{.start = 0x6000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
Christopher Ferris570b76f2017-06-30 17:18:16 -0700124
Christopher Ferris5f118512017-09-01 11:17:16 -0700125 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
126 [&](uint64_t offset, const void* ptr, size_t size) {
127 memory_->SetMemory(0x6000 + offset, ptr, size);
128 });
129
130 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
Christopher Ferris570b76f2017-06-30 17:18:16 -0700131 ASSERT_TRUE(elf.get() != nullptr);
132 ASSERT_TRUE(elf->valid());
133 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
134 EXPECT_EQ(ELFCLASS64, elf->class_type());
135 EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
136}
137
138TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
Christopher Ferris5f118512017-09-01 11:17:16 -0700139 MapInfo info{.start = 0x2000, .end = 0x3000, .offset = 0, .flags = PROT_READ, .name = ""};
Christopher Ferris570b76f2017-06-30 17:18:16 -0700140
Christopher Ferris5f118512017-09-01 11:17:16 -0700141 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
142 [&](uint64_t offset, const void* ptr, size_t size) {
143 memory_->SetMemory(0x2000 + offset, ptr, size);
144 });
145
146 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true));
Christopher Ferris570b76f2017-06-30 17:18:16 -0700147 ASSERT_TRUE(elf.get() != nullptr);
148 ASSERT_TRUE(elf->valid());
149 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
150 EXPECT_EQ(ELFCLASS32, elf->class_type());
151 EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
152}
153
154TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
Christopher Ferris5f118512017-09-01 11:17:16 -0700155 MapInfo info{.start = 0x5000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
Christopher Ferris570b76f2017-06-30 17:18:16 -0700156
Christopher Ferris5f118512017-09-01 11:17:16 -0700157 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
158 [&](uint64_t offset, const void* ptr, size_t size) {
159 memory_->SetMemory(0x5000 + offset, ptr, size);
160 });
161
162 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true));
Christopher Ferris570b76f2017-06-30 17:18:16 -0700163 ASSERT_TRUE(elf.get() != nullptr);
164 ASSERT_TRUE(elf->valid());
165 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
166 EXPECT_EQ(ELFCLASS64, elf->class_type());
167 EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
168}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700169
Christopher Ferris5f118512017-09-01 11:17:16 -0700170TEST_F(MapInfoGetElfTest, end_le_start) {
171 MapInfo info{.start = 0x1000, .end = 0x1000, .offset = 0, .flags = PROT_READ, .name = elf_.path};
172
173 Elf32_Ehdr ehdr;
174 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
175 ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
176
177 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
178 ASSERT_FALSE(elf->valid());
179
180 info.elf = nullptr;
181 info.end = 0xfff;
182 elf.reset(info.GetElf(process_memory_, false));
183 ASSERT_FALSE(elf->valid());
184
185 // Make sure this test is valid.
186 info.elf = nullptr;
187 info.end = 0x2000;
188 elf.reset(info.GetElf(process_memory_, false));
189 ASSERT_TRUE(elf->valid());
190}
191
192// Verify that if the offset is non-zero but there is no elf at the offset,
193// that the full file is used.
194TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
195 MapInfo info{
196 .start = 0x1000, .end = 0x2000, .offset = 0x100, .flags = PROT_READ, .name = elf_.path};
197
198 std::vector<uint8_t> buffer(0x1000);
199 memset(buffer.data(), 0, buffer.size());
200 Elf32_Ehdr ehdr;
201 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
202 memcpy(buffer.data(), &ehdr, sizeof(ehdr));
203 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
204
205 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
206 ASSERT_TRUE(elf->valid());
207 ASSERT_TRUE(elf->memory() != nullptr);
208 ASSERT_EQ(0x100U, info.elf_offset);
209
210 // Read the entire file.
211 memset(buffer.data(), 0, buffer.size());
Josh Gaoef35aa52017-10-18 11:44:51 -0700212 ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
Christopher Ferris5f118512017-09-01 11:17:16 -0700213 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
214 for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
215 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
216 }
217
Josh Gaoef35aa52017-10-18 11:44:51 -0700218 ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
Christopher Ferris5f118512017-09-01 11:17:16 -0700219}
220
221// Verify that if the offset is non-zero and there is an elf at that
222// offset, that only part of the file is used.
223TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
224 MapInfo info{
225 .start = 0x1000, .end = 0x2000, .offset = 0x2000, .flags = PROT_READ, .name = elf_.path};
226
227 std::vector<uint8_t> buffer(0x4000);
228 memset(buffer.data(), 0, buffer.size());
229 Elf32_Ehdr ehdr;
230 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
231 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
232 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
233
234 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
235 ASSERT_TRUE(elf->valid());
236 ASSERT_TRUE(elf->memory() != nullptr);
237 ASSERT_EQ(0U, info.elf_offset);
238
239 // Read the valid part of the file.
Josh Gaoef35aa52017-10-18 11:44:51 -0700240 ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
Christopher Ferris5f118512017-09-01 11:17:16 -0700241 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
242 for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
243 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
244 }
245
Josh Gaoef35aa52017-10-18 11:44:51 -0700246 ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
Christopher Ferris5f118512017-09-01 11:17:16 -0700247}
248
249// Verify that if the offset is non-zero and there is an elf at that
250// offset, that only part of the file is used. Further verify that if the
251// embedded elf is bigger than the initial map, the new object is larger
252// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
253TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
254 MapInfo info{
255 .start = 0x5000, .end = 0x6000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
256
257 std::vector<uint8_t> buffer(0x4000);
258 memset(buffer.data(), 0, buffer.size());
259 Elf32_Ehdr ehdr;
260 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
261 ehdr.e_shoff = 0x2000;
262 ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
263 ehdr.e_shnum = 4;
264 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
265 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
266
267 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
268 ASSERT_TRUE(elf->valid());
269 ASSERT_TRUE(elf->memory() != nullptr);
270 ASSERT_EQ(0U, info.elf_offset);
271
272 // Verify the memory is a valid elf.
273 memset(buffer.data(), 0, buffer.size());
Josh Gaoef35aa52017-10-18 11:44:51 -0700274 ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
Christopher Ferris5f118512017-09-01 11:17:16 -0700275 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
276
277 // Read past the end of what would normally be the size of the map.
Josh Gaoef35aa52017-10-18 11:44:51 -0700278 ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
Christopher Ferris5f118512017-09-01 11:17:16 -0700279}
280
281TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
282 MapInfo info{
283 .start = 0x7000, .end = 0x8000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
284
285 std::vector<uint8_t> buffer(0x4000);
286 memset(buffer.data(), 0, buffer.size());
287 Elf64_Ehdr ehdr;
288 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
289 ehdr.e_shoff = 0x2000;
290 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
291 ehdr.e_shnum = 4;
292 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
293 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
294
295 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
296 ASSERT_TRUE(elf->valid());
297 ASSERT_TRUE(elf->memory() != nullptr);
298 ASSERT_EQ(0U, info.elf_offset);
299
300 // Verify the memory is a valid elf.
301 memset(buffer.data(), 0, buffer.size());
Josh Gaoef35aa52017-10-18 11:44:51 -0700302 ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
Christopher Ferris5f118512017-09-01 11:17:16 -0700303 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
304
305 // Read past the end of what would normally be the size of the map.
Josh Gaoef35aa52017-10-18 11:44:51 -0700306 ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
Christopher Ferris5f118512017-09-01 11:17:16 -0700307}
308
309TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
310 MapInfo info{.start = 0x9000, .end = 0xa000, .offset = 0x1000, .flags = 0, .name = ""};
311
312 // Create valid elf data in process memory only.
313 Elf64_Ehdr ehdr;
314 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
315 ehdr.e_shoff = 0x2000;
316 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
317 ehdr.e_shnum = 4;
318 memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
319
320 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
321 ASSERT_FALSE(elf->valid());
322
323 info.elf = nullptr;
324 info.flags = PROT_READ;
325 elf.reset(info.GetElf(process_memory_, false));
326 ASSERT_TRUE(elf->valid());
327}
328
329TEST_F(MapInfoGetElfTest, check_device_maps) {
330 MapInfo info{.start = 0x7000,
331 .end = 0x8000,
332 .offset = 0x1000,
333 .flags = PROT_READ | MAPS_FLAGS_DEVICE_MAP,
334 .name = "/dev/something"};
335
336 // Create valid elf data in process memory for this to verify that only
337 // the name is causing invalid elf data.
338 Elf64_Ehdr ehdr;
339 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
340 ehdr.e_shoff = 0x2000;
341 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
342 ehdr.e_shnum = 4;
343 memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
344
345 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
346 ASSERT_FALSE(elf->valid());
347
348 // Set the name to nothing to verify that it still fails.
349 info.elf = nullptr;
350 info.name = "";
351 elf.reset(info.GetElf(process_memory_, false));
352 ASSERT_FALSE(elf->valid());
353
354 // Change the flags and verify the elf is valid now.
355 info.elf = nullptr;
356 info.flags = PROT_READ;
357 elf.reset(info.GetElf(process_memory_, false));
358 ASSERT_TRUE(elf->valid());
359}
360
Christopher Ferrisd226a512017-07-14 10:37:19 -0700361} // namespace unwindstack