blob: ed1be3b33468355460981025ea55b8c782548f54 [file] [log] [blame]
Christopher Ferris3958f802017-02-01 15:44:40 -08001/*
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>
Christopher Ferrisbae69f12017-06-28 14:51:54 -070018#include <fcntl.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <unistd.h>
Christopher Ferris3958f802017-02-01 15:44:40 -080022
23#include <gtest/gtest.h>
24
Christopher Ferrisd226a512017-07-14 10:37:19 -070025#include <unwindstack/Elf.h>
26#include <unwindstack/MapInfo.h>
Christopher Ferris3958f802017-02-01 15:44:40 -080027
Christopher Ferris570b76f2017-06-30 17:18:16 -070028#include "ElfTestUtils.h"
Christopher Ferrisa0196652017-07-18 16:09:20 -070029#include "LogFake.h"
Christopher Ferris3958f802017-02-01 15:44:40 -080030#include "MemoryFake.h"
31
32#if !defined(PT_ARM_EXIDX)
33#define PT_ARM_EXIDX 0x70000001
34#endif
35
Christopher Ferrisd226a512017-07-14 10:37:19 -070036namespace unwindstack {
37
Christopher Ferris3958f802017-02-01 15:44:40 -080038class ElfTest : public ::testing::Test {
39 protected:
40 void SetUp() override {
41 memory_ = new MemoryFake;
42 }
43
Christopher Ferris570b76f2017-06-30 17:18:16 -070044 void InitElf32(uint32_t machine_type) {
Christopher Ferris3958f802017-02-01 15:44:40 -080045 Elf32_Ehdr ehdr;
Christopher Ferris570b76f2017-06-30 17:18:16 -070046 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type);
Christopher Ferris3958f802017-02-01 15:44:40 -080047
Christopher Ferris3958f802017-02-01 15:44:40 -080048 ehdr.e_phoff = 0x100;
Christopher Ferris3958f802017-02-01 15:44:40 -080049 ehdr.e_ehsize = sizeof(ehdr);
50 ehdr.e_phentsize = sizeof(Elf32_Phdr);
51 ehdr.e_phnum = 1;
52 ehdr.e_shentsize = sizeof(Elf32_Shdr);
Christopher Ferris570b76f2017-06-30 17:18:16 -070053 if (machine_type == EM_ARM) {
Christopher Ferris3958f802017-02-01 15:44:40 -080054 ehdr.e_flags = 0x5000200;
55 ehdr.e_phnum = 2;
56 }
57 memory_->SetMemory(0, &ehdr, sizeof(ehdr));
58
59 Elf32_Phdr phdr;
60 memset(&phdr, 0, sizeof(phdr));
61 phdr.p_type = PT_LOAD;
Christopher Ferris3958f802017-02-01 15:44:40 -080062 phdr.p_filesz = 0x10000;
63 phdr.p_memsz = 0x10000;
64 phdr.p_flags = PF_R | PF_X;
65 phdr.p_align = 0x1000;
66 memory_->SetMemory(0x100, &phdr, sizeof(phdr));
67
Christopher Ferris570b76f2017-06-30 17:18:16 -070068 if (machine_type == EM_ARM) {
Christopher Ferris3958f802017-02-01 15:44:40 -080069 memset(&phdr, 0, sizeof(phdr));
70 phdr.p_type = PT_ARM_EXIDX;
71 phdr.p_offset = 0x30000;
72 phdr.p_vaddr = 0x30000;
73 phdr.p_paddr = 0x30000;
74 phdr.p_filesz = 16;
75 phdr.p_memsz = 16;
76 phdr.p_flags = PF_R;
77 phdr.p_align = 0x4;
78 memory_->SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
79 }
80 }
81
Christopher Ferris570b76f2017-06-30 17:18:16 -070082 void InitElf64(uint32_t machine_type) {
Christopher Ferris3958f802017-02-01 15:44:40 -080083 Elf64_Ehdr ehdr;
Christopher Ferris570b76f2017-06-30 17:18:16 -070084 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type);
Christopher Ferris3958f802017-02-01 15:44:40 -080085
Christopher Ferris3958f802017-02-01 15:44:40 -080086 ehdr.e_phoff = 0x100;
Christopher Ferris3958f802017-02-01 15:44:40 -080087 ehdr.e_flags = 0x5000200;
88 ehdr.e_ehsize = sizeof(ehdr);
89 ehdr.e_phentsize = sizeof(Elf64_Phdr);
90 ehdr.e_phnum = 1;
91 ehdr.e_shentsize = sizeof(Elf64_Shdr);
Christopher Ferris3958f802017-02-01 15:44:40 -080092 memory_->SetMemory(0, &ehdr, sizeof(ehdr));
93
94 Elf64_Phdr phdr;
95 memset(&phdr, 0, sizeof(phdr));
96 phdr.p_type = PT_LOAD;
Christopher Ferris3958f802017-02-01 15:44:40 -080097 phdr.p_filesz = 0x10000;
98 phdr.p_memsz = 0x10000;
99 phdr.p_flags = PF_R | PF_X;
100 phdr.p_align = 0x1000;
101 memory_->SetMemory(0x100, &phdr, sizeof(phdr));
102 }
103
104 MemoryFake* memory_;
105};
106
107TEST_F(ElfTest, invalid_memory) {
108 Elf elf(memory_);
109
110 ASSERT_FALSE(elf.Init());
111 ASSERT_FALSE(elf.valid());
112}
113
114TEST_F(ElfTest, elf_invalid) {
115 Elf elf(memory_);
116
117 InitElf32(EM_386);
118
119 // Corrupt the ELF signature.
120 memory_->SetData32(0, 0x7f000000);
121
122 ASSERT_FALSE(elf.Init());
123 ASSERT_FALSE(elf.valid());
124 ASSERT_TRUE(elf.interface() == nullptr);
125
126 std::string name;
127 ASSERT_FALSE(elf.GetSoname(&name));
128
129 uint64_t func_offset;
130 ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
131
132 ASSERT_FALSE(elf.Step(0, nullptr, nullptr));
133}
134
Christopher Ferrisa0196652017-07-18 16:09:20 -0700135TEST_F(ElfTest, elf32_invalid_machine) {
136 Elf elf(memory_);
137
138 InitElf32(EM_PPC);
139
140 ResetLogs();
141 ASSERT_FALSE(elf.Init());
142
143 ASSERT_EQ("", GetFakeLogBuf());
144 ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86: e_machine = 20\n\n",
145 GetFakeLogPrint());
146}
147
148TEST_F(ElfTest, elf64_invalid_machine) {
149 Elf elf(memory_);
150
151 InitElf64(EM_PPC64);
152
153 ResetLogs();
154 ASSERT_FALSE(elf.Init());
155
156 ASSERT_EQ("", GetFakeLogBuf());
157 ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64: e_machine = 21\n\n",
158 GetFakeLogPrint());
159}
160
Christopher Ferris3958f802017-02-01 15:44:40 -0800161TEST_F(ElfTest, elf_arm) {
162 Elf elf(memory_);
163
164 InitElf32(EM_ARM);
165
166 ASSERT_TRUE(elf.Init());
167 ASSERT_TRUE(elf.valid());
168 ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
169 ASSERT_EQ(ELFCLASS32, elf.class_type());
170 ASSERT_TRUE(elf.interface() != nullptr);
171}
172
173TEST_F(ElfTest, elf_x86) {
174 Elf elf(memory_);
175
176 InitElf32(EM_386);
177
178 ASSERT_TRUE(elf.Init());
179 ASSERT_TRUE(elf.valid());
180 ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
181 ASSERT_EQ(ELFCLASS32, elf.class_type());
182 ASSERT_TRUE(elf.interface() != nullptr);
183}
184
185TEST_F(ElfTest, elf_arm64) {
186 Elf elf(memory_);
187
188 InitElf64(EM_AARCH64);
189
190 ASSERT_TRUE(elf.Init());
191 ASSERT_TRUE(elf.valid());
192 ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
193 ASSERT_EQ(ELFCLASS64, elf.class_type());
194 ASSERT_TRUE(elf.interface() != nullptr);
195}
196
197TEST_F(ElfTest, elf_x86_64) {
198 Elf elf(memory_);
199
200 InitElf64(EM_X86_64);
201
202 ASSERT_TRUE(elf.Init());
203 ASSERT_TRUE(elf.valid());
204 ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
205 ASSERT_EQ(ELFCLASS64, elf.class_type());
206 ASSERT_TRUE(elf.interface() != nullptr);
207}
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700208
Christopher Ferris570b76f2017-06-30 17:18:16 -0700209TEST_F(ElfTest, gnu_debugdata_init_fail32) {
210 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
211 [&](uint64_t offset, const void* ptr, size_t size) {
212 memory_->SetMemory(offset, ptr, size);
213 });
214
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700215 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700216 ASSERT_TRUE(elf.Init());
217 ASSERT_TRUE(elf.interface() != nullptr);
218 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700219 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
220 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700221}
222
223TEST_F(ElfTest, gnu_debugdata_init_fail64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700224 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
225 [&](uint64_t offset, const void* ptr, size_t size) {
226 memory_->SetMemory(offset, ptr, size);
227 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700228
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700229 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700230 ASSERT_TRUE(elf.Init());
231 ASSERT_TRUE(elf.interface() != nullptr);
232 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700233 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
234 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
235}
236
237TEST_F(ElfTest, gnu_debugdata_init32) {
238 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
239 [&](uint64_t offset, const void* ptr, size_t size) {
240 memory_->SetMemory(offset, ptr, size);
241 });
242
243 Elf elf(memory_);
244 ASSERT_TRUE(elf.Init());
245 ASSERT_TRUE(elf.interface() != nullptr);
246 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
247 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
248 EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700249
250 elf.InitGnuDebugdata();
251 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
252}
253
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700254TEST_F(ElfTest, gnu_debugdata_init64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700255 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
256 [&](uint64_t offset, const void* ptr, size_t size) {
257 memory_->SetMemory(offset, ptr, size);
258 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700259
Christopher Ferris570b76f2017-06-30 17:18:16 -0700260 Elf elf(memory_);
261 ASSERT_TRUE(elf.Init());
262 ASSERT_TRUE(elf.interface() != nullptr);
263 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
264 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
265 EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
266
267 elf.InitGnuDebugdata();
268 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700269}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700270
271class MockElf : public Elf {
272 public:
273 MockElf(Memory* memory) : Elf(memory) {}
274 virtual ~MockElf() = default;
275
276 void set_valid(bool valid) { valid_ = valid; }
277 void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
278};
279
280TEST_F(ElfTest, rel_pc) {
281 MockElf elf(memory_);
282
283 ElfInterface* interface = new ElfInterface32(memory_);
284 elf.set_elf_interface(interface);
285
286 elf.set_valid(true);
287 interface->set_load_bias(0);
288 MapInfo map_info{.start = 0x1000, .end = 0x2000};
289
290 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
291
292 interface->set_load_bias(0x3000);
293 ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
294
295 elf.set_valid(false);
296 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
297}
298
299} // namespace unwindstack