blob: 42a0246ae5f9587d182a904ab2e42cc442d18df2 [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
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700132 bool finished;
133 ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished));
Christopher Ferris3958f802017-02-01 15:44:40 -0800134}
135
Christopher Ferrisa0196652017-07-18 16:09:20 -0700136TEST_F(ElfTest, elf32_invalid_machine) {
137 Elf elf(memory_);
138
139 InitElf32(EM_PPC);
140
141 ResetLogs();
142 ASSERT_FALSE(elf.Init());
143
144 ASSERT_EQ("", GetFakeLogBuf());
145 ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86: e_machine = 20\n\n",
146 GetFakeLogPrint());
147}
148
149TEST_F(ElfTest, elf64_invalid_machine) {
150 Elf elf(memory_);
151
152 InitElf64(EM_PPC64);
153
154 ResetLogs();
155 ASSERT_FALSE(elf.Init());
156
157 ASSERT_EQ("", GetFakeLogBuf());
158 ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64: e_machine = 21\n\n",
159 GetFakeLogPrint());
160}
161
Christopher Ferris3958f802017-02-01 15:44:40 -0800162TEST_F(ElfTest, elf_arm) {
163 Elf elf(memory_);
164
165 InitElf32(EM_ARM);
166
167 ASSERT_TRUE(elf.Init());
168 ASSERT_TRUE(elf.valid());
169 ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
170 ASSERT_EQ(ELFCLASS32, elf.class_type());
171 ASSERT_TRUE(elf.interface() != nullptr);
172}
173
174TEST_F(ElfTest, elf_x86) {
175 Elf elf(memory_);
176
177 InitElf32(EM_386);
178
179 ASSERT_TRUE(elf.Init());
180 ASSERT_TRUE(elf.valid());
181 ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
182 ASSERT_EQ(ELFCLASS32, elf.class_type());
183 ASSERT_TRUE(elf.interface() != nullptr);
184}
185
186TEST_F(ElfTest, elf_arm64) {
187 Elf elf(memory_);
188
189 InitElf64(EM_AARCH64);
190
191 ASSERT_TRUE(elf.Init());
192 ASSERT_TRUE(elf.valid());
193 ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
194 ASSERT_EQ(ELFCLASS64, elf.class_type());
195 ASSERT_TRUE(elf.interface() != nullptr);
196}
197
198TEST_F(ElfTest, elf_x86_64) {
199 Elf elf(memory_);
200
201 InitElf64(EM_X86_64);
202
203 ASSERT_TRUE(elf.Init());
204 ASSERT_TRUE(elf.valid());
205 ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
206 ASSERT_EQ(ELFCLASS64, elf.class_type());
207 ASSERT_TRUE(elf.interface() != nullptr);
208}
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700209
Christopher Ferris570b76f2017-06-30 17:18:16 -0700210TEST_F(ElfTest, gnu_debugdata_init_fail32) {
211 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
212 [&](uint64_t offset, const void* ptr, size_t size) {
213 memory_->SetMemory(offset, ptr, size);
214 });
215
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700216 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700217 ASSERT_TRUE(elf.Init());
218 ASSERT_TRUE(elf.interface() != nullptr);
219 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700220 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
221 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700222}
223
224TEST_F(ElfTest, gnu_debugdata_init_fail64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700225 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
226 [&](uint64_t offset, const void* ptr, size_t size) {
227 memory_->SetMemory(offset, ptr, size);
228 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700229
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700230 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700231 ASSERT_TRUE(elf.Init());
232 ASSERT_TRUE(elf.interface() != nullptr);
233 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700234 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
235 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
236}
237
238TEST_F(ElfTest, gnu_debugdata_init32) {
239 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
240 [&](uint64_t offset, const void* ptr, size_t size) {
241 memory_->SetMemory(offset, ptr, size);
242 });
243
244 Elf elf(memory_);
245 ASSERT_TRUE(elf.Init());
246 ASSERT_TRUE(elf.interface() != nullptr);
247 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
248 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
249 EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700250
251 elf.InitGnuDebugdata();
252 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
253}
254
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700255TEST_F(ElfTest, gnu_debugdata_init64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700256 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
257 [&](uint64_t offset, const void* ptr, size_t size) {
258 memory_->SetMemory(offset, ptr, size);
259 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700260
Christopher Ferris570b76f2017-06-30 17:18:16 -0700261 Elf elf(memory_);
262 ASSERT_TRUE(elf.Init());
263 ASSERT_TRUE(elf.interface() != nullptr);
264 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
265 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
266 EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
267
268 elf.InitGnuDebugdata();
269 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700270}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700271
272class MockElf : public Elf {
273 public:
274 MockElf(Memory* memory) : Elf(memory) {}
275 virtual ~MockElf() = default;
276
277 void set_valid(bool valid) { valid_ = valid; }
278 void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
279};
280
281TEST_F(ElfTest, rel_pc) {
282 MockElf elf(memory_);
283
284 ElfInterface* interface = new ElfInterface32(memory_);
285 elf.set_elf_interface(interface);
286
287 elf.set_valid(true);
288 interface->set_load_bias(0);
289 MapInfo map_info{.start = 0x1000, .end = 0x2000};
290
291 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
292
293 interface->set_load_bias(0x3000);
294 ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
295
296 elf.set_valid(false);
297 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
298}
299
300} // namespace unwindstack