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) { 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 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 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 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. 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> 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. 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 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. 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. 500*5f7ef652SRahman 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: 508c245c21cSRahman Lavaee - Name: .llvm_bb_addr_map 509c245c21cSRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 510c245c21cSRahman Lavaee Entries: 511c245c21cSRahman Lavaee - Address: 0x11111 512c245c21cSRahman Lavaee BBEntries: 513c245c21cSRahman Lavaee - AddressOffset: 0x0 514c245c21cSRahman Lavaee Size: 0x1 515c245c21cSRahman Lavaee Metadata: 0x2 516c245c21cSRahman Lavaee )"); 517c245c21cSRahman Lavaee 518c245c21cSRahman Lavaee auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 519c245c21cSRahman Lavaee SmallString<0> Storage; 520c245c21cSRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 521c245c21cSRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 522c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 523c245c21cSRahman Lavaee const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 524c245c21cSRahman Lavaee 525c245c21cSRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 526c245c21cSRahman Lavaee Elf.getSection(1); 527c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 528c245c21cSRahman Lavaee EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 529c245c21cSRahman Lavaee FailedWithMessage(ErrMsg)); 530c245c21cSRahman Lavaee }; 531c245c21cSRahman Lavaee 532c245c21cSRahman Lavaee // Check that we can detect the malformed encoding when the section is 533c245c21cSRahman Lavaee // truncated. 534c245c21cSRahman Lavaee SmallString<128> TruncatedYamlString(CommonYamlString); 535c245c21cSRahman Lavaee TruncatedYamlString += R"( 536c245c21cSRahman Lavaee ShSize: 0x8 537c245c21cSRahman Lavaee )"; 538c245c21cSRahman Lavaee DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x00000008: " 539c245c21cSRahman Lavaee "malformed uleb128, extends past end"); 540c245c21cSRahman Lavaee 541c245c21cSRahman Lavaee // Check that we can detect when the encoded BB entry fields exceed the UINT32 542c245c21cSRahman Lavaee // limit. 543c245c21cSRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(3, 544c245c21cSRahman Lavaee CommonYamlString); 545c245c21cSRahman Lavaee OverInt32LimitYamlStrings[0] += R"( 546c245c21cSRahman Lavaee - AddressOffset: 0x100000000 547c245c21cSRahman Lavaee Size: 0xFFFFFFFF 548c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF 549c245c21cSRahman Lavaee )"; 550c245c21cSRahman Lavaee 551c245c21cSRahman Lavaee OverInt32LimitYamlStrings[1] += R"( 552c245c21cSRahman Lavaee - AddressOffset: 0xFFFFFFFF 553c245c21cSRahman Lavaee Size: 0x100000000 554c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF 555c245c21cSRahman Lavaee )"; 556c245c21cSRahman Lavaee 557c245c21cSRahman Lavaee OverInt32LimitYamlStrings[2] += R"( 558c245c21cSRahman Lavaee - AddressOffset: 0xFFFFFFFF 559c245c21cSRahman Lavaee Size: 0xFFFFFFFF 560c245c21cSRahman Lavaee Metadata: 0x100000000 561c245c21cSRahman Lavaee )"; 562c245c21cSRahman Lavaee 563c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[0], 564c245c21cSRahman Lavaee "ULEB128 value at offset 0xc exceeds UINT32_MAX (0x100000000)"); 565c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[1], 566c245c21cSRahman Lavaee "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 567c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[2], 568c245c21cSRahman Lavaee "ULEB128 value at offset 0x16 exceeds UINT32_MAX (0x100000000)"); 569c245c21cSRahman Lavaee 570c245c21cSRahman Lavaee // Check the proper error handling when the section has fields exceeding 571c245c21cSRahman Lavaee // UINT32 and is also truncated. This is for checking that we don't generate 572c245c21cSRahman Lavaee // unhandled errors. 573c245c21cSRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 574c245c21cSRahman Lavaee 3, OverInt32LimitYamlStrings[1]); 575c245c21cSRahman Lavaee // Truncate before the end of the 5-byte field. 576c245c21cSRahman Lavaee OverInt32LimitAndTruncated[0] += R"( 577c245c21cSRahman Lavaee ShSize: 0x15 578c245c21cSRahman Lavaee )"; 579c245c21cSRahman Lavaee // Truncate at the end of the 5-byte field. 580c245c21cSRahman Lavaee OverInt32LimitAndTruncated[1] += R"( 581c245c21cSRahman Lavaee ShSize: 0x16 582c245c21cSRahman Lavaee )"; 583c245c21cSRahman Lavaee // Truncate after the end of the 5-byte field. 584c245c21cSRahman Lavaee OverInt32LimitAndTruncated[2] += R"( 585c245c21cSRahman Lavaee ShSize: 0x17 586c245c21cSRahman Lavaee )"; 587c245c21cSRahman Lavaee 588c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[0], 589c245c21cSRahman Lavaee "unable to decode LEB128 at offset 0x00000011: malformed uleb128, " 590c245c21cSRahman Lavaee "extends past end"); 591c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[1], 592c245c21cSRahman Lavaee "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 593c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[2], 594c245c21cSRahman Lavaee "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 595c245c21cSRahman Lavaee 596c245c21cSRahman Lavaee // Check for proper error handling when the 'NumBlocks' field is overridden 597c245c21cSRahman Lavaee // with an out-of-range value. 598c245c21cSRahman Lavaee SmallString<128> OverLimitNumBlocks(CommonYamlString); 599c245c21cSRahman Lavaee OverLimitNumBlocks += R"( 600c245c21cSRahman Lavaee NumBlocks: 0x100000000 601c245c21cSRahman Lavaee )"; 602c245c21cSRahman Lavaee 603c245c21cSRahman Lavaee DoCheck(OverLimitNumBlocks, 604c245c21cSRahman Lavaee "ULEB128 value at offset 0x8 exceeds UINT32_MAX (0x100000000)"); 605c245c21cSRahman Lavaee } 6068ec73e96SAmir Ayupov 607*5f7ef652SRahman Lavaee // Test for the ELFObjectFile::readBBAddrMap API. 608*5f7ef652SRahman Lavaee TEST(ELFObjectFileTest, ReadBBAddrMap) { 609*5f7ef652SRahman Lavaee StringRef CommonYamlString(R"( 610*5f7ef652SRahman Lavaee --- !ELF 611*5f7ef652SRahman Lavaee FileHeader: 612*5f7ef652SRahman Lavaee Class: ELFCLASS64 613*5f7ef652SRahman Lavaee Data: ELFDATA2LSB 614*5f7ef652SRahman Lavaee Type: ET_EXEC 615*5f7ef652SRahman Lavaee Sections: 616*5f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_1 617*5f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 618*5f7ef652SRahman Lavaee Link: 1 619*5f7ef652SRahman Lavaee Entries: 620*5f7ef652SRahman Lavaee - Address: 0x11111 621*5f7ef652SRahman Lavaee BBEntries: 622*5f7ef652SRahman Lavaee - AddressOffset: 0x0 623*5f7ef652SRahman Lavaee Size: 0x1 624*5f7ef652SRahman Lavaee Metadata: 0x2 625*5f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_2 626*5f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 627*5f7ef652SRahman Lavaee Link: 1 628*5f7ef652SRahman Lavaee Entries: 629*5f7ef652SRahman Lavaee - Address: 0x22222 630*5f7ef652SRahman Lavaee BBEntries: 631*5f7ef652SRahman Lavaee - AddressOffset: 0x0 632*5f7ef652SRahman Lavaee Size: 0x2 633*5f7ef652SRahman Lavaee Metadata: 0x4 634*5f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map 635*5f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 636*5f7ef652SRahman Lavaee # Link: 0 (by default) 637*5f7ef652SRahman Lavaee Entries: 638*5f7ef652SRahman Lavaee - Address: 0x33333 639*5f7ef652SRahman Lavaee BBEntries: 640*5f7ef652SRahman Lavaee - AddressOffset: 0x0 641*5f7ef652SRahman Lavaee Size: 0x3 642*5f7ef652SRahman Lavaee Metadata: 0x6 643*5f7ef652SRahman Lavaee )"); 644*5f7ef652SRahman Lavaee 645*5f7ef652SRahman Lavaee BBAddrMap E1 = {0x11111, {{0x0, 0x1, 0x2}}}; 646*5f7ef652SRahman Lavaee BBAddrMap E2 = {0x22222, {{0x0, 0x2, 0x4}}}; 647*5f7ef652SRahman Lavaee BBAddrMap E3 = {0x33333, {{0x0, 0x3, 0x6}}}; 648*5f7ef652SRahman Lavaee 649*5f7ef652SRahman Lavaee std::vector<BBAddrMap> Section0BBAddrMaps = {E3}; 650*5f7ef652SRahman Lavaee std::vector<BBAddrMap> Section1BBAddrMaps = {E1, E2}; 651*5f7ef652SRahman Lavaee std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3}; 652*5f7ef652SRahman Lavaee 653*5f7ef652SRahman Lavaee auto DoCheckSucceeds = [&](StringRef YamlString, 654*5f7ef652SRahman Lavaee Optional<unsigned> TextSectionIndex, 655*5f7ef652SRahman Lavaee std::vector<BBAddrMap> ExpectedResult) { 656*5f7ef652SRahman Lavaee SmallString<0> Storage; 657*5f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 658*5f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 659*5f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 660*5f7ef652SRahman Lavaee 661*5f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 662*5f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1); 663*5f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 664*5f7ef652SRahman Lavaee auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 665*5f7ef652SRahman Lavaee EXPECT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 666*5f7ef652SRahman Lavaee EXPECT_EQ(*BBAddrMaps, ExpectedResult); 667*5f7ef652SRahman Lavaee }; 668*5f7ef652SRahman Lavaee 669*5f7ef652SRahman Lavaee auto DoCheckFails = [&](StringRef YamlString, 670*5f7ef652SRahman Lavaee Optional<unsigned> TextSectionIndex, 671*5f7ef652SRahman Lavaee const char *ErrMsg) { 672*5f7ef652SRahman Lavaee SmallString<0> Storage; 673*5f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 674*5f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 675*5f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 676*5f7ef652SRahman Lavaee 677*5f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 678*5f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1); 679*5f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 680*5f7ef652SRahman Lavaee EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 681*5f7ef652SRahman Lavaee FailedWithMessage(ErrMsg)); 682*5f7ef652SRahman Lavaee }; 683*5f7ef652SRahman Lavaee 684*5f7ef652SRahman Lavaee // Check that we can retrieve the data in the normal case. 685*5f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/None, AllBBAddrMaps); 686*5f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); 687*5f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section1BBAddrMaps); 688*5f7ef652SRahman Lavaee // Check that when no bb-address-map section is found for a text section, 689*5f7ef652SRahman Lavaee // we return an empty result. 690*5f7ef652SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, {}); 691*5f7ef652SRahman Lavaee 692*5f7ef652SRahman Lavaee // Check that we detect when a bb-addr-map section is linked to an invalid 693*5f7ef652SRahman Lavaee // (not present) section. 694*5f7ef652SRahman Lavaee SmallString<128> InvalidLinkedYamlString(CommonYamlString); 695*5f7ef652SRahman Lavaee InvalidLinkedYamlString += R"( 696*5f7ef652SRahman Lavaee Link: 10 697*5f7ef652SRahman Lavaee )"; 698*5f7ef652SRahman Lavaee 699*5f7ef652SRahman Lavaee DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/1, 700*5f7ef652SRahman Lavaee "unable to get the linked-to section for SHT_LLVM_BB_ADDR_MAP " 701*5f7ef652SRahman Lavaee "section with index 3: invalid section index: 10"); 702*5f7ef652SRahman Lavaee // Linked sections are not checked when we don't target a specific text 703*5f7ef652SRahman Lavaee // section. 704*5f7ef652SRahman Lavaee DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/None, 705*5f7ef652SRahman Lavaee AllBBAddrMaps); 706*5f7ef652SRahman Lavaee 707*5f7ef652SRahman Lavaee // Check that we can detect when bb-address-map decoding fails. 708*5f7ef652SRahman Lavaee SmallString<128> TruncatedYamlString(CommonYamlString); 709*5f7ef652SRahman Lavaee TruncatedYamlString += R"( 710*5f7ef652SRahman Lavaee ShSize: 0x8 711*5f7ef652SRahman Lavaee )"; 712*5f7ef652SRahman Lavaee 713*5f7ef652SRahman Lavaee DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/None, 714*5f7ef652SRahman Lavaee "unable to read SHT_LLVM_BB_ADDR_MAP section with index 3: " 715*5f7ef652SRahman Lavaee "unable to decode LEB128 at offset 0x00000008: malformed " 716*5f7ef652SRahman Lavaee "uleb128, extends past end"); 717*5f7ef652SRahman Lavaee // Check that we can read the other section's bb-address-maps which are 718*5f7ef652SRahman Lavaee // valid. 719*5f7ef652SRahman Lavaee DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/1, 720*5f7ef652SRahman Lavaee Section1BBAddrMaps); 721*5f7ef652SRahman Lavaee } 722*5f7ef652SRahman Lavaee 7238ec73e96SAmir Ayupov // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 7248ec73e96SAmir Ayupov // section for executable and relocatable files. 7258ec73e96SAmir Ayupov TEST(ELFObjectFileTest, ExecutableWithRelocs) { 7268ec73e96SAmir Ayupov StringRef HeaderString(R"( 7278ec73e96SAmir Ayupov --- !ELF 7288ec73e96SAmir Ayupov FileHeader: 7298ec73e96SAmir Ayupov Class: ELFCLASS64 7308ec73e96SAmir Ayupov Data: ELFDATA2LSB 7318ec73e96SAmir Ayupov )"); 7328ec73e96SAmir Ayupov StringRef ContentsString(R"( 7338ec73e96SAmir Ayupov Sections: 7348ec73e96SAmir Ayupov - Name: .text 7358ec73e96SAmir Ayupov Type: SHT_PROGBITS 7368ec73e96SAmir Ayupov Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 7378ec73e96SAmir Ayupov - Name: .rela.text 7388ec73e96SAmir Ayupov Type: SHT_RELA 7398ec73e96SAmir Ayupov Flags: [ SHF_INFO_LINK ] 7408ec73e96SAmir Ayupov Info: .text 7418ec73e96SAmir Ayupov )"); 7428ec73e96SAmir Ayupov 7438ec73e96SAmir Ayupov auto DoCheck = [&](StringRef YamlString) { 7448ec73e96SAmir Ayupov SmallString<0> Storage; 7458ec73e96SAmir Ayupov Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 7468ec73e96SAmir Ayupov toBinary<ELF64LE>(Storage, YamlString); 7478ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 7488ec73e96SAmir Ayupov const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 7498ec73e96SAmir Ayupov 7508ec73e96SAmir Ayupov bool FoundRela; 7518ec73e96SAmir Ayupov 7528ec73e96SAmir Ayupov for (SectionRef Sec : Obj.sections()) { 7538ec73e96SAmir Ayupov Expected<StringRef> SecNameOrErr = Sec.getName(); 7548ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 7558ec73e96SAmir Ayupov StringRef SecName = *SecNameOrErr; 7568ec73e96SAmir Ayupov if (SecName != ".rela.text") 7578ec73e96SAmir Ayupov continue; 7588ec73e96SAmir Ayupov FoundRela = true; 7598ec73e96SAmir Ayupov Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 7608ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 7618ec73e96SAmir Ayupov section_iterator RelSec = *RelSecOrErr; 7628ec73e96SAmir Ayupov ASSERT_NE(RelSec, Obj.section_end()); 7638ec73e96SAmir Ayupov Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 7648ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 7658ec73e96SAmir Ayupov StringRef TextSecName = *TextSecNameOrErr; 7668ec73e96SAmir Ayupov EXPECT_EQ(TextSecName, ".text"); 7678ec73e96SAmir Ayupov } 7688ec73e96SAmir Ayupov ASSERT_TRUE(FoundRela); 7698ec73e96SAmir Ayupov }; 7708ec73e96SAmir Ayupov 7718ec73e96SAmir Ayupov // Check ET_EXEC file (`ld --emit-relocs` use-case). 7728ec73e96SAmir Ayupov SmallString<128> ExecFileYamlString(HeaderString); 7738ec73e96SAmir Ayupov ExecFileYamlString += R"( 7748ec73e96SAmir Ayupov Type: ET_EXEC 7758ec73e96SAmir Ayupov )"; 7768ec73e96SAmir Ayupov ExecFileYamlString += ContentsString; 7778ec73e96SAmir Ayupov DoCheck(ExecFileYamlString); 7788ec73e96SAmir Ayupov 7798ec73e96SAmir Ayupov // Check ET_REL file. 7808ec73e96SAmir Ayupov SmallString<128> RelocatableFileYamlString(HeaderString); 7818ec73e96SAmir Ayupov RelocatableFileYamlString += R"( 7828ec73e96SAmir Ayupov Type: ET_REL 7838ec73e96SAmir Ayupov )"; 7848ec73e96SAmir Ayupov RelocatableFileYamlString += ContentsString; 7858ec73e96SAmir Ayupov DoCheck(RelocatableFileYamlString); 7868ec73e96SAmir Ayupov } 787