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>
makeElfData__anon1f6e23b00111::DataForTest265921782fSKazushi (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
DataForTest__anon1f6e23b00111::DataForTest555921782fSKazushi (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
checkFormatAndArch(const DataForTest & D,StringRef Fmt,Triple::ArchType Arch)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
generateData(uint16_t Machine)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
TEST(ELFObjectFileTest,MachineTestForNoneOrUnused)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
TEST(ELFObjectFileTest,MachineTestForVE)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
TEST(ELFObjectFileTest,MachineTestForX86_64)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
TEST(ELFObjectFileTest,MachineTestFor386)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
TEST(ELFObjectFileTest,MachineTestForMIPS)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
TEST(ELFObjectFileTest,MachineTestForAMDGPU)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
TEST(ELFObjectFileTest,MachineTestForIAMCU)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
TEST(ELFObjectFileTest,MachineTestForAARCH64)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
TEST(ELFObjectFileTest,MachineTestForPPC64)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
TEST(ELFObjectFileTest,MachineTestForPPC)176c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForPPC) {
177696bd307SBrandon Bergren std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",
178c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"};
179696bd307SBrandon Bergren std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,
180696bd307SBrandon Bergren Triple::ppcle, Triple::ppc};
181c78d2766SGeorgii Rymar size_t I = 0;
182696bd307SBrandon Bergren for (const DataForTest &D : generateData(ELF::EM_PPC)) {
183696bd307SBrandon Bergren checkFormatAndArch(D, Formats[I], Archs[I]);
184696bd307SBrandon Bergren ++I;
185696bd307SBrandon Bergren }
186c78d2766SGeorgii Rymar }
187c78d2766SGeorgii Rymar
TEST(ELFObjectFileTest,MachineTestForRISCV)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
TEST(ELFObjectFileTest,MachineTestForARM)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
TEST(ELFObjectFileTest,MachineTestForS390)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
TEST(ELFObjectFileTest,MachineTestForSPARCV9)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
TEST(ELFObjectFileTest,MachineTestForSPARC)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
TEST(ELFObjectFileTest,MachineTestForSPARC32PLUS)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
TEST(ELFObjectFileTest,MachineTestForBPF)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
TEST(ELFObjectFileTest,MachineTestForAVR)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
TEST(ELFObjectFileTest,MachineTestForHEXAGON)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
TEST(ELFObjectFileTest,MachineTestForLANAI)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
TEST(ELFObjectFileTest,MachineTestForMSP430)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
TEST(ELFObjectFileTest,MachineTestForLoongArch)292e53e6ec6SLu Weining TEST(ELFObjectFileTest, MachineTestForLoongArch) {
293e53e6ec6SLu Weining std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch",
294e53e6ec6SLu Weining "elf64-loongarch", "elf64-loongarch"};
295e53e6ec6SLu Weining std::array<Triple::ArchType, 4> Archs = {
296e53e6ec6SLu Weining Triple::loongarch32, Triple::loongarch32, Triple::loongarch64,
297e53e6ec6SLu Weining Triple::loongarch64};
298e53e6ec6SLu Weining size_t I = 0;
299e53e6ec6SLu Weining for (const DataForTest &D : generateData(ELF::EM_LOONGARCH)) {
300e53e6ec6SLu Weining checkFormatAndArch(D, Formats[I], Archs[I]);
301e53e6ec6SLu Weining ++I;
302e53e6ec6SLu Weining }
303e53e6ec6SLu Weining }
304e53e6ec6SLu Weining
TEST(ELFObjectFileTest,MachineTestForCSKY)30569f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, MachineTestForCSKY) {
30669f2c79fSZi Xuan Wu std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
30769f2c79fSZi Xuan Wu "elf64-unknown", "elf64-unknown"};
30869f2c79fSZi Xuan Wu size_t I = 0;
30969f2c79fSZi Xuan Wu for (const DataForTest &D : generateData(ELF::EM_CSKY))
31069f2c79fSZi Xuan Wu checkFormatAndArch(D, Formats[I++], Triple::csky);
31169f2c79fSZi Xuan Wu }
31269f2c79fSZi Xuan Wu
31369f2c79fSZi Xuan Wu // ELF relative relocation type test.
TEST(ELFObjectFileTest,RelativeRelocationTypeTest)31469f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
31569f2c79fSZi Xuan Wu EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
31669f2c79fSZi Xuan Wu }
3171af3cb54SGeorgii Rymar
3181af3cb54SGeorgii Rymar template <class ELFT>
toBinary(SmallVectorImpl<char> & Storage,StringRef Yaml)3191af3cb54SGeorgii Rymar static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
3201af3cb54SGeorgii Rymar StringRef Yaml) {
3211af3cb54SGeorgii Rymar raw_svector_ostream OS(Storage);
3221af3cb54SGeorgii Rymar yaml::Input YIn(Yaml);
3231af3cb54SGeorgii Rymar if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
3241af3cb54SGeorgii Rymar return createStringError(std::errc::invalid_argument,
3251af3cb54SGeorgii Rymar "unable to convert YAML");
3261af3cb54SGeorgii Rymar return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
3271af3cb54SGeorgii Rymar }
3281af3cb54SGeorgii Rymar
3291af3cb54SGeorgii Rymar // Check we are able to create an ELFObjectFile even when the content of the
3301af3cb54SGeorgii Rymar // SHT_SYMTAB_SHNDX section can't be read properly.
TEST(ELFObjectFileTest,InvalidSymtabShndxTest)3311af3cb54SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
3321af3cb54SGeorgii Rymar SmallString<0> Storage;
3331af3cb54SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
3341af3cb54SGeorgii Rymar --- !ELF
3351af3cb54SGeorgii Rymar FileHeader:
3361af3cb54SGeorgii Rymar Class: ELFCLASS64
3371af3cb54SGeorgii Rymar Data: ELFDATA2LSB
3381af3cb54SGeorgii Rymar Type: ET_REL
3391af3cb54SGeorgii Rymar Sections:
3401af3cb54SGeorgii Rymar - Name: .symtab_shndx
3411af3cb54SGeorgii Rymar Type: SHT_SYMTAB_SHNDX
3421af3cb54SGeorgii Rymar Entries: [ 0 ]
3431af3cb54SGeorgii Rymar ShSize: 0xFFFFFFFF
3441af3cb54SGeorgii Rymar )");
3451af3cb54SGeorgii Rymar
3461af3cb54SGeorgii Rymar ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
3471af3cb54SGeorgii Rymar }
34878aea983SGeorgii Rymar
34978aea983SGeorgii Rymar // Test that we are able to create an ELFObjectFile even when loadable segments
35078aea983SGeorgii Rymar // are unsorted by virtual address.
35178aea983SGeorgii Rymar // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
35278aea983SGeorgii Rymar
TEST(ELFObjectFileTest,InvalidLoadSegmentsOrderTest)35378aea983SGeorgii Rymar TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
35478aea983SGeorgii Rymar SmallString<0> Storage;
35578aea983SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
35678aea983SGeorgii Rymar --- !ELF
35778aea983SGeorgii Rymar FileHeader:
35878aea983SGeorgii Rymar Class: ELFCLASS64
35978aea983SGeorgii Rymar Data: ELFDATA2LSB
36078aea983SGeorgii Rymar Type: ET_EXEC
36178aea983SGeorgii Rymar Sections:
36278aea983SGeorgii Rymar - Name: .foo
36378aea983SGeorgii Rymar Type: SHT_PROGBITS
36478aea983SGeorgii Rymar Address: 0x1000
36578aea983SGeorgii Rymar Offset: 0x3000
36678aea983SGeorgii Rymar ContentArray: [ 0x11 ]
36778aea983SGeorgii Rymar - Name: .bar
36878aea983SGeorgii Rymar Type: SHT_PROGBITS
36978aea983SGeorgii Rymar Address: 0x2000
37078aea983SGeorgii Rymar Offset: 0x4000
37178aea983SGeorgii Rymar ContentArray: [ 0x99 ]
37278aea983SGeorgii Rymar ProgramHeaders:
37378aea983SGeorgii Rymar - Type: PT_LOAD
37478aea983SGeorgii Rymar VAddr: 0x2000
37578aea983SGeorgii Rymar FirstSec: .bar
37678aea983SGeorgii Rymar LastSec: .bar
37778aea983SGeorgii Rymar - Type: PT_LOAD
37878aea983SGeorgii Rymar VAddr: 0x1000
37978aea983SGeorgii Rymar FirstSec: .foo
38078aea983SGeorgii Rymar LastSec: .foo
38178aea983SGeorgii Rymar )");
38278aea983SGeorgii Rymar
38378aea983SGeorgii Rymar ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
38478aea983SGeorgii Rymar
38578aea983SGeorgii Rymar std::string WarnString;
38678aea983SGeorgii Rymar auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
38778aea983SGeorgii Rymar Expected<const uint8_t *> DataOrErr =
38878aea983SGeorgii Rymar ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
38978aea983SGeorgii Rymar EXPECT_TRUE(WarnString.empty());
39078aea983SGeorgii Rymar WarnString = Msg.str();
39178aea983SGeorgii Rymar return Error::success();
39278aea983SGeorgii Rymar });
39378aea983SGeorgii Rymar
39478aea983SGeorgii Rymar if (!DataOrErr) {
39578aea983SGeorgii Rymar ADD_FAILURE() << toString(DataOrErr.takeError());
39678aea983SGeorgii Rymar return nullptr;
39778aea983SGeorgii Rymar }
39878aea983SGeorgii Rymar
39978aea983SGeorgii Rymar EXPECT_TRUE(WarnString ==
40078aea983SGeorgii Rymar "loadable segments are unsorted by virtual address");
40178aea983SGeorgii Rymar WarnString = "";
40278aea983SGeorgii Rymar return *DataOrErr;
40378aea983SGeorgii Rymar };
40478aea983SGeorgii Rymar
40578aea983SGeorgii Rymar const uint8_t *Data = ToMappedAddr(0x1000);
40678aea983SGeorgii Rymar ASSERT_TRUE(Data);
40778aea983SGeorgii Rymar MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
40878aea983SGeorgii Rymar EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
40978aea983SGeorgii Rymar EXPECT_EQ(Data[0], 0x11);
41078aea983SGeorgii Rymar
41178aea983SGeorgii Rymar Data = ToMappedAddr(0x2000);
41278aea983SGeorgii Rymar ASSERT_TRUE(Data);
41378aea983SGeorgii Rymar Buf = ExpectedFile->getMemoryBufferRef();
41478aea983SGeorgii Rymar EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
41578aea983SGeorgii Rymar EXPECT_EQ(Data[0], 0x99);
41678aea983SGeorgii Rymar }
417407d4200SGeorgii Rymar
418407d4200SGeorgii Rymar // This is a test for API that is related to symbols.
419407d4200SGeorgii Rymar // We check that errors are properly reported here.
TEST(ELFObjectFileTest,InvalidSymbolTest)420407d4200SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymbolTest) {
421407d4200SGeorgii Rymar SmallString<0> Storage;
422407d4200SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
423407d4200SGeorgii Rymar --- !ELF
424407d4200SGeorgii Rymar FileHeader:
425407d4200SGeorgii Rymar Class: ELFCLASS64
426407d4200SGeorgii Rymar Data: ELFDATA2LSB
427407d4200SGeorgii Rymar Type: ET_DYN
428407d4200SGeorgii Rymar Machine: EM_X86_64
429407d4200SGeorgii Rymar Sections:
430407d4200SGeorgii Rymar - Name: .symtab
431407d4200SGeorgii Rymar Type: SHT_SYMTAB
432407d4200SGeorgii Rymar )");
433407d4200SGeorgii Rymar
434407d4200SGeorgii Rymar ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
435407d4200SGeorgii Rymar const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
436407d4200SGeorgii Rymar const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
437407d4200SGeorgii Rymar
438407d4200SGeorgii Rymar Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
439407d4200SGeorgii Rymar ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
440407d4200SGeorgii Rymar ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
441407d4200SGeorgii Rymar
4428590b5ccSGeorgii Rymar auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
443407d4200SGeorgii Rymar ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
444407d4200SGeorgii Rymar
445407d4200SGeorgii Rymar // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
446407d4200SGeorgii Rymar // SymbolRef::getName() calls it internally. We can't test it directly,
447407d4200SGeorgii Rymar // because it is protected.
4488590b5ccSGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
4498590b5ccSGeorgii Rymar FailedWithMessage(ErrMsg));
450407d4200SGeorgii Rymar
451407d4200SGeorgii Rymar // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
452407d4200SGeorgii Rymar EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
453407d4200SGeorgii Rymar FailedWithMessage(ErrMsg));
454407d4200SGeorgii Rymar
455407d4200SGeorgii Rymar // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
4568590b5ccSGeorgii Rymar // SymbolRef::getSection() calls it internally. We can't test it
4578590b5ccSGeorgii Rymar // directly, because it is protected.
458407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
459407d4200SGeorgii Rymar FailedWithMessage(ErrMsg));
460407d4200SGeorgii Rymar
461407d4200SGeorgii Rymar // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
462407d4200SGeorgii Rymar // SymbolRef::getFlags() calls it internally. We can't test it directly,
463407d4200SGeorgii Rymar // because it is protected.
464407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
465407d4200SGeorgii Rymar FailedWithMessage(ErrMsg));
466407d4200SGeorgii Rymar
467407d4200SGeorgii Rymar // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
468407d4200SGeorgii Rymar // SymbolRef::getType() calls it internally. We can't test it directly,
469407d4200SGeorgii Rymar // because it is protected.
4708590b5ccSGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
4718590b5ccSGeorgii Rymar FailedWithMessage(ErrMsg));
472407d4200SGeorgii Rymar
473407d4200SGeorgii Rymar // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
4748590b5ccSGeorgii Rymar // SymbolRef::getAddress() calls it internally. We can't test it
4758590b5ccSGeorgii Rymar // directly, because it is protected.
476407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
477407d4200SGeorgii Rymar FailedWithMessage(ErrMsg));
478407d4200SGeorgii Rymar
479407d4200SGeorgii Rymar // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
480407d4200SGeorgii Rymar // method that generates errors for all cases above.
4818590b5ccSGeorgii Rymar EXPECT_THAT_EXPECTED(
4828590b5ccSGeorgii Rymar Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
483407d4200SGeorgii Rymar EXPECT_THAT_ERROR(
484407d4200SGeorgii Rymar Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
485407d4200SGeorgii Rymar .takeError(),
486407d4200SGeorgii Rymar FailedWithMessage(ErrMsg));
4878590b5ccSGeorgii Rymar };
4888590b5ccSGeorgii Rymar
4898590b5ccSGeorgii Rymar // We create a symbol with an index that is too large to exist in the symbol
4908590b5ccSGeorgii Rymar // table.
4918590b5ccSGeorgii Rymar DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
4928590b5ccSGeorgii Rymar "section (0x18)");
4938590b5ccSGeorgii Rymar
4948590b5ccSGeorgii Rymar // We create a symbol with an index that is too large to exist in the object.
4958590b5ccSGeorgii Rymar DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
4968590b5ccSGeorgii Rymar "end of the section (0x18)");
497407d4200SGeorgii Rymar }
498c245c21cSRahman Lavaee
499c245c21cSRahman Lavaee // Tests for error paths of the ELFFile::decodeBBAddrMap API.
TEST(ELFObjectFileTest,InvalidDecodeBBAddrMap)5005f7ef652SRahman Lavaee TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
501c245c21cSRahman Lavaee StringRef CommonYamlString(R"(
502c245c21cSRahman Lavaee --- !ELF
503c245c21cSRahman Lavaee FileHeader:
504c245c21cSRahman Lavaee Class: ELFCLASS64
505c245c21cSRahman Lavaee Data: ELFDATA2LSB
506c245c21cSRahman Lavaee Type: ET_EXEC
507c245c21cSRahman Lavaee Sections:
508*0aa6df65SRahman Lavaee - Type: SHT_LLVM_BB_ADDR_MAP
509*0aa6df65SRahman Lavaee Name: .llvm_bb_addr_map
510c245c21cSRahman Lavaee Entries:
511c245c21cSRahman Lavaee - Address: 0x11111
512c245c21cSRahman Lavaee )");
513c245c21cSRahman Lavaee
514c245c21cSRahman Lavaee auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
515c245c21cSRahman Lavaee SmallString<0> Storage;
516c245c21cSRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
517c245c21cSRahman Lavaee toBinary<ELF64LE>(Storage, YamlString);
518c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
519c245c21cSRahman Lavaee const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
520c245c21cSRahman Lavaee
521c245c21cSRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
522c245c21cSRahman Lavaee Elf.getSection(1);
523c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
524c245c21cSRahman Lavaee EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
525c245c21cSRahman Lavaee FailedWithMessage(ErrMsg));
526c245c21cSRahman Lavaee };
527c245c21cSRahman Lavaee
528*0aa6df65SRahman Lavaee // Check that we can detect unsupported versions.
529*0aa6df65SRahman Lavaee SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
530*0aa6df65SRahman Lavaee UnsupportedVersionYamlString += R"(
531*0aa6df65SRahman Lavaee Version: 2
532*0aa6df65SRahman Lavaee BBEntries:
533*0aa6df65SRahman Lavaee - AddressOffset: 0x0
534*0aa6df65SRahman Lavaee Size: 0x1
535*0aa6df65SRahman Lavaee Metadata: 0x2
536*0aa6df65SRahman Lavaee )";
537*0aa6df65SRahman Lavaee
538*0aa6df65SRahman Lavaee DoCheck(UnsupportedVersionYamlString,
539*0aa6df65SRahman Lavaee "unsupported SHT_LLVM_BB_ADDR_MAP version: 2");
540*0aa6df65SRahman Lavaee
541*0aa6df65SRahman Lavaee SmallString<128> CommonVersionedYamlString(CommonYamlString);
542*0aa6df65SRahman Lavaee CommonVersionedYamlString += R"(
543*0aa6df65SRahman Lavaee Version: 1
544*0aa6df65SRahman Lavaee BBEntries:
545*0aa6df65SRahman Lavaee - AddressOffset: 0x0
546*0aa6df65SRahman Lavaee Size: 0x1
547*0aa6df65SRahman Lavaee Metadata: 0x2
548*0aa6df65SRahman Lavaee )";
549*0aa6df65SRahman Lavaee
550c245c21cSRahman Lavaee // Check that we can detect the malformed encoding when the section is
551c245c21cSRahman Lavaee // truncated.
552*0aa6df65SRahman Lavaee SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
553c245c21cSRahman Lavaee TruncatedYamlString += R"(
554*0aa6df65SRahman Lavaee ShSize: 0xa
555c245c21cSRahman Lavaee )";
556*0aa6df65SRahman Lavaee DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000a: "
557c245c21cSRahman Lavaee "malformed uleb128, extends past end");
558c245c21cSRahman Lavaee
559c245c21cSRahman Lavaee // Check that we can detect when the encoded BB entry fields exceed the UINT32
560c245c21cSRahman Lavaee // limit.
561*0aa6df65SRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
562*0aa6df65SRahman Lavaee 3, CommonVersionedYamlString);
563c245c21cSRahman Lavaee OverInt32LimitYamlStrings[0] += R"(
564c245c21cSRahman Lavaee - AddressOffset: 0x100000000
565c245c21cSRahman Lavaee Size: 0xFFFFFFFF
566c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF
567c245c21cSRahman Lavaee )";
568c245c21cSRahman Lavaee
569c245c21cSRahman Lavaee OverInt32LimitYamlStrings[1] += R"(
570c245c21cSRahman Lavaee - AddressOffset: 0xFFFFFFFF
571c245c21cSRahman Lavaee Size: 0x100000000
572c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF
573c245c21cSRahman Lavaee )";
574c245c21cSRahman Lavaee
575c245c21cSRahman Lavaee OverInt32LimitYamlStrings[2] += R"(
576c245c21cSRahman Lavaee - AddressOffset: 0xFFFFFFFF
577c245c21cSRahman Lavaee Size: 0xFFFFFFFF
578c245c21cSRahman Lavaee Metadata: 0x100000000
579c245c21cSRahman Lavaee )";
580c245c21cSRahman Lavaee
581c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[0],
582*0aa6df65SRahman Lavaee "ULEB128 value at offset 0xe exceeds UINT32_MAX (0x100000000)");
583c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[1],
584*0aa6df65SRahman Lavaee "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
585c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[2],
586*0aa6df65SRahman Lavaee "ULEB128 value at offset 0x18 exceeds UINT32_MAX (0x100000000)");
587c245c21cSRahman Lavaee
588c245c21cSRahman Lavaee // Check the proper error handling when the section has fields exceeding
589c245c21cSRahman Lavaee // UINT32 and is also truncated. This is for checking that we don't generate
590c245c21cSRahman Lavaee // unhandled errors.
591c245c21cSRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
592c245c21cSRahman Lavaee 3, OverInt32LimitYamlStrings[1]);
593c245c21cSRahman Lavaee // Truncate before the end of the 5-byte field.
594c245c21cSRahman Lavaee OverInt32LimitAndTruncated[0] += R"(
595*0aa6df65SRahman Lavaee ShSize: 0x17
596c245c21cSRahman Lavaee )";
597c245c21cSRahman Lavaee // Truncate at the end of the 5-byte field.
598c245c21cSRahman Lavaee OverInt32LimitAndTruncated[1] += R"(
599*0aa6df65SRahman Lavaee ShSize: 0x18
600c245c21cSRahman Lavaee )";
601c245c21cSRahman Lavaee // Truncate after the end of the 5-byte field.
602c245c21cSRahman Lavaee OverInt32LimitAndTruncated[2] += R"(
603*0aa6df65SRahman Lavaee ShSize: 0x19
604c245c21cSRahman Lavaee )";
605c245c21cSRahman Lavaee
606c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[0],
607*0aa6df65SRahman Lavaee "unable to decode LEB128 at offset 0x00000013: malformed uleb128, "
608c245c21cSRahman Lavaee "extends past end");
609c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[1],
610*0aa6df65SRahman Lavaee "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
611c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[2],
612*0aa6df65SRahman Lavaee "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
613c245c21cSRahman Lavaee
614c245c21cSRahman Lavaee // Check for proper error handling when the 'NumBlocks' field is overridden
615c245c21cSRahman Lavaee // with an out-of-range value.
616*0aa6df65SRahman Lavaee SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
617c245c21cSRahman Lavaee OverLimitNumBlocks += R"(
618c245c21cSRahman Lavaee NumBlocks: 0x100000000
619c245c21cSRahman Lavaee )";
620c245c21cSRahman Lavaee
621c245c21cSRahman Lavaee DoCheck(OverLimitNumBlocks,
622*0aa6df65SRahman Lavaee "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
623c245c21cSRahman Lavaee }
6248ec73e96SAmir Ayupov
6255f7ef652SRahman Lavaee // Test for the ELFObjectFile::readBBAddrMap API.
TEST(ELFObjectFileTest,ReadBBAddrMap)6265f7ef652SRahman Lavaee TEST(ELFObjectFileTest, ReadBBAddrMap) {
6275f7ef652SRahman Lavaee StringRef CommonYamlString(R"(
6285f7ef652SRahman Lavaee --- !ELF
6295f7ef652SRahman Lavaee FileHeader:
6305f7ef652SRahman Lavaee Class: ELFCLASS64
6315f7ef652SRahman Lavaee Data: ELFDATA2LSB
6325f7ef652SRahman Lavaee Type: ET_EXEC
6335f7ef652SRahman Lavaee Sections:
6345f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_1
6355f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP
6365f7ef652SRahman Lavaee Link: 1
6375f7ef652SRahman Lavaee Entries:
638*0aa6df65SRahman Lavaee - Version: 1
639*0aa6df65SRahman Lavaee Address: 0x11111
6405f7ef652SRahman Lavaee BBEntries:
6415f7ef652SRahman Lavaee - AddressOffset: 0x0
6425f7ef652SRahman Lavaee Size: 0x1
6435f7ef652SRahman Lavaee Metadata: 0x2
6445f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_2
6455f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP
6465f7ef652SRahman Lavaee Link: 1
6475f7ef652SRahman Lavaee Entries:
648*0aa6df65SRahman Lavaee - Version: 1
649*0aa6df65SRahman Lavaee Address: 0x22222
6505f7ef652SRahman Lavaee BBEntries:
6515f7ef652SRahman Lavaee - AddressOffset: 0x0
6525f7ef652SRahman Lavaee Size: 0x2
6535f7ef652SRahman Lavaee Metadata: 0x4
6545f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map
655*0aa6df65SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP_V0
6565f7ef652SRahman Lavaee # Link: 0 (by default)
6575f7ef652SRahman Lavaee Entries:
658*0aa6df65SRahman Lavaee - Version: 0
659*0aa6df65SRahman Lavaee Address: 0x33333
6605f7ef652SRahman Lavaee BBEntries:
6615f7ef652SRahman Lavaee - AddressOffset: 0x0
6625f7ef652SRahman Lavaee Size: 0x3
6635f7ef652SRahman Lavaee Metadata: 0x6
6645f7ef652SRahman Lavaee )");
6655f7ef652SRahman Lavaee
6665f7ef652SRahman Lavaee BBAddrMap E1 = {0x11111, {{0x0, 0x1, 0x2}}};
6675f7ef652SRahman Lavaee BBAddrMap E2 = {0x22222, {{0x0, 0x2, 0x4}}};
6685f7ef652SRahman Lavaee BBAddrMap E3 = {0x33333, {{0x0, 0x3, 0x6}}};
6695f7ef652SRahman Lavaee
6705f7ef652SRahman Lavaee std::vector<BBAddrMap> Section0BBAddrMaps = {E3};
6715f7ef652SRahman Lavaee std::vector<BBAddrMap> Section1BBAddrMaps = {E1, E2};
6725f7ef652SRahman Lavaee std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3};
6735f7ef652SRahman Lavaee
6745f7ef652SRahman Lavaee auto DoCheckSucceeds = [&](StringRef YamlString,
6755f7ef652SRahman Lavaee Optional<unsigned> TextSectionIndex,
6765f7ef652SRahman Lavaee std::vector<BBAddrMap> ExpectedResult) {
6775f7ef652SRahman Lavaee SmallString<0> Storage;
6785f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
6795f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString);
6805f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
6815f7ef652SRahman Lavaee
6825f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
6835f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1);
6845f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
6855f7ef652SRahman Lavaee auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);
6865f7ef652SRahman Lavaee EXPECT_THAT_EXPECTED(BBAddrMaps, Succeeded());
6875f7ef652SRahman Lavaee EXPECT_EQ(*BBAddrMaps, ExpectedResult);
6885f7ef652SRahman Lavaee };
6895f7ef652SRahman Lavaee
6905f7ef652SRahman Lavaee auto DoCheckFails = [&](StringRef YamlString,
6915f7ef652SRahman Lavaee Optional<unsigned> TextSectionIndex,
6925f7ef652SRahman Lavaee const char *ErrMsg) {
6935f7ef652SRahman Lavaee SmallString<0> Storage;
6945f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
6955f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString);
6965f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
6975f7ef652SRahman Lavaee
6985f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
6995f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1);
7005f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
7015f7ef652SRahman Lavaee EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(),
7025f7ef652SRahman Lavaee FailedWithMessage(ErrMsg));
7035f7ef652SRahman Lavaee };
7045f7ef652SRahman Lavaee
7055f7ef652SRahman Lavaee // Check that we can retrieve the data in the normal case.
7065f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/None, AllBBAddrMaps);
7075f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps);
7085f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section1BBAddrMaps);
7095f7ef652SRahman Lavaee // Check that when no bb-address-map section is found for a text section,
7105f7ef652SRahman Lavaee // we return an empty result.
7115f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, {});
7125f7ef652SRahman Lavaee
7135f7ef652SRahman Lavaee // Check that we detect when a bb-addr-map section is linked to an invalid
7145f7ef652SRahman Lavaee // (not present) section.
7155f7ef652SRahman Lavaee SmallString<128> InvalidLinkedYamlString(CommonYamlString);
7165f7ef652SRahman Lavaee InvalidLinkedYamlString += R"(
7175f7ef652SRahman Lavaee Link: 10
7185f7ef652SRahman Lavaee )";
7195f7ef652SRahman Lavaee
7205f7ef652SRahman Lavaee DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/1,
721*0aa6df65SRahman Lavaee "unable to get the linked-to section for "
722*0aa6df65SRahman Lavaee "SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: invalid section "
723*0aa6df65SRahman Lavaee "index: 10");
7245f7ef652SRahman Lavaee // Linked sections are not checked when we don't target a specific text
7255f7ef652SRahman Lavaee // section.
7265f7ef652SRahman Lavaee DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/None,
7275f7ef652SRahman Lavaee AllBBAddrMaps);
7285f7ef652SRahman Lavaee
7295f7ef652SRahman Lavaee // Check that we can detect when bb-address-map decoding fails.
7305f7ef652SRahman Lavaee SmallString<128> TruncatedYamlString(CommonYamlString);
7315f7ef652SRahman Lavaee TruncatedYamlString += R"(
7325f7ef652SRahman Lavaee ShSize: 0x8
7335f7ef652SRahman Lavaee )";
7345f7ef652SRahman Lavaee
7355f7ef652SRahman Lavaee DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/None,
736*0aa6df65SRahman Lavaee "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: "
7375f7ef652SRahman Lavaee "unable to decode LEB128 at offset 0x00000008: malformed "
7385f7ef652SRahman Lavaee "uleb128, extends past end");
7395f7ef652SRahman Lavaee // Check that we can read the other section's bb-address-maps which are
7405f7ef652SRahman Lavaee // valid.
7415f7ef652SRahman Lavaee DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/1,
7425f7ef652SRahman Lavaee Section1BBAddrMaps);
7435f7ef652SRahman Lavaee }
7445f7ef652SRahman Lavaee
7458ec73e96SAmir Ayupov // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
7468ec73e96SAmir Ayupov // section for executable and relocatable files.
TEST(ELFObjectFileTest,ExecutableWithRelocs)7478ec73e96SAmir Ayupov TEST(ELFObjectFileTest, ExecutableWithRelocs) {
7488ec73e96SAmir Ayupov StringRef HeaderString(R"(
7498ec73e96SAmir Ayupov --- !ELF
7508ec73e96SAmir Ayupov FileHeader:
7518ec73e96SAmir Ayupov Class: ELFCLASS64
7528ec73e96SAmir Ayupov Data: ELFDATA2LSB
7538ec73e96SAmir Ayupov )");
7548ec73e96SAmir Ayupov StringRef ContentsString(R"(
7558ec73e96SAmir Ayupov Sections:
7568ec73e96SAmir Ayupov - Name: .text
7578ec73e96SAmir Ayupov Type: SHT_PROGBITS
7588ec73e96SAmir Ayupov Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
7598ec73e96SAmir Ayupov - Name: .rela.text
7608ec73e96SAmir Ayupov Type: SHT_RELA
7618ec73e96SAmir Ayupov Flags: [ SHF_INFO_LINK ]
7628ec73e96SAmir Ayupov Info: .text
7638ec73e96SAmir Ayupov )");
7648ec73e96SAmir Ayupov
7658ec73e96SAmir Ayupov auto DoCheck = [&](StringRef YamlString) {
7668ec73e96SAmir Ayupov SmallString<0> Storage;
7678ec73e96SAmir Ayupov Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
7688ec73e96SAmir Ayupov toBinary<ELF64LE>(Storage, YamlString);
7698ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
7708ec73e96SAmir Ayupov const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
7718ec73e96SAmir Ayupov
7728ec73e96SAmir Ayupov bool FoundRela;
7738ec73e96SAmir Ayupov
7748ec73e96SAmir Ayupov for (SectionRef Sec : Obj.sections()) {
7758ec73e96SAmir Ayupov Expected<StringRef> SecNameOrErr = Sec.getName();
7768ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());
7778ec73e96SAmir Ayupov StringRef SecName = *SecNameOrErr;
7788ec73e96SAmir Ayupov if (SecName != ".rela.text")
7798ec73e96SAmir Ayupov continue;
7808ec73e96SAmir Ayupov FoundRela = true;
7818ec73e96SAmir Ayupov Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
7828ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());
7838ec73e96SAmir Ayupov section_iterator RelSec = *RelSecOrErr;
7848ec73e96SAmir Ayupov ASSERT_NE(RelSec, Obj.section_end());
7858ec73e96SAmir Ayupov Expected<StringRef> TextSecNameOrErr = RelSec->getName();
7868ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());
7878ec73e96SAmir Ayupov StringRef TextSecName = *TextSecNameOrErr;
7888ec73e96SAmir Ayupov EXPECT_EQ(TextSecName, ".text");
7898ec73e96SAmir Ayupov }
7908ec73e96SAmir Ayupov ASSERT_TRUE(FoundRela);
7918ec73e96SAmir Ayupov };
7928ec73e96SAmir Ayupov
7938ec73e96SAmir Ayupov // Check ET_EXEC file (`ld --emit-relocs` use-case).
7948ec73e96SAmir Ayupov SmallString<128> ExecFileYamlString(HeaderString);
7958ec73e96SAmir Ayupov ExecFileYamlString += R"(
7968ec73e96SAmir Ayupov Type: ET_EXEC
7978ec73e96SAmir Ayupov )";
7988ec73e96SAmir Ayupov ExecFileYamlString += ContentsString;
7998ec73e96SAmir Ayupov DoCheck(ExecFileYamlString);
8008ec73e96SAmir Ayupov
8018ec73e96SAmir Ayupov // Check ET_REL file.
8028ec73e96SAmir Ayupov SmallString<128> RelocatableFileYamlString(HeaderString);
8038ec73e96SAmir Ayupov RelocatableFileYamlString += R"(
8048ec73e96SAmir Ayupov Type: ET_REL
8058ec73e96SAmir Ayupov )";
8068ec73e96SAmir Ayupov RelocatableFileYamlString += ContentsString;
8078ec73e96SAmir Ayupov DoCheck(RelocatableFileYamlString);
8088ec73e96SAmir Ayupov }
809