xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 5921782f744deffb5f5bfd96f6a7932a4ff75666)
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