xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 69f2c79f2ad2c3ebdb000cb1311612db7bd2bef8)
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 std::array<DataForTest, 4> generateData(uint16_t Machine) {
76   return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),
77           DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),
78           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),
79           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};
80 }
81 
82 } // namespace
83 
84 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {
85   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
86                                       "elf64-unknown", "elf64-unknown"};
87   size_t I = 0;
88   for (const DataForTest &D : generateData(ELF::EM_NONE))
89     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
90 
91   // Test an arbitrary unused EM_* value (255).
92   I = 0;
93   for (const DataForTest &D : generateData(255))
94     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
95 }
96 
97 TEST(ELFObjectFileTest, MachineTestForVE) {
98   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
99                                       "elf64-ve", "elf64-ve"};
100   size_t I = 0;
101   for (const DataForTest &D : generateData(ELF::EM_VE))
102     checkFormatAndArch(D, Formats[I++], Triple::ve);
103 }
104 
105 TEST(ELFObjectFileTest, MachineTestForX86_64) {
106   std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",
107                                       "elf64-x86-64", "elf64-x86-64"};
108   size_t I = 0;
109   for (const DataForTest &D : generateData(ELF::EM_X86_64))
110     checkFormatAndArch(D, Formats[I++], Triple::x86_64);
111 }
112 
113 TEST(ELFObjectFileTest, MachineTestFor386) {
114   std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",
115                                       "elf64-i386"};
116   size_t I = 0;
117   for (const DataForTest &D : generateData(ELF::EM_386))
118     checkFormatAndArch(D, Formats[I++], Triple::x86);
119 }
120 
121 TEST(ELFObjectFileTest, MachineTestForMIPS) {
122   std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",
123                                       "elf64-mips"};
124   std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,
125                                            Triple::mips64el, Triple::mips64};
126   size_t I = 0;
127   for (const DataForTest &D : generateData(ELF::EM_MIPS)) {
128     checkFormatAndArch(D, Formats[I], Archs[I]);
129     ++I;
130   }
131 }
132 
133 TEST(ELFObjectFileTest, MachineTestForAMDGPU) {
134   std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",
135                                       "elf64-amdgpu", "elf64-amdgpu"};
136   size_t I = 0;
137   for (const DataForTest &D : generateData(ELF::EM_AMDGPU))
138     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
139 }
140 
141 TEST(ELFObjectFileTest, MachineTestForIAMCU) {
142   std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",
143                                       "elf64-unknown", "elf64-unknown"};
144   size_t I = 0;
145   for (const DataForTest &D : generateData(ELF::EM_IAMCU))
146     checkFormatAndArch(D, Formats[I++], Triple::x86);
147 }
148 
149 TEST(ELFObjectFileTest, MachineTestForAARCH64) {
150   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
151                                       "elf64-littleaarch64",
152                                       "elf64-bigaarch64"};
153   std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,
154                                            Triple::aarch64, Triple::aarch64_be};
155   size_t I = 0;
156   for (const DataForTest &D : generateData(ELF::EM_AARCH64)) {
157     checkFormatAndArch(D, Formats[I], Archs[I]);
158     ++I;
159   }
160 }
161 
162 TEST(ELFObjectFileTest, MachineTestForPPC64) {
163   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
164                                       "elf64-powerpcle", "elf64-powerpc"};
165   std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,
166                                            Triple::ppc64le, Triple::ppc64};
167   size_t I = 0;
168   for (const DataForTest &D : generateData(ELF::EM_PPC64)) {
169     checkFormatAndArch(D, Formats[I], Archs[I]);
170     ++I;
171   }
172 }
173 
174 TEST(ELFObjectFileTest, MachineTestForPPC) {
175   std::array<StringRef, 4> Formats = {"elf32-powerpc", "elf32-powerpc",
176                                       "elf64-unknown", "elf64-unknown"};
177   size_t I = 0;
178   for (const DataForTest &D : generateData(ELF::EM_PPC))
179     checkFormatAndArch(D, Formats[I++], Triple::ppc);
180 }
181 
182 TEST(ELFObjectFileTest, MachineTestForRISCV) {
183   std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv",
184                                       "elf64-littleriscv", "elf64-littleriscv"};
185   std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32,
186                                            Triple::riscv64, Triple::riscv64};
187   size_t I = 0;
188   for (const DataForTest &D : generateData(ELF::EM_RISCV)) {
189     checkFormatAndArch(D, Formats[I], Archs[I]);
190     ++I;
191   }
192 }
193 
194 TEST(ELFObjectFileTest, MachineTestForARM) {
195   std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",
196                                       "elf64-unknown", "elf64-unknown"};
197   size_t I = 0;
198   for (const DataForTest &D : generateData(ELF::EM_ARM))
199     checkFormatAndArch(D, Formats[I++], Triple::arm);
200 }
201 
202 TEST(ELFObjectFileTest, MachineTestForS390) {
203   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
204                                       "elf64-s390", "elf64-s390"};
205   size_t I = 0;
206   for (const DataForTest &D : generateData(ELF::EM_S390))
207     checkFormatAndArch(D, Formats[I++], Triple::systemz);
208 }
209 
210 TEST(ELFObjectFileTest, MachineTestForSPARCV9) {
211   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
212                                       "elf64-sparc", "elf64-sparc"};
213   size_t I = 0;
214   for (const DataForTest &D : generateData(ELF::EM_SPARCV9))
215     checkFormatAndArch(D, Formats[I++], Triple::sparcv9);
216 }
217 
218 TEST(ELFObjectFileTest, MachineTestForSPARC) {
219   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
220                                       "elf64-unknown", "elf64-unknown"};
221   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
222                                            Triple::sparcel, Triple::sparc};
223   size_t I = 0;
224   for (const DataForTest &D : generateData(ELF::EM_SPARC)) {
225     checkFormatAndArch(D, Formats[I], Archs[I]);
226     ++I;
227   }
228 }
229 
230 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {
231   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
232                                       "elf64-unknown", "elf64-unknown"};
233   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
234                                            Triple::sparcel, Triple::sparc};
235   size_t I = 0;
236   for (const DataForTest &D : generateData(ELF::EM_SPARC32PLUS)) {
237     checkFormatAndArch(D, Formats[I], Archs[I]);
238     ++I;
239   }
240 }
241 
242 TEST(ELFObjectFileTest, MachineTestForBPF) {
243   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
244                                       "elf64-bpf", "elf64-bpf"};
245   std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,
246                                            Triple::bpfel, Triple::bpfeb};
247   size_t I = 0;
248   for (const DataForTest &D : generateData(ELF::EM_BPF)) {
249     checkFormatAndArch(D, Formats[I], Archs[I]);
250     ++I;
251   }
252 }
253 
254 TEST(ELFObjectFileTest, MachineTestForAVR) {
255   std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",
256                                       "elf64-unknown"};
257   size_t I = 0;
258   for (const DataForTest &D : generateData(ELF::EM_AVR))
259     checkFormatAndArch(D, Formats[I++], Triple::avr);
260 }
261 
262 TEST(ELFObjectFileTest, MachineTestForHEXAGON) {
263   std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",
264                                       "elf64-unknown", "elf64-unknown"};
265   size_t I = 0;
266   for (const DataForTest &D : generateData(ELF::EM_HEXAGON))
267     checkFormatAndArch(D, Formats[I++], Triple::hexagon);
268 }
269 
270 TEST(ELFObjectFileTest, MachineTestForLANAI) {
271   std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",
272                                       "elf64-unknown", "elf64-unknown"};
273   size_t I = 0;
274   for (const DataForTest &D : generateData(ELF::EM_LANAI))
275     checkFormatAndArch(D, Formats[I++], Triple::lanai);
276 }
277 
278 TEST(ELFObjectFileTest, MachineTestForMSP430) {
279   std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",
280                                       "elf64-unknown", "elf64-unknown"};
281   size_t I = 0;
282   for (const DataForTest &D : generateData(ELF::EM_MSP430))
283     checkFormatAndArch(D, Formats[I++], Triple::msp430);
284 }
285 
286 TEST(ELFObjectFileTest, MachineTestForCSKY) {
287   std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
288                                       "elf64-unknown", "elf64-unknown"};
289   size_t I = 0;
290   for (const DataForTest &D : generateData(ELF::EM_CSKY))
291     checkFormatAndArch(D, Formats[I++], Triple::csky);
292 }
293 
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