1 /* 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 <fcntl.h> 19 #include <sys/stat.h> 20 #include <sys/types.h> 21 #include <unistd.h> 22 23 #include <gtest/gtest.h> 24 25 #include <unwindstack/Elf.h> 26 #include <unwindstack/MapInfo.h> 27 28 #include "ElfTestUtils.h" 29 #include "LogFake.h" 30 #include "MemoryFake.h" 31 32 #if !defined(PT_ARM_EXIDX) 33 #define PT_ARM_EXIDX 0x70000001 34 #endif 35 36 namespace unwindstack { 37 38 class ElfTest : public ::testing::Test { 39 protected: 40 void SetUp() override { 41 memory_ = new MemoryFake; 42 } 43 44 void InitElf32(uint32_t machine_type) { 45 Elf32_Ehdr ehdr; 46 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type); 47 48 ehdr.e_phoff = 0x100; 49 ehdr.e_ehsize = sizeof(ehdr); 50 ehdr.e_phentsize = sizeof(Elf32_Phdr); 51 ehdr.e_phnum = 1; 52 ehdr.e_shentsize = sizeof(Elf32_Shdr); 53 if (machine_type == EM_ARM) { 54 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; 62 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 68 if (machine_type == EM_ARM) { 69 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 82 void InitElf64(uint32_t machine_type) { 83 Elf64_Ehdr ehdr; 84 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type); 85 86 ehdr.e_phoff = 0x100; 87 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); 92 memory_->SetMemory(0, &ehdr, sizeof(ehdr)); 93 94 Elf64_Phdr phdr; 95 memset(&phdr, 0, sizeof(phdr)); 96 phdr.p_type = PT_LOAD; 97 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 107 TEST_F(ElfTest, invalid_memory) { 108 Elf elf(memory_); 109 110 ASSERT_FALSE(elf.Init()); 111 ASSERT_FALSE(elf.valid()); 112 } 113 114 TEST_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 135 TEST_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 148 TEST_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 161 TEST_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 173 TEST_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 185 TEST_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 197 TEST_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 } 208 209 TEST_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 223 TEST_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 237 TEST_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 254 TEST_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 271 class 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 280 TEST_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 300