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/Testing/Support/Error.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 using namespace llvm::object; 16 17 namespace { 18 19 // A struct to initialize a buffer to represent an ELF object file. 20 struct DataForTest { 21 std::vector<uint8_t> Data; 22 23 template <typename T> 24 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 25 uint16_t Machine) { 26 T Ehdr{}; // Zero-initialise the header. 27 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 28 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 29 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 30 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 31 Ehdr.e_ident[ELF::EI_CLASS] = Class; 32 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 33 Ehdr.e_ident[ELF::EI_VERSION] = 1; 34 Ehdr.e_type = ELF::ET_REL; 35 Ehdr.e_machine = Machine; 36 Ehdr.e_version = 1; 37 Ehdr.e_ehsize = sizeof(T); 38 39 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 40 if (sys::IsLittleEndianHost != IsLittleEndian) { 41 sys::swapByteOrder(Ehdr.e_type); 42 sys::swapByteOrder(Ehdr.e_machine); 43 sys::swapByteOrder(Ehdr.e_version); 44 sys::swapByteOrder(Ehdr.e_ehsize); 45 } 46 47 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 48 std::vector<uint8_t> Bytes; 49 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 50 return Bytes; 51 } 52 53 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) { 54 if (Class == ELF::ELFCLASS64) 55 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 56 else { 57 assert(Class == ELF::ELFCLASS32); 58 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine); 59 } 60 } 61 }; 62 63 void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 64 Triple::ArchType Arch) { 65 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 66 object::ObjectFile::createELFObjectFile( 67 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 68 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 69 70 const ObjectFile &File = *(*ELFObjOrErr).get(); 71 EXPECT_EQ(Fmt, File.getFileFormatName()); 72 EXPECT_EQ(Arch, File.getArch()); 73 } 74 75 } // namespace 76 77 TEST(ELFObjectFileTest, MachineTestForVE) { 78 checkFormatAndArch({ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_VE}, 79 "elf64-ve", Triple::ve); 80 } 81 82 TEST(ELFObjectFileTest, MachineTestForX86_64) { 83 checkFormatAndArch({ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_X86_64}, 84 "elf64-x86-64", Triple::x86_64); 85 } 86 87 TEST(ELFObjectFileTest, MachineTestFor386) { 88 checkFormatAndArch({ELF::ELFCLASS32, ELF::ELFDATA2LSB, ELF::EM_386}, 89 "elf32-i386", Triple::x86); 90 } 91 92 TEST(ELFObjectFileTest, MachineTestForMIPS) { 93 checkFormatAndArch({ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_MIPS}, 94 "elf64-mips", Triple::mips64el); 95 96 checkFormatAndArch({ELF::ELFCLASS64, ELF::ELFDATA2MSB, ELF::EM_MIPS}, 97 "elf64-mips", Triple::mips64); 98 99 checkFormatAndArch({ELF::ELFCLASS32, ELF::ELFDATA2LSB, ELF::EM_MIPS}, 100 "elf32-mips", Triple::mipsel); 101 102 checkFormatAndArch({ELF::ELFCLASS32, ELF::ELFDATA2MSB, ELF::EM_MIPS}, 103 "elf32-mips", Triple::mips); 104 } 105