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