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 template <class ELFT> 18 static Expected<ELFObjectFile<ELFT>> create(ArrayRef<uint8_t> Data) { 19 return ELFObjectFile<ELFT>::create( 20 MemoryBufferRef(toStringRef(Data), "Test buffer")); 21 } 22 23 // A class to initialize a buffer to represent an ELF object file. 24 struct DataForTest { 25 std::vector<uint8_t> Data; 26 27 template <typename T> 28 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 29 uint16_t Machine) { 30 T Ehdr{}; // Zero-initialise the header. 31 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 32 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 33 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 34 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 35 Ehdr.e_ident[ELF::EI_CLASS] = Class; 36 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 37 Ehdr.e_ident[ELF::EI_VERSION] = 1; 38 Ehdr.e_type = ELF::ET_REL; 39 Ehdr.e_machine = Machine; 40 Ehdr.e_version = 1; 41 Ehdr.e_ehsize = sizeof(T); 42 43 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 44 if (sys::IsLittleEndianHost != IsLittleEndian) { 45 sys::swapByteOrder(Ehdr.e_type); 46 sys::swapByteOrder(Ehdr.e_machine); 47 sys::swapByteOrder(Ehdr.e_version); 48 sys::swapByteOrder(Ehdr.e_ehsize); 49 } 50 51 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 52 std::vector<uint8_t> Bytes; 53 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 54 return Bytes; 55 } 56 57 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) { 58 if (Class == ELF::ELFCLASS64) 59 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 60 else { 61 assert(Class == ELF::ELFCLASS32); 62 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 63 } 64 } 65 }; 66 67 TEST(ELFObjectFileTest, MachineTestForVE) { 68 DataForTest Data(ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_VE); 69 auto ExpectedFile = create<ELF64LE>(Data.Data); 70 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 71 const ELFObjectFile<ELF64LE> &File = *ExpectedFile; 72 EXPECT_EQ("elf64-ve", File.getFileFormatName()); 73 EXPECT_EQ(Triple::ve, File.getArch()); 74 } 75 76 TEST(ELFObjectFileTest, MachineTestForX86_64) { 77 DataForTest Data(ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_X86_64); 78 auto ExpectedFile = create<ELF64LE>(Data.Data); 79 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 80 const ELFObjectFile<ELF64LE> &File = *ExpectedFile; 81 EXPECT_EQ("elf64-x86-64", File.getFileFormatName()); 82 EXPECT_EQ(Triple::x86_64, File.getArch()); 83 } 84 85 TEST(ELFObjectFileTest, MachineTestFor386) { 86 DataForTest Data(ELF::ELFCLASS32, ELF::ELFDATA2LSB, ELF::EM_386); 87 auto ExpectedFile = create<ELF32LE>(Data.Data); 88 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 89 const ELFObjectFile<ELF32LE> &File = *ExpectedFile; 90 EXPECT_EQ("elf32-i386", File.getFileFormatName()); 91 EXPECT_EQ(Triple::x86, File.getArch()); 92 } 93 94 TEST(ELFObjectFileTest, MachineTestForMIPS) { 95 { 96 DataForTest Data(ELF::ELFCLASS64, ELF::ELFDATA2LSB, ELF::EM_MIPS); 97 auto ExpectedFile = create<ELF64LE>(Data.Data); 98 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 99 const ELFObjectFile<ELF64LE> &File = *ExpectedFile; 100 EXPECT_EQ("elf64-mips", File.getFileFormatName()); 101 EXPECT_EQ(Triple::mips64el, File.getArch()); 102 } 103 { 104 DataForTest Data(ELF::ELFCLASS64, ELF::ELFDATA2MSB, ELF::EM_MIPS); 105 auto ExpectedFile = create<ELF64BE>(Data.Data); 106 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 107 const ELFObjectFile<ELF64BE> &File = *ExpectedFile; 108 EXPECT_EQ("elf64-mips", File.getFileFormatName()); 109 EXPECT_EQ(Triple::mips64, File.getArch()); 110 } 111 { 112 DataForTest Data(ELF::ELFCLASS32, ELF::ELFDATA2LSB, ELF::EM_MIPS); 113 auto ExpectedFile = create<ELF32LE>(Data.Data); 114 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 115 const ELFObjectFile<ELF32LE> &File = *ExpectedFile; 116 EXPECT_EQ("elf32-mips", File.getFileFormatName()); 117 EXPECT_EQ(Triple::mipsel, File.getArch()); 118 } 119 { 120 DataForTest Data(ELF::ELFCLASS32, ELF::ELFDATA2MSB, ELF::EM_MIPS); 121 auto ExpectedFile = create<ELF32BE>(Data.Data); 122 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 123 const ELFObjectFile<ELF32BE> &File = *ExpectedFile; 124 EXPECT_EQ("elf32-mips", File.getFileFormatName()); 125 EXPECT_EQ(Triple::mips, File.getArch()); 126 } 127 } 128