1708 lines · cpp
1//===- ELFObjectFileTest.cpp - Tests for ELFObjectFile --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Object/ELFObjectFile.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/BinaryFormat/ELF.h"12#include "llvm/ObjectYAML/yaml2obj.h"13#include "llvm/Support/BlockFrequency.h"14#include "llvm/Support/MemoryBuffer.h"15#include "llvm/Support/YAMLTraits.h"16#include "llvm/Testing/Support/Error.h"17#include "gtest/gtest.h"18 19#include "llvm/Support/thread.h"20#include "llvm/TargetParser/Host.h"21 22using namespace llvm;23using namespace llvm::object;24 25namespace {26 27// A struct to initialize a buffer to represent an ELF object file.28struct DataForTest {29 std::vector<uint8_t> Data;30 31 template <typename T>32 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding,33 uint16_t Machine, uint8_t OS,34 uint16_t Flags) {35 T Ehdr{}; // Zero-initialise the header.36 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f;37 Ehdr.e_ident[ELF::EI_MAG1] = 'E';38 Ehdr.e_ident[ELF::EI_MAG2] = 'L';39 Ehdr.e_ident[ELF::EI_MAG3] = 'F';40 Ehdr.e_ident[ELF::EI_CLASS] = Class;41 Ehdr.e_ident[ELF::EI_DATA] = Encoding;42 Ehdr.e_ident[ELF::EI_VERSION] = 1;43 Ehdr.e_ident[ELF::EI_OSABI] = OS;44 Ehdr.e_type = ELF::ET_REL;45 Ehdr.e_machine = Machine;46 Ehdr.e_version = 1;47 Ehdr.e_flags = Flags;48 Ehdr.e_ehsize = sizeof(T);49 50 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB;51 if (sys::IsLittleEndianHost != IsLittleEndian) {52 sys::swapByteOrder(Ehdr.e_type);53 sys::swapByteOrder(Ehdr.e_machine);54 sys::swapByteOrder(Ehdr.e_version);55 sys::swapByteOrder(Ehdr.e_ehsize);56 }57 58 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr);59 std::vector<uint8_t> Bytes;60 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes));61 return Bytes;62 }63 64 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine,65 uint8_t OS = ELF::ELFOSABI_NONE, uint16_t Flags = 0) {66 if (Class == ELF::ELFCLASS64)67 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine, OS, Flags);68 else {69 assert(Class == ELF::ELFCLASS32);70 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine, OS, Flags);71 }72 }73};74 75void checkFormatAndArch(const DataForTest &D, StringRef Fmt,76 Triple::ArchType Arch) {77 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr =78 object::ObjectFile::createELFObjectFile(79 MemoryBufferRef(toStringRef(D.Data), "dummyELF"));80 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());81 82 const ObjectFile &File = *(*ELFObjOrErr).get();83 EXPECT_EQ(Fmt, File.getFileFormatName());84 EXPECT_EQ(Arch, File.getArch());85}86 87std::array<DataForTest, 4> generateData(uint16_t Machine) {88 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),89 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),90 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),91 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};92}93 94} // namespace95 96TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {97 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",98 "elf64-unknown", "elf64-unknown"};99 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE)))100 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);101 102 // Test an arbitrary unused EM_* value (255).103 for (auto [Idx, Data] : enumerate(generateData(255)))104 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);105}106 107TEST(ELFObjectFileTest, MachineTestForVE) {108 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",109 "elf64-ve", "elf64-ve"};110 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE)))111 checkFormatAndArch(Data, Formats[Idx], Triple::ve);112}113 114TEST(ELFObjectFileTest, MachineTestForX86_64) {115 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",116 "elf64-x86-64", "elf64-x86-64"};117 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64)))118 checkFormatAndArch(Data, Formats[Idx], Triple::x86_64);119}120 121TEST(ELFObjectFileTest, MachineTestFor386) {122 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",123 "elf64-i386"};124 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386)))125 checkFormatAndArch(Data, Formats[Idx], Triple::x86);126}127 128TEST(ELFObjectFileTest, MachineTestForMIPS) {129 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",130 "elf64-mips"};131 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,132 Triple::mips64el, Triple::mips64};133 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS)))134 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);135}136 137TEST(ELFObjectFileTest, MachineTestForAMDGPU) {138 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",139 "elf64-amdgpu", "elf64-amdgpu"};140 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU)))141 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);142}143 144TEST(ELFObjectFileTest, MachineTestForIAMCU) {145 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",146 "elf64-unknown", "elf64-unknown"};147 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU)))148 checkFormatAndArch(Data, Formats[Idx], Triple::x86);149}150 151TEST(ELFObjectFileTest, MachineTestForAARCH64) {152 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",153 "elf64-littleaarch64",154 "elf64-bigaarch64"};155 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,156 Triple::aarch64, Triple::aarch64_be};157 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64)))158 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);159}160 161TEST(ELFObjectFileTest, MachineTestForPPC64) {162 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",163 "elf64-powerpcle", "elf64-powerpc"};164 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,165 Triple::ppc64le, Triple::ppc64};166 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64)))167 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);168}169 170TEST(ELFObjectFileTest, MachineTestForPPC) {171 std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",172 "elf64-unknown", "elf64-unknown"};173 std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,174 Triple::ppcle, Triple::ppc};175 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC)))176 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);177}178 179TEST(ELFObjectFileTest, MachineTestForRISCV) {180 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-bigriscv",181 "elf64-littleriscv", "elf64-bigriscv"};182 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32be,183 Triple::riscv64, Triple::riscv64be};184 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV)))185 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);186}187 188TEST(ELFObjectFileTest, MachineTestForARM) {189 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",190 "elf64-unknown", "elf64-unknown"};191 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM)))192 checkFormatAndArch(Data, Formats[Idx], Triple::arm);193}194 195TEST(ELFObjectFileTest, MachineTestForS390) {196 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",197 "elf64-s390", "elf64-s390"};198 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390)))199 checkFormatAndArch(Data, Formats[Idx], Triple::systemz);200}201 202TEST(ELFObjectFileTest, MachineTestForSPARCV9) {203 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",204 "elf64-sparc", "elf64-sparc"};205 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9)))206 checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9);207}208 209TEST(ELFObjectFileTest, MachineTestForSPARC) {210 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",211 "elf64-unknown", "elf64-unknown"};212 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,213 Triple::sparcel, Triple::sparc};214 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC)))215 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);216}217 218TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {219 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",220 "elf64-unknown", "elf64-unknown"};221 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,222 Triple::sparcel, Triple::sparc};223 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS)))224 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);225}226 227TEST(ELFObjectFileTest, MachineTestForBPF) {228 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",229 "elf64-bpf", "elf64-bpf"};230 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,231 Triple::bpfel, Triple::bpfeb};232 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF)))233 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);234}235 236TEST(ELFObjectFileTest, MachineTestForAVR) {237 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",238 "elf64-unknown"};239 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR)))240 checkFormatAndArch(Data, Formats[Idx], Triple::avr);241}242 243TEST(ELFObjectFileTest, MachineTestForHEXAGON) {244 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",245 "elf64-unknown", "elf64-unknown"};246 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON)))247 checkFormatAndArch(Data, Formats[Idx], Triple::hexagon);248}249 250TEST(ELFObjectFileTest, MachineTestForLANAI) {251 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",252 "elf64-unknown", "elf64-unknown"};253 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI)))254 checkFormatAndArch(Data, Formats[Idx], Triple::lanai);255}256 257TEST(ELFObjectFileTest, MachineTestForMSP430) {258 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",259 "elf64-unknown", "elf64-unknown"};260 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430)))261 checkFormatAndArch(Data, Formats[Idx], Triple::msp430);262}263 264TEST(ELFObjectFileTest, MachineTestForLoongArch) {265 std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch",266 "elf64-loongarch", "elf64-loongarch"};267 std::array<Triple::ArchType, 4> Archs = {268 Triple::loongarch32, Triple::loongarch32, Triple::loongarch64,269 Triple::loongarch64};270 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH)))271 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);272}273 274TEST(ELFObjectFileTest, MachineTestForCSKY) {275 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",276 "elf64-unknown", "elf64-unknown"};277 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY)))278 checkFormatAndArch(Data, Formats[Idx], Triple::csky);279}280 281TEST(ELFObjectFileTest, MachineTestForXtensa) {282 std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa",283 "elf64-unknown", "elf64-unknown"};284 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA)))285 checkFormatAndArch(Data, Formats[Idx], Triple::xtensa);286}287 288TEST(ELFObjectFileTest, CheckOSAndTriple) {289 std::tuple<uint16_t, uint8_t, StringRef> Formats[] = {290 {ELF::EM_AMDGPU, ELF::ELFOSABI_AMDGPU_HSA, "amdgcn-amd-amdhsa"},291 {ELF::EM_X86_64, ELF::ELFOSABI_LINUX, "x86_64--linux"},292 {ELF::EM_X86_64, ELF::ELFOSABI_NETBSD, "x86_64--netbsd"},293 {ELF::EM_X86_64, ELF::ELFOSABI_HURD, "x86_64--hurd"},294 {ELF::EM_X86_64, ELF::ELFOSABI_SOLARIS, "x86_64--solaris"},295 {ELF::EM_X86_64, ELF::ELFOSABI_AIX, "x86_64--aix"},296 {ELF::EM_X86_64, ELF::ELFOSABI_FREEBSD, "x86_64--freebsd"},297 {ELF::EM_X86_64, ELF::ELFOSABI_OPENBSD, "x86_64--openbsd"},298 {ELF::EM_CUDA, ELF::ELFOSABI_CUDA, "nvptx64-nvidia-cuda"}};299 for (auto [Machine, OS, Triple] : Formats) {300 const DataForTest D(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine, OS,301 ELF::EF_AMDGPU_MACH_AMDGCN_LAST);302 Expected<ELF64LEObjectFile> ELFObjOrErr = ELF64LEObjectFile::create(303 MemoryBufferRef(toStringRef(D.Data), "dummyELF"));304 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());305 306 auto &ELFObj = *ELFObjOrErr;307 llvm::Triple TheTriple = ELFObj.makeTriple();308 309 // The AMDGPU architecture will be unknown on big-endian testers.310 if (TheTriple.getArch() == Triple::UnknownArch)311 continue;312 313 EXPECT_EQ(Triple, TheTriple.getTriple());314 }315}316 317// ELF relative relocation type test.318TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {319 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));320}321 322template <class ELFT>323static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,324 StringRef Yaml) {325 raw_svector_ostream OS(Storage);326 yaml::Input YIn(Yaml);327 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))328 return createStringError(std::errc::invalid_argument,329 "unable to convert YAML");330 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));331}332 333// Check we are able to create an ELFObjectFile even when the content of the334// SHT_SYMTAB_SHNDX section can't be read properly.335TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {336 SmallString<0> Storage;337 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(338--- !ELF339FileHeader:340 Class: ELFCLASS64341 Data: ELFDATA2LSB342 Type: ET_REL343Sections:344 - Name: .symtab_shndx345 Type: SHT_SYMTAB_SHNDX346 Entries: [ 0 ]347 ShSize: 0xFFFFFFFF348)");349 350 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());351}352 353// Test that we are able to create an ELFObjectFile even when loadable segments354// are unsorted by virtual address.355// Test that ELFFile<ELFT>::toMappedAddr works properly in this case.356 357TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {358 SmallString<0> Storage;359 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(360--- !ELF361FileHeader:362 Class: ELFCLASS64363 Data: ELFDATA2LSB364 Type: ET_EXEC365Sections:366 - Name: .foo367 Type: SHT_PROGBITS368 Address: 0x1000369 Offset: 0x3000370 ContentArray: [ 0x11 ]371 - Name: .bar372 Type: SHT_PROGBITS373 Address: 0x2000374 Offset: 0x4000375 ContentArray: [ 0x99 ]376ProgramHeaders:377 - Type: PT_LOAD378 VAddr: 0x2000379 FirstSec: .bar380 LastSec: .bar381 - Type: PT_LOAD382 VAddr: 0x1000383 FirstSec: .foo384 LastSec: .foo385)");386 387 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());388 389 std::string WarnString;390 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {391 Expected<const uint8_t *> DataOrErr =392 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {393 EXPECT_TRUE(WarnString.empty());394 WarnString = Msg.str();395 return Error::success();396 });397 398 if (!DataOrErr) {399 ADD_FAILURE() << toString(DataOrErr.takeError());400 return nullptr;401 }402 403 EXPECT_TRUE(WarnString ==404 "loadable segments are unsorted by virtual address");405 WarnString = "";406 return *DataOrErr;407 };408 409 const uint8_t *Data = ToMappedAddr(0x1000);410 ASSERT_TRUE(Data);411 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();412 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);413 EXPECT_EQ(Data[0], 0x11);414 415 Data = ToMappedAddr(0x2000);416 ASSERT_TRUE(Data);417 Buf = ExpectedFile->getMemoryBufferRef();418 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);419 EXPECT_EQ(Data[0], 0x99);420}421 422// This is a test for API that is related to symbols.423// We check that errors are properly reported here.424TEST(ELFObjectFileTest, InvalidSymbolTest) {425 SmallString<0> Storage;426 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(427--- !ELF428FileHeader:429 Class: ELFCLASS64430 Data: ELFDATA2LSB431 Type: ET_DYN432 Machine: EM_X86_64433Sections:434 - Name: .symtab435 Type: SHT_SYMTAB436)");437 438 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());439 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();440 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;441 442 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);443 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());444 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);445 446 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {447 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);448 449 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().450 // SymbolRef::getName() calls it internally. We can't test it directly,451 // because it is protected.452 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),453 FailedWithMessage(ErrMsg));454 455 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().456 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),457 FailedWithMessage(ErrMsg));458 459 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().460 // SymbolRef::getSection() calls it internally. We can't test it461 // directly, because it is protected.462 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),463 FailedWithMessage(ErrMsg));464 465 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().466 // SymbolRef::getFlags() calls it internally. We can't test it directly,467 // because it is protected.468 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),469 FailedWithMessage(ErrMsg));470 471 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().472 // SymbolRef::getType() calls it internally. We can't test it directly,473 // because it is protected.474 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),475 FailedWithMessage(ErrMsg));476 477 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().478 // SymbolRef::getAddress() calls it internally. We can't test it479 // directly, because it is protected.480 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),481 FailedWithMessage(ErrMsg));482 483 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying484 // method that generates errors for all cases above.485 EXPECT_THAT_EXPECTED(486 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());487 EXPECT_THAT_ERROR(488 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)489 .takeError(),490 FailedWithMessage(ErrMsg));491 };492 493 // We create a symbol with an index that is too large to exist in the symbol494 // table.495 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "496 "section (0x18)");497 498 // We create a symbol with an index that is too large to exist in the object.499 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "500 "end of the section (0x18)");501}502 503// Tests for error paths of the ELFFile::decodeBBAddrMap API.504TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {505 StringRef CommonYamlString(R"(506--- !ELF507FileHeader:508 Class: ELFCLASS64509 Data: ELFDATA2LSB510 Type: ET_EXEC511Sections:512 - Type: SHT_LLVM_BB_ADDR_MAP513 Name: .llvm_bb_addr_map514 Entries:515)");516 517 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {518 SmallString<0> Storage;519 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =520 toBinary<ELF64LE>(Storage, YamlString);521 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());522 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();523 524 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =525 Elf.getSection(1);526 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());527 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),528 FailedWithMessage(ErrMsg));529 };530 531 // Check that we can detect unsupported versions.532 SmallString<128> UnsupportedVersionYamlString(CommonYamlString);533 UnsupportedVersionYamlString += R"(534 - Version: 6535 BBRanges:536 - BaseAddress: 0x11111537 BBEntries:538 - AddressOffset: 0x0539 Size: 0x1540 Metadata: 0x2541)";542 543 {544 SCOPED_TRACE("unsupported version");545 DoCheck(UnsupportedVersionYamlString,546 "unsupported SHT_LLVM_BB_ADDR_MAP version: 6");547 }548 549 SmallString<128> ZeroBBRangesYamlString(CommonYamlString);550 ZeroBBRangesYamlString += R"(551 - Version: 3552 Feature: 0x8553 BBRanges: []554)";555 {556 SCOPED_TRACE("zero bb ranges");557 DoCheck(ZeroBBRangesYamlString,558 "invalid zero number of BB ranges at offset 3 in "559 "SHT_LLVM_BB_ADDR_MAP section with index 1");560 }561 562 SmallString<128> CommonVersionedYamlString(CommonYamlString);563 CommonVersionedYamlString += R"(564 - Version: 3565 BBRanges:566 - BaseAddress: 0x11111567 BBEntries:568 - AddressOffset: 0x0569 Size: 0x1570 Metadata: 0x2571)";572 573 // Check that we can detect the malformed encoding when the section is574 // truncated.575 SmallString<128> TruncatedYamlString(CommonVersionedYamlString);576 TruncatedYamlString += R"(577 ShSize: 0xb578)";579 {580 SCOPED_TRACE("truncated section");581 DoCheck(TruncatedYamlString,582 "unable to decode LEB128 at offset 0x0000000b: "583 "malformed uleb128, extends past end");584 }585 586 // Check that we can detect when the encoded BB entry fields exceed the UINT32587 // limit.588 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(589 3, CommonVersionedYamlString);590 OverInt32LimitYamlStrings[0] += R"(591 - ID: 1592 AddressOffset: 0x100000000593 Size: 0xFFFFFFFF594 Metadata: 0xFFFFFFFF595)";596 597 OverInt32LimitYamlStrings[1] += R"(598 - ID: 2599 AddressOffset: 0xFFFFFFFF600 Size: 0x100000000601 Metadata: 0xFFFFFFFF602)";603 604 OverInt32LimitYamlStrings[2] += R"(605 - ID: 3606 AddressOffset: 0xFFFFFFFF607 Size: 0xFFFFFFFF608 Metadata: 0x100000000609)";610 611 {612 SCOPED_TRACE("overlimit fields");613 DoCheck(OverInt32LimitYamlStrings[0],614 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");615 DoCheck(OverInt32LimitYamlStrings[1],616 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");617 DoCheck(OverInt32LimitYamlStrings[2],618 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");619 }620 621 // Check the proper error handling when the section has fields exceeding622 // UINT32 and is also truncated. This is for checking that we don't generate623 // unhandled errors.624 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(625 3, OverInt32LimitYamlStrings[1]);626 // Truncate before the end of the 5-byte field.627 OverInt32LimitAndTruncated[0] += R"(628 ShSize: 0x19629)";630 // Truncate at the end of the 5-byte field.631 OverInt32LimitAndTruncated[1] += R"(632 ShSize: 0x1a633)";634 // Truncate after the end of the 5-byte field.635 OverInt32LimitAndTruncated[2] += R"(636 ShSize: 0x1b637)";638 639 {640 SCOPED_TRACE("overlimit fields, truncated section");641 DoCheck(OverInt32LimitAndTruncated[0],642 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "643 "extends past end");644 DoCheck(OverInt32LimitAndTruncated[1],645 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");646 DoCheck(OverInt32LimitAndTruncated[2],647 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");648 }649 650 // Check for proper error handling when the 'NumBlocks' field is overridden651 // with an out-of-range value.652 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);653 OverLimitNumBlocks += R"(654 NumBlocks: 0x100000000655)";656 657 {658 SCOPED_TRACE("overlimit 'NumBlocks' field");659 DoCheck(OverLimitNumBlocks,660 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");661 }662 663 // Check for proper error handling when the 'NumBBRanges' field is overridden664 // with an out-of-range value.665 SmallString<128> OverLimitNumBBRanges(CommonVersionedYamlString);666 OverLimitNumBBRanges += R"(667 NumBBRanges: 0x100000000668 Feature: 0x8669)";670 DoCheck(OverLimitNumBBRanges,671 "ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)");672 673 // Check that we can detect unsupported version for callsite offsets.674 SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);675 UnsupportedLowVersionYamlString += R"(676 - Version: 2677 Feature: 0x20678 BBRanges:679 - BBEntries:680 - AddressOffset: 0x0681 Size: 0x1682 Metadata: 0x2683 CallsiteEndOffsets: [ 0x1 ]684)";685 686 {687 SCOPED_TRACE("unsupported version");688 DoCheck(UnsupportedLowVersionYamlString,689 "version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when callsite"690 " offsets feature is enabled: version = 2 feature = 32");691 }692}693 694// Test for the ELFObjectFile::readBBAddrMap API.695TEST(ELFObjectFileTest, ReadBBAddrMap) {696 StringRef CommonYamlString(R"(697--- !ELF698FileHeader:699 Class: ELFCLASS64700 Data: ELFDATA2LSB701 Type: ET_EXEC702Sections:703 - Name: .llvm_bb_addr_map_1704 Type: SHT_LLVM_BB_ADDR_MAP705 Link: 1706 Entries:707 - Version: 3708 Feature: 0x20709 BBRanges:710 - BaseAddress: 0x11111711 BBEntries:712 - ID: 1713 AddressOffset: 0x0714 Size: 0x1715 Metadata: 0x2716 CallsiteEndOffsets: [ 0x1 , 0x1 ]717 - Name: .llvm_bb_addr_map_2718 Type: SHT_LLVM_BB_ADDR_MAP719 Link: 1720 Entries:721 - Version: 3722 Feature: 0x8723 BBRanges:724 - BaseAddress: 0x22222725 BBEntries:726 - ID: 2727 AddressOffset: 0x0728 Size: 0x2729 Metadata: 0x4730 - BaseAddress: 0xFFFFF731 BBEntries:732 - ID: 15733 AddressOffset: 0xF0734 Size: 0xF1735 Metadata: 0x1F736 - Name: .llvm_bb_addr_map_3737 Type: SHT_LLVM_BB_ADDR_MAP738 Link: 2739 Entries:740 - Version: 2741 BBRanges:742 - BaseAddress: 0x33333743 BBEntries:744 - ID: 0745 AddressOffset: 0x0746 Size: 0x3747 Metadata: 0x6748 - Name: .llvm_bb_addr_map_4749 Type: SHT_LLVM_BB_ADDR_MAP750 # Link: 0 (by default, can be overriden)751 Entries:752 - Version: 2753 BBRanges:754 - BaseAddress: 0x44444755 BBEntries:756 - ID: 0757 AddressOffset: 0x0758 Size: 0x4759 Metadata: 0x18760)");761 762 BBAddrMap E1 = {763 {{0x11111,764 {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0}}}}};765 BBAddrMap E2 = {766 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}},767 {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0}}}}};768 BBAddrMap E3 = {769 {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0}}}}};770 BBAddrMap E4 = {771 {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0}}}}};772 773 std::vector<BBAddrMap> Section0BBAddrMaps = {E4};774 std::vector<BBAddrMap> Section1BBAddrMaps = {E3};775 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};776 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};777 778 auto DoCheckSucceeds = [&](StringRef YamlString,779 std::optional<unsigned> TextSectionIndex,780 std::vector<BBAddrMap> ExpectedResult) {781 SCOPED_TRACE("for TextSectionIndex: " +782 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +783 " and object yaml:\n" + YamlString);784 SmallString<0> Storage;785 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =786 toBinary<ELF64LE>(Storage, YamlString);787 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());788 789 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =790 ElfOrErr->getELFFile().getSection(1);791 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());792 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);793 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());794 EXPECT_EQ(*BBAddrMaps, ExpectedResult);795 };796 797 auto DoCheckFails = [&](StringRef YamlString,798 std::optional<unsigned> TextSectionIndex,799 const char *ErrMsg) {800 SCOPED_TRACE("for TextSectionIndex: " +801 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +802 " and object yaml:\n" + YamlString);803 SmallString<0> Storage;804 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =805 toBinary<ELF64LE>(Storage, YamlString);806 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());807 808 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =809 ElfOrErr->getELFFile().getSection(1);810 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());811 EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(),812 FailedWithMessage(ErrMsg));813 };814 815 {816 SCOPED_TRACE("normal sections");817 // Check that we can retrieve the data in the normal case.818 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,819 AllBBAddrMaps);820 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,821 Section0BBAddrMaps);822 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,823 Section1BBAddrMaps);824 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,825 Section2BBAddrMaps);826 // Check that when no bb-address-map section is found for a text section,827 // we return an empty result.828 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});829 }830 831 // Check that we detect when a bb-addr-map section is linked to an invalid832 // (not present) section.833 SmallString<128> InvalidLinkedYamlString(CommonYamlString);834 InvalidLinkedYamlString += R"(835 Link: 121836)";837 838 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,839 "unable to get the linked-to section for "840 "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section "841 "index: 121");842 {843 SCOPED_TRACE("invalid linked section");844 // Linked sections are not checked when we don't target a specific text845 // section.846 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,847 AllBBAddrMaps);848 }849 850 // Check that we can detect when bb-address-map decoding fails.851 SmallString<128> TruncatedYamlString(CommonYamlString);852 TruncatedYamlString += R"(853 ShSize: 0xa854)";855 856 {857 SCOPED_TRACE("truncated section");858 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,859 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: "860 "unable to decode LEB128 at offset 0x0000000a: malformed "861 "uleb128, extends past end");862 863 // Check that we can read the other section's bb-address-maps which are864 // valid.865 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,866 Section1BBAddrMaps);867 }868}869 870// Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap871// API.872TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) {873 StringRef CommonYamlString(R"(874--- !ELF875FileHeader:876 Class: ELFCLASS64877 Data: ELFDATA2LSB878 Type: ET_EXEC879Sections:880 - Type: SHT_LLVM_BB_ADDR_MAP881 Name: .llvm_bb_addr_map882 Entries:883)");884 885 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {886 SmallString<0> Storage;887 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =888 toBinary<ELF64LE>(Storage, YamlString);889 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());890 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();891 892 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =893 Elf.getSection(1);894 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());895 896 std::vector<PGOAnalysisMap> PGOAnalyses;897 EXPECT_THAT_ERROR(898 Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses)899 .takeError(),900 FailedWithMessage(ErrMsg));901 };902 903 // Check that we can detect unsupported versions that are too old.904 SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);905 UnsupportedLowVersionYamlString += R"(906 - Version: 1907 Feature: 0x0908 BBRanges:909 - BBEntries:910 - AddressOffset: 0x0911 Size: 0x1912 Metadata: 0x2913)";914 915 {916 SCOPED_TRACE("unsupported version");917 DoCheck(UnsupportedLowVersionYamlString,918 "unsupported SHT_LLVM_BB_ADDR_MAP version: 1");919 }920 921 // Check that we fail when function entry count is enabled but not provided.922 SmallString<128> MissingFuncEntryCount(CommonYamlString);923 MissingFuncEntryCount += R"(924 - Version: 2925 Feature: 0x01926)";927 928 {929 SCOPED_TRACE("missing function entry count");930 DoCheck(MissingFuncEntryCount,931 "unexpected end of data at offset 0x2 while reading [0x2, 0xa)");932 }933 934 // Check that we fail when basic block frequency is enabled but not provided.935 SmallString<128> MissingBBFreq(CommonYamlString);936 MissingBBFreq += R"(937 - Version: 2938 Feature: 0x02939 BBRanges:940 - BBEntries:941 - ID: 1942 AddressOffset: 0x0943 Size: 0x1944 Metadata: 0x2945)";946 947 {948 SCOPED_TRACE("missing bb frequency");949 DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: "950 "malformed uleb128, extends past end");951 }952 953 // Check that we fail when branch probability is enabled but not provided.954 SmallString<128> MissingBrProb(CommonYamlString);955 MissingBrProb += R"(956 - Version: 2957 Feature: 0x04958 BBRanges:959 - BBEntries:960 - ID: 1961 AddressOffset: 0x0962 Size: 0x1963 Metadata: 0x6964 - ID: 2965 AddressOffset: 0x1966 Size: 0x1967 Metadata: 0x2968 - ID: 3969 AddressOffset: 0x2970 Size: 0x1971 Metadata: 0x2972 PGOAnalyses:973 - PGOBBEntries:974 - Successors:975 - ID: 2976 BrProb: 0x80000000977 - ID: 3978 BrProb: 0x80000000979 - Successors:980 - ID: 3981 BrProb: 0xF0000000982)";983 984 {985 SCOPED_TRACE("missing branch probability");986 DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: "987 "malformed uleb128, extends past end");988 }989}990 991// Test for the ELFObjectFile::readBBAddrMap API with BBHash.992TEST(ELFObjectFileTest, ReadBBHash) {993 StringRef CommonYamlString(R"(994--- !ELF995FileHeader:996 Class: ELFCLASS64997 Data: ELFDATA2LSB998 Type: ET_EXEC999Sections:1000 - Name: .llvm_bb_addr_map_11001 Type: SHT_LLVM_BB_ADDR_MAP1002 Link: 11003 Entries:1004 - Version: 41005 Feature: 0x601006 BBRanges:1007 - BaseAddress: 0x111111008 BBEntries:1009 - ID: 11010 AddressOffset: 0x01011 Size: 0x11012 Metadata: 0x21013 CallsiteEndOffsets: [ 0x1 , 0x1 ]1014 Hash: 0x11015 - Name: .llvm_bb_addr_map_21016 Type: SHT_LLVM_BB_ADDR_MAP1017 Link: 11018 Entries:1019 - Version: 41020 Feature: 0x481021 BBRanges:1022 - BaseAddress: 0x222221023 BBEntries:1024 - ID: 21025 AddressOffset: 0x01026 Size: 0x21027 Metadata: 0x41028 Hash: 0x21029 - BaseAddress: 0xFFFFF1030 BBEntries:1031 - ID: 151032 AddressOffset: 0xF01033 Size: 0xF11034 Metadata: 0x1F1035 Hash: 0xF1036 - Name: .llvm_bb_addr_map_31037 Type: SHT_LLVM_BB_ADDR_MAP1038 Link: 21039 Entries:1040 - Version: 41041 Feature: 0x401042 BBRanges:1043 - BaseAddress: 0x333331044 BBEntries:1045 - ID: 01046 AddressOffset: 0x01047 Size: 0x31048 Metadata: 0x61049 Hash: 0x31050 - Name: .llvm_bb_addr_map_41051 Type: SHT_LLVM_BB_ADDR_MAP1052 # Link: 0 (by default, can be overriden)1053 Entries:1054 - Version: 41055 Feature: 0x401056 BBRanges:1057 - BaseAddress: 0x444441058 BBEntries:1059 - ID: 01060 AddressOffset: 0x01061 Size: 0x41062 Metadata: 0x181063 Hash: 0x41064)");1065 1066 BBAddrMap E1 = {1067 {{0x11111,1068 {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}, 0x1}}}}};1069 BBAddrMap E2 = {1070 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0x2}}},1071 {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}, 0xF}}}}};1072 BBAddrMap E3 = {1073 {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0x3}}}}};1074 BBAddrMap E4 = {1075 {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0x4}}}}};1076 1077 std::vector<BBAddrMap> Section0BBAddrMaps = {E4};1078 std::vector<BBAddrMap> Section1BBAddrMaps = {E3};1079 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};1080 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};1081 1082 auto DoCheckSucceeds = [&](StringRef YamlString,1083 std::optional<unsigned> TextSectionIndex,1084 std::vector<BBAddrMap> ExpectedResult) {1085 SCOPED_TRACE("for TextSectionIndex: " +1086 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +1087 " and object yaml:\n" + YamlString);1088 SmallString<0> Storage;1089 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1090 toBinary<ELF64LE>(Storage, YamlString);1091 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1092 1093 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =1094 ElfOrErr->getELFFile().getSection(1);1095 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());1096 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);1097 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());1098 EXPECT_EQ(*BBAddrMaps, ExpectedResult);1099 };1100 1101 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,1102 AllBBAddrMaps);1103 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps);1104 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps);1105 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps);1106}1107 1108// Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap.1109TEST(ELFObjectFileTest, ReadPGOAnalysisMap) {1110 StringRef CommonYamlString(R"(1111--- !ELF1112FileHeader:1113 Class: ELFCLASS641114 Data: ELFDATA2LSB1115 Type: ET_EXEC1116Sections:1117 - Name: .llvm_bb_addr_map_11118 Type: SHT_LLVM_BB_ADDR_MAP1119 Link: 11120 Entries:1121 - Version: 21122 Feature: 0x11123 BBRanges:1124 - BaseAddress: 0x111111125 BBEntries:1126 - ID: 11127 AddressOffset: 0x01128 Size: 0x11129 Metadata: 0x21130 PGOAnalyses:1131 - FuncEntryCount: 8921132 - Name: .llvm_bb_addr_map_21133 Type: SHT_LLVM_BB_ADDR_MAP1134 Link: 11135 Entries:1136 - Version: 21137 Feature: 0x21138 BBRanges:1139 - BaseAddress: 0x222221140 BBEntries:1141 - ID: 21142 AddressOffset: 0x01143 Size: 0x21144 Metadata: 0x41145 PGOAnalyses:1146 - PGOBBEntries:1147 - BBFreq: 3431148 - Name: .llvm_bb_addr_map_31149 Type: SHT_LLVM_BB_ADDR_MAP1150 Link: 21151 Entries:1152 - Version: 21153 Feature: 0x41154 BBRanges:1155 - BaseAddress: 0x333331156 BBEntries:1157 - ID: 01158 AddressOffset: 0x01159 Size: 0x31160 Metadata: 0x61161 - ID: 11162 AddressOffset: 0x01163 Size: 0x31164 Metadata: 0x41165 - ID: 21166 AddressOffset: 0x01167 Size: 0x31168 Metadata: 0x01169 PGOAnalyses:1170 - PGOBBEntries:1171 - Successors:1172 - ID: 11173 BrProb: 0x111111111174 - ID: 21175 BrProb: 0xeeeeeeee1176 - Successors:1177 - ID: 21178 BrProb: 0xffffffff1179 - Successors: []1180 - Name: .llvm_bb_addr_map_41181 Type: SHT_LLVM_BB_ADDR_MAP1182 # Link: 0 (by default, can be overriden)1183 Entries:1184 - Version: 51185 Feature: 0x871186 BBRanges:1187 - BaseAddress: 0x444441188 BBEntries:1189 - ID: 01190 AddressOffset: 0x01191 Size: 0x41192 Metadata: 0x181193 - ID: 11194 AddressOffset: 0x01195 Size: 0x41196 Metadata: 0x01197 - ID: 21198 AddressOffset: 0x01199 Size: 0x41200 Metadata: 0x01201 - ID: 31202 AddressOffset: 0x01203 Size: 0x41204 Metadata: 0x01205 PGOAnalyses:1206 - FuncEntryCount: 10001207 PGOBBEntries:1208 - BBFreq: 10001209 PostLinkBBFreq: 501210 Successors:1211 - ID: 11212 BrProb: 0x222222221213 - ID: 21214 BrProb: 0x333333331215 - ID: 31216 BrProb: 0xaaaaaaaa1217 - BBFreq: 1331218 Successors:1219 - ID: 21220 BrProb: 0x111111111221 - ID: 31222 BrProb: 0xeeeeeeee1223 - BBFreq: 181224 Successors:1225 - ID: 31226 BrProb: 0xffffffff1227 - BBFreq: 10001228 Successors: []1229 - Name: .llvm_bb_addr_map_51230 Type: SHT_LLVM_BB_ADDR_MAP1231 # Link: 0 (by default, can be overriden)1232 Entries:1233 - Version: 21234 Feature: 0x01235 BBRanges:1236 - BaseAddress: 0x555551237 BBEntries:1238 - ID: 21239 AddressOffset: 0x01240 Size: 0x21241 Metadata: 0x41242 PGOAnalyses: [{}]1243 - Name: .llvm_bb_addr_map_61244 Type: SHT_LLVM_BB_ADDR_MAP1245 # Link: 0 (by default, can be overriden)1246 Entries:1247 - Version: 51248 Feature: 0x8c1249 BBRanges:1250 - BaseAddress: 0x666661251 BBEntries:1252 - ID: 01253 AddressOffset: 0x01254 Size: 0x61255 Metadata: 0x61256 - ID: 11257 AddressOffset: 0x01258 Size: 0x61259 Metadata: 0x41260 - BaseAddress: 0x6666611261 BBEntries:1262 - ID: 21263 AddressOffset: 0x01264 Size: 0x61265 Metadata: 0x01266 PGOAnalyses:1267 - PGOBBEntries:1268 - Successors:1269 - ID: 11270 BrProb: 0x222222221271 PostLinkBrFreq: 71272 - ID: 21273 BrProb: 0xcccccccc1274 - Successors:1275 - ID: 21276 BrProb: 0x888888881277 - Successors: []1278)");1279 1280 BBAddrMap E1 = {1281 {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}, 0}}}}};1282 PGOAnalysisMap P1 = {1283 892, {}, {true, false, false, false, false, false, false, false}};1284 BBAddrMap E2 = {1285 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}};1286 PGOAnalysisMap P2 = {{},1287 {{BlockFrequency(343), 0, {}}},1288 {false, true, false, false, false, false, false, false}};1289 BBAddrMap E3 = {1290 {{0x33333,1291 {{0, 0x0, 0x3, {false, true, true, false, false}, {}, 0},1292 {1, 0x3, 0x3, {false, false, true, false, false}, {}, 0},1293 {2, 0x6, 0x3, {false, false, false, false, false}, {}, 0}}}}};1294 PGOAnalysisMap P3 = {1295 {},1296 {{{},1297 0,1298 {{1, BranchProbability::getRaw(0x1111'1111), 0},1299 {2, BranchProbability::getRaw(0xeeee'eeee), 0}}},1300 {{}, 0, {{2, BranchProbability::getRaw(0xffff'ffff), 0}}},1301 {{}, 0, {}}},1302 {false, false, true, false, false, false, false, false}};1303 BBAddrMap E4 = {1304 {{0x44444,1305 {{0, 0x0, 0x4, {false, false, false, true, true}, {}, 0},1306 {1, 0x4, 0x4, {false, false, false, false, false}, {}, 0},1307 {2, 0x8, 0x4, {false, false, false, false, false}, {}, 0},1308 {3, 0xc, 0x4, {false, false, false, false, false}, {}, 0}}}}};1309 PGOAnalysisMap P4 = {1000,1310 {{BlockFrequency(1000),1311 50,1312 {{1, BranchProbability::getRaw(0x2222'2222), 0},1313 {2, BranchProbability::getRaw(0x3333'3333), 0},1314 {3, BranchProbability::getRaw(0xaaaa'aaaa), 0}}},1315 {BlockFrequency(133),1316 0,1317 {{2, BranchProbability::getRaw(0x1111'1111), 0},1318 {3, BranchProbability::getRaw(0xeeee'eeee), 0}}},1319 {BlockFrequency(18),1320 0,1321 {{3, BranchProbability::getRaw(0xffff'ffff), 0}}},1322 {BlockFrequency(1000), 0, {}}},1323 {true, true, true, false, false, false, false, true}};1324 BBAddrMap E5 = {1325 {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}, 0}}}}};1326 PGOAnalysisMap P5 = {1327 {}, {}, {false, false, false, false, false, false, false, false}};1328 BBAddrMap E6 = {1329 {{0x66666,1330 {{0, 0x0, 0x6, {false, true, true, false, false}, {}, 0},1331 {1, 0x6, 0x6, {false, false, true, false, false}, {}, 0}}},1332 {0x666661,1333 {{2, 0x0, 0x6, {false, false, false, false, false}, {}, 0}}}}};1334 PGOAnalysisMap P6 = {1335 {},1336 {{{},1337 0,1338 {{1, BranchProbability::getRaw(0x2222'2222), 7},1339 {2, BranchProbability::getRaw(0xcccc'cccc), 0}}},1340 {{}, 0, {{2, BranchProbability::getRaw(0x8888'8888), 0}}},1341 {{}, 0, {}}},1342 {false, false, true, true, false, false, false, true}};1343 1344 std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6};1345 std::vector<BBAddrMap> Section1BBAddrMaps = {E3};1346 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};1347 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4, E5, E6};1348 1349 std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4, P5, P6};1350 std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3};1351 std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2};1352 std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4, P5, P6};1353 1354 auto DoCheckSucceeds =1355 [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex,1356 std::vector<BBAddrMap> ExpectedResult,1357 std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) {1358 SCOPED_TRACE(1359 "for TextSectionIndex: " +1360 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +1361 " and object yaml:\n" + YamlString);1362 SmallString<0> Storage;1363 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1364 toBinary<ELF64LE>(Storage, YamlString);1365 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1366 1367 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =1368 ElfOrErr->getELFFile().getSection(1);1369 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());1370 1371 std::vector<PGOAnalysisMap> PGOAnalyses;1372 auto BBAddrMaps = ElfOrErr->readBBAddrMap(1373 TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr);1374 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());1375 EXPECT_EQ(*BBAddrMaps, ExpectedResult);1376 if (ExpectedPGO) {1377 EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size());1378 for (const auto &PGO : PGOAnalyses) {1379 errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n";1380 for (const auto &PGOBB : PGO.BBEntries)1381 errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n";1382 }1383 errs() << " To expected:\n";1384 for (const auto &PGO : *ExpectedPGO) {1385 errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n";1386 for (const auto &PGOBB : PGO.BBEntries)1387 errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n";1388 }1389 EXPECT_EQ(PGOAnalyses, *ExpectedPGO);1390 for (auto &&[BB, PGO] : llvm::zip(*BBAddrMaps, PGOAnalyses)) {1391 if (PGO.FeatEnable.BBFreq || PGO.FeatEnable.BrProb)1392 EXPECT_EQ(BB.getNumBBEntries(), PGO.BBEntries.size());1393 }1394 }1395 };1396 1397 auto DoCheckFails = [&](StringRef YamlString,1398 std::optional<unsigned> TextSectionIndex,1399 const char *ErrMsg) {1400 SCOPED_TRACE("for TextSectionIndex: " +1401 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +1402 " and object yaml:\n" + YamlString);1403 SmallString<0> Storage;1404 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1405 toBinary<ELF64LE>(Storage, YamlString);1406 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1407 1408 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =1409 ElfOrErr->getELFFile().getSection(1);1410 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());1411 std::vector<PGOAnalysisMap> PGOAnalyses;1412 EXPECT_THAT_ERROR(1413 ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(),1414 FailedWithMessage(ErrMsg));1415 };1416 1417 {1418 SCOPED_TRACE("normal sections");1419 // Check that we can retrieve the data in the normal case.1420 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,1421 AllBBAddrMaps, std::nullopt);1422 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,1423 Section0BBAddrMaps, std::nullopt);1424 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,1425 Section1BBAddrMaps, std::nullopt);1426 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,1427 Section2BBAddrMaps, std::nullopt);1428 1429 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,1430 AllBBAddrMaps, AllPGOAnalysisMaps);1431 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,1432 Section0BBAddrMaps, Section0PGOAnalysisMaps);1433 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,1434 Section1BBAddrMaps, Section1PGOAnalysisMaps);1435 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,1436 Section2BBAddrMaps, Section2PGOAnalysisMaps);1437 // Check that when no bb-address-map section is found for a text section,1438 // we return an empty result.1439 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt);1440 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {},1441 std::vector<PGOAnalysisMap>{});1442 }1443 1444 // Check that we detect when a bb-addr-map section is linked to an invalid1445 // (not present) section.1446 SmallString<128> InvalidLinkedYamlString(CommonYamlString);1447 InvalidLinkedYamlString += R"(1448 Link: 1211449)";1450 1451 {1452 SCOPED_TRACE("invalid linked section");1453 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/5,1454 "unable to get the linked-to section for "1455 "SHT_LLVM_BB_ADDR_MAP section with index 6: invalid section "1456 "index: 121");1457 1458 // Linked sections are not checked when we don't target a specific text1459 // section.1460 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,1461 AllBBAddrMaps, std::nullopt);1462 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,1463 AllBBAddrMaps, AllPGOAnalysisMaps);1464 }1465 1466 // Check that we can detect when bb-address-map decoding fails.1467 SmallString<128> TruncatedYamlString(CommonYamlString);1468 TruncatedYamlString += R"(1469 ShSize: 0xa1470)";1471 1472 {1473 SCOPED_TRACE("truncated section");1474 DoCheckFails(1475 TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,1476 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 6: "1477 "unexpected end of data at offset 0xa while reading [0x4, 0xc)");1478 // Check that we can read the other section's bb-address-maps which are1479 // valid.1480 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,1481 Section1BBAddrMaps, std::nullopt);1482 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,1483 Section1BBAddrMaps, Section1PGOAnalysisMaps);1484 }1485}1486 1487// Test for ObjectFile::getRelocatedSection: check that it returns a relocated1488// section for executable and relocatable files.1489TEST(ELFObjectFileTest, ExecutableWithRelocs) {1490 StringRef HeaderString(R"(1491--- !ELF1492FileHeader:1493 Class: ELFCLASS641494 Data: ELFDATA2LSB1495)");1496 StringRef ContentsString(R"(1497Sections:1498 - Name: .text1499 Type: SHT_PROGBITS1500 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]1501 - Name: .rela.text1502 Type: SHT_RELA1503 Flags: [ SHF_INFO_LINK ]1504 Info: .text1505)");1506 1507 auto DoCheck = [&](StringRef YamlString) {1508 SmallString<0> Storage;1509 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1510 toBinary<ELF64LE>(Storage, YamlString);1511 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1512 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;1513 1514 bool FoundRela;1515 1516 for (SectionRef Sec : Obj.sections()) {1517 Expected<StringRef> SecNameOrErr = Sec.getName();1518 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());1519 StringRef SecName = *SecNameOrErr;1520 if (SecName != ".rela.text")1521 continue;1522 FoundRela = true;1523 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();1524 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());1525 section_iterator RelSec = *RelSecOrErr;1526 ASSERT_NE(RelSec, Obj.section_end());1527 Expected<StringRef> TextSecNameOrErr = RelSec->getName();1528 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());1529 StringRef TextSecName = *TextSecNameOrErr;1530 EXPECT_EQ(TextSecName, ".text");1531 }1532 ASSERT_TRUE(FoundRela);1533 };1534 1535 // Check ET_EXEC file (`ld --emit-relocs` use-case).1536 SmallString<128> ExecFileYamlString(HeaderString);1537 ExecFileYamlString += R"(1538 Type: ET_EXEC1539)";1540 ExecFileYamlString += ContentsString;1541 DoCheck(ExecFileYamlString);1542 1543 // Check ET_REL file.1544 SmallString<128> RelocatableFileYamlString(HeaderString);1545 RelocatableFileYamlString += R"(1546 Type: ET_REL1547)";1548 RelocatableFileYamlString += ContentsString;1549 DoCheck(RelocatableFileYamlString);1550}1551 1552TEST(ELFObjectFileTest, GetSectionAndRelocations) {1553 StringRef HeaderString(R"(1554--- !ELF1555FileHeader:1556 Class: ELFCLASS641557 Data: ELFDATA2LSB1558 Type: ET_EXEC1559)");1560 1561 using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>;1562 1563 auto DoCheckSucceeds = [&](StringRef ContentsString,1564 std::function<Expected<bool>(const Elf_Shdr &)>1565 Matcher) {1566 SmallString<0> Storage;1567 SmallString<128> FullYamlString(HeaderString);1568 FullYamlString += ContentsString;1569 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1570 toBinary<ELF64LE>(Storage, FullYamlString);1571 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1572 1573 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =1574 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);1575 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded());1576 1577 // Basic verification to make sure we have the correct section types.1578 for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) {1579 ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS);1580 ASSERT_TRUE(RelaSec->sh_type == ELF::SHT_RELA ||1581 RelaSec->sh_type == ELF::SHT_CREL);1582 }1583 };1584 1585 auto DoCheckFails = [&](StringRef ContentsString,1586 std::function<Expected<bool>(const Elf_Shdr &)>1587 Matcher,1588 const char *ErrorMessage) {1589 SmallString<0> Storage;1590 SmallString<128> FullYamlString(HeaderString);1591 FullYamlString += ContentsString;1592 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =1593 toBinary<ELF64LE>(Storage, FullYamlString);1594 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1595 1596 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =1597 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);1598 ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(),1599 FailedWithMessage(ErrorMessage));1600 };1601 1602 auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool {1603 return Sec.sh_type == ELF::SHT_PROGBITS;1604 };1605 1606 StringRef TwoTextSections = R"(1607Sections:1608 - Name: .text1609 Type: SHT_PROGBITS1610 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]1611 - Name: .rela.text1612 Type: SHT_RELA1613 Flags: [ SHF_INFO_LINK ]1614 Info: .text1615 - Name: .text21616 Type: SHT_PROGBITS1617 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]1618 - Name: .rela.text21619 Type: SHT_RELA1620 Flags: [ SHF_INFO_LINK ]1621 Info: .text21622)";1623 DoCheckSucceeds(TwoTextSections, DefaultMatcher);1624 1625 StringRef OneTextSection = R"(1626Sections:1627 - Name: .text1628 Type: SHT_PROGBITS1629 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]1630)";1631 1632 auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> {1633 if (Sec.sh_type == ELF::SHT_PROGBITS)1634 return createError("This was supposed to fail.");1635 return false;1636 };1637 1638 DoCheckFails(OneTextSection, ErroringMatcher, "This was supposed to fail.");1639 1640 StringRef MissingRelocatableContent = R"(1641Sections:1642 - Name: .rela.text1643 Type: SHT_RELA1644 Flags: [ SHF_INFO_LINK ]1645 Info: 0xFF1646)";1647 1648 DoCheckFails(MissingRelocatableContent, DefaultMatcher,1649 "SHT_RELA section with index 1: failed to get a "1650 "relocated section: invalid section index: 255");1651 1652 StringRef OneTextSectionCREL = R"(1653Sections:1654 - Name: .text1655 Type: SHT_PROGBITS1656 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]1657 - Name: .crel.tex1658 Type: SHT_CREL1659 Flags: [ SHF_INFO_LINK ]1660 Info: .text1661)";1662 1663 DoCheckSucceeds(OneTextSectionCREL, DefaultMatcher);1664}1665 1666TEST(ELFObjectFileTest, ELFSymbolRefLess) {1667 SmallString<0> Storage;1668 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(1669--- !ELF1670FileHeader:1671 Class: ELFCLASS641672 Data: ELFDATA2LSB1673 Type: ET_DYN1674 Machine: EM_X86_641675)");1676 1677 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());1678 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;1679 1680 const uint32_t ValLow = 0x00000001;1681 const uint32_t ValHigh = 0x00000100;1682 1683 auto MakeSymbol = [&Obj](size_t SymtabIndex, size_t SymbolIndex) {1684 DataRefImpl Data;1685 Data.d.a = SymtabIndex;1686 Data.d.b = SymbolIndex;1687 SymbolRef Sym(Data, &Obj);1688 return ELFSymbolRef(Sym);1689 };1690 1691 ELFSymbolRef ELFSymLowLow = MakeSymbol(ValLow, ValLow);1692 ELFSymbolRef ELFSymLowHigh = MakeSymbol(ValLow, ValHigh);1693 ELFSymbolRef ELFSymHighLow = MakeSymbol(ValHigh, ValLow);1694 ELFSymbolRef ELFSymHighHigh = MakeSymbol(ValHigh, ValHigh);1695 1696 EXPECT_TRUE(ELFSymLowLow < ELFSymLowHigh);1697 EXPECT_FALSE(ELFSymLowHigh < ELFSymLowLow);1698 EXPECT_FALSE(ELFSymLowLow < ELFSymLowLow);1699 1700 EXPECT_TRUE(ELFSymLowLow < ELFSymHighHigh);1701 EXPECT_TRUE(ELFSymLowHigh < ELFSymHighLow);1702 EXPECT_TRUE(ELFSymLowLow < ELFSymHighLow);1703 1704 EXPECT_FALSE(ELFSymHighLow < ELFSymLowHigh);1705 EXPECT_FALSE(ELFSymHighHigh < ELFSymLowLow);1706 EXPECT_FALSE(ELFSymHighLow < ELFSymLowLow);1707}1708