1 //===- ELFObjectFileTest.cpp - Tests for ELFObjectFile --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Object/ELFObjectFile.h" 10 #include "llvm/Support/MemoryBuffer.h" 11 #include "llvm/ObjectYAML/yaml2obj.h" 12 #include "llvm/Support/YAMLTraits.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "gtest/gtest.h" 15 16 using namespace llvm; 17 using namespace llvm::object; 18 19 namespace { 20 21 // A struct to initialize a buffer to represent an ELF object file. 22 struct DataForTest { 23 std::vector<uint8_t> Data; 24 25 template <typename T> 26 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 27 uint16_t Machine) { 28 T Ehdr{}; // Zero-initialise the header. 29 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 30 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 31 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 32 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 33 Ehdr.e_ident[ELF::EI_CLASS] = Class; 34 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 35 Ehdr.e_ident[ELF::EI_VERSION] = 1; 36 Ehdr.e_type = ELF::ET_REL; 37 Ehdr.e_machine = Machine; 38 Ehdr.e_version = 1; 39 Ehdr.e_ehsize = sizeof(T); 40 41 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 42 if (sys::IsLittleEndianHost != IsLittleEndian) { 43 sys::swapByteOrder(Ehdr.e_type); 44 sys::swapByteOrder(Ehdr.e_machine); 45 sys::swapByteOrder(Ehdr.e_version); 46 sys::swapByteOrder(Ehdr.e_ehsize); 47 } 48 49 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 50 std::vector<uint8_t> Bytes; 51 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 52 return Bytes; 53 } 54 55 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) { 56 if (Class == ELF::ELFCLASS64) 57 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 58 else { 59 assert(Class == ELF::ELFCLASS32); 60 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine); 61 } 62 } 63 }; 64 65 void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 66 Triple::ArchType Arch) { 67 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 68 object::ObjectFile::createELFObjectFile( 69 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 70 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 71 72 const ObjectFile &File = *(*ELFObjOrErr).get(); 73 EXPECT_EQ(Fmt, File.getFileFormatName()); 74 EXPECT_EQ(Arch, File.getArch()); 75 } 76 77 std::array<DataForTest, 4> generateData(uint16_t Machine) { 78 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine), 79 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine), 80 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine), 81 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)}; 82 } 83 84 } // namespace 85 86 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) { 87 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 88 "elf64-unknown", "elf64-unknown"}; 89 size_t I = 0; 90 for (const DataForTest &D : generateData(ELF::EM_NONE)) 91 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 92 93 // Test an arbitrary unused EM_* value (255). 94 I = 0; 95 for (const DataForTest &D : generateData(255)) 96 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 97 } 98 99 TEST(ELFObjectFileTest, MachineTestForVE) { 100 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 101 "elf64-ve", "elf64-ve"}; 102 size_t I = 0; 103 for (const DataForTest &D : generateData(ELF::EM_VE)) 104 checkFormatAndArch(D, Formats[I++], Triple::ve); 105 } 106 107 TEST(ELFObjectFileTest, MachineTestForX86_64) { 108 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64", 109 "elf64-x86-64", "elf64-x86-64"}; 110 size_t I = 0; 111 for (const DataForTest &D : generateData(ELF::EM_X86_64)) 112 checkFormatAndArch(D, Formats[I++], Triple::x86_64); 113 } 114 115 TEST(ELFObjectFileTest, MachineTestFor386) { 116 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386", 117 "elf64-i386"}; 118 size_t I = 0; 119 for (const DataForTest &D : generateData(ELF::EM_386)) 120 checkFormatAndArch(D, Formats[I++], Triple::x86); 121 } 122 123 TEST(ELFObjectFileTest, MachineTestForMIPS) { 124 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips", 125 "elf64-mips"}; 126 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips, 127 Triple::mips64el, Triple::mips64}; 128 size_t I = 0; 129 for (const DataForTest &D : generateData(ELF::EM_MIPS)) { 130 checkFormatAndArch(D, Formats[I], Archs[I]); 131 ++I; 132 } 133 } 134 135 TEST(ELFObjectFileTest, MachineTestForAMDGPU) { 136 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu", 137 "elf64-amdgpu", "elf64-amdgpu"}; 138 size_t I = 0; 139 for (const DataForTest &D : generateData(ELF::EM_AMDGPU)) 140 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 141 } 142 143 TEST(ELFObjectFileTest, MachineTestForIAMCU) { 144 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu", 145 "elf64-unknown", "elf64-unknown"}; 146 size_t I = 0; 147 for (const DataForTest &D : generateData(ELF::EM_IAMCU)) 148 checkFormatAndArch(D, Formats[I++], Triple::x86); 149 } 150 151 TEST(ELFObjectFileTest, MachineTestForAARCH64) { 152 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 153 "elf64-littleaarch64", 154 "elf64-bigaarch64"}; 155 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be, 156 Triple::aarch64, Triple::aarch64_be}; 157 size_t I = 0; 158 for (const DataForTest &D : generateData(ELF::EM_AARCH64)) { 159 checkFormatAndArch(D, Formats[I], Archs[I]); 160 ++I; 161 } 162 } 163 164 TEST(ELFObjectFileTest, MachineTestForPPC64) { 165 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 166 "elf64-powerpcle", "elf64-powerpc"}; 167 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64, 168 Triple::ppc64le, Triple::ppc64}; 169 size_t I = 0; 170 for (const DataForTest &D : generateData(ELF::EM_PPC64)) { 171 checkFormatAndArch(D, Formats[I], Archs[I]); 172 ++I; 173 } 174 } 175 176 TEST(ELFObjectFileTest, MachineTestForPPC) { 177 std::array<StringRef, 4> Formats = {"elf32-powerpc", "elf32-powerpc", 178 "elf64-unknown", "elf64-unknown"}; 179 size_t I = 0; 180 for (const DataForTest &D : generateData(ELF::EM_PPC)) 181 checkFormatAndArch(D, Formats[I++], Triple::ppc); 182 } 183 184 TEST(ELFObjectFileTest, MachineTestForRISCV) { 185 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", 186 "elf64-littleriscv", "elf64-littleriscv"}; 187 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, 188 Triple::riscv64, Triple::riscv64}; 189 size_t I = 0; 190 for (const DataForTest &D : generateData(ELF::EM_RISCV)) { 191 checkFormatAndArch(D, Formats[I], Archs[I]); 192 ++I; 193 } 194 } 195 196 TEST(ELFObjectFileTest, MachineTestForARM) { 197 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm", 198 "elf64-unknown", "elf64-unknown"}; 199 size_t I = 0; 200 for (const DataForTest &D : generateData(ELF::EM_ARM)) 201 checkFormatAndArch(D, Formats[I++], Triple::arm); 202 } 203 204 TEST(ELFObjectFileTest, MachineTestForS390) { 205 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 206 "elf64-s390", "elf64-s390"}; 207 size_t I = 0; 208 for (const DataForTest &D : generateData(ELF::EM_S390)) 209 checkFormatAndArch(D, Formats[I++], Triple::systemz); 210 } 211 212 TEST(ELFObjectFileTest, MachineTestForSPARCV9) { 213 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 214 "elf64-sparc", "elf64-sparc"}; 215 size_t I = 0; 216 for (const DataForTest &D : generateData(ELF::EM_SPARCV9)) 217 checkFormatAndArch(D, Formats[I++], Triple::sparcv9); 218 } 219 220 TEST(ELFObjectFileTest, MachineTestForSPARC) { 221 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 222 "elf64-unknown", "elf64-unknown"}; 223 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 224 Triple::sparcel, Triple::sparc}; 225 size_t I = 0; 226 for (const DataForTest &D : generateData(ELF::EM_SPARC)) { 227 checkFormatAndArch(D, Formats[I], Archs[I]); 228 ++I; 229 } 230 } 231 232 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) { 233 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 234 "elf64-unknown", "elf64-unknown"}; 235 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 236 Triple::sparcel, Triple::sparc}; 237 size_t I = 0; 238 for (const DataForTest &D : generateData(ELF::EM_SPARC32PLUS)) { 239 checkFormatAndArch(D, Formats[I], Archs[I]); 240 ++I; 241 } 242 } 243 244 TEST(ELFObjectFileTest, MachineTestForBPF) { 245 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 246 "elf64-bpf", "elf64-bpf"}; 247 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb, 248 Triple::bpfel, Triple::bpfeb}; 249 size_t I = 0; 250 for (const DataForTest &D : generateData(ELF::EM_BPF)) { 251 checkFormatAndArch(D, Formats[I], Archs[I]); 252 ++I; 253 } 254 } 255 256 TEST(ELFObjectFileTest, MachineTestForAVR) { 257 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown", 258 "elf64-unknown"}; 259 size_t I = 0; 260 for (const DataForTest &D : generateData(ELF::EM_AVR)) 261 checkFormatAndArch(D, Formats[I++], Triple::avr); 262 } 263 264 TEST(ELFObjectFileTest, MachineTestForHEXAGON) { 265 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon", 266 "elf64-unknown", "elf64-unknown"}; 267 size_t I = 0; 268 for (const DataForTest &D : generateData(ELF::EM_HEXAGON)) 269 checkFormatAndArch(D, Formats[I++], Triple::hexagon); 270 } 271 272 TEST(ELFObjectFileTest, MachineTestForLANAI) { 273 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai", 274 "elf64-unknown", "elf64-unknown"}; 275 size_t I = 0; 276 for (const DataForTest &D : generateData(ELF::EM_LANAI)) 277 checkFormatAndArch(D, Formats[I++], Triple::lanai); 278 } 279 280 TEST(ELFObjectFileTest, MachineTestForMSP430) { 281 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430", 282 "elf64-unknown", "elf64-unknown"}; 283 size_t I = 0; 284 for (const DataForTest &D : generateData(ELF::EM_MSP430)) 285 checkFormatAndArch(D, Formats[I++], Triple::msp430); 286 } 287 288 TEST(ELFObjectFileTest, MachineTestForCSKY) { 289 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 290 "elf64-unknown", "elf64-unknown"}; 291 size_t I = 0; 292 for (const DataForTest &D : generateData(ELF::EM_CSKY)) 293 checkFormatAndArch(D, Formats[I++], Triple::csky); 294 } 295 296 // ELF relative relocation type test. 297 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 298 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 299 } 300 301 template <class ELFT> 302 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 303 StringRef Yaml) { 304 raw_svector_ostream OS(Storage); 305 yaml::Input YIn(Yaml); 306 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 307 return createStringError(std::errc::invalid_argument, 308 "unable to convert YAML"); 309 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 310 } 311 312 // Check we are able to create an ELFObjectFile even when the content of the 313 // SHT_SYMTAB_SHNDX section can't be read properly. 314 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 315 SmallString<0> Storage; 316 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 317 --- !ELF 318 FileHeader: 319 Class: ELFCLASS64 320 Data: ELFDATA2LSB 321 Type: ET_REL 322 Sections: 323 - Name: .symtab_shndx 324 Type: SHT_SYMTAB_SHNDX 325 Entries: [ 0 ] 326 ShSize: 0xFFFFFFFF 327 )"); 328 329 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 330 } 331 332 // Test that we are able to create an ELFObjectFile even when loadable segments 333 // are unsorted by virtual address. 334 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 335 336 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 337 SmallString<0> Storage; 338 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 339 --- !ELF 340 FileHeader: 341 Class: ELFCLASS64 342 Data: ELFDATA2LSB 343 Type: ET_EXEC 344 Sections: 345 - Name: .foo 346 Type: SHT_PROGBITS 347 Address: 0x1000 348 Offset: 0x3000 349 ContentArray: [ 0x11 ] 350 - Name: .bar 351 Type: SHT_PROGBITS 352 Address: 0x2000 353 Offset: 0x4000 354 ContentArray: [ 0x99 ] 355 ProgramHeaders: 356 - Type: PT_LOAD 357 VAddr: 0x2000 358 FirstSec: .bar 359 LastSec: .bar 360 - Type: PT_LOAD 361 VAddr: 0x1000 362 FirstSec: .foo 363 LastSec: .foo 364 )"); 365 366 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 367 368 std::string WarnString; 369 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 370 Expected<const uint8_t *> DataOrErr = 371 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 372 EXPECT_TRUE(WarnString.empty()); 373 WarnString = Msg.str(); 374 return Error::success(); 375 }); 376 377 if (!DataOrErr) { 378 ADD_FAILURE() << toString(DataOrErr.takeError()); 379 return nullptr; 380 } 381 382 EXPECT_TRUE(WarnString == 383 "loadable segments are unsorted by virtual address"); 384 WarnString = ""; 385 return *DataOrErr; 386 }; 387 388 const uint8_t *Data = ToMappedAddr(0x1000); 389 ASSERT_TRUE(Data); 390 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 391 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 392 EXPECT_EQ(Data[0], 0x11); 393 394 Data = ToMappedAddr(0x2000); 395 ASSERT_TRUE(Data); 396 Buf = ExpectedFile->getMemoryBufferRef(); 397 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 398 EXPECT_EQ(Data[0], 0x99); 399 } 400 401 // This is a test for API that is related to symbols. 402 // We check that errors are properly reported here. 403 TEST(ELFObjectFileTest, InvalidSymbolTest) { 404 SmallString<0> Storage; 405 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 406 --- !ELF 407 FileHeader: 408 Class: ELFCLASS64 409 Data: ELFDATA2LSB 410 Type: ET_DYN 411 Machine: EM_X86_64 412 Sections: 413 - Name: .symtab 414 Type: SHT_SYMTAB 415 )"); 416 417 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 418 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 419 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 420 421 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 422 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 423 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 424 425 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 426 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 427 428 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 429 // SymbolRef::getName() calls it internally. We can't test it directly, 430 // because it is protected. 431 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 432 FailedWithMessage(ErrMsg)); 433 434 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 435 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 436 FailedWithMessage(ErrMsg)); 437 438 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 439 // SymbolRef::getSection() calls it internally. We can't test it 440 // directly, because it is protected. 441 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 442 FailedWithMessage(ErrMsg)); 443 444 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 445 // SymbolRef::getFlags() calls it internally. We can't test it directly, 446 // because it is protected. 447 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 448 FailedWithMessage(ErrMsg)); 449 450 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 451 // SymbolRef::getType() calls it internally. We can't test it directly, 452 // because it is protected. 453 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 454 FailedWithMessage(ErrMsg)); 455 456 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 457 // SymbolRef::getAddress() calls it internally. We can't test it 458 // directly, because it is protected. 459 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 460 FailedWithMessage(ErrMsg)); 461 462 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 463 // method that generates errors for all cases above. 464 EXPECT_THAT_EXPECTED( 465 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 466 EXPECT_THAT_ERROR( 467 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 468 .takeError(), 469 FailedWithMessage(ErrMsg)); 470 }; 471 472 // We create a symbol with an index that is too large to exist in the symbol 473 // table. 474 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 475 "section (0x18)"); 476 477 // We create a symbol with an index that is too large to exist in the object. 478 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 479 "end of the section (0x18)"); 480 } 481