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