blob: 72ceb85ee4265211a37f10ff2856ab2c74ac615a [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 Ferris3958f802017-02-01 15:44:40 -080029#include "MemoryFake.h"
30
31#if !defined(PT_ARM_EXIDX)
32#define PT_ARM_EXIDX 0x70000001
33#endif
34
Christopher Ferrisd226a512017-07-14 10:37:19 -070035namespace unwindstack {
36
Christopher Ferris3958f802017-02-01 15:44:40 -080037class ElfTest : public ::testing::Test {
38 protected:
39 void SetUp() override {
40 memory_ = new MemoryFake;
41 }
42
Christopher Ferris570b76f2017-06-30 17:18:16 -070043 void InitElf32(uint32_t machine_type) {
Christopher Ferris3958f802017-02-01 15:44:40 -080044 Elf32_Ehdr ehdr;
Christopher Ferris570b76f2017-06-30 17:18:16 -070045 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type);
Christopher Ferris3958f802017-02-01 15:44:40 -080046
Christopher Ferris3958f802017-02-01 15:44:40 -080047 ehdr.e_phoff = 0x100;
Christopher Ferris3958f802017-02-01 15:44:40 -080048 ehdr.e_ehsize = sizeof(ehdr);
49 ehdr.e_phentsize = sizeof(Elf32_Phdr);
50 ehdr.e_phnum = 1;
51 ehdr.e_shentsize = sizeof(Elf32_Shdr);
Christopher Ferris570b76f2017-06-30 17:18:16 -070052 if (machine_type == EM_ARM) {
Christopher Ferris3958f802017-02-01 15:44:40 -080053 ehdr.e_flags = 0x5000200;
54 ehdr.e_phnum = 2;
55 }
56 memory_->SetMemory(0, &ehdr, sizeof(ehdr));
57
58 Elf32_Phdr phdr;
59 memset(&phdr, 0, sizeof(phdr));
60 phdr.p_type = PT_LOAD;
Christopher Ferris3958f802017-02-01 15:44:40 -080061 phdr.p_filesz = 0x10000;
62 phdr.p_memsz = 0x10000;
63 phdr.p_flags = PF_R | PF_X;
64 phdr.p_align = 0x1000;
65 memory_->SetMemory(0x100, &phdr, sizeof(phdr));
66
Christopher Ferris570b76f2017-06-30 17:18:16 -070067 if (machine_type == EM_ARM) {
Christopher Ferris3958f802017-02-01 15:44:40 -080068 memset(&phdr, 0, sizeof(phdr));
69 phdr.p_type = PT_ARM_EXIDX;
70 phdr.p_offset = 0x30000;
71 phdr.p_vaddr = 0x30000;
72 phdr.p_paddr = 0x30000;
73 phdr.p_filesz = 16;
74 phdr.p_memsz = 16;
75 phdr.p_flags = PF_R;
76 phdr.p_align = 0x4;
77 memory_->SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
78 }
79 }
80
Christopher Ferris570b76f2017-06-30 17:18:16 -070081 void InitElf64(uint32_t machine_type) {
Christopher Ferris3958f802017-02-01 15:44:40 -080082 Elf64_Ehdr ehdr;
Christopher Ferris570b76f2017-06-30 17:18:16 -070083 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type);
Christopher Ferris3958f802017-02-01 15:44:40 -080084
Christopher Ferris3958f802017-02-01 15:44:40 -080085 ehdr.e_phoff = 0x100;
Christopher Ferris3958f802017-02-01 15:44:40 -080086 ehdr.e_flags = 0x5000200;
87 ehdr.e_ehsize = sizeof(ehdr);
88 ehdr.e_phentsize = sizeof(Elf64_Phdr);
89 ehdr.e_phnum = 1;
90 ehdr.e_shentsize = sizeof(Elf64_Shdr);
Christopher Ferris3958f802017-02-01 15:44:40 -080091 memory_->SetMemory(0, &ehdr, sizeof(ehdr));
92
93 Elf64_Phdr phdr;
94 memset(&phdr, 0, sizeof(phdr));
95 phdr.p_type = PT_LOAD;
Christopher Ferris3958f802017-02-01 15:44:40 -080096 phdr.p_filesz = 0x10000;
97 phdr.p_memsz = 0x10000;
98 phdr.p_flags = PF_R | PF_X;
99 phdr.p_align = 0x1000;
100 memory_->SetMemory(0x100, &phdr, sizeof(phdr));
101 }
102
103 MemoryFake* memory_;
104};
105
106TEST_F(ElfTest, invalid_memory) {
107 Elf elf(memory_);
108
109 ASSERT_FALSE(elf.Init());
110 ASSERT_FALSE(elf.valid());
111}
112
113TEST_F(ElfTest, elf_invalid) {
114 Elf elf(memory_);
115
116 InitElf32(EM_386);
117
118 // Corrupt the ELF signature.
119 memory_->SetData32(0, 0x7f000000);
120
121 ASSERT_FALSE(elf.Init());
122 ASSERT_FALSE(elf.valid());
123 ASSERT_TRUE(elf.interface() == nullptr);
124
125 std::string name;
126 ASSERT_FALSE(elf.GetSoname(&name));
127
128 uint64_t func_offset;
129 ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
130
131 ASSERT_FALSE(elf.Step(0, nullptr, nullptr));
132}
133
134TEST_F(ElfTest, elf_arm) {
135 Elf elf(memory_);
136
137 InitElf32(EM_ARM);
138
139 ASSERT_TRUE(elf.Init());
140 ASSERT_TRUE(elf.valid());
141 ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
142 ASSERT_EQ(ELFCLASS32, elf.class_type());
143 ASSERT_TRUE(elf.interface() != nullptr);
144}
145
146TEST_F(ElfTest, elf_x86) {
147 Elf elf(memory_);
148
149 InitElf32(EM_386);
150
151 ASSERT_TRUE(elf.Init());
152 ASSERT_TRUE(elf.valid());
153 ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
154 ASSERT_EQ(ELFCLASS32, elf.class_type());
155 ASSERT_TRUE(elf.interface() != nullptr);
156}
157
158TEST_F(ElfTest, elf_arm64) {
159 Elf elf(memory_);
160
161 InitElf64(EM_AARCH64);
162
163 ASSERT_TRUE(elf.Init());
164 ASSERT_TRUE(elf.valid());
165 ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
166 ASSERT_EQ(ELFCLASS64, elf.class_type());
167 ASSERT_TRUE(elf.interface() != nullptr);
168}
169
170TEST_F(ElfTest, elf_x86_64) {
171 Elf elf(memory_);
172
173 InitElf64(EM_X86_64);
174
175 ASSERT_TRUE(elf.Init());
176 ASSERT_TRUE(elf.valid());
177 ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
178 ASSERT_EQ(ELFCLASS64, elf.class_type());
179 ASSERT_TRUE(elf.interface() != nullptr);
180}
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700181
Christopher Ferris570b76f2017-06-30 17:18:16 -0700182TEST_F(ElfTest, gnu_debugdata_init_fail32) {
183 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
184 [&](uint64_t offset, const void* ptr, size_t size) {
185 memory_->SetMemory(offset, ptr, size);
186 });
187
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700188 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700189 ASSERT_TRUE(elf.Init());
190 ASSERT_TRUE(elf.interface() != nullptr);
191 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700192 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
193 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700194}
195
196TEST_F(ElfTest, gnu_debugdata_init_fail64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700197 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
198 [&](uint64_t offset, const void* ptr, size_t size) {
199 memory_->SetMemory(offset, ptr, size);
200 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700201
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700202 Elf elf(memory_);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700203 ASSERT_TRUE(elf.Init());
204 ASSERT_TRUE(elf.interface() != nullptr);
205 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
Christopher Ferris570b76f2017-06-30 17:18:16 -0700206 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
207 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
208}
209
210TEST_F(ElfTest, gnu_debugdata_init32) {
211 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
212 [&](uint64_t offset, const void* ptr, size_t size) {
213 memory_->SetMemory(offset, ptr, size);
214 });
215
216 Elf elf(memory_);
217 ASSERT_TRUE(elf.Init());
218 ASSERT_TRUE(elf.interface() != nullptr);
219 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
220 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
221 EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size());
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700222
223 elf.InitGnuDebugdata();
224 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
225}
226
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700227TEST_F(ElfTest, gnu_debugdata_init64) {
Christopher Ferris570b76f2017-06-30 17:18:16 -0700228 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
229 [&](uint64_t offset, const void* ptr, size_t size) {
230 memory_->SetMemory(offset, ptr, size);
231 });
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700232
Christopher Ferris570b76f2017-06-30 17:18:16 -0700233 Elf elf(memory_);
234 ASSERT_TRUE(elf.Init());
235 ASSERT_TRUE(elf.interface() != nullptr);
236 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
237 EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
238 EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size());
239
240 elf.InitGnuDebugdata();
241 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
Christopher Ferrisbae69f12017-06-28 14:51:54 -0700242}
Christopher Ferrisd226a512017-07-14 10:37:19 -0700243
244class MockElf : public Elf {
245 public:
246 MockElf(Memory* memory) : Elf(memory) {}
247 virtual ~MockElf() = default;
248
249 void set_valid(bool valid) { valid_ = valid; }
250 void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
251};
252
253TEST_F(ElfTest, rel_pc) {
254 MockElf elf(memory_);
255
256 ElfInterface* interface = new ElfInterface32(memory_);
257 elf.set_elf_interface(interface);
258
259 elf.set_valid(true);
260 interface->set_load_bias(0);
261 MapInfo map_info{.start = 0x1000, .end = 0x2000};
262
263 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
264
265 interface->set_load_bias(0x3000);
266 ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
267
268 elf.set_valid(false);
269 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
270}
271
272} // namespace unwindstack