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" 108a0e0c22SSergei Barannikov #include "llvm/ADT/STLExtras.h" 111af3cb54SGeorgii Rymar #include "llvm/ObjectYAML/yaml2obj.h" 12105adf2cSMicah Weston #include "llvm/Support/BlockFrequency.h" 138a0e0c22SSergei Barannikov #include "llvm/Support/MemoryBuffer.h" 141af3cb54SGeorgii Rymar #include "llvm/Support/YAMLTraits.h" 155921782fSKazushi (Jam) Marukawa #include "llvm/Testing/Support/Error.h" 165921782fSKazushi (Jam) Marukawa #include "gtest/gtest.h" 175921782fSKazushi (Jam) Marukawa 183d6841b2SRahman Lavaee #include "llvm/Support/thread.h" 19d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h" 203d6841b2SRahman Lavaee 215921782fSKazushi (Jam) Marukawa using namespace llvm; 225921782fSKazushi (Jam) Marukawa using namespace llvm::object; 235921782fSKazushi (Jam) Marukawa 24154901c2SGeorgii Rymar namespace { 255921782fSKazushi (Jam) Marukawa 26154901c2SGeorgii Rymar // A struct to initialize a buffer to represent an ELF object file. 275921782fSKazushi (Jam) Marukawa struct DataForTest { 285921782fSKazushi (Jam) Marukawa std::vector<uint8_t> Data; 295921782fSKazushi (Jam) Marukawa 305921782fSKazushi (Jam) Marukawa template <typename T> 315921782fSKazushi (Jam) Marukawa std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 323b337bbcSJoseph Huber uint16_t Machine, uint8_t OS, 333b337bbcSJoseph Huber uint16_t Flags) { 345921782fSKazushi (Jam) Marukawa T Ehdr{}; // Zero-initialise the header. 355921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 365921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 375921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 385921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 395921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_CLASS] = Class; 405921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_DATA] = Encoding; 415921782fSKazushi (Jam) Marukawa Ehdr.e_ident[ELF::EI_VERSION] = 1; 423b337bbcSJoseph Huber Ehdr.e_ident[ELF::EI_OSABI] = OS; 435921782fSKazushi (Jam) Marukawa Ehdr.e_type = ELF::ET_REL; 445921782fSKazushi (Jam) Marukawa Ehdr.e_machine = Machine; 455921782fSKazushi (Jam) Marukawa Ehdr.e_version = 1; 463b337bbcSJoseph Huber Ehdr.e_flags = Flags; 475921782fSKazushi (Jam) Marukawa Ehdr.e_ehsize = sizeof(T); 485921782fSKazushi (Jam) Marukawa 495921782fSKazushi (Jam) Marukawa bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 505921782fSKazushi (Jam) Marukawa if (sys::IsLittleEndianHost != IsLittleEndian) { 515921782fSKazushi (Jam) Marukawa sys::swapByteOrder(Ehdr.e_type); 525921782fSKazushi (Jam) Marukawa sys::swapByteOrder(Ehdr.e_machine); 535921782fSKazushi (Jam) Marukawa sys::swapByteOrder(Ehdr.e_version); 545921782fSKazushi (Jam) Marukawa sys::swapByteOrder(Ehdr.e_ehsize); 555921782fSKazushi (Jam) Marukawa } 565921782fSKazushi (Jam) Marukawa 575921782fSKazushi (Jam) Marukawa uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 585921782fSKazushi (Jam) Marukawa std::vector<uint8_t> Bytes; 595921782fSKazushi (Jam) Marukawa std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 605921782fSKazushi (Jam) Marukawa return Bytes; 615921782fSKazushi (Jam) Marukawa } 625921782fSKazushi (Jam) Marukawa 633b337bbcSJoseph Huber DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine, 643b337bbcSJoseph Huber uint8_t OS = ELF::ELFOSABI_NONE, uint16_t Flags = 0) { 655921782fSKazushi (Jam) Marukawa if (Class == ELF::ELFCLASS64) 663b337bbcSJoseph Huber Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine, OS, Flags); 675921782fSKazushi (Jam) Marukawa else { 685921782fSKazushi (Jam) Marukawa assert(Class == ELF::ELFCLASS32); 693b337bbcSJoseph Huber Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine, OS, Flags); 705921782fSKazushi (Jam) Marukawa } 715921782fSKazushi (Jam) Marukawa } 725921782fSKazushi (Jam) Marukawa }; 735921782fSKazushi (Jam) Marukawa 74154901c2SGeorgii Rymar void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 75154901c2SGeorgii Rymar Triple::ArchType Arch) { 76154901c2SGeorgii Rymar Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 77154901c2SGeorgii Rymar object::ObjectFile::createELFObjectFile( 78154901c2SGeorgii Rymar MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 79154901c2SGeorgii Rymar ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 80154901c2SGeorgii Rymar 81154901c2SGeorgii Rymar const ObjectFile &File = *(*ELFObjOrErr).get(); 82154901c2SGeorgii Rymar EXPECT_EQ(Fmt, File.getFileFormatName()); 83154901c2SGeorgii Rymar EXPECT_EQ(Arch, File.getArch()); 84154901c2SGeorgii Rymar } 85154901c2SGeorgii Rymar 86c78d2766SGeorgii Rymar std::array<DataForTest, 4> generateData(uint16_t Machine) { 87c78d2766SGeorgii Rymar return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine), 88c78d2766SGeorgii Rymar DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine), 89c78d2766SGeorgii Rymar DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine), 90c78d2766SGeorgii Rymar DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)}; 91c78d2766SGeorgii Rymar } 92c78d2766SGeorgii Rymar 93154901c2SGeorgii Rymar } // namespace 94154901c2SGeorgii Rymar 95c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) { 96c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 97c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 988a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE))) 998a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch); 100c78d2766SGeorgii Rymar 101c78d2766SGeorgii Rymar // Test an arbitrary unused EM_* value (255). 1028a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(255))) 1038a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch); 104c78d2766SGeorgii Rymar } 105c78d2766SGeorgii Rymar 1065921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForVE) { 107c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 108c78d2766SGeorgii Rymar "elf64-ve", "elf64-ve"}; 1098a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE))) 1108a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::ve); 1115921782fSKazushi (Jam) Marukawa } 1125921782fSKazushi (Jam) Marukawa 1135921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForX86_64) { 114c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64", 115c78d2766SGeorgii Rymar "elf64-x86-64", "elf64-x86-64"}; 1168a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64))) 1178a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::x86_64); 1185921782fSKazushi (Jam) Marukawa } 1195921782fSKazushi (Jam) Marukawa 1205921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestFor386) { 121c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386", 122c78d2766SGeorgii Rymar "elf64-i386"}; 1238a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386))) 1248a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::x86); 1255921782fSKazushi (Jam) Marukawa } 1265921782fSKazushi (Jam) Marukawa 1275921782fSKazushi (Jam) Marukawa TEST(ELFObjectFileTest, MachineTestForMIPS) { 128c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips", 129c78d2766SGeorgii Rymar "elf64-mips"}; 130c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips, 131c78d2766SGeorgii Rymar Triple::mips64el, Triple::mips64}; 1328a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS))) 1338a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 134c78d2766SGeorgii Rymar } 135154901c2SGeorgii Rymar 136c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAMDGPU) { 137c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu", 138c78d2766SGeorgii Rymar "elf64-amdgpu", "elf64-amdgpu"}; 1398a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU))) 1408a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], 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"}; 1468a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU))) 1478a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::x86); 148c78d2766SGeorgii Rymar } 149154901c2SGeorgii Rymar 150c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAARCH64) { 151c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 152c78d2766SGeorgii Rymar "elf64-littleaarch64", 153c78d2766SGeorgii Rymar "elf64-bigaarch64"}; 154c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be, 155c78d2766SGeorgii Rymar Triple::aarch64, Triple::aarch64_be}; 1568a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64))) 1578a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 158c78d2766SGeorgii Rymar } 159c78d2766SGeorgii Rymar 160c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForPPC64) { 161c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 162c78d2766SGeorgii Rymar "elf64-powerpcle", "elf64-powerpc"}; 163c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64, 164c78d2766SGeorgii Rymar Triple::ppc64le, Triple::ppc64}; 1658a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64))) 1668a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 167c78d2766SGeorgii Rymar } 168c78d2766SGeorgii Rymar 169c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForPPC) { 170696bd307SBrandon Bergren std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc", 171c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 172696bd307SBrandon Bergren std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc, 173696bd307SBrandon Bergren Triple::ppcle, Triple::ppc}; 1748a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC))) 1758a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 176c78d2766SGeorgii Rymar } 177c78d2766SGeorgii Rymar 178c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForRISCV) { 179c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", 180c78d2766SGeorgii Rymar "elf64-littleriscv", "elf64-littleriscv"}; 181c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, 182c78d2766SGeorgii Rymar Triple::riscv64, Triple::riscv64}; 1838a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV))) 1848a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 185c78d2766SGeorgii Rymar } 186c78d2766SGeorgii Rymar 187c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForARM) { 188c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm", 189c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 1908a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM))) 1918a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::arm); 192c78d2766SGeorgii Rymar } 193c78d2766SGeorgii Rymar 194c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForS390) { 195c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 196c78d2766SGeorgii Rymar "elf64-s390", "elf64-s390"}; 1978a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390))) 1988a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::systemz); 199c78d2766SGeorgii Rymar } 200c78d2766SGeorgii Rymar 201c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARCV9) { 202c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 203c78d2766SGeorgii Rymar "elf64-sparc", "elf64-sparc"}; 2048a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9))) 2058a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9); 206c78d2766SGeorgii Rymar } 207c78d2766SGeorgii Rymar 208c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARC) { 209c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 210c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 211c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 212c78d2766SGeorgii Rymar Triple::sparcel, Triple::sparc}; 2138a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC))) 2148a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 215c78d2766SGeorgii Rymar } 216c78d2766SGeorgii Rymar 217c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) { 218c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 219c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 220c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 221c78d2766SGeorgii Rymar Triple::sparcel, Triple::sparc}; 2228a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS))) 2238a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 224c78d2766SGeorgii Rymar } 225c78d2766SGeorgii Rymar 226c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForBPF) { 227c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 228c78d2766SGeorgii Rymar "elf64-bpf", "elf64-bpf"}; 229c78d2766SGeorgii Rymar std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb, 230c78d2766SGeorgii Rymar Triple::bpfel, Triple::bpfeb}; 2318a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF))) 2328a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 233c78d2766SGeorgii Rymar } 234c78d2766SGeorgii Rymar 235c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForAVR) { 236c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown", 237c78d2766SGeorgii Rymar "elf64-unknown"}; 2388a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR))) 2398a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::avr); 240c78d2766SGeorgii Rymar } 241c78d2766SGeorgii Rymar 242c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForHEXAGON) { 243c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon", 244c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 2458a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON))) 2468a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::hexagon); 247c78d2766SGeorgii Rymar } 248c78d2766SGeorgii Rymar 249c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForLANAI) { 250c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai", 251c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 2528a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI))) 2538a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::lanai); 254c78d2766SGeorgii Rymar } 255c78d2766SGeorgii Rymar 256c78d2766SGeorgii Rymar TEST(ELFObjectFileTest, MachineTestForMSP430) { 257c78d2766SGeorgii Rymar std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430", 258c78d2766SGeorgii Rymar "elf64-unknown", "elf64-unknown"}; 2598a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430))) 2608a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::msp430); 2615921782fSKazushi (Jam) Marukawa } 26269f2c79fSZi Xuan Wu 263e53e6ec6SLu Weining TEST(ELFObjectFileTest, MachineTestForLoongArch) { 264e53e6ec6SLu Weining std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch", 265e53e6ec6SLu Weining "elf64-loongarch", "elf64-loongarch"}; 266e53e6ec6SLu Weining std::array<Triple::ArchType, 4> Archs = { 267e53e6ec6SLu Weining Triple::loongarch32, Triple::loongarch32, Triple::loongarch64, 268e53e6ec6SLu Weining Triple::loongarch64}; 2698a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH))) 2708a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 271e53e6ec6SLu Weining } 272e53e6ec6SLu Weining 27369f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, MachineTestForCSKY) { 27469f2c79fSZi Xuan Wu std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 27569f2c79fSZi Xuan Wu "elf64-unknown", "elf64-unknown"}; 2768a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY))) 2778a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::csky); 27869f2c79fSZi Xuan Wu } 27969f2c79fSZi Xuan Wu 280310f7652SAndrei Safronov TEST(ELFObjectFileTest, MachineTestForXtensa) { 281310f7652SAndrei Safronov std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa", 282310f7652SAndrei Safronov "elf64-unknown", "elf64-unknown"}; 2838a0e0c22SSergei Barannikov for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA))) 2848a0e0c22SSergei Barannikov checkFormatAndArch(Data, Formats[Idx], Triple::xtensa); 285310f7652SAndrei Safronov } 286310f7652SAndrei Safronov 2873b337bbcSJoseph Huber TEST(ELFObjectFileTest, CheckOSAndTriple) { 2883b337bbcSJoseph Huber std::tuple<uint16_t, uint8_t, StringRef> Formats[] = { 2893b337bbcSJoseph Huber {ELF::EM_AMDGPU, ELF::ELFOSABI_AMDGPU_HSA, "amdgcn-amd-amdhsa"}, 2903b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_LINUX, "x86_64--linux"}, 2913b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_NETBSD, "x86_64--netbsd"}, 2923b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_HURD, "x86_64--hurd"}, 2933b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_SOLARIS, "x86_64--solaris"}, 2943b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_AIX, "x86_64--aix"}, 2953b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_FREEBSD, "x86_64--freebsd"}, 2963b337bbcSJoseph Huber {ELF::EM_X86_64, ELF::ELFOSABI_OPENBSD, "x86_64--openbsd"}, 2973b337bbcSJoseph Huber {ELF::EM_CUDA, ELF::ELFOSABI_CUDA, "nvptx64-nvidia-cuda"}}; 2983b337bbcSJoseph Huber for (auto [Machine, OS, Triple] : Formats) { 2993b337bbcSJoseph Huber const DataForTest D(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine, OS, 3003b337bbcSJoseph Huber ELF::EF_AMDGPU_MACH_AMDGCN_LAST); 301dfe9bb4dSJoseph Huber Expected<ELF64LEObjectFile> ELFObjOrErr = ELF64LEObjectFile::create( 3023b337bbcSJoseph Huber MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 3033b337bbcSJoseph Huber ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 3043b337bbcSJoseph Huber 305dfe9bb4dSJoseph Huber auto &ELFObj = *ELFObjOrErr; 306c2f5e435SJoseph Huber llvm::Triple TheTriple = ELFObj.makeTriple(); 307c2f5e435SJoseph Huber 308c2f5e435SJoseph Huber // The AMDGPU architecture will be unknown on big-endian testers. 3090cb98167SJoseph Huber if (TheTriple.getArch() == Triple::UnknownArch) 310c2f5e435SJoseph Huber continue; 311c2f5e435SJoseph Huber 312c2f5e435SJoseph Huber EXPECT_EQ(Triple, TheTriple.getTriple()); 3133b337bbcSJoseph Huber } 3143b337bbcSJoseph Huber } 3153b337bbcSJoseph Huber 31669f2c79fSZi Xuan Wu // ELF relative relocation type test. 31769f2c79fSZi Xuan Wu TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 31869f2c79fSZi Xuan Wu EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 31969f2c79fSZi Xuan Wu } 3201af3cb54SGeorgii Rymar 3211af3cb54SGeorgii Rymar template <class ELFT> 3221af3cb54SGeorgii Rymar static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 3231af3cb54SGeorgii Rymar StringRef Yaml) { 3241af3cb54SGeorgii Rymar raw_svector_ostream OS(Storage); 3251af3cb54SGeorgii Rymar yaml::Input YIn(Yaml); 3261af3cb54SGeorgii Rymar if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 3271af3cb54SGeorgii Rymar return createStringError(std::errc::invalid_argument, 3281af3cb54SGeorgii Rymar "unable to convert YAML"); 3291af3cb54SGeorgii Rymar return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 3301af3cb54SGeorgii Rymar } 3311af3cb54SGeorgii Rymar 3321af3cb54SGeorgii Rymar // Check we are able to create an ELFObjectFile even when the content of the 3331af3cb54SGeorgii Rymar // SHT_SYMTAB_SHNDX section can't be read properly. 3341af3cb54SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 3351af3cb54SGeorgii Rymar SmallString<0> Storage; 3361af3cb54SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 3371af3cb54SGeorgii Rymar --- !ELF 3381af3cb54SGeorgii Rymar FileHeader: 3391af3cb54SGeorgii Rymar Class: ELFCLASS64 3401af3cb54SGeorgii Rymar Data: ELFDATA2LSB 3411af3cb54SGeorgii Rymar Type: ET_REL 3421af3cb54SGeorgii Rymar Sections: 3431af3cb54SGeorgii Rymar - Name: .symtab_shndx 3441af3cb54SGeorgii Rymar Type: SHT_SYMTAB_SHNDX 3451af3cb54SGeorgii Rymar Entries: [ 0 ] 3461af3cb54SGeorgii Rymar ShSize: 0xFFFFFFFF 3471af3cb54SGeorgii Rymar )"); 3481af3cb54SGeorgii Rymar 3491af3cb54SGeorgii Rymar ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 3501af3cb54SGeorgii Rymar } 35178aea983SGeorgii Rymar 35278aea983SGeorgii Rymar // Test that we are able to create an ELFObjectFile even when loadable segments 35378aea983SGeorgii Rymar // are unsorted by virtual address. 35478aea983SGeorgii Rymar // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 35578aea983SGeorgii Rymar 35678aea983SGeorgii Rymar TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 35778aea983SGeorgii Rymar SmallString<0> Storage; 35878aea983SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 35978aea983SGeorgii Rymar --- !ELF 36078aea983SGeorgii Rymar FileHeader: 36178aea983SGeorgii Rymar Class: ELFCLASS64 36278aea983SGeorgii Rymar Data: ELFDATA2LSB 36378aea983SGeorgii Rymar Type: ET_EXEC 36478aea983SGeorgii Rymar Sections: 36578aea983SGeorgii Rymar - Name: .foo 36678aea983SGeorgii Rymar Type: SHT_PROGBITS 36778aea983SGeorgii Rymar Address: 0x1000 36878aea983SGeorgii Rymar Offset: 0x3000 36978aea983SGeorgii Rymar ContentArray: [ 0x11 ] 37078aea983SGeorgii Rymar - Name: .bar 37178aea983SGeorgii Rymar Type: SHT_PROGBITS 37278aea983SGeorgii Rymar Address: 0x2000 37378aea983SGeorgii Rymar Offset: 0x4000 37478aea983SGeorgii Rymar ContentArray: [ 0x99 ] 37578aea983SGeorgii Rymar ProgramHeaders: 37678aea983SGeorgii Rymar - Type: PT_LOAD 37778aea983SGeorgii Rymar VAddr: 0x2000 37878aea983SGeorgii Rymar FirstSec: .bar 37978aea983SGeorgii Rymar LastSec: .bar 38078aea983SGeorgii Rymar - Type: PT_LOAD 38178aea983SGeorgii Rymar VAddr: 0x1000 38278aea983SGeorgii Rymar FirstSec: .foo 38378aea983SGeorgii Rymar LastSec: .foo 38478aea983SGeorgii Rymar )"); 38578aea983SGeorgii Rymar 38678aea983SGeorgii Rymar ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 38778aea983SGeorgii Rymar 38878aea983SGeorgii Rymar std::string WarnString; 38978aea983SGeorgii Rymar auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 39078aea983SGeorgii Rymar Expected<const uint8_t *> DataOrErr = 39178aea983SGeorgii Rymar ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 39278aea983SGeorgii Rymar EXPECT_TRUE(WarnString.empty()); 39378aea983SGeorgii Rymar WarnString = Msg.str(); 39478aea983SGeorgii Rymar return Error::success(); 39578aea983SGeorgii Rymar }); 39678aea983SGeorgii Rymar 39778aea983SGeorgii Rymar if (!DataOrErr) { 39878aea983SGeorgii Rymar ADD_FAILURE() << toString(DataOrErr.takeError()); 39978aea983SGeorgii Rymar return nullptr; 40078aea983SGeorgii Rymar } 40178aea983SGeorgii Rymar 40278aea983SGeorgii Rymar EXPECT_TRUE(WarnString == 40378aea983SGeorgii Rymar "loadable segments are unsorted by virtual address"); 40478aea983SGeorgii Rymar WarnString = ""; 40578aea983SGeorgii Rymar return *DataOrErr; 40678aea983SGeorgii Rymar }; 40778aea983SGeorgii Rymar 40878aea983SGeorgii Rymar const uint8_t *Data = ToMappedAddr(0x1000); 40978aea983SGeorgii Rymar ASSERT_TRUE(Data); 41078aea983SGeorgii Rymar MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 41178aea983SGeorgii Rymar EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 41278aea983SGeorgii Rymar EXPECT_EQ(Data[0], 0x11); 41378aea983SGeorgii Rymar 41478aea983SGeorgii Rymar Data = ToMappedAddr(0x2000); 41578aea983SGeorgii Rymar ASSERT_TRUE(Data); 41678aea983SGeorgii Rymar Buf = ExpectedFile->getMemoryBufferRef(); 41778aea983SGeorgii Rymar EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 41878aea983SGeorgii Rymar EXPECT_EQ(Data[0], 0x99); 41978aea983SGeorgii Rymar } 420407d4200SGeorgii Rymar 421407d4200SGeorgii Rymar // This is a test for API that is related to symbols. 422407d4200SGeorgii Rymar // We check that errors are properly reported here. 423407d4200SGeorgii Rymar TEST(ELFObjectFileTest, InvalidSymbolTest) { 424407d4200SGeorgii Rymar SmallString<0> Storage; 425407d4200SGeorgii Rymar Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 426407d4200SGeorgii Rymar --- !ELF 427407d4200SGeorgii Rymar FileHeader: 428407d4200SGeorgii Rymar Class: ELFCLASS64 429407d4200SGeorgii Rymar Data: ELFDATA2LSB 430407d4200SGeorgii Rymar Type: ET_DYN 431407d4200SGeorgii Rymar Machine: EM_X86_64 432407d4200SGeorgii Rymar Sections: 433407d4200SGeorgii Rymar - Name: .symtab 434407d4200SGeorgii Rymar Type: SHT_SYMTAB 435407d4200SGeorgii Rymar )"); 436407d4200SGeorgii Rymar 437407d4200SGeorgii Rymar ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 438407d4200SGeorgii Rymar const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 439407d4200SGeorgii Rymar const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 440407d4200SGeorgii Rymar 441407d4200SGeorgii Rymar Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 442407d4200SGeorgii Rymar ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 443407d4200SGeorgii Rymar ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 444407d4200SGeorgii Rymar 4458590b5ccSGeorgii Rymar auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 446407d4200SGeorgii Rymar ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 447407d4200SGeorgii Rymar 448407d4200SGeorgii Rymar // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 449407d4200SGeorgii Rymar // SymbolRef::getName() calls it internally. We can't test it directly, 450407d4200SGeorgii Rymar // because it is protected. 4518590b5ccSGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 4528590b5ccSGeorgii Rymar FailedWithMessage(ErrMsg)); 453407d4200SGeorgii Rymar 454407d4200SGeorgii Rymar // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 455407d4200SGeorgii Rymar EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 456407d4200SGeorgii Rymar FailedWithMessage(ErrMsg)); 457407d4200SGeorgii Rymar 458407d4200SGeorgii Rymar // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 4598590b5ccSGeorgii Rymar // SymbolRef::getSection() calls it internally. We can't test it 4608590b5ccSGeorgii Rymar // directly, because it is protected. 461407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 462407d4200SGeorgii Rymar FailedWithMessage(ErrMsg)); 463407d4200SGeorgii Rymar 464407d4200SGeorgii Rymar // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 465407d4200SGeorgii Rymar // SymbolRef::getFlags() calls it internally. We can't test it directly, 466407d4200SGeorgii Rymar // because it is protected. 467407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 468407d4200SGeorgii Rymar FailedWithMessage(ErrMsg)); 469407d4200SGeorgii Rymar 470407d4200SGeorgii Rymar // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 471407d4200SGeorgii Rymar // SymbolRef::getType() calls it internally. We can't test it directly, 472407d4200SGeorgii Rymar // because it is protected. 4738590b5ccSGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 4748590b5ccSGeorgii Rymar FailedWithMessage(ErrMsg)); 475407d4200SGeorgii Rymar 476407d4200SGeorgii Rymar // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 4778590b5ccSGeorgii Rymar // SymbolRef::getAddress() calls it internally. We can't test it 4788590b5ccSGeorgii Rymar // directly, because it is protected. 479407d4200SGeorgii Rymar EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 480407d4200SGeorgii Rymar FailedWithMessage(ErrMsg)); 481407d4200SGeorgii Rymar 482407d4200SGeorgii Rymar // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 483407d4200SGeorgii Rymar // method that generates errors for all cases above. 4848590b5ccSGeorgii Rymar EXPECT_THAT_EXPECTED( 4858590b5ccSGeorgii Rymar Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 486407d4200SGeorgii Rymar EXPECT_THAT_ERROR( 487407d4200SGeorgii Rymar Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 488407d4200SGeorgii Rymar .takeError(), 489407d4200SGeorgii Rymar FailedWithMessage(ErrMsg)); 4908590b5ccSGeorgii Rymar }; 4918590b5ccSGeorgii Rymar 4928590b5ccSGeorgii Rymar // We create a symbol with an index that is too large to exist in the symbol 4938590b5ccSGeorgii Rymar // table. 4948590b5ccSGeorgii Rymar DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 4958590b5ccSGeorgii Rymar "section (0x18)"); 4968590b5ccSGeorgii Rymar 4978590b5ccSGeorgii Rymar // We create a symbol with an index that is too large to exist in the object. 4988590b5ccSGeorgii Rymar DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 4998590b5ccSGeorgii Rymar "end of the section (0x18)"); 500407d4200SGeorgii Rymar } 501c245c21cSRahman Lavaee 502c245c21cSRahman Lavaee // Tests for error paths of the ELFFile::decodeBBAddrMap API. 5035f7ef652SRahman Lavaee TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { 504c245c21cSRahman Lavaee StringRef CommonYamlString(R"( 505c245c21cSRahman Lavaee --- !ELF 506c245c21cSRahman Lavaee FileHeader: 507c245c21cSRahman Lavaee Class: ELFCLASS64 508c245c21cSRahman Lavaee Data: ELFDATA2LSB 509c245c21cSRahman Lavaee Type: ET_EXEC 510c245c21cSRahman Lavaee Sections: 5110aa6df65SRahman Lavaee - Type: SHT_LLVM_BB_ADDR_MAP 5120aa6df65SRahman Lavaee Name: .llvm_bb_addr_map 513c245c21cSRahman Lavaee Entries: 514c245c21cSRahman Lavaee )"); 515c245c21cSRahman Lavaee 516c245c21cSRahman Lavaee auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 517c245c21cSRahman Lavaee SmallString<0> Storage; 518c245c21cSRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 519c245c21cSRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 520c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 521c245c21cSRahman Lavaee const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 522c245c21cSRahman Lavaee 523c245c21cSRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 524c245c21cSRahman Lavaee Elf.getSection(1); 525c245c21cSRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 526c245c21cSRahman Lavaee EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 527c245c21cSRahman Lavaee FailedWithMessage(ErrMsg)); 528c245c21cSRahman Lavaee }; 529c245c21cSRahman Lavaee 5300aa6df65SRahman Lavaee // Check that we can detect unsupported versions. 5310aa6df65SRahman Lavaee SmallString<128> UnsupportedVersionYamlString(CommonYamlString); 5320aa6df65SRahman Lavaee UnsupportedVersionYamlString += R"( 533acec6419SRahman Lavaee - Version: 3 534acec6419SRahman Lavaee BBRanges: 535acec6419SRahman Lavaee - BaseAddress: 0x11111 5360aa6df65SRahman Lavaee BBEntries: 5370aa6df65SRahman Lavaee - AddressOffset: 0x0 5380aa6df65SRahman Lavaee Size: 0x1 5390aa6df65SRahman Lavaee Metadata: 0x2 5400aa6df65SRahman Lavaee )"; 5410aa6df65SRahman Lavaee 5426ba2c2bbSRahman Lavaee { 5436ba2c2bbSRahman Lavaee SCOPED_TRACE("unsupported version"); 5440aa6df65SRahman Lavaee DoCheck(UnsupportedVersionYamlString, 5453d6841b2SRahman Lavaee "unsupported SHT_LLVM_BB_ADDR_MAP version: 3"); 5466ba2c2bbSRahman Lavaee } 5470aa6df65SRahman Lavaee 548acec6419SRahman Lavaee SmallString<128> ZeroBBRangesYamlString(CommonYamlString); 549acec6419SRahman Lavaee ZeroBBRangesYamlString += R"( 550acec6419SRahman Lavaee - Version: 2 551acec6419SRahman Lavaee Feature: 0x8 552acec6419SRahman Lavaee BBRanges: [] 553acec6419SRahman Lavaee )"; 554acec6419SRahman Lavaee { 555acec6419SRahman Lavaee SCOPED_TRACE("zero bb ranges"); 556acec6419SRahman Lavaee DoCheck(ZeroBBRangesYamlString, 557acec6419SRahman Lavaee "invalid zero number of BB ranges at offset 3 in " 558acec6419SRahman Lavaee "SHT_LLVM_BB_ADDR_MAP section with index 1"); 559acec6419SRahman Lavaee } 560acec6419SRahman Lavaee 5610aa6df65SRahman Lavaee SmallString<128> CommonVersionedYamlString(CommonYamlString); 5620aa6df65SRahman Lavaee CommonVersionedYamlString += R"( 563acec6419SRahman Lavaee - Version: 2 564acec6419SRahman Lavaee BBRanges: 565acec6419SRahman Lavaee - BaseAddress: 0x11111 5660aa6df65SRahman Lavaee BBEntries: 567acec6419SRahman Lavaee - AddressOffset: 0x0 5680aa6df65SRahman Lavaee Size: 0x1 5690aa6df65SRahman Lavaee Metadata: 0x2 5700aa6df65SRahman Lavaee )"; 5710aa6df65SRahman Lavaee 572c245c21cSRahman Lavaee // Check that we can detect the malformed encoding when the section is 573c245c21cSRahman Lavaee // truncated. 5740aa6df65SRahman Lavaee SmallString<128> TruncatedYamlString(CommonVersionedYamlString); 575c245c21cSRahman Lavaee TruncatedYamlString += R"( 5763d6841b2SRahman Lavaee ShSize: 0xb 577c245c21cSRahman Lavaee )"; 5786ba2c2bbSRahman Lavaee { 5796ba2c2bbSRahman Lavaee SCOPED_TRACE("truncated section"); 5806ba2c2bbSRahman Lavaee DoCheck(TruncatedYamlString, 5816ba2c2bbSRahman Lavaee "unable to decode LEB128 at offset 0x0000000b: " 582c245c21cSRahman Lavaee "malformed uleb128, extends past end"); 5836ba2c2bbSRahman Lavaee } 584c245c21cSRahman Lavaee 585c245c21cSRahman Lavaee // Check that we can detect when the encoded BB entry fields exceed the UINT32 586c245c21cSRahman Lavaee // limit. 5870aa6df65SRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings( 5880aa6df65SRahman Lavaee 3, CommonVersionedYamlString); 589c245c21cSRahman Lavaee OverInt32LimitYamlStrings[0] += R"( 5903d6841b2SRahman Lavaee - ID: 1 5913d6841b2SRahman Lavaee AddressOffset: 0x100000000 592c245c21cSRahman Lavaee Size: 0xFFFFFFFF 593c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF 594c245c21cSRahman Lavaee )"; 595c245c21cSRahman Lavaee 596c245c21cSRahman Lavaee OverInt32LimitYamlStrings[1] += R"( 5973d6841b2SRahman Lavaee - ID: 2 5983d6841b2SRahman Lavaee AddressOffset: 0xFFFFFFFF 599c245c21cSRahman Lavaee Size: 0x100000000 600c245c21cSRahman Lavaee Metadata: 0xFFFFFFFF 601c245c21cSRahman Lavaee )"; 602c245c21cSRahman Lavaee 603c245c21cSRahman Lavaee OverInt32LimitYamlStrings[2] += R"( 6043d6841b2SRahman Lavaee - ID: 3 6053d6841b2SRahman Lavaee AddressOffset: 0xFFFFFFFF 606c245c21cSRahman Lavaee Size: 0xFFFFFFFF 607c245c21cSRahman Lavaee Metadata: 0x100000000 608c245c21cSRahman Lavaee )"; 609c245c21cSRahman Lavaee 6106ba2c2bbSRahman Lavaee { 6116ba2c2bbSRahman Lavaee SCOPED_TRACE("overlimit fields"); 612c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[0], 6133d6841b2SRahman Lavaee "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)"); 614c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[1], 6153d6841b2SRahman Lavaee "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 616c245c21cSRahman Lavaee DoCheck(OverInt32LimitYamlStrings[2], 6173d6841b2SRahman Lavaee "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)"); 6186ba2c2bbSRahman Lavaee } 619c245c21cSRahman Lavaee 620c245c21cSRahman Lavaee // Check the proper error handling when the section has fields exceeding 621c245c21cSRahman Lavaee // UINT32 and is also truncated. This is for checking that we don't generate 622c245c21cSRahman Lavaee // unhandled errors. 623c245c21cSRahman Lavaee SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 624c245c21cSRahman Lavaee 3, OverInt32LimitYamlStrings[1]); 625c245c21cSRahman Lavaee // Truncate before the end of the 5-byte field. 626c245c21cSRahman Lavaee OverInt32LimitAndTruncated[0] += R"( 6273d6841b2SRahman Lavaee ShSize: 0x19 628c245c21cSRahman Lavaee )"; 629c245c21cSRahman Lavaee // Truncate at the end of the 5-byte field. 630c245c21cSRahman Lavaee OverInt32LimitAndTruncated[1] += R"( 6313d6841b2SRahman Lavaee ShSize: 0x1a 632c245c21cSRahman Lavaee )"; 633c245c21cSRahman Lavaee // Truncate after the end of the 5-byte field. 634c245c21cSRahman Lavaee OverInt32LimitAndTruncated[2] += R"( 6353d6841b2SRahman Lavaee ShSize: 0x1b 636c245c21cSRahman Lavaee )"; 637c245c21cSRahman Lavaee 6386ba2c2bbSRahman Lavaee { 6396ba2c2bbSRahman Lavaee SCOPED_TRACE("overlimit fields, truncated section"); 640c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[0], 6413d6841b2SRahman Lavaee "unable to decode LEB128 at offset 0x00000015: malformed uleb128, " 642c245c21cSRahman Lavaee "extends past end"); 643c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[1], 6443d6841b2SRahman Lavaee "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 645c245c21cSRahman Lavaee DoCheck(OverInt32LimitAndTruncated[2], 6463d6841b2SRahman Lavaee "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 6476ba2c2bbSRahman Lavaee } 648c245c21cSRahman Lavaee 649c245c21cSRahman Lavaee // Check for proper error handling when the 'NumBlocks' field is overridden 650c245c21cSRahman Lavaee // with an out-of-range value. 6510aa6df65SRahman Lavaee SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString); 652c245c21cSRahman Lavaee OverLimitNumBlocks += R"( 653c245c21cSRahman Lavaee NumBlocks: 0x100000000 654c245c21cSRahman Lavaee )"; 655c245c21cSRahman Lavaee 6566ba2c2bbSRahman Lavaee { 6576ba2c2bbSRahman Lavaee SCOPED_TRACE("overlimit 'NumBlocks' field"); 658c245c21cSRahman Lavaee DoCheck(OverLimitNumBlocks, 6590aa6df65SRahman Lavaee "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)"); 660c245c21cSRahman Lavaee } 661acec6419SRahman Lavaee 662acec6419SRahman Lavaee // Check for proper error handling when the 'NumBBRanges' field is overridden 663acec6419SRahman Lavaee // with an out-of-range value. 664acec6419SRahman Lavaee SmallString<128> OverLimitNumBBRanges(CommonVersionedYamlString); 665acec6419SRahman Lavaee OverLimitNumBBRanges += R"( 666acec6419SRahman Lavaee NumBBRanges: 0x100000000 667acec6419SRahman Lavaee Feature: 0x8 668acec6419SRahman Lavaee )"; 669acec6419SRahman Lavaee DoCheck(OverLimitNumBBRanges, 670acec6419SRahman Lavaee "ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)"); 6716ba2c2bbSRahman Lavaee } 6728ec73e96SAmir Ayupov 6735f7ef652SRahman Lavaee // Test for the ELFObjectFile::readBBAddrMap API. 6745f7ef652SRahman Lavaee TEST(ELFObjectFileTest, ReadBBAddrMap) { 6755f7ef652SRahman Lavaee StringRef CommonYamlString(R"( 6765f7ef652SRahman Lavaee --- !ELF 6775f7ef652SRahman Lavaee FileHeader: 6785f7ef652SRahman Lavaee Class: ELFCLASS64 6795f7ef652SRahman Lavaee Data: ELFDATA2LSB 6805f7ef652SRahman Lavaee Type: ET_EXEC 6815f7ef652SRahman Lavaee Sections: 6825f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_1 6835f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 6845f7ef652SRahman Lavaee Link: 1 6855f7ef652SRahman Lavaee Entries: 6863d6841b2SRahman Lavaee - Version: 2 687acec6419SRahman Lavaee BBRanges: 688acec6419SRahman Lavaee - BaseAddress: 0x11111 6895f7ef652SRahman Lavaee BBEntries: 6903d6841b2SRahman Lavaee - ID: 1 6913d6841b2SRahman Lavaee AddressOffset: 0x0 6925f7ef652SRahman Lavaee Size: 0x1 6935f7ef652SRahman Lavaee Metadata: 0x2 6945f7ef652SRahman Lavaee - Name: .llvm_bb_addr_map_2 6955f7ef652SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 6965f7ef652SRahman Lavaee Link: 1 6975f7ef652SRahman Lavaee Entries: 6983d6841b2SRahman Lavaee - Version: 2 699acec6419SRahman Lavaee Feature: 0x8 700acec6419SRahman Lavaee BBRanges: 701acec6419SRahman Lavaee - BaseAddress: 0x22222 7025f7ef652SRahman Lavaee BBEntries: 7033d6841b2SRahman Lavaee - ID: 2 7043d6841b2SRahman Lavaee AddressOffset: 0x0 7055f7ef652SRahman Lavaee Size: 0x2 7065f7ef652SRahman Lavaee Metadata: 0x4 707acec6419SRahman Lavaee - BaseAddress: 0xFFFFF 708acec6419SRahman Lavaee BBEntries: 709acec6419SRahman Lavaee - ID: 15 710acec6419SRahman Lavaee AddressOffset: 0xF0 711acec6419SRahman Lavaee Size: 0xF1 712acec6419SRahman Lavaee Metadata: 0x1F 7133d6841b2SRahman Lavaee - Name: .llvm_bb_addr_map_3 7143d6841b2SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 7153d6841b2SRahman Lavaee Link: 2 7166015a045SRahman Lavaee Entries: 7173d6841b2SRahman Lavaee - Version: 1 718acec6419SRahman Lavaee BBRanges: 719acec6419SRahman Lavaee - BaseAddress: 0x33333 7206015a045SRahman Lavaee BBEntries: 7213d6841b2SRahman Lavaee - ID: 0 7223d6841b2SRahman Lavaee AddressOffset: 0x0 72396b6ee1bSRahman Lavaee Size: 0x3 72496b6ee1bSRahman Lavaee Metadata: 0x6 7253d6841b2SRahman Lavaee - Name: .llvm_bb_addr_map_4 726acec6419SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 7273d6841b2SRahman Lavaee # Link: 0 (by default, can be overriden) 7283d6841b2SRahman Lavaee Entries: 729acec6419SRahman Lavaee - Version: 2 730acec6419SRahman Lavaee BBRanges: 731acec6419SRahman Lavaee - BaseAddress: 0x44444 7323d6841b2SRahman Lavaee BBEntries: 7333d6841b2SRahman Lavaee - ID: 0 7343d6841b2SRahman Lavaee AddressOffset: 0x0 7353d6841b2SRahman Lavaee Size: 0x4 7369c3c6f6aSRahman Lavaee Metadata: 0x18 7375f7ef652SRahman Lavaee )"); 7385f7ef652SRahman Lavaee 739acec6419SRahman Lavaee BBAddrMap E1 = { 740acec6419SRahman Lavaee {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}}; 741acec6419SRahman Lavaee BBAddrMap E2 = { 742acec6419SRahman Lavaee {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}, 743acec6419SRahman Lavaee {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}}}}}}; 744acec6419SRahman Lavaee BBAddrMap E3 = { 745acec6419SRahman Lavaee {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}}}; 746acec6419SRahman Lavaee BBAddrMap E4 = { 747acec6419SRahman Lavaee {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}}}; 7485f7ef652SRahman Lavaee 7493d6841b2SRahman Lavaee std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; 7503d6841b2SRahman Lavaee std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 7513d6841b2SRahman Lavaee std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 7523d6841b2SRahman Lavaee std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; 7535f7ef652SRahman Lavaee 7545f7ef652SRahman Lavaee auto DoCheckSucceeds = [&](StringRef YamlString, 755c302fb5cSFangrui Song std::optional<unsigned> TextSectionIndex, 7565f7ef652SRahman Lavaee std::vector<BBAddrMap> ExpectedResult) { 7576ba2c2bbSRahman Lavaee SCOPED_TRACE("for TextSectionIndex: " + 7586ba2c2bbSRahman Lavaee (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 7596ba2c2bbSRahman Lavaee " and object yaml:\n" + YamlString); 7605f7ef652SRahman Lavaee SmallString<0> Storage; 7615f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 7625f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 7635f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 7645f7ef652SRahman Lavaee 7655f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 7665f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1); 7675f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 7685f7ef652SRahman Lavaee auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 769105adf2cSMicah Weston ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 7705f7ef652SRahman Lavaee EXPECT_EQ(*BBAddrMaps, ExpectedResult); 7715f7ef652SRahman Lavaee }; 7725f7ef652SRahman Lavaee 7735f7ef652SRahman Lavaee auto DoCheckFails = [&](StringRef YamlString, 774c302fb5cSFangrui Song std::optional<unsigned> TextSectionIndex, 7755f7ef652SRahman Lavaee const char *ErrMsg) { 7766ba2c2bbSRahman Lavaee SCOPED_TRACE("for TextSectionIndex: " + 7776ba2c2bbSRahman Lavaee (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 7786ba2c2bbSRahman Lavaee " and object yaml:\n" + YamlString); 7795f7ef652SRahman Lavaee SmallString<0> Storage; 7805f7ef652SRahman Lavaee Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 7815f7ef652SRahman Lavaee toBinary<ELF64LE>(Storage, YamlString); 7825f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 7835f7ef652SRahman Lavaee 7845f7ef652SRahman Lavaee Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 7855f7ef652SRahman Lavaee ElfOrErr->getELFFile().getSection(1); 7865f7ef652SRahman Lavaee ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 7875f7ef652SRahman Lavaee EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 7885f7ef652SRahman Lavaee FailedWithMessage(ErrMsg)); 7895f7ef652SRahman Lavaee }; 7905f7ef652SRahman Lavaee 7916ba2c2bbSRahman Lavaee { 7926ba2c2bbSRahman Lavaee SCOPED_TRACE("normal sections"); 7935f7ef652SRahman Lavaee // Check that we can retrieve the data in the normal case. 794b6a01caaSKazu Hirata DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 795b6a01caaSKazu Hirata AllBBAddrMaps); 7966ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 7976ba2c2bbSRahman Lavaee Section0BBAddrMaps); 7986ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 7996ba2c2bbSRahman Lavaee Section1BBAddrMaps); 8006ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 8016ba2c2bbSRahman Lavaee Section2BBAddrMaps); 8025f7ef652SRahman Lavaee // Check that when no bb-address-map section is found for a text section, 8035f7ef652SRahman Lavaee // we return an empty result. 8043d6841b2SRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}); 8056ba2c2bbSRahman Lavaee } 8065f7ef652SRahman Lavaee 8075f7ef652SRahman Lavaee // Check that we detect when a bb-addr-map section is linked to an invalid 8085f7ef652SRahman Lavaee // (not present) section. 8095f7ef652SRahman Lavaee SmallString<128> InvalidLinkedYamlString(CommonYamlString); 8105f7ef652SRahman Lavaee InvalidLinkedYamlString += R"( 811acec6419SRahman Lavaee Link: 121 8125f7ef652SRahman Lavaee )"; 8135f7ef652SRahman Lavaee 8143d6841b2SRahman Lavaee DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4, 8150aa6df65SRahman Lavaee "unable to get the linked-to section for " 816acec6419SRahman Lavaee "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section " 817acec6419SRahman Lavaee "index: 121"); 8186ba2c2bbSRahman Lavaee { 8196ba2c2bbSRahman Lavaee SCOPED_TRACE("invalid linked section"); 8205f7ef652SRahman Lavaee // Linked sections are not checked when we don't target a specific text 8215f7ef652SRahman Lavaee // section. 822b6a01caaSKazu Hirata DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 8235f7ef652SRahman Lavaee AllBBAddrMaps); 8246ba2c2bbSRahman Lavaee } 8255f7ef652SRahman Lavaee 8265f7ef652SRahman Lavaee // Check that we can detect when bb-address-map decoding fails. 8275f7ef652SRahman Lavaee SmallString<128> TruncatedYamlString(CommonYamlString); 8285f7ef652SRahman Lavaee TruncatedYamlString += R"( 829acec6419SRahman Lavaee ShSize: 0xa 8305f7ef652SRahman Lavaee )"; 8315f7ef652SRahman Lavaee 8326ba2c2bbSRahman Lavaee { 8336ba2c2bbSRahman Lavaee SCOPED_TRACE("truncated section"); 834b6a01caaSKazu Hirata DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 835acec6419SRahman Lavaee "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: " 836acec6419SRahman Lavaee "unable to decode LEB128 at offset 0x0000000a: malformed " 8375f7ef652SRahman Lavaee "uleb128, extends past end"); 8386ba2c2bbSRahman Lavaee 8395f7ef652SRahman Lavaee // Check that we can read the other section's bb-address-maps which are 8405f7ef652SRahman Lavaee // valid. 8413d6841b2SRahman Lavaee DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 8425f7ef652SRahman Lavaee Section1BBAddrMaps); 8435f7ef652SRahman Lavaee } 8446ba2c2bbSRahman Lavaee } 8455f7ef652SRahman Lavaee 846105adf2cSMicah Weston // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap 847105adf2cSMicah Weston // API. 848105adf2cSMicah Weston TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) { 849105adf2cSMicah Weston StringRef CommonYamlString(R"( 850105adf2cSMicah Weston --- !ELF 851105adf2cSMicah Weston FileHeader: 852105adf2cSMicah Weston Class: ELFCLASS64 853105adf2cSMicah Weston Data: ELFDATA2LSB 854105adf2cSMicah Weston Type: ET_EXEC 855105adf2cSMicah Weston Sections: 856105adf2cSMicah Weston - Type: SHT_LLVM_BB_ADDR_MAP 857105adf2cSMicah Weston Name: .llvm_bb_addr_map 858105adf2cSMicah Weston Entries: 859105adf2cSMicah Weston )"); 860105adf2cSMicah Weston 861105adf2cSMicah Weston auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 862105adf2cSMicah Weston SmallString<0> Storage; 863105adf2cSMicah Weston Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 864105adf2cSMicah Weston toBinary<ELF64LE>(Storage, YamlString); 865105adf2cSMicah Weston ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 866105adf2cSMicah Weston const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 867105adf2cSMicah Weston 868105adf2cSMicah Weston Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 869105adf2cSMicah Weston Elf.getSection(1); 870105adf2cSMicah Weston ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 871105adf2cSMicah Weston 872105adf2cSMicah Weston std::vector<PGOAnalysisMap> PGOAnalyses; 873105adf2cSMicah Weston EXPECT_THAT_ERROR( 874105adf2cSMicah Weston Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses) 875105adf2cSMicah Weston .takeError(), 876105adf2cSMicah Weston FailedWithMessage(ErrMsg)); 877105adf2cSMicah Weston }; 878105adf2cSMicah Weston 879105adf2cSMicah Weston // Check that we can detect unsupported versions that are too old. 880105adf2cSMicah Weston SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString); 881105adf2cSMicah Weston UnsupportedLowVersionYamlString += R"( 882acec6419SRahman Lavaee - Version: 1 883105adf2cSMicah Weston Feature: 0x4 884acec6419SRahman Lavaee BBRanges: 885acec6419SRahman Lavaee - BBEntries: 886105adf2cSMicah Weston - AddressOffset: 0x0 887105adf2cSMicah Weston Size: 0x1 888105adf2cSMicah Weston Metadata: 0x2 889105adf2cSMicah Weston )"; 890105adf2cSMicah Weston 8916ba2c2bbSRahman Lavaee { 8926ba2c2bbSRahman Lavaee SCOPED_TRACE("unsupported version"); 893105adf2cSMicah Weston DoCheck(UnsupportedLowVersionYamlString, 894105adf2cSMicah Weston "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features " 895105adf2cSMicah Weston "are enabled: version = 1 feature = 4"); 8966ba2c2bbSRahman Lavaee } 897105adf2cSMicah Weston 898105adf2cSMicah Weston SmallString<128> CommonVersionedYamlString(CommonYamlString); 899105adf2cSMicah Weston CommonVersionedYamlString += R"( 900acec6419SRahman Lavaee - Version: 2 901acec6419SRahman Lavaee BBRanges: 902acec6419SRahman Lavaee - BBEntries: 903105adf2cSMicah Weston - ID: 1 904105adf2cSMicah Weston AddressOffset: 0x0 905105adf2cSMicah Weston Size: 0x1 906105adf2cSMicah Weston Metadata: 0x2 907105adf2cSMicah Weston )"; 908105adf2cSMicah Weston 909105adf2cSMicah Weston // Check that we fail when function entry count is enabled but not provided. 910105adf2cSMicah Weston SmallString<128> MissingFuncEntryCount(CommonYamlString); 911105adf2cSMicah Weston MissingFuncEntryCount += R"( 912acec6419SRahman Lavaee - Version: 2 913105adf2cSMicah Weston Feature: 0x01 914105adf2cSMicah Weston )"; 915105adf2cSMicah Weston 9166ba2c2bbSRahman Lavaee { 9176ba2c2bbSRahman Lavaee SCOPED_TRACE("missing function entry count"); 918105adf2cSMicah Weston DoCheck(MissingFuncEntryCount, 919acec6419SRahman Lavaee "unexpected end of data at offset 0x2 while reading [0x2, 0xa)"); 9206ba2c2bbSRahman Lavaee } 921105adf2cSMicah Weston 922105adf2cSMicah Weston // Check that we fail when basic block frequency is enabled but not provided. 923105adf2cSMicah Weston SmallString<128> MissingBBFreq(CommonYamlString); 924105adf2cSMicah Weston MissingBBFreq += R"( 925acec6419SRahman Lavaee - Version: 2 926105adf2cSMicah Weston Feature: 0x02 927acec6419SRahman Lavaee BBRanges: 928acec6419SRahman Lavaee - BBEntries: 929105adf2cSMicah Weston - ID: 1 930105adf2cSMicah Weston AddressOffset: 0x0 931105adf2cSMicah Weston Size: 0x1 932105adf2cSMicah Weston Metadata: 0x2 933105adf2cSMicah Weston )"; 934105adf2cSMicah Weston 9356ba2c2bbSRahman Lavaee { 9366ba2c2bbSRahman Lavaee SCOPED_TRACE("missing bb frequency"); 937105adf2cSMicah Weston DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: " 938105adf2cSMicah Weston "malformed uleb128, extends past end"); 9396ba2c2bbSRahman Lavaee } 940105adf2cSMicah Weston 941105adf2cSMicah Weston // Check that we fail when branch probability is enabled but not provided. 942105adf2cSMicah Weston SmallString<128> MissingBrProb(CommonYamlString); 943105adf2cSMicah Weston MissingBrProb += R"( 944acec6419SRahman Lavaee - Version: 2 945105adf2cSMicah Weston Feature: 0x04 946acec6419SRahman Lavaee BBRanges: 947acec6419SRahman Lavaee - BBEntries: 948105adf2cSMicah Weston - ID: 1 949105adf2cSMicah Weston AddressOffset: 0x0 950105adf2cSMicah Weston Size: 0x1 951105adf2cSMicah Weston Metadata: 0x6 952105adf2cSMicah Weston - ID: 2 953105adf2cSMicah Weston AddressOffset: 0x1 954105adf2cSMicah Weston Size: 0x1 955105adf2cSMicah Weston Metadata: 0x2 956105adf2cSMicah Weston - ID: 3 957105adf2cSMicah Weston AddressOffset: 0x2 958105adf2cSMicah Weston Size: 0x1 959105adf2cSMicah Weston Metadata: 0x2 960105adf2cSMicah Weston PGOAnalyses: 961105adf2cSMicah Weston - PGOBBEntries: 962105adf2cSMicah Weston - Successors: 963105adf2cSMicah Weston - ID: 2 964105adf2cSMicah Weston BrProb: 0x80000000 965105adf2cSMicah Weston - ID: 3 966105adf2cSMicah Weston BrProb: 0x80000000 967105adf2cSMicah Weston - Successors: 968105adf2cSMicah Weston - ID: 3 969105adf2cSMicah Weston BrProb: 0xF0000000 970105adf2cSMicah Weston )"; 971105adf2cSMicah Weston 9726ba2c2bbSRahman Lavaee { 9736ba2c2bbSRahman Lavaee SCOPED_TRACE("missing branch probability"); 974105adf2cSMicah Weston DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: " 975105adf2cSMicah Weston "malformed uleb128, extends past end"); 976105adf2cSMicah Weston } 9776ba2c2bbSRahman Lavaee } 978105adf2cSMicah Weston 979105adf2cSMicah Weston // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap. 980105adf2cSMicah Weston TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { 981105adf2cSMicah Weston StringRef CommonYamlString(R"( 982105adf2cSMicah Weston --- !ELF 983105adf2cSMicah Weston FileHeader: 984105adf2cSMicah Weston Class: ELFCLASS64 985105adf2cSMicah Weston Data: ELFDATA2LSB 986105adf2cSMicah Weston Type: ET_EXEC 987105adf2cSMicah Weston Sections: 988105adf2cSMicah Weston - Name: .llvm_bb_addr_map_1 989105adf2cSMicah Weston Type: SHT_LLVM_BB_ADDR_MAP 990105adf2cSMicah Weston Link: 1 991105adf2cSMicah Weston Entries: 992105adf2cSMicah Weston - Version: 2 993105adf2cSMicah Weston Feature: 0x1 994acec6419SRahman Lavaee BBRanges: 995acec6419SRahman Lavaee - BaseAddress: 0x11111 996105adf2cSMicah Weston BBEntries: 997105adf2cSMicah Weston - ID: 1 998105adf2cSMicah Weston AddressOffset: 0x0 999105adf2cSMicah Weston Size: 0x1 1000105adf2cSMicah Weston Metadata: 0x2 1001105adf2cSMicah Weston PGOAnalyses: 1002105adf2cSMicah Weston - FuncEntryCount: 892 1003105adf2cSMicah Weston - Name: .llvm_bb_addr_map_2 1004105adf2cSMicah Weston Type: SHT_LLVM_BB_ADDR_MAP 1005105adf2cSMicah Weston Link: 1 1006105adf2cSMicah Weston Entries: 1007105adf2cSMicah Weston - Version: 2 1008105adf2cSMicah Weston Feature: 0x2 1009acec6419SRahman Lavaee BBRanges: 1010acec6419SRahman Lavaee - BaseAddress: 0x22222 1011105adf2cSMicah Weston BBEntries: 1012105adf2cSMicah Weston - ID: 2 1013105adf2cSMicah Weston AddressOffset: 0x0 1014105adf2cSMicah Weston Size: 0x2 1015105adf2cSMicah Weston Metadata: 0x4 1016105adf2cSMicah Weston PGOAnalyses: 1017105adf2cSMicah Weston - PGOBBEntries: 1018105adf2cSMicah Weston - BBFreq: 343 1019105adf2cSMicah Weston - Name: .llvm_bb_addr_map_3 1020105adf2cSMicah Weston Type: SHT_LLVM_BB_ADDR_MAP 1021105adf2cSMicah Weston Link: 2 1022105adf2cSMicah Weston Entries: 1023105adf2cSMicah Weston - Version: 2 1024105adf2cSMicah Weston Feature: 0x4 1025acec6419SRahman Lavaee BBRanges: 1026acec6419SRahman Lavaee - BaseAddress: 0x33333 1027105adf2cSMicah Weston BBEntries: 1028105adf2cSMicah Weston - ID: 0 1029105adf2cSMicah Weston AddressOffset: 0x0 1030105adf2cSMicah Weston Size: 0x3 1031105adf2cSMicah Weston Metadata: 0x6 1032105adf2cSMicah Weston - ID: 1 1033105adf2cSMicah Weston AddressOffset: 0x0 1034105adf2cSMicah Weston Size: 0x3 1035105adf2cSMicah Weston Metadata: 0x4 1036105adf2cSMicah Weston - ID: 2 1037105adf2cSMicah Weston AddressOffset: 0x0 1038105adf2cSMicah Weston Size: 0x3 1039105adf2cSMicah Weston Metadata: 0x0 1040105adf2cSMicah Weston PGOAnalyses: 1041105adf2cSMicah Weston - PGOBBEntries: 1042105adf2cSMicah Weston - Successors: 1043105adf2cSMicah Weston - ID: 1 1044105adf2cSMicah Weston BrProb: 0x11111111 1045105adf2cSMicah Weston - ID: 2 1046105adf2cSMicah Weston BrProb: 0xeeeeeeee 1047105adf2cSMicah Weston - Successors: 1048105adf2cSMicah Weston - ID: 2 1049105adf2cSMicah Weston BrProb: 0xffffffff 1050105adf2cSMicah Weston - Successors: [] 1051105adf2cSMicah Weston - Name: .llvm_bb_addr_map_4 1052105adf2cSMicah Weston Type: SHT_LLVM_BB_ADDR_MAP 1053105adf2cSMicah Weston # Link: 0 (by default, can be overriden) 1054105adf2cSMicah Weston Entries: 1055105adf2cSMicah Weston - Version: 2 1056105adf2cSMicah Weston Feature: 0x7 1057acec6419SRahman Lavaee BBRanges: 1058acec6419SRahman Lavaee - BaseAddress: 0x44444 1059105adf2cSMicah Weston BBEntries: 1060105adf2cSMicah Weston - ID: 0 1061105adf2cSMicah Weston AddressOffset: 0x0 1062105adf2cSMicah Weston Size: 0x4 1063105adf2cSMicah Weston Metadata: 0x18 1064105adf2cSMicah Weston - ID: 1 1065105adf2cSMicah Weston AddressOffset: 0x0 1066105adf2cSMicah Weston Size: 0x4 1067105adf2cSMicah Weston Metadata: 0x0 1068105adf2cSMicah Weston - ID: 2 1069105adf2cSMicah Weston AddressOffset: 0x0 1070105adf2cSMicah Weston Size: 0x4 1071105adf2cSMicah Weston Metadata: 0x0 1072105adf2cSMicah Weston - ID: 3 1073105adf2cSMicah Weston AddressOffset: 0x0 1074105adf2cSMicah Weston Size: 0x4 1075105adf2cSMicah Weston Metadata: 0x0 1076105adf2cSMicah Weston PGOAnalyses: 1077105adf2cSMicah Weston - FuncEntryCount: 1000 1078105adf2cSMicah Weston PGOBBEntries: 1079105adf2cSMicah Weston - BBFreq: 1000 1080105adf2cSMicah Weston Successors: 1081105adf2cSMicah Weston - ID: 1 1082105adf2cSMicah Weston BrProb: 0x22222222 1083105adf2cSMicah Weston - ID: 2 1084105adf2cSMicah Weston BrProb: 0x33333333 1085105adf2cSMicah Weston - ID: 3 1086105adf2cSMicah Weston BrProb: 0xaaaaaaaa 1087105adf2cSMicah Weston - BBFreq: 133 1088105adf2cSMicah Weston Successors: 1089105adf2cSMicah Weston - ID: 2 1090105adf2cSMicah Weston BrProb: 0x11111111 1091105adf2cSMicah Weston - ID: 3 1092105adf2cSMicah Weston BrProb: 0xeeeeeeee 1093105adf2cSMicah Weston - BBFreq: 18 1094105adf2cSMicah Weston Successors: 1095105adf2cSMicah Weston - ID: 3 1096105adf2cSMicah Weston BrProb: 0xffffffff 1097105adf2cSMicah Weston - BBFreq: 1000 1098105adf2cSMicah Weston Successors: [] 10992873060fSMicah Weston - Name: .llvm_bb_addr_map_5 11002873060fSMicah Weston Type: SHT_LLVM_BB_ADDR_MAP 11012873060fSMicah Weston # Link: 0 (by default, can be overriden) 11022873060fSMicah Weston Entries: 11032873060fSMicah Weston - Version: 2 11042873060fSMicah Weston Feature: 0x0 1105acec6419SRahman Lavaee BBRanges: 1106acec6419SRahman Lavaee - BaseAddress: 0x55555 11072873060fSMicah Weston BBEntries: 11082873060fSMicah Weston - ID: 2 11092873060fSMicah Weston AddressOffset: 0x0 11102873060fSMicah Weston Size: 0x2 11112873060fSMicah Weston Metadata: 0x4 11122873060fSMicah Weston PGOAnalyses: [{}] 1113acec6419SRahman Lavaee - Name: .llvm_bb_addr_map_6 1114acec6419SRahman Lavaee Type: SHT_LLVM_BB_ADDR_MAP 1115acec6419SRahman Lavaee # Link: 0 (by default, can be overriden) 1116acec6419SRahman Lavaee Entries: 1117acec6419SRahman Lavaee - Version: 2 1118acec6419SRahman Lavaee Feature: 0xc 1119acec6419SRahman Lavaee BBRanges: 1120acec6419SRahman Lavaee - BaseAddress: 0x66666 1121acec6419SRahman Lavaee BBEntries: 1122acec6419SRahman Lavaee - ID: 0 1123acec6419SRahman Lavaee AddressOffset: 0x0 1124acec6419SRahman Lavaee Size: 0x6 1125acec6419SRahman Lavaee Metadata: 0x6 1126acec6419SRahman Lavaee - ID: 1 1127acec6419SRahman Lavaee AddressOffset: 0x0 1128acec6419SRahman Lavaee Size: 0x6 1129acec6419SRahman Lavaee Metadata: 0x4 1130acec6419SRahman Lavaee - BaseAddress: 0x666661 1131acec6419SRahman Lavaee BBEntries: 1132acec6419SRahman Lavaee - ID: 2 1133acec6419SRahman Lavaee AddressOffset: 0x0 1134acec6419SRahman Lavaee Size: 0x6 1135acec6419SRahman Lavaee Metadata: 0x0 1136acec6419SRahman Lavaee PGOAnalyses: 1137acec6419SRahman Lavaee - PGOBBEntries: 1138acec6419SRahman Lavaee - Successors: 1139acec6419SRahman Lavaee - ID: 1 1140acec6419SRahman Lavaee BrProb: 0x22222222 1141acec6419SRahman Lavaee - ID: 2 1142acec6419SRahman Lavaee BrProb: 0xcccccccc 1143acec6419SRahman Lavaee - Successors: 1144acec6419SRahman Lavaee - ID: 2 1145acec6419SRahman Lavaee BrProb: 0x88888888 1146acec6419SRahman Lavaee - Successors: [] 1147105adf2cSMicah Weston )"); 1148105adf2cSMicah Weston 1149acec6419SRahman Lavaee BBAddrMap E1 = { 1150acec6419SRahman Lavaee {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}}; 1151*cf83a7fdSLei Wang PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false}}; 1152acec6419SRahman Lavaee BBAddrMap E2 = { 1153acec6419SRahman Lavaee {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; 1154acec6419SRahman Lavaee PGOAnalysisMap P2 = { 1155*cf83a7fdSLei Wang {}, {{BlockFrequency(343), {}}}, {false, true, false, false, false}}; 1156acec6419SRahman Lavaee BBAddrMap E3 = {{{0x33333, 1157acec6419SRahman Lavaee {{0, 0x0, 0x3, {false, true, true, false, false}}, 1158105adf2cSMicah Weston {1, 0x3, 0x3, {false, false, true, false, false}}, 1159acec6419SRahman Lavaee {2, 0x6, 0x3, {false, false, false, false, false}}}}}}; 1160105adf2cSMicah Weston PGOAnalysisMap P3 = {{}, 1161105adf2cSMicah Weston {{{}, 1162105adf2cSMicah Weston {{1, BranchProbability::getRaw(0x1111'1111)}, 1163105adf2cSMicah Weston {2, BranchProbability::getRaw(0xeeee'eeee)}}}, 1164105adf2cSMicah Weston {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, 1165105adf2cSMicah Weston {{}, {}}}, 1166*cf83a7fdSLei Wang {false, false, true, false, false}}; 1167acec6419SRahman Lavaee BBAddrMap E4 = {{{0x44444, 1168acec6419SRahman Lavaee {{0, 0x0, 0x4, {false, false, false, true, true}}, 1169105adf2cSMicah Weston {1, 0x4, 0x4, {false, false, false, false, false}}, 1170105adf2cSMicah Weston {2, 0x8, 0x4, {false, false, false, false, false}}, 1171acec6419SRahman Lavaee {3, 0xc, 0x4, {false, false, false, false, false}}}}}}; 1172105adf2cSMicah Weston PGOAnalysisMap P4 = { 1173105adf2cSMicah Weston 1000, 1174105adf2cSMicah Weston {{BlockFrequency(1000), 1175105adf2cSMicah Weston {{1, BranchProbability::getRaw(0x2222'2222)}, 1176105adf2cSMicah Weston {2, BranchProbability::getRaw(0x3333'3333)}, 1177105adf2cSMicah Weston {3, BranchProbability::getRaw(0xaaaa'aaaa)}}}, 1178105adf2cSMicah Weston {BlockFrequency(133), 1179105adf2cSMicah Weston {{2, BranchProbability::getRaw(0x1111'1111)}, 1180105adf2cSMicah Weston {3, BranchProbability::getRaw(0xeeee'eeee)}}}, 1181105adf2cSMicah Weston {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, 1182105adf2cSMicah Weston {BlockFrequency(1000), {}}}, 1183*cf83a7fdSLei Wang {true, true, true, false, false}}; 1184acec6419SRahman Lavaee BBAddrMap E5 = { 1185acec6419SRahman Lavaee {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; 1186*cf83a7fdSLei Wang PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false}}; 1187acec6419SRahman Lavaee BBAddrMap E6 = { 1188acec6419SRahman Lavaee {{0x66666, 1189acec6419SRahman Lavaee {{0, 0x0, 0x6, {false, true, true, false, false}}, 1190acec6419SRahman Lavaee {1, 0x6, 0x6, {false, false, true, false, false}}}}, 1191acec6419SRahman Lavaee {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}}}}}}; 1192acec6419SRahman Lavaee PGOAnalysisMap P6 = {{}, 1193acec6419SRahman Lavaee {{{}, 1194acec6419SRahman Lavaee {{1, BranchProbability::getRaw(0x2222'2222)}, 1195acec6419SRahman Lavaee {2, BranchProbability::getRaw(0xcccc'cccc)}}}, 1196acec6419SRahman Lavaee {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}}, 1197acec6419SRahman Lavaee {{}, {}}}, 1198*cf83a7fdSLei Wang {false, false, true, true, false}}; 1199105adf2cSMicah Weston 1200acec6419SRahman Lavaee std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6}; 1201105adf2cSMicah Weston std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 1202105adf2cSMicah Weston std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 1203acec6419SRahman Lavaee std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4, E5, E6}; 1204105adf2cSMicah Weston 1205acec6419SRahman Lavaee std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4, P5, P6}; 1206105adf2cSMicah Weston std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3}; 1207105adf2cSMicah Weston std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2}; 1208acec6419SRahman Lavaee std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4, P5, P6}; 1209105adf2cSMicah Weston 1210105adf2cSMicah Weston auto DoCheckSucceeds = 1211105adf2cSMicah Weston [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex, 1212105adf2cSMicah Weston std::vector<BBAddrMap> ExpectedResult, 1213105adf2cSMicah Weston std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) { 12146ba2c2bbSRahman Lavaee SCOPED_TRACE( 12156ba2c2bbSRahman Lavaee "for TextSectionIndex: " + 12166ba2c2bbSRahman Lavaee (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 12176ba2c2bbSRahman Lavaee " and object yaml:\n" + YamlString); 1218105adf2cSMicah Weston SmallString<0> Storage; 1219105adf2cSMicah Weston Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1220105adf2cSMicah Weston toBinary<ELF64LE>(Storage, YamlString); 1221105adf2cSMicah Weston ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1222105adf2cSMicah Weston 1223105adf2cSMicah Weston Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1224105adf2cSMicah Weston ElfOrErr->getELFFile().getSection(1); 1225105adf2cSMicah Weston ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1226105adf2cSMicah Weston 1227105adf2cSMicah Weston std::vector<PGOAnalysisMap> PGOAnalyses; 1228105adf2cSMicah Weston auto BBAddrMaps = ElfOrErr->readBBAddrMap( 1229105adf2cSMicah Weston TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr); 1230105adf2cSMicah Weston ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 1231105adf2cSMicah Weston EXPECT_EQ(*BBAddrMaps, ExpectedResult); 1232105adf2cSMicah Weston if (ExpectedPGO) { 1233105adf2cSMicah Weston EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size()); 1234acec6419SRahman Lavaee for (const auto &PGO : PGOAnalyses) { 1235acec6419SRahman Lavaee errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n"; 1236acec6419SRahman Lavaee for (const auto &PGOBB : PGO.BBEntries) 1237acec6419SRahman Lavaee errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n"; 1238acec6419SRahman Lavaee } 1239acec6419SRahman Lavaee errs() << " To expected:\n"; 1240acec6419SRahman Lavaee for (const auto &PGO : *ExpectedPGO) { 1241acec6419SRahman Lavaee errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n"; 1242acec6419SRahman Lavaee for (const auto &PGOBB : PGO.BBEntries) 1243acec6419SRahman Lavaee errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n"; 1244acec6419SRahman Lavaee } 1245105adf2cSMicah Weston EXPECT_EQ(PGOAnalyses, *ExpectedPGO); 12462873060fSMicah Weston for (auto &&[BB, PGO] : llvm::zip(*BBAddrMaps, PGOAnalyses)) { 12472873060fSMicah Weston if (PGO.FeatEnable.BBFreq || PGO.FeatEnable.BrProb) 1248acec6419SRahman Lavaee EXPECT_EQ(BB.getNumBBEntries(), PGO.BBEntries.size()); 12492873060fSMicah Weston } 1250105adf2cSMicah Weston } 1251105adf2cSMicah Weston }; 1252105adf2cSMicah Weston 1253105adf2cSMicah Weston auto DoCheckFails = [&](StringRef YamlString, 1254105adf2cSMicah Weston std::optional<unsigned> TextSectionIndex, 1255105adf2cSMicah Weston const char *ErrMsg) { 12566ba2c2bbSRahman Lavaee SCOPED_TRACE("for TextSectionIndex: " + 12576ba2c2bbSRahman Lavaee (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 12586ba2c2bbSRahman Lavaee " and object yaml:\n" + YamlString); 1259105adf2cSMicah Weston SmallString<0> Storage; 1260105adf2cSMicah Weston Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1261105adf2cSMicah Weston toBinary<ELF64LE>(Storage, YamlString); 1262105adf2cSMicah Weston ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1263105adf2cSMicah Weston 1264105adf2cSMicah Weston Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1265105adf2cSMicah Weston ElfOrErr->getELFFile().getSection(1); 1266105adf2cSMicah Weston ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1267105adf2cSMicah Weston std::vector<PGOAnalysisMap> PGOAnalyses; 1268105adf2cSMicah Weston EXPECT_THAT_ERROR( 1269105adf2cSMicah Weston ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(), 1270105adf2cSMicah Weston FailedWithMessage(ErrMsg)); 1271105adf2cSMicah Weston }; 1272105adf2cSMicah Weston 12736ba2c2bbSRahman Lavaee { 12746ba2c2bbSRahman Lavaee SCOPED_TRACE("normal sections"); 1275105adf2cSMicah Weston // Check that we can retrieve the data in the normal case. 1276105adf2cSMicah Weston DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1277105adf2cSMicah Weston AllBBAddrMaps, std::nullopt); 12786ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 12796ba2c2bbSRahman Lavaee Section0BBAddrMaps, std::nullopt); 12806ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 12816ba2c2bbSRahman Lavaee Section1BBAddrMaps, std::nullopt); 12826ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 12836ba2c2bbSRahman Lavaee Section2BBAddrMaps, std::nullopt); 1284105adf2cSMicah Weston 1285105adf2cSMicah Weston DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1286105adf2cSMicah Weston AllBBAddrMaps, AllPGOAnalysisMaps); 12876ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 12886ba2c2bbSRahman Lavaee Section0BBAddrMaps, Section0PGOAnalysisMaps); 12896ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 12906ba2c2bbSRahman Lavaee Section1BBAddrMaps, Section1PGOAnalysisMaps); 12916ba2c2bbSRahman Lavaee DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 12926ba2c2bbSRahman Lavaee Section2BBAddrMaps, Section2PGOAnalysisMaps); 1293105adf2cSMicah Weston // Check that when no bb-address-map section is found for a text section, 1294105adf2cSMicah Weston // we return an empty result. 1295105adf2cSMicah Weston DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt); 1296105adf2cSMicah Weston DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, 1297105adf2cSMicah Weston std::vector<PGOAnalysisMap>{}); 12986ba2c2bbSRahman Lavaee } 1299105adf2cSMicah Weston 1300105adf2cSMicah Weston // Check that we detect when a bb-addr-map section is linked to an invalid 1301105adf2cSMicah Weston // (not present) section. 1302105adf2cSMicah Weston SmallString<128> InvalidLinkedYamlString(CommonYamlString); 1303105adf2cSMicah Weston InvalidLinkedYamlString += R"( 1304acec6419SRahman Lavaee Link: 121 1305105adf2cSMicah Weston )"; 1306105adf2cSMicah Weston 13076ba2c2bbSRahman Lavaee { 13086ba2c2bbSRahman Lavaee SCOPED_TRACE("invalid linked section"); 13092873060fSMicah Weston DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/5, 1310105adf2cSMicah Weston "unable to get the linked-to section for " 1311acec6419SRahman Lavaee "SHT_LLVM_BB_ADDR_MAP section with index 6: invalid section " 1312acec6419SRahman Lavaee "index: 121"); 13136ba2c2bbSRahman Lavaee 1314105adf2cSMicah Weston // Linked sections are not checked when we don't target a specific text 1315105adf2cSMicah Weston // section. 1316105adf2cSMicah Weston DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1317105adf2cSMicah Weston AllBBAddrMaps, std::nullopt); 1318105adf2cSMicah Weston DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1319105adf2cSMicah Weston AllBBAddrMaps, AllPGOAnalysisMaps); 13206ba2c2bbSRahman Lavaee } 1321105adf2cSMicah Weston 1322105adf2cSMicah Weston // Check that we can detect when bb-address-map decoding fails. 1323105adf2cSMicah Weston SmallString<128> TruncatedYamlString(CommonYamlString); 1324105adf2cSMicah Weston TruncatedYamlString += R"( 1325105adf2cSMicah Weston ShSize: 0xa 1326105adf2cSMicah Weston )"; 1327105adf2cSMicah Weston 13286ba2c2bbSRahman Lavaee { 13296ba2c2bbSRahman Lavaee SCOPED_TRACE("truncated section"); 1330acec6419SRahman Lavaee DoCheckFails( 1331acec6419SRahman Lavaee TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 1332acec6419SRahman Lavaee "unable to read SHT_LLVM_BB_ADDR_MAP section with index 6: " 1333acec6419SRahman Lavaee "unexpected end of data at offset 0xa while reading [0x3, 0xb)"); 1334105adf2cSMicah Weston // Check that we can read the other section's bb-address-maps which are 1335105adf2cSMicah Weston // valid. 1336105adf2cSMicah Weston DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1337105adf2cSMicah Weston Section1BBAddrMaps, std::nullopt); 1338105adf2cSMicah Weston DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1339105adf2cSMicah Weston Section1BBAddrMaps, Section1PGOAnalysisMaps); 1340105adf2cSMicah Weston } 13416ba2c2bbSRahman Lavaee } 1342105adf2cSMicah Weston 13438ec73e96SAmir Ayupov // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 13448ec73e96SAmir Ayupov // section for executable and relocatable files. 13458ec73e96SAmir Ayupov TEST(ELFObjectFileTest, ExecutableWithRelocs) { 13468ec73e96SAmir Ayupov StringRef HeaderString(R"( 13478ec73e96SAmir Ayupov --- !ELF 13488ec73e96SAmir Ayupov FileHeader: 13498ec73e96SAmir Ayupov Class: ELFCLASS64 13508ec73e96SAmir Ayupov Data: ELFDATA2LSB 13518ec73e96SAmir Ayupov )"); 13528ec73e96SAmir Ayupov StringRef ContentsString(R"( 13538ec73e96SAmir Ayupov Sections: 13548ec73e96SAmir Ayupov - Name: .text 13558ec73e96SAmir Ayupov Type: SHT_PROGBITS 13568ec73e96SAmir Ayupov Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 13578ec73e96SAmir Ayupov - Name: .rela.text 13588ec73e96SAmir Ayupov Type: SHT_RELA 13598ec73e96SAmir Ayupov Flags: [ SHF_INFO_LINK ] 13608ec73e96SAmir Ayupov Info: .text 13618ec73e96SAmir Ayupov )"); 13628ec73e96SAmir Ayupov 13638ec73e96SAmir Ayupov auto DoCheck = [&](StringRef YamlString) { 13648ec73e96SAmir Ayupov SmallString<0> Storage; 13658ec73e96SAmir Ayupov Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 13668ec73e96SAmir Ayupov toBinary<ELF64LE>(Storage, YamlString); 13678ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 13688ec73e96SAmir Ayupov const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 13698ec73e96SAmir Ayupov 13708ec73e96SAmir Ayupov bool FoundRela; 13718ec73e96SAmir Ayupov 13728ec73e96SAmir Ayupov for (SectionRef Sec : Obj.sections()) { 13738ec73e96SAmir Ayupov Expected<StringRef> SecNameOrErr = Sec.getName(); 13748ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 13758ec73e96SAmir Ayupov StringRef SecName = *SecNameOrErr; 13768ec73e96SAmir Ayupov if (SecName != ".rela.text") 13778ec73e96SAmir Ayupov continue; 13788ec73e96SAmir Ayupov FoundRela = true; 13798ec73e96SAmir Ayupov Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 13808ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 13818ec73e96SAmir Ayupov section_iterator RelSec = *RelSecOrErr; 13828ec73e96SAmir Ayupov ASSERT_NE(RelSec, Obj.section_end()); 13838ec73e96SAmir Ayupov Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 13848ec73e96SAmir Ayupov ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 13858ec73e96SAmir Ayupov StringRef TextSecName = *TextSecNameOrErr; 13868ec73e96SAmir Ayupov EXPECT_EQ(TextSecName, ".text"); 13878ec73e96SAmir Ayupov } 13888ec73e96SAmir Ayupov ASSERT_TRUE(FoundRela); 13898ec73e96SAmir Ayupov }; 13908ec73e96SAmir Ayupov 13918ec73e96SAmir Ayupov // Check ET_EXEC file (`ld --emit-relocs` use-case). 13928ec73e96SAmir Ayupov SmallString<128> ExecFileYamlString(HeaderString); 13938ec73e96SAmir Ayupov ExecFileYamlString += R"( 13948ec73e96SAmir Ayupov Type: ET_EXEC 13958ec73e96SAmir Ayupov )"; 13968ec73e96SAmir Ayupov ExecFileYamlString += ContentsString; 13978ec73e96SAmir Ayupov DoCheck(ExecFileYamlString); 13988ec73e96SAmir Ayupov 13998ec73e96SAmir Ayupov // Check ET_REL file. 14008ec73e96SAmir Ayupov SmallString<128> RelocatableFileYamlString(HeaderString); 14018ec73e96SAmir Ayupov RelocatableFileYamlString += R"( 14028ec73e96SAmir Ayupov Type: ET_REL 14038ec73e96SAmir Ayupov )"; 14048ec73e96SAmir Ayupov RelocatableFileYamlString += ContentsString; 14058ec73e96SAmir Ayupov DoCheck(RelocatableFileYamlString); 14068ec73e96SAmir Ayupov } 14079c645a99SAiden Grossman 14089c645a99SAiden Grossman TEST(ELFObjectFileTest, GetSectionAndRelocations) { 14099c645a99SAiden Grossman StringRef HeaderString(R"( 14109c645a99SAiden Grossman --- !ELF 14119c645a99SAiden Grossman FileHeader: 14129c645a99SAiden Grossman Class: ELFCLASS64 14139c645a99SAiden Grossman Data: ELFDATA2LSB 14149c645a99SAiden Grossman Type: ET_EXEC 14159c645a99SAiden Grossman )"); 14169c645a99SAiden Grossman 14179c645a99SAiden Grossman using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>; 14189c645a99SAiden Grossman 14199c645a99SAiden Grossman auto DoCheckSucceeds = [&](StringRef ContentsString, 14209c645a99SAiden Grossman std::function<Expected<bool>(const Elf_Shdr &)> 14219c645a99SAiden Grossman Matcher) { 14229c645a99SAiden Grossman SmallString<0> Storage; 14239c645a99SAiden Grossman SmallString<128> FullYamlString(HeaderString); 14249c645a99SAiden Grossman FullYamlString += ContentsString; 14259c645a99SAiden Grossman Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 14269c645a99SAiden Grossman toBinary<ELF64LE>(Storage, FullYamlString); 14279c645a99SAiden Grossman ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 14289c645a99SAiden Grossman 14299c645a99SAiden Grossman Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 14309c645a99SAiden Grossman ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 14319c645a99SAiden Grossman ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded()); 14329c645a99SAiden Grossman 14339c645a99SAiden Grossman // Basic verification to make sure we have the correct section types. 14349c645a99SAiden Grossman for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) { 14359c645a99SAiden Grossman ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS); 14369c645a99SAiden Grossman ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA); 14379c645a99SAiden Grossman } 14389c645a99SAiden Grossman }; 14399c645a99SAiden Grossman 14409c645a99SAiden Grossman auto DoCheckFails = [&](StringRef ContentsString, 14419c645a99SAiden Grossman std::function<Expected<bool>(const Elf_Shdr &)> 14429c645a99SAiden Grossman Matcher, 14439c645a99SAiden Grossman const char *ErrorMessage) { 14449c645a99SAiden Grossman SmallString<0> Storage; 14459c645a99SAiden Grossman SmallString<128> FullYamlString(HeaderString); 14469c645a99SAiden Grossman FullYamlString += ContentsString; 14479c645a99SAiden Grossman Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 14489c645a99SAiden Grossman toBinary<ELF64LE>(Storage, FullYamlString); 14499c645a99SAiden Grossman ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 14509c645a99SAiden Grossman 14519c645a99SAiden Grossman Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 14529c645a99SAiden Grossman ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 14539c645a99SAiden Grossman ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(), 14549c645a99SAiden Grossman FailedWithMessage(ErrorMessage)); 14559c645a99SAiden Grossman }; 14569c645a99SAiden Grossman 14579c645a99SAiden Grossman auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool { 14589c645a99SAiden Grossman return Sec.sh_type == ELF::SHT_PROGBITS; 14599c645a99SAiden Grossman }; 14609c645a99SAiden Grossman 14619c645a99SAiden Grossman StringRef TwoTextSections = R"( 14629c645a99SAiden Grossman Sections: 14639c645a99SAiden Grossman - Name: .text 14649c645a99SAiden Grossman Type: SHT_PROGBITS 14659c645a99SAiden Grossman Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 14669c645a99SAiden Grossman - Name: .rela.text 14679c645a99SAiden Grossman Type: SHT_RELA 14689c645a99SAiden Grossman Flags: [ SHF_INFO_LINK ] 14699c645a99SAiden Grossman Info: .text 14709c645a99SAiden Grossman - Name: .text2 14719c645a99SAiden Grossman Type: SHT_PROGBITS 14729c645a99SAiden Grossman Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 14739c645a99SAiden Grossman - Name: .rela.text2 14749c645a99SAiden Grossman Type: SHT_RELA 14759c645a99SAiden Grossman Flags: [ SHF_INFO_LINK ] 14769c645a99SAiden Grossman Info: .text2 14779c645a99SAiden Grossman )"; 14789c645a99SAiden Grossman DoCheckSucceeds(TwoTextSections, DefaultMatcher); 14799c645a99SAiden Grossman 14809c645a99SAiden Grossman StringRef OneTextSection = R"( 14819c645a99SAiden Grossman Sections: 14829c645a99SAiden Grossman - Name: .text 14839c645a99SAiden Grossman Type: SHT_PROGBITS 14849c645a99SAiden Grossman Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 14859c645a99SAiden Grossman )"; 14869c645a99SAiden Grossman 14879c645a99SAiden Grossman auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> { 14889c645a99SAiden Grossman if (Sec.sh_type == ELF::SHT_PROGBITS) 14899c645a99SAiden Grossman return createError("This was supposed to fail."); 14909c645a99SAiden Grossman return false; 14919c645a99SAiden Grossman }; 14929c645a99SAiden Grossman 14933b337bbcSJoseph Huber DoCheckFails(OneTextSection, ErroringMatcher, "This was supposed to fail."); 14949c645a99SAiden Grossman 14959c645a99SAiden Grossman StringRef MissingRelocatableContent = R"( 14969c645a99SAiden Grossman Sections: 14979c645a99SAiden Grossman - Name: .rela.text 14989c645a99SAiden Grossman Type: SHT_RELA 14999c645a99SAiden Grossman Flags: [ SHF_INFO_LINK ] 15009c645a99SAiden Grossman Info: 0xFF 15019c645a99SAiden Grossman )"; 15029c645a99SAiden Grossman 15039c645a99SAiden Grossman DoCheckFails(MissingRelocatableContent, DefaultMatcher, 15049c645a99SAiden Grossman "SHT_RELA section with index 1: failed to get a " 15059c645a99SAiden Grossman "relocated section: invalid section index: 255"); 15069c645a99SAiden Grossman } 1507df6d2faaSAmir Ayupov 1508df6d2faaSAmir Ayupov TEST(ELFObjectFileTest, ELFSymbolRefLess) { 1509df6d2faaSAmir Ayupov SmallString<0> Storage; 1510df6d2faaSAmir Ayupov Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 1511df6d2faaSAmir Ayupov --- !ELF 1512df6d2faaSAmir Ayupov FileHeader: 1513df6d2faaSAmir Ayupov Class: ELFCLASS64 1514df6d2faaSAmir Ayupov Data: ELFDATA2LSB 1515df6d2faaSAmir Ayupov Type: ET_DYN 1516df6d2faaSAmir Ayupov Machine: EM_X86_64 1517df6d2faaSAmir Ayupov )"); 1518df6d2faaSAmir Ayupov 1519df6d2faaSAmir Ayupov ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1520df6d2faaSAmir Ayupov const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 1521df6d2faaSAmir Ayupov 1522df6d2faaSAmir Ayupov const uint32_t ValLow = 0x00000001; 1523df6d2faaSAmir Ayupov const uint32_t ValHigh = 0x00000100; 1524df6d2faaSAmir Ayupov 1525df6d2faaSAmir Ayupov auto MakeSymbol = [&Obj](size_t SymtabIndex, size_t SymbolIndex) { 1526df6d2faaSAmir Ayupov DataRefImpl Data; 1527df6d2faaSAmir Ayupov Data.d.a = SymtabIndex; 1528df6d2faaSAmir Ayupov Data.d.b = SymbolIndex; 1529df6d2faaSAmir Ayupov SymbolRef Sym(Data, &Obj); 1530df6d2faaSAmir Ayupov return ELFSymbolRef(Sym); 1531df6d2faaSAmir Ayupov }; 1532df6d2faaSAmir Ayupov 1533df6d2faaSAmir Ayupov ELFSymbolRef ELFSymLowLow = MakeSymbol(ValLow, ValLow); 1534df6d2faaSAmir Ayupov ELFSymbolRef ELFSymLowHigh = MakeSymbol(ValLow, ValHigh); 1535df6d2faaSAmir Ayupov ELFSymbolRef ELFSymHighLow = MakeSymbol(ValHigh, ValLow); 1536df6d2faaSAmir Ayupov ELFSymbolRef ELFSymHighHigh = MakeSymbol(ValHigh, ValHigh); 1537df6d2faaSAmir Ayupov 1538df6d2faaSAmir Ayupov EXPECT_TRUE(ELFSymLowLow < ELFSymLowHigh); 1539df6d2faaSAmir Ayupov EXPECT_FALSE(ELFSymLowHigh < ELFSymLowLow); 1540df6d2faaSAmir Ayupov EXPECT_FALSE(ELFSymLowLow < ELFSymLowLow); 1541df6d2faaSAmir Ayupov 1542df6d2faaSAmir Ayupov EXPECT_TRUE(ELFSymLowLow < ELFSymHighHigh); 1543df6d2faaSAmir Ayupov EXPECT_TRUE(ELFSymLowHigh < ELFSymHighLow); 1544df6d2faaSAmir Ayupov EXPECT_TRUE(ELFSymLowLow < ELFSymHighLow); 1545df6d2faaSAmir Ayupov 1546df6d2faaSAmir Ayupov EXPECT_FALSE(ELFSymHighLow < ELFSymLowHigh); 1547df6d2faaSAmir Ayupov EXPECT_FALSE(ELFSymHighHigh < ELFSymLowLow); 1548df6d2faaSAmir Ayupov EXPECT_FALSE(ELFSymHighLow < ELFSymLowLow); 1549df6d2faaSAmir Ayupov } 1550