15921782fSKazushi (Jam) Marukawa //===- ELFObjectFileTest.cpp - Tests for ELFObjectFile --------------------===//
25921782fSKazushi (Jam) Marukawa //
35921782fSKazushi (Jam) Marukawa // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45921782fSKazushi (Jam) Marukawa // See https://llvm.org/LICENSE.txt for license information.
55921782fSKazushi (Jam) Marukawa // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65921782fSKazushi (Jam) Marukawa //
75921782fSKazushi (Jam) Marukawa //===----------------------------------------------------------------------===//
85921782fSKazushi (Jam) Marukawa 
95921782fSKazushi (Jam) Marukawa #include "llvm/Object/ELFObjectFile.h"
105921782fSKazushi (Jam) Marukawa #include "llvm/Support/MemoryBuffer.h"
111af3cb54SGeorgii Rymar #include "llvm/ObjectYAML/yaml2obj.h"
121af3cb54SGeorgii Rymar #include "llvm/Support/YAMLTraits.h"
135921782fSKazushi (Jam) Marukawa #include "llvm/Testing/Support/Error.h"
145921782fSKazushi (Jam) Marukawa #include "gtest/gtest.h"
155921782fSKazushi (Jam) Marukawa 
165921782fSKazushi (Jam) Marukawa using namespace llvm;
175921782fSKazushi (Jam) Marukawa using namespace llvm::object;
185921782fSKazushi (Jam) Marukawa 
19154901c2SGeorgii Rymar namespace {
205921782fSKazushi (Jam) Marukawa 
21154901c2SGeorgii Rymar // A struct to initialize a buffer to represent an ELF object file.
225921782fSKazushi (Jam) Marukawa struct DataForTest {
235921782fSKazushi (Jam) Marukawa   std::vector<uint8_t> Data;
245921782fSKazushi (Jam) Marukawa 
255921782fSKazushi (Jam) Marukawa   template <typename T>
265921782fSKazushi (Jam) Marukawa   std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding,
275921782fSKazushi (Jam) Marukawa                                    uint16_t Machine) {
285921782fSKazushi (Jam) Marukawa     T Ehdr{}; // Zero-initialise the header.
295921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_MAG0] = 0x7f;
305921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_MAG1] = 'E';
315921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_MAG2] = 'L';
325921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_MAG3] = 'F';
335921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_CLASS] = Class;
345921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_DATA] = Encoding;
355921782fSKazushi (Jam) Marukawa     Ehdr.e_ident[ELF::EI_VERSION] = 1;
365921782fSKazushi (Jam) Marukawa     Ehdr.e_type = ELF::ET_REL;
375921782fSKazushi (Jam) Marukawa     Ehdr.e_machine = Machine;
385921782fSKazushi (Jam) Marukawa     Ehdr.e_version = 1;
395921782fSKazushi (Jam) Marukawa     Ehdr.e_ehsize = sizeof(T);
405921782fSKazushi (Jam) Marukawa 
415921782fSKazushi (Jam) Marukawa     bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB;
425921782fSKazushi (Jam) Marukawa     if (sys::IsLittleEndianHost != IsLittleEndian) {
435921782fSKazushi (Jam) Marukawa       sys::swapByteOrder(Ehdr.e_type);
445921782fSKazushi (Jam) Marukawa       sys::swapByteOrder(Ehdr.e_machine);
455921782fSKazushi (Jam) Marukawa       sys::swapByteOrder(Ehdr.e_version);
465921782fSKazushi (Jam) Marukawa       sys::swapByteOrder(Ehdr.e_ehsize);
475921782fSKazushi (Jam) Marukawa     }
485921782fSKazushi (Jam) Marukawa 
495921782fSKazushi (Jam) Marukawa     uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr);
505921782fSKazushi (Jam) Marukawa     std::vector<uint8_t> Bytes;
515921782fSKazushi (Jam) Marukawa     std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes));
525921782fSKazushi (Jam) Marukawa     return Bytes;
535921782fSKazushi (Jam) Marukawa   }
545921782fSKazushi (Jam) Marukawa 
555921782fSKazushi (Jam) Marukawa   DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) {
565921782fSKazushi (Jam) Marukawa     if (Class == ELF::ELFCLASS64)
575921782fSKazushi (Jam) Marukawa       Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine);
585921782fSKazushi (Jam) Marukawa     else {
595921782fSKazushi (Jam) Marukawa       assert(Class == ELF::ELFCLASS32);
60154901c2SGeorgii Rymar       Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine);
615921782fSKazushi (Jam) Marukawa     }
625921782fSKazushi (Jam) Marukawa   }
635921782fSKazushi (Jam) Marukawa };
645921782fSKazushi (Jam) Marukawa 
65154901c2SGeorgii Rymar void checkFormatAndArch(const DataForTest &D, StringRef Fmt,
66154901c2SGeorgii Rymar                         Triple::ArchType Arch) {
67154901c2SGeorgii Rymar   Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr =
68154901c2SGeorgii Rymar       object::ObjectFile::createELFObjectFile(
69154901c2SGeorgii Rymar           MemoryBufferRef(toStringRef(D.Data), "dummyELF"));
70154901c2SGeorgii Rymar   ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());
71154901c2SGeorgii Rymar 
72154901c2SGeorgii Rymar   const ObjectFile &File = *(*ELFObjOrErr).get();
73154901c2SGeorgii Rymar   EXPECT_EQ(Fmt, File.getFileFormatName());
74154901c2SGeorgii Rymar   EXPECT_EQ(Arch, File.getArch());
75154901c2SGeorgii Rymar }
76154901c2SGeorgii Rymar 
77c78d2766SGeorgii Rymar std::array<DataForTest, 4> generateData(uint16_t Machine) {
78c78d2766SGeorgii Rymar   return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),
79c78d2766SGeorgii Rymar           DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),
80c78d2766SGeorgii Rymar           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),
81c78d2766SGeorgii Rymar           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};
82c78d2766SGeorgii Rymar }
83c78d2766SGeorgii Rymar 
84154901c2SGeorgii Rymar } // namespace
85154901c2SGeorgii Rymar 
86c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {
87c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
88c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
89c78d2766SGeorgii Rymar   size_t I = 0;
90c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_NONE))
91c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
92c78d2766SGeorgii Rymar 
93c78d2766SGeorgii Rymar   // Test an arbitrary unused EM_* value (255).
94c78d2766SGeorgii Rymar   I = 0;
95c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(255))
96c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
97c78d2766SGeorgii Rymar }
98c78d2766SGeorgii Rymar 
995921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForVE) {
100c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
101c78d2766SGeorgii Rymar                                       "elf64-ve", "elf64-ve"};
102c78d2766SGeorgii Rymar   size_t I = 0;
103c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_VE))
104c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::ve);
1055921782fSKazushi (Jam) Marukawa }
1065921782fSKazushi (Jam) Marukawa 
1075921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForX86_64) {
108c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",
109c78d2766SGeorgii Rymar                                       "elf64-x86-64", "elf64-x86-64"};
110c78d2766SGeorgii Rymar   size_t I = 0;
111c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_X86_64))
112c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::x86_64);
1135921782fSKazushi (Jam) Marukawa }
1145921782fSKazushi (Jam) Marukawa 
1155921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestFor386) {
116c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",
117c78d2766SGeorgii Rymar                                       "elf64-i386"};
118c78d2766SGeorgii Rymar   size_t I = 0;
119c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_386))
120c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::x86);
1215921782fSKazushi (Jam) Marukawa }
1225921782fSKazushi (Jam) Marukawa 
1235921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForMIPS) {
124c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",
125c78d2766SGeorgii Rymar                                       "elf64-mips"};
126c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,
127c78d2766SGeorgii Rymar                                            Triple::mips64el, Triple::mips64};
128c78d2766SGeorgii Rymar   size_t I = 0;
129c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_MIPS)) {
130c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
131c78d2766SGeorgii Rymar     ++I;
132c78d2766SGeorgii Rymar   }
133c78d2766SGeorgii Rymar }
134154901c2SGeorgii Rymar 
135c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAMDGPU) {
136c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",
137c78d2766SGeorgii Rymar                                       "elf64-amdgpu", "elf64-amdgpu"};
138c78d2766SGeorgii Rymar   size_t I = 0;
139c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_AMDGPU))
140c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::UnknownArch);
141c78d2766SGeorgii Rymar }
142154901c2SGeorgii Rymar 
143c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForIAMCU) {
144c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",
145c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
146c78d2766SGeorgii Rymar   size_t I = 0;
147c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_IAMCU))
148c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::x86);
149c78d2766SGeorgii Rymar }
150154901c2SGeorgii Rymar 
151c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAARCH64) {
152c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
153c78d2766SGeorgii Rymar                                       "elf64-littleaarch64",
154c78d2766SGeorgii Rymar                                       "elf64-bigaarch64"};
155c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,
156c78d2766SGeorgii Rymar                                            Triple::aarch64, Triple::aarch64_be};
157c78d2766SGeorgii Rymar   size_t I = 0;
158c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_AARCH64)) {
159c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
160c78d2766SGeorgii Rymar     ++I;
161c78d2766SGeorgii Rymar   }
162c78d2766SGeorgii Rymar }
163c78d2766SGeorgii Rymar 
164c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForPPC64) {
165c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
166c78d2766SGeorgii Rymar                                       "elf64-powerpcle", "elf64-powerpc"};
167c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,
168c78d2766SGeorgii Rymar                                            Triple::ppc64le, Triple::ppc64};
169c78d2766SGeorgii Rymar   size_t I = 0;
170c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_PPC64)) {
171c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
172c78d2766SGeorgii Rymar     ++I;
173c78d2766SGeorgii Rymar   }
174c78d2766SGeorgii Rymar }
175c78d2766SGeorgii Rymar 
176c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForPPC) {
177*696bd307SBrandon Bergren   std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",
178c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
179*696bd307SBrandon Bergren   std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,
180*696bd307SBrandon Bergren                                            Triple::ppcle, Triple::ppc};
181c78d2766SGeorgii Rymar   size_t I = 0;
182*696bd307SBrandon Bergren   for (const DataForTest &D : generateData(ELF::EM_PPC)) {
183*696bd307SBrandon Bergren     checkFormatAndArch(D, Formats[I], Archs[I]);
184*696bd307SBrandon Bergren     ++I;
185*696bd307SBrandon Bergren   }
186c78d2766SGeorgii Rymar }
187c78d2766SGeorgii Rymar 
188c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForRISCV) {
189c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv",
190c78d2766SGeorgii Rymar                                       "elf64-littleriscv", "elf64-littleriscv"};
191c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32,
192c78d2766SGeorgii Rymar                                            Triple::riscv64, Triple::riscv64};
193c78d2766SGeorgii Rymar   size_t I = 0;
194c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_RISCV)) {
195c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
196c78d2766SGeorgii Rymar     ++I;
197c78d2766SGeorgii Rymar   }
198c78d2766SGeorgii Rymar }
199c78d2766SGeorgii Rymar 
200c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForARM) {
201c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",
202c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
203c78d2766SGeorgii Rymar   size_t I = 0;
204c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_ARM))
205c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::arm);
206c78d2766SGeorgii Rymar }
207c78d2766SGeorgii Rymar 
208c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForS390) {
209c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
210c78d2766SGeorgii Rymar                                       "elf64-s390", "elf64-s390"};
211c78d2766SGeorgii Rymar   size_t I = 0;
212c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_S390))
213c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::systemz);
214c78d2766SGeorgii Rymar }
215c78d2766SGeorgii Rymar 
216c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARCV9) {
217c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
218c78d2766SGeorgii Rymar                                       "elf64-sparc", "elf64-sparc"};
219c78d2766SGeorgii Rymar   size_t I = 0;
220c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_SPARCV9))
221c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::sparcv9);
222c78d2766SGeorgii Rymar }
223c78d2766SGeorgii Rymar 
224c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARC) {
225c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
226c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
227c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
228c78d2766SGeorgii Rymar                                            Triple::sparcel, Triple::sparc};
229c78d2766SGeorgii Rymar   size_t I = 0;
230c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_SPARC)) {
231c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
232c78d2766SGeorgii Rymar     ++I;
233c78d2766SGeorgii Rymar   }
234c78d2766SGeorgii Rymar }
235c78d2766SGeorgii Rymar 
236c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {
237c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
238c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
239c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
240c78d2766SGeorgii Rymar                                            Triple::sparcel, Triple::sparc};
241c78d2766SGeorgii Rymar   size_t I = 0;
242c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_SPARC32PLUS)) {
243c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
244c78d2766SGeorgii Rymar     ++I;
245c78d2766SGeorgii Rymar   }
246c78d2766SGeorgii Rymar }
247c78d2766SGeorgii Rymar 
248c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForBPF) {
249c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
250c78d2766SGeorgii Rymar                                       "elf64-bpf", "elf64-bpf"};
251c78d2766SGeorgii Rymar   std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,
252c78d2766SGeorgii Rymar                                            Triple::bpfel, Triple::bpfeb};
253c78d2766SGeorgii Rymar   size_t I = 0;
254c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_BPF)) {
255c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I], Archs[I]);
256c78d2766SGeorgii Rymar     ++I;
257c78d2766SGeorgii Rymar   }
258c78d2766SGeorgii Rymar }
259c78d2766SGeorgii Rymar 
260c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAVR) {
261c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",
262c78d2766SGeorgii Rymar                                       "elf64-unknown"};
263c78d2766SGeorgii Rymar   size_t I = 0;
264c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_AVR))
265c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::avr);
266c78d2766SGeorgii Rymar }
267c78d2766SGeorgii Rymar 
268c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForHEXAGON) {
269c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",
270c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
271c78d2766SGeorgii Rymar   size_t I = 0;
272c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_HEXAGON))
273c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::hexagon);
274c78d2766SGeorgii Rymar }
275c78d2766SGeorgii Rymar 
276c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForLANAI) {
277c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",
278c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
279c78d2766SGeorgii Rymar   size_t I = 0;
280c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_LANAI))
281c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::lanai);
282c78d2766SGeorgii Rymar }
283c78d2766SGeorgii Rymar 
284c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForMSP430) {
285c78d2766SGeorgii Rymar   std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",
286c78d2766SGeorgii Rymar                                       "elf64-unknown", "elf64-unknown"};
287c78d2766SGeorgii Rymar   size_t I = 0;
288c78d2766SGeorgii Rymar   for (const DataForTest &D : generateData(ELF::EM_MSP430))
289c78d2766SGeorgii Rymar     checkFormatAndArch(D, Formats[I++], Triple::msp430);
2905921782fSKazushi (Jam) Marukawa }
29169f2c79fSZi Xuan Wu 
29269f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, MachineTestForCSKY) {
29369f2c79fSZi Xuan Wu   std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
29469f2c79fSZi Xuan Wu                                       "elf64-unknown", "elf64-unknown"};
29569f2c79fSZi Xuan Wu   size_t I = 0;
29669f2c79fSZi Xuan Wu   for (const DataForTest &D : generateData(ELF::EM_CSKY))
29769f2c79fSZi Xuan Wu     checkFormatAndArch(D, Formats[I++], Triple::csky);
29869f2c79fSZi Xuan Wu }
29969f2c79fSZi Xuan Wu 
30069f2c79fSZi Xuan Wu // ELF relative relocation type test.
30169f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
30269f2c79fSZi Xuan Wu   EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
30369f2c79fSZi Xuan Wu }
3041af3cb54SGeorgii Rymar 
3051af3cb54SGeorgii Rymar template <class ELFT>
3061af3cb54SGeorgii Rymar static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
3071af3cb54SGeorgii Rymar                                               StringRef Yaml) {
3081af3cb54SGeorgii Rymar   raw_svector_ostream OS(Storage);
3091af3cb54SGeorgii Rymar   yaml::Input YIn(Yaml);
3101af3cb54SGeorgii Rymar   if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
3111af3cb54SGeorgii Rymar     return createStringError(std::errc::invalid_argument,
3121af3cb54SGeorgii Rymar                              "unable to convert YAML");
3131af3cb54SGeorgii Rymar   return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
3141af3cb54SGeorgii Rymar }
3151af3cb54SGeorgii Rymar 
3161af3cb54SGeorgii Rymar // Check we are able to create an ELFObjectFile even when the content of the
3171af3cb54SGeorgii Rymar // SHT_SYMTAB_SHNDX section can't be read properly.
3181af3cb54SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
3191af3cb54SGeorgii Rymar   SmallString<0> Storage;
3201af3cb54SGeorgii Rymar   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
3211af3cb54SGeorgii Rymar --- !ELF
3221af3cb54SGeorgii Rymar FileHeader:
3231af3cb54SGeorgii Rymar   Class: ELFCLASS64
3241af3cb54SGeorgii Rymar   Data:  ELFDATA2LSB
3251af3cb54SGeorgii Rymar   Type:  ET_REL
3261af3cb54SGeorgii Rymar Sections:
3271af3cb54SGeorgii Rymar   - Name:    .symtab_shndx
3281af3cb54SGeorgii Rymar     Type:    SHT_SYMTAB_SHNDX
3291af3cb54SGeorgii Rymar     Entries: [ 0 ]
3301af3cb54SGeorgii Rymar     ShSize: 0xFFFFFFFF
3311af3cb54SGeorgii Rymar )");
3321af3cb54SGeorgii Rymar 
3331af3cb54SGeorgii Rymar   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
3341af3cb54SGeorgii Rymar }
33578aea983SGeorgii Rymar 
33678aea983SGeorgii Rymar // Test that we are able to create an ELFObjectFile even when loadable segments
33778aea983SGeorgii Rymar // are unsorted by virtual address.
33878aea983SGeorgii Rymar // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
33978aea983SGeorgii Rymar 
34078aea983SGeorgii Rymar TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
34178aea983SGeorgii Rymar   SmallString<0> Storage;
34278aea983SGeorgii Rymar   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
34378aea983SGeorgii Rymar --- !ELF
34478aea983SGeorgii Rymar FileHeader:
34578aea983SGeorgii Rymar   Class: ELFCLASS64
34678aea983SGeorgii Rymar   Data:  ELFDATA2LSB
34778aea983SGeorgii Rymar   Type:  ET_EXEC
34878aea983SGeorgii Rymar Sections:
34978aea983SGeorgii Rymar   - Name:         .foo
35078aea983SGeorgii Rymar     Type:         SHT_PROGBITS
35178aea983SGeorgii Rymar     Address:      0x1000
35278aea983SGeorgii Rymar     Offset:       0x3000
35378aea983SGeorgii Rymar     ContentArray: [ 0x11 ]
35478aea983SGeorgii Rymar   - Name:         .bar
35578aea983SGeorgii Rymar     Type:         SHT_PROGBITS
35678aea983SGeorgii Rymar     Address:      0x2000
35778aea983SGeorgii Rymar     Offset:       0x4000
35878aea983SGeorgii Rymar     ContentArray: [ 0x99 ]
35978aea983SGeorgii Rymar ProgramHeaders:
36078aea983SGeorgii Rymar   - Type:     PT_LOAD
36178aea983SGeorgii Rymar     VAddr:    0x2000
36278aea983SGeorgii Rymar     FirstSec: .bar
36378aea983SGeorgii Rymar     LastSec:  .bar
36478aea983SGeorgii Rymar   - Type:     PT_LOAD
36578aea983SGeorgii Rymar     VAddr:    0x1000
36678aea983SGeorgii Rymar     FirstSec: .foo
36778aea983SGeorgii Rymar     LastSec:  .foo
36878aea983SGeorgii Rymar )");
36978aea983SGeorgii Rymar 
37078aea983SGeorgii Rymar   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
37178aea983SGeorgii Rymar 
37278aea983SGeorgii Rymar   std::string WarnString;
37378aea983SGeorgii Rymar   auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
37478aea983SGeorgii Rymar     Expected<const uint8_t *> DataOrErr =
37578aea983SGeorgii Rymar         ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
37678aea983SGeorgii Rymar           EXPECT_TRUE(WarnString.empty());
37778aea983SGeorgii Rymar           WarnString = Msg.str();
37878aea983SGeorgii Rymar           return Error::success();
37978aea983SGeorgii Rymar         });
38078aea983SGeorgii Rymar 
38178aea983SGeorgii Rymar     if (!DataOrErr) {
38278aea983SGeorgii Rymar       ADD_FAILURE() << toString(DataOrErr.takeError());
38378aea983SGeorgii Rymar       return nullptr;
38478aea983SGeorgii Rymar     }
38578aea983SGeorgii Rymar 
38678aea983SGeorgii Rymar     EXPECT_TRUE(WarnString ==
38778aea983SGeorgii Rymar                 "loadable segments are unsorted by virtual address");
38878aea983SGeorgii Rymar     WarnString = "";
38978aea983SGeorgii Rymar     return *DataOrErr;
39078aea983SGeorgii Rymar   };
39178aea983SGeorgii Rymar 
39278aea983SGeorgii Rymar   const uint8_t *Data = ToMappedAddr(0x1000);
39378aea983SGeorgii Rymar   ASSERT_TRUE(Data);
39478aea983SGeorgii Rymar   MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
39578aea983SGeorgii Rymar   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
39678aea983SGeorgii Rymar   EXPECT_EQ(Data[0], 0x11);
39778aea983SGeorgii Rymar 
39878aea983SGeorgii Rymar   Data = ToMappedAddr(0x2000);
39978aea983SGeorgii Rymar   ASSERT_TRUE(Data);
40078aea983SGeorgii Rymar   Buf = ExpectedFile->getMemoryBufferRef();
40178aea983SGeorgii Rymar   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
40278aea983SGeorgii Rymar   EXPECT_EQ(Data[0], 0x99);
40378aea983SGeorgii Rymar }
404407d4200SGeorgii Rymar 
405407d4200SGeorgii Rymar // This is a test for API that is related to symbols.
406407d4200SGeorgii Rymar // We check that errors are properly reported here.
407407d4200SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymbolTest) {
408407d4200SGeorgii Rymar   SmallString<0> Storage;
409407d4200SGeorgii Rymar   Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
410407d4200SGeorgii Rymar --- !ELF
411407d4200SGeorgii Rymar FileHeader:
412407d4200SGeorgii Rymar   Class:   ELFCLASS64
413407d4200SGeorgii Rymar   Data:    ELFDATA2LSB
414407d4200SGeorgii Rymar   Type:    ET_DYN
415407d4200SGeorgii Rymar   Machine: EM_X86_64
416407d4200SGeorgii Rymar Sections:
417407d4200SGeorgii Rymar   - Name: .symtab
418407d4200SGeorgii Rymar     Type: SHT_SYMTAB
419407d4200SGeorgii Rymar )");
420407d4200SGeorgii Rymar 
421407d4200SGeorgii Rymar   ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
422407d4200SGeorgii Rymar   const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
423407d4200SGeorgii Rymar   const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
424407d4200SGeorgii Rymar 
425407d4200SGeorgii Rymar   Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
426407d4200SGeorgii Rymar   ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
427407d4200SGeorgii Rymar   ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
428407d4200SGeorgii Rymar 
4298590b5ccSGeorgii Rymar   auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
430407d4200SGeorgii Rymar     ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
431407d4200SGeorgii Rymar 
432407d4200SGeorgii Rymar     // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
433407d4200SGeorgii Rymar     //    SymbolRef::getName() calls it internally. We can't test it directly,
434407d4200SGeorgii Rymar     //    because it is protected.
4358590b5ccSGeorgii Rymar     EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
4368590b5ccSGeorgii Rymar                       FailedWithMessage(ErrMsg));
437407d4200SGeorgii Rymar 
438407d4200SGeorgii Rymar     // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
439407d4200SGeorgii Rymar     EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
440407d4200SGeorgii Rymar                       FailedWithMessage(ErrMsg));
441407d4200SGeorgii Rymar 
442407d4200SGeorgii Rymar     // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
4438590b5ccSGeorgii Rymar     //    SymbolRef::getSection() calls it internally. We can't test it
4448590b5ccSGeorgii Rymar     //    directly, because it is protected.
445407d4200SGeorgii Rymar     EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
446407d4200SGeorgii Rymar                       FailedWithMessage(ErrMsg));
447407d4200SGeorgii Rymar 
448407d4200SGeorgii Rymar     // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
449407d4200SGeorgii Rymar     //    SymbolRef::getFlags() calls it internally. We can't test it directly,
450407d4200SGeorgii Rymar     //    because it is protected.
451407d4200SGeorgii Rymar     EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
452407d4200SGeorgii Rymar                       FailedWithMessage(ErrMsg));
453407d4200SGeorgii Rymar 
454407d4200SGeorgii Rymar     // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
455407d4200SGeorgii Rymar     //    SymbolRef::getType() calls it internally. We can't test it directly,
456407d4200SGeorgii Rymar     //    because it is protected.
4578590b5ccSGeorgii Rymar     EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
4588590b5ccSGeorgii Rymar                       FailedWithMessage(ErrMsg));
459407d4200SGeorgii Rymar 
460407d4200SGeorgii Rymar     // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
4618590b5ccSGeorgii Rymar     //    SymbolRef::getAddress() calls it internally. We can't test it
4628590b5ccSGeorgii Rymar     //    directly, because it is protected.
463407d4200SGeorgii Rymar     EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
464407d4200SGeorgii Rymar                       FailedWithMessage(ErrMsg));
465407d4200SGeorgii Rymar 
466407d4200SGeorgii Rymar     // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
467407d4200SGeorgii Rymar     // method that generates errors for all cases above.
4688590b5ccSGeorgii Rymar     EXPECT_THAT_EXPECTED(
4698590b5ccSGeorgii Rymar         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
470407d4200SGeorgii Rymar     EXPECT_THAT_ERROR(
471407d4200SGeorgii Rymar         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
472407d4200SGeorgii Rymar             .takeError(),
473407d4200SGeorgii Rymar         FailedWithMessage(ErrMsg));
4748590b5ccSGeorgii Rymar   };
4758590b5ccSGeorgii Rymar 
4768590b5ccSGeorgii Rymar   // We create a symbol with an index that is too large to exist in the symbol
4778590b5ccSGeorgii Rymar   // table.
4788590b5ccSGeorgii Rymar   DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
4798590b5ccSGeorgii Rymar                "section (0x18)");
4808590b5ccSGeorgii Rymar 
4818590b5ccSGeorgii Rymar   // We create a symbol with an index that is too large to exist in the object.
4828590b5ccSGeorgii Rymar   DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
4838590b5ccSGeorgii Rymar                       "end of the section (0x18)");
484407d4200SGeorgii Rymar }
485