summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'libunwindstack/tests/ElfTest.cpp')
-rw-r--r--libunwindstack/tests/ElfTest.cpp177
1 files changed, 133 insertions, 44 deletions
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 25fec8e3a..ed1be3b33 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -15,20 +15,25 @@
15 */ 15 */
16 16
17#include <elf.h> 17#include <elf.h>
18#include <fcntl.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#include <unistd.h>
18 22
19#include <gtest/gtest.h> 23#include <gtest/gtest.h>
20 24
21#include "Elf.h" 25#include <unwindstack/Elf.h>
26#include <unwindstack/MapInfo.h>
22 27
28#include "ElfTestUtils.h"
29#include "LogFake.h"
23#include "MemoryFake.h" 30#include "MemoryFake.h"
24 31
25#if !defined(PT_ARM_EXIDX) 32#if !defined(PT_ARM_EXIDX)
26#define PT_ARM_EXIDX 0x70000001 33#define PT_ARM_EXIDX 0x70000001
27#endif 34#endif
28 35
29#if !defined(EM_AARCH64) 36namespace unwindstack {
30#define EM_AARCH64 183
31#endif
32 37
33class ElfTest : public ::testing::Test { 38class ElfTest : public ::testing::Test {
34 protected: 39 protected:
@@ -36,35 +41,16 @@ class ElfTest : public ::testing::Test {
36 memory_ = new MemoryFake; 41 memory_ = new MemoryFake;
37 } 42 }
38 43
39 template <typename Ehdr> 44 void InitElf32(uint32_t machine_type) {
40 void InitEhdr(Ehdr* ehdr) {
41 memset(ehdr, 0, sizeof(Ehdr));
42 memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG);
43 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
44 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
45 ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
46 }
47
48 void InitElf32(uint32_t type) {
49 Elf32_Ehdr ehdr; 45 Elf32_Ehdr ehdr;
46 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type);
50 47
51 InitEhdr<Elf32_Ehdr>(&ehdr);
52 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
53
54 ehdr.e_type = ET_DYN;
55 ehdr.e_machine = type;
56 ehdr.e_version = EV_CURRENT;
57 ehdr.e_entry = 0;
58 ehdr.e_phoff = 0x100; 48 ehdr.e_phoff = 0x100;
59 ehdr.e_shoff = 0;
60 ehdr.e_flags = 0;
61 ehdr.e_ehsize = sizeof(ehdr); 49 ehdr.e_ehsize = sizeof(ehdr);
62 ehdr.e_phentsize = sizeof(Elf32_Phdr); 50 ehdr.e_phentsize = sizeof(Elf32_Phdr);
63 ehdr.e_phnum = 1; 51 ehdr.e_phnum = 1;
64 ehdr.e_shentsize = sizeof(Elf32_Shdr); 52 ehdr.e_shentsize = sizeof(Elf32_Shdr);
65 ehdr.e_shnum = 0; 53 if (machine_type == EM_ARM) {
66 ehdr.e_shstrndx = 0;
67 if (type == EM_ARM) {
68 ehdr.e_flags = 0x5000200; 54 ehdr.e_flags = 0x5000200;
69 ehdr.e_phnum = 2; 55 ehdr.e_phnum = 2;
70 } 56 }
@@ -73,16 +59,13 @@ class ElfTest : public ::testing::Test {
73 Elf32_Phdr phdr; 59 Elf32_Phdr phdr;
74 memset(&phdr, 0, sizeof(phdr)); 60 memset(&phdr, 0, sizeof(phdr));
75 phdr.p_type = PT_LOAD; 61 phdr.p_type = PT_LOAD;
76 phdr.p_offset = 0;
77 phdr.p_vaddr = 0;
78 phdr.p_paddr = 0;
79 phdr.p_filesz = 0x10000; 62 phdr.p_filesz = 0x10000;
80 phdr.p_memsz = 0x10000; 63 phdr.p_memsz = 0x10000;
81 phdr.p_flags = PF_R | PF_X; 64 phdr.p_flags = PF_R | PF_X;
82 phdr.p_align = 0x1000; 65 phdr.p_align = 0x1000;
83 memory_->SetMemory(0x100, &phdr, sizeof(phdr)); 66 memory_->SetMemory(0x100, &phdr, sizeof(phdr));
84 67
85 if (type == EM_ARM) { 68 if (machine_type == EM_ARM) {
86 memset(&phdr, 0, sizeof(phdr)); 69 memset(&phdr, 0, sizeof(phdr));
87 phdr.p_type = PT_ARM_EXIDX; 70 phdr.p_type = PT_ARM_EXIDX;
88 phdr.p_offset = 0x30000; 71 phdr.p_offset = 0x30000;
@@ -96,33 +79,21 @@ class ElfTest : public ::testing::Test {
96 } 79 }
97 } 80 }
98 81
99 void InitElf64(uint32_t type) { 82 void InitElf64(uint32_t machine_type) {
100 Elf64_Ehdr ehdr; 83 Elf64_Ehdr ehdr;
84 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type);
101 85
102 InitEhdr<Elf64_Ehdr>(&ehdr);
103 ehdr.e_ident[EI_CLASS] = ELFCLASS64;
104
105 ehdr.e_type = ET_DYN;
106 ehdr.e_machine = type;
107 ehdr.e_version = EV_CURRENT;
108 ehdr.e_entry = 0;
109 ehdr.e_phoff = 0x100; 86 ehdr.e_phoff = 0x100;
110 ehdr.e_shoff = 0;
111 ehdr.e_flags = 0x5000200; 87 ehdr.e_flags = 0x5000200;
112 ehdr.e_ehsize = sizeof(ehdr); 88 ehdr.e_ehsize = sizeof(ehdr);
113 ehdr.e_phentsize = sizeof(Elf64_Phdr); 89 ehdr.e_phentsize = sizeof(Elf64_Phdr);
114 ehdr.e_phnum = 1; 90 ehdr.e_phnum = 1;
115 ehdr.e_shentsize = sizeof(Elf64_Shdr); 91 ehdr.e_shentsize = sizeof(Elf64_Shdr);
116 ehdr.e_shnum = 0;
117 ehdr.e_shstrndx = 0;
118 memory_->SetMemory(0, &ehdr, sizeof(ehdr)); 92 memory_->SetMemory(0, &ehdr, sizeof(ehdr));
119 93
120 Elf64_Phdr phdr; 94 Elf64_Phdr phdr;
121 memset(&phdr, 0, sizeof(phdr)); 95 memset(&phdr, 0, sizeof(phdr));
122 phdr.p_type = PT_LOAD; 96 phdr.p_type = PT_LOAD;
123 phdr.p_offset = 0;
124 phdr.p_vaddr = 0;
125 phdr.p_paddr = 0;
126 phdr.p_filesz = 0x10000; 97 phdr.p_filesz = 0x10000;
127 phdr.p_memsz = 0x10000; 98 phdr.p_memsz = 0x10000;
128 phdr.p_flags = PF_R | PF_X; 99 phdr.p_flags = PF_R | PF_X;
@@ -161,6 +132,32 @@ TEST_F(ElfTest, elf_invalid) {
161 ASSERT_FALSE(elf.Step(0, nullptr, nullptr)); 132 ASSERT_FALSE(elf.Step(0, nullptr, nullptr));
162} 133}
163 134
135TEST_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
164TEST_F(ElfTest, elf_arm) { 161TEST_F(ElfTest, elf_arm) {
165 Elf elf(memory_); 162 Elf elf(memory_);
166 163
@@ -208,3 +205,95 @@ TEST_F(ElfTest, elf_x86_64) {
208 ASSERT_EQ(ELFCLASS64, elf.class_type()); 205 ASSERT_EQ(ELFCLASS64, elf.class_type());
209 ASSERT_TRUE(elf.interface() != nullptr); 206 ASSERT_TRUE(elf.interface() != nullptr);
210} 207}
208
209TEST_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
215 Elf elf(memory_);
216 ASSERT_TRUE(elf.Init());
217 ASSERT_TRUE(elf.interface() != nullptr);
218 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
219 EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
220 EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
221}
222
223TEST_F(ElfTest, gnu_debugdata_init_fail64) {
224 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 });
228
229 Elf elf(memory_);
230 ASSERT_TRUE(elf.Init());
231 ASSERT_TRUE(elf.interface() != nullptr);
232 ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
233 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());
249
250 elf.InitGnuDebugdata();
251 ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
252}
253
254TEST_F(ElfTest, gnu_debugdata_init64) {
255 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 });
259
260 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);
269}
270
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