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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Object/ELFObjectFile.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ObjectYAML/yaml2obj.h" 12 #include "llvm/Support/BlockFrequency.h" 13 #include "llvm/Support/MemoryBuffer.h" 14 #include "llvm/Support/YAMLTraits.h" 15 #include "llvm/Testing/Support/Error.h" 16 #include "gtest/gtest.h" 17 18 #include "llvm/Support/thread.h" 19 #include "llvm/TargetParser/Host.h" 20 21 using namespace llvm; 22 using namespace llvm::object; 23 24 namespace { 25 26 // A struct to initialize a buffer to represent an ELF object file. 27 struct DataForTest { 28 std::vector<uint8_t> Data; 29 30 template <typename T> 31 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 32 uint16_t Machine, uint8_t OS, 33 uint16_t Flags) { 34 T Ehdr{}; // Zero-initialise the header. 35 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 36 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 37 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 38 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 39 Ehdr.e_ident[ELF::EI_CLASS] = Class; 40 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 41 Ehdr.e_ident[ELF::EI_VERSION] = 1; 42 Ehdr.e_ident[ELF::EI_OSABI] = OS; 43 Ehdr.e_type = ELF::ET_REL; 44 Ehdr.e_machine = Machine; 45 Ehdr.e_version = 1; 46 Ehdr.e_flags = Flags; 47 Ehdr.e_ehsize = sizeof(T); 48 49 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 50 if (sys::IsLittleEndianHost != IsLittleEndian) { 51 sys::swapByteOrder(Ehdr.e_type); 52 sys::swapByteOrder(Ehdr.e_machine); 53 sys::swapByteOrder(Ehdr.e_version); 54 sys::swapByteOrder(Ehdr.e_ehsize); 55 } 56 57 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 58 std::vector<uint8_t> Bytes; 59 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 60 return Bytes; 61 } 62 63 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine, 64 uint8_t OS = ELF::ELFOSABI_NONE, uint16_t Flags = 0) { 65 if (Class == ELF::ELFCLASS64) 66 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine, OS, Flags); 67 else { 68 assert(Class == ELF::ELFCLASS32); 69 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine, OS, Flags); 70 } 71 } 72 }; 73 74 void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 75 Triple::ArchType Arch) { 76 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 77 object::ObjectFile::createELFObjectFile( 78 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 79 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 80 81 const ObjectFile &File = *(*ELFObjOrErr).get(); 82 EXPECT_EQ(Fmt, File.getFileFormatName()); 83 EXPECT_EQ(Arch, File.getArch()); 84 } 85 86 std::array<DataForTest, 4> generateData(uint16_t Machine) { 87 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine), 88 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine), 89 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine), 90 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)}; 91 } 92 93 } // namespace 94 95 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) { 96 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 97 "elf64-unknown", "elf64-unknown"}; 98 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE))) 99 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch); 100 101 // Test an arbitrary unused EM_* value (255). 102 for (auto [Idx, Data] : enumerate(generateData(255))) 103 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch); 104 } 105 106 TEST(ELFObjectFileTest, MachineTestForVE) { 107 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 108 "elf64-ve", "elf64-ve"}; 109 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE))) 110 checkFormatAndArch(Data, Formats[Idx], Triple::ve); 111 } 112 113 TEST(ELFObjectFileTest, MachineTestForX86_64) { 114 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64", 115 "elf64-x86-64", "elf64-x86-64"}; 116 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64))) 117 checkFormatAndArch(Data, Formats[Idx], Triple::x86_64); 118 } 119 120 TEST(ELFObjectFileTest, MachineTestFor386) { 121 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386", 122 "elf64-i386"}; 123 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386))) 124 checkFormatAndArch(Data, Formats[Idx], Triple::x86); 125 } 126 127 TEST(ELFObjectFileTest, MachineTestForMIPS) { 128 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips", 129 "elf64-mips"}; 130 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips, 131 Triple::mips64el, Triple::mips64}; 132 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS))) 133 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 134 } 135 136 TEST(ELFObjectFileTest, MachineTestForAMDGPU) { 137 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu", 138 "elf64-amdgpu", "elf64-amdgpu"}; 139 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU))) 140 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch); 141 } 142 143 TEST(ELFObjectFileTest, MachineTestForIAMCU) { 144 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu", 145 "elf64-unknown", "elf64-unknown"}; 146 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU))) 147 checkFormatAndArch(Data, Formats[Idx], Triple::x86); 148 } 149 150 TEST(ELFObjectFileTest, MachineTestForAARCH64) { 151 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 152 "elf64-littleaarch64", 153 "elf64-bigaarch64"}; 154 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be, 155 Triple::aarch64, Triple::aarch64_be}; 156 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64))) 157 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 158 } 159 160 TEST(ELFObjectFileTest, MachineTestForPPC64) { 161 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 162 "elf64-powerpcle", "elf64-powerpc"}; 163 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64, 164 Triple::ppc64le, Triple::ppc64}; 165 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64))) 166 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 167 } 168 169 TEST(ELFObjectFileTest, MachineTestForPPC) { 170 std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc", 171 "elf64-unknown", "elf64-unknown"}; 172 std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc, 173 Triple::ppcle, Triple::ppc}; 174 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC))) 175 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 176 } 177 178 TEST(ELFObjectFileTest, MachineTestForRISCV) { 179 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", 180 "elf64-littleriscv", "elf64-littleriscv"}; 181 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, 182 Triple::riscv64, Triple::riscv64}; 183 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV))) 184 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 185 } 186 187 TEST(ELFObjectFileTest, MachineTestForARM) { 188 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm", 189 "elf64-unknown", "elf64-unknown"}; 190 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM))) 191 checkFormatAndArch(Data, Formats[Idx], Triple::arm); 192 } 193 194 TEST(ELFObjectFileTest, MachineTestForS390) { 195 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 196 "elf64-s390", "elf64-s390"}; 197 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390))) 198 checkFormatAndArch(Data, Formats[Idx], Triple::systemz); 199 } 200 201 TEST(ELFObjectFileTest, MachineTestForSPARCV9) { 202 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 203 "elf64-sparc", "elf64-sparc"}; 204 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9))) 205 checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9); 206 } 207 208 TEST(ELFObjectFileTest, MachineTestForSPARC) { 209 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 210 "elf64-unknown", "elf64-unknown"}; 211 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 212 Triple::sparcel, Triple::sparc}; 213 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC))) 214 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 215 } 216 217 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) { 218 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 219 "elf64-unknown", "elf64-unknown"}; 220 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 221 Triple::sparcel, Triple::sparc}; 222 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS))) 223 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 224 } 225 226 TEST(ELFObjectFileTest, MachineTestForBPF) { 227 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 228 "elf64-bpf", "elf64-bpf"}; 229 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb, 230 Triple::bpfel, Triple::bpfeb}; 231 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF))) 232 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 233 } 234 235 TEST(ELFObjectFileTest, MachineTestForAVR) { 236 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown", 237 "elf64-unknown"}; 238 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR))) 239 checkFormatAndArch(Data, Formats[Idx], Triple::avr); 240 } 241 242 TEST(ELFObjectFileTest, MachineTestForHEXAGON) { 243 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon", 244 "elf64-unknown", "elf64-unknown"}; 245 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON))) 246 checkFormatAndArch(Data, Formats[Idx], Triple::hexagon); 247 } 248 249 TEST(ELFObjectFileTest, MachineTestForLANAI) { 250 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai", 251 "elf64-unknown", "elf64-unknown"}; 252 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI))) 253 checkFormatAndArch(Data, Formats[Idx], Triple::lanai); 254 } 255 256 TEST(ELFObjectFileTest, MachineTestForMSP430) { 257 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430", 258 "elf64-unknown", "elf64-unknown"}; 259 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430))) 260 checkFormatAndArch(Data, Formats[Idx], Triple::msp430); 261 } 262 263 TEST(ELFObjectFileTest, MachineTestForLoongArch) { 264 std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch", 265 "elf64-loongarch", "elf64-loongarch"}; 266 std::array<Triple::ArchType, 4> Archs = { 267 Triple::loongarch32, Triple::loongarch32, Triple::loongarch64, 268 Triple::loongarch64}; 269 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH))) 270 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); 271 } 272 273 TEST(ELFObjectFileTest, MachineTestForCSKY) { 274 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 275 "elf64-unknown", "elf64-unknown"}; 276 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY))) 277 checkFormatAndArch(Data, Formats[Idx], Triple::csky); 278 } 279 280 TEST(ELFObjectFileTest, MachineTestForXtensa) { 281 std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa", 282 "elf64-unknown", "elf64-unknown"}; 283 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA))) 284 checkFormatAndArch(Data, Formats[Idx], Triple::xtensa); 285 } 286 287 TEST(ELFObjectFileTest, CheckOSAndTriple) { 288 std::tuple<uint16_t, uint8_t, StringRef> Formats[] = { 289 {ELF::EM_AMDGPU, ELF::ELFOSABI_AMDGPU_HSA, "amdgcn-amd-amdhsa"}, 290 {ELF::EM_X86_64, ELF::ELFOSABI_LINUX, "x86_64--linux"}, 291 {ELF::EM_X86_64, ELF::ELFOSABI_NETBSD, "x86_64--netbsd"}, 292 {ELF::EM_X86_64, ELF::ELFOSABI_HURD, "x86_64--hurd"}, 293 {ELF::EM_X86_64, ELF::ELFOSABI_SOLARIS, "x86_64--solaris"}, 294 {ELF::EM_X86_64, ELF::ELFOSABI_AIX, "x86_64--aix"}, 295 {ELF::EM_X86_64, ELF::ELFOSABI_FREEBSD, "x86_64--freebsd"}, 296 {ELF::EM_X86_64, ELF::ELFOSABI_OPENBSD, "x86_64--openbsd"}, 297 {ELF::EM_CUDA, ELF::ELFOSABI_CUDA, "nvptx64-nvidia-cuda"}}; 298 for (auto [Machine, OS, Triple] : Formats) { 299 const DataForTest D(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine, OS, 300 ELF::EF_AMDGPU_MACH_AMDGCN_LAST); 301 Expected<ELF64LEObjectFile> ELFObjOrErr = ELF64LEObjectFile::create( 302 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 303 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 304 305 auto &ELFObj = *ELFObjOrErr; 306 llvm::Triple TheTriple = ELFObj.makeTriple(); 307 308 // The AMDGPU architecture will be unknown on big-endian testers. 309 if (TheTriple.getArch() == Triple::UnknownArch) 310 continue; 311 312 EXPECT_EQ(Triple, TheTriple.getTriple()); 313 } 314 } 315 316 // ELF relative relocation type test. 317 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 318 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 319 } 320 321 template <class ELFT> 322 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 323 StringRef Yaml) { 324 raw_svector_ostream OS(Storage); 325 yaml::Input YIn(Yaml); 326 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 327 return createStringError(std::errc::invalid_argument, 328 "unable to convert YAML"); 329 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 330 } 331 332 // Check we are able to create an ELFObjectFile even when the content of the 333 // SHT_SYMTAB_SHNDX section can't be read properly. 334 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 335 SmallString<0> Storage; 336 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 337 --- !ELF 338 FileHeader: 339 Class: ELFCLASS64 340 Data: ELFDATA2LSB 341 Type: ET_REL 342 Sections: 343 - Name: .symtab_shndx 344 Type: SHT_SYMTAB_SHNDX 345 Entries: [ 0 ] 346 ShSize: 0xFFFFFFFF 347 )"); 348 349 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 350 } 351 352 // Test that we are able to create an ELFObjectFile even when loadable segments 353 // are unsorted by virtual address. 354 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 355 356 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 357 SmallString<0> Storage; 358 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 359 --- !ELF 360 FileHeader: 361 Class: ELFCLASS64 362 Data: ELFDATA2LSB 363 Type: ET_EXEC 364 Sections: 365 - Name: .foo 366 Type: SHT_PROGBITS 367 Address: 0x1000 368 Offset: 0x3000 369 ContentArray: [ 0x11 ] 370 - Name: .bar 371 Type: SHT_PROGBITS 372 Address: 0x2000 373 Offset: 0x4000 374 ContentArray: [ 0x99 ] 375 ProgramHeaders: 376 - Type: PT_LOAD 377 VAddr: 0x2000 378 FirstSec: .bar 379 LastSec: .bar 380 - Type: PT_LOAD 381 VAddr: 0x1000 382 FirstSec: .foo 383 LastSec: .foo 384 )"); 385 386 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 387 388 std::string WarnString; 389 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 390 Expected<const uint8_t *> DataOrErr = 391 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 392 EXPECT_TRUE(WarnString.empty()); 393 WarnString = Msg.str(); 394 return Error::success(); 395 }); 396 397 if (!DataOrErr) { 398 ADD_FAILURE() << toString(DataOrErr.takeError()); 399 return nullptr; 400 } 401 402 EXPECT_TRUE(WarnString == 403 "loadable segments are unsorted by virtual address"); 404 WarnString = ""; 405 return *DataOrErr; 406 }; 407 408 const uint8_t *Data = ToMappedAddr(0x1000); 409 ASSERT_TRUE(Data); 410 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 411 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 412 EXPECT_EQ(Data[0], 0x11); 413 414 Data = ToMappedAddr(0x2000); 415 ASSERT_TRUE(Data); 416 Buf = ExpectedFile->getMemoryBufferRef(); 417 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 418 EXPECT_EQ(Data[0], 0x99); 419 } 420 421 // This is a test for API that is related to symbols. 422 // We check that errors are properly reported here. 423 TEST(ELFObjectFileTest, InvalidSymbolTest) { 424 SmallString<0> Storage; 425 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 426 --- !ELF 427 FileHeader: 428 Class: ELFCLASS64 429 Data: ELFDATA2LSB 430 Type: ET_DYN 431 Machine: EM_X86_64 432 Sections: 433 - Name: .symtab 434 Type: SHT_SYMTAB 435 )"); 436 437 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 438 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 439 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 440 441 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 442 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 443 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 444 445 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 446 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 447 448 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 449 // SymbolRef::getName() calls it internally. We can't test it directly, 450 // because it is protected. 451 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 452 FailedWithMessage(ErrMsg)); 453 454 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 455 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 456 FailedWithMessage(ErrMsg)); 457 458 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 459 // SymbolRef::getSection() calls it internally. We can't test it 460 // directly, because it is protected. 461 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 462 FailedWithMessage(ErrMsg)); 463 464 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 465 // SymbolRef::getFlags() calls it internally. We can't test it directly, 466 // because it is protected. 467 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 468 FailedWithMessage(ErrMsg)); 469 470 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 471 // SymbolRef::getType() calls it internally. We can't test it directly, 472 // because it is protected. 473 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 474 FailedWithMessage(ErrMsg)); 475 476 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 477 // SymbolRef::getAddress() calls it internally. We can't test it 478 // directly, because it is protected. 479 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 480 FailedWithMessage(ErrMsg)); 481 482 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 483 // method that generates errors for all cases above. 484 EXPECT_THAT_EXPECTED( 485 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 486 EXPECT_THAT_ERROR( 487 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 488 .takeError(), 489 FailedWithMessage(ErrMsg)); 490 }; 491 492 // We create a symbol with an index that is too large to exist in the symbol 493 // table. 494 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 495 "section (0x18)"); 496 497 // We create a symbol with an index that is too large to exist in the object. 498 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 499 "end of the section (0x18)"); 500 } 501 502 // Tests for error paths of the ELFFile::decodeBBAddrMap API. 503 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { 504 StringRef CommonYamlString(R"( 505 --- !ELF 506 FileHeader: 507 Class: ELFCLASS64 508 Data: ELFDATA2LSB 509 Type: ET_EXEC 510 Sections: 511 - Type: SHT_LLVM_BB_ADDR_MAP 512 Name: .llvm_bb_addr_map 513 Entries: 514 )"); 515 516 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 517 SmallString<0> Storage; 518 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 519 toBinary<ELF64LE>(Storage, YamlString); 520 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 521 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 522 523 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 524 Elf.getSection(1); 525 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 526 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 527 FailedWithMessage(ErrMsg)); 528 }; 529 530 // Check that we can detect unsupported versions. 531 SmallString<128> UnsupportedVersionYamlString(CommonYamlString); 532 UnsupportedVersionYamlString += R"( 533 - Version: 3 534 BBRanges: 535 - BaseAddress: 0x11111 536 BBEntries: 537 - AddressOffset: 0x0 538 Size: 0x1 539 Metadata: 0x2 540 )"; 541 542 { 543 SCOPED_TRACE("unsupported version"); 544 DoCheck(UnsupportedVersionYamlString, 545 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3"); 546 } 547 548 SmallString<128> ZeroBBRangesYamlString(CommonYamlString); 549 ZeroBBRangesYamlString += R"( 550 - Version: 2 551 Feature: 0x8 552 BBRanges: [] 553 )"; 554 { 555 SCOPED_TRACE("zero bb ranges"); 556 DoCheck(ZeroBBRangesYamlString, 557 "invalid zero number of BB ranges at offset 3 in " 558 "SHT_LLVM_BB_ADDR_MAP section with index 1"); 559 } 560 561 SmallString<128> CommonVersionedYamlString(CommonYamlString); 562 CommonVersionedYamlString += R"( 563 - Version: 2 564 BBRanges: 565 - BaseAddress: 0x11111 566 BBEntries: 567 - AddressOffset: 0x0 568 Size: 0x1 569 Metadata: 0x2 570 )"; 571 572 // Check that we can detect the malformed encoding when the section is 573 // truncated. 574 SmallString<128> TruncatedYamlString(CommonVersionedYamlString); 575 TruncatedYamlString += R"( 576 ShSize: 0xb 577 )"; 578 { 579 SCOPED_TRACE("truncated section"); 580 DoCheck(TruncatedYamlString, 581 "unable to decode LEB128 at offset 0x0000000b: " 582 "malformed uleb128, extends past end"); 583 } 584 585 // Check that we can detect when the encoded BB entry fields exceed the UINT32 586 // limit. 587 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings( 588 3, CommonVersionedYamlString); 589 OverInt32LimitYamlStrings[0] += R"( 590 - ID: 1 591 AddressOffset: 0x100000000 592 Size: 0xFFFFFFFF 593 Metadata: 0xFFFFFFFF 594 )"; 595 596 OverInt32LimitYamlStrings[1] += R"( 597 - ID: 2 598 AddressOffset: 0xFFFFFFFF 599 Size: 0x100000000 600 Metadata: 0xFFFFFFFF 601 )"; 602 603 OverInt32LimitYamlStrings[2] += R"( 604 - ID: 3 605 AddressOffset: 0xFFFFFFFF 606 Size: 0xFFFFFFFF 607 Metadata: 0x100000000 608 )"; 609 610 { 611 SCOPED_TRACE("overlimit fields"); 612 DoCheck(OverInt32LimitYamlStrings[0], 613 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)"); 614 DoCheck(OverInt32LimitYamlStrings[1], 615 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 616 DoCheck(OverInt32LimitYamlStrings[2], 617 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)"); 618 } 619 620 // Check the proper error handling when the section has fields exceeding 621 // UINT32 and is also truncated. This is for checking that we don't generate 622 // unhandled errors. 623 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 624 3, OverInt32LimitYamlStrings[1]); 625 // Truncate before the end of the 5-byte field. 626 OverInt32LimitAndTruncated[0] += R"( 627 ShSize: 0x19 628 )"; 629 // Truncate at the end of the 5-byte field. 630 OverInt32LimitAndTruncated[1] += R"( 631 ShSize: 0x1a 632 )"; 633 // Truncate after the end of the 5-byte field. 634 OverInt32LimitAndTruncated[2] += R"( 635 ShSize: 0x1b 636 )"; 637 638 { 639 SCOPED_TRACE("overlimit fields, truncated section"); 640 DoCheck(OverInt32LimitAndTruncated[0], 641 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, " 642 "extends past end"); 643 DoCheck(OverInt32LimitAndTruncated[1], 644 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 645 DoCheck(OverInt32LimitAndTruncated[2], 646 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 647 } 648 649 // Check for proper error handling when the 'NumBlocks' field is overridden 650 // with an out-of-range value. 651 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString); 652 OverLimitNumBlocks += R"( 653 NumBlocks: 0x100000000 654 )"; 655 656 { 657 SCOPED_TRACE("overlimit 'NumBlocks' field"); 658 DoCheck(OverLimitNumBlocks, 659 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)"); 660 } 661 662 // Check for proper error handling when the 'NumBBRanges' field is overridden 663 // with an out-of-range value. 664 SmallString<128> OverLimitNumBBRanges(CommonVersionedYamlString); 665 OverLimitNumBBRanges += R"( 666 NumBBRanges: 0x100000000 667 Feature: 0x8 668 )"; 669 DoCheck(OverLimitNumBBRanges, 670 "ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)"); 671 } 672 673 // Test for the ELFObjectFile::readBBAddrMap API. 674 TEST(ELFObjectFileTest, ReadBBAddrMap) { 675 StringRef CommonYamlString(R"( 676 --- !ELF 677 FileHeader: 678 Class: ELFCLASS64 679 Data: ELFDATA2LSB 680 Type: ET_EXEC 681 Sections: 682 - Name: .llvm_bb_addr_map_1 683 Type: SHT_LLVM_BB_ADDR_MAP 684 Link: 1 685 Entries: 686 - Version: 2 687 BBRanges: 688 - BaseAddress: 0x11111 689 BBEntries: 690 - ID: 1 691 AddressOffset: 0x0 692 Size: 0x1 693 Metadata: 0x2 694 - Name: .llvm_bb_addr_map_2 695 Type: SHT_LLVM_BB_ADDR_MAP 696 Link: 1 697 Entries: 698 - Version: 2 699 Feature: 0x8 700 BBRanges: 701 - BaseAddress: 0x22222 702 BBEntries: 703 - ID: 2 704 AddressOffset: 0x0 705 Size: 0x2 706 Metadata: 0x4 707 - BaseAddress: 0xFFFFF 708 BBEntries: 709 - ID: 15 710 AddressOffset: 0xF0 711 Size: 0xF1 712 Metadata: 0x1F 713 - Name: .llvm_bb_addr_map_3 714 Type: SHT_LLVM_BB_ADDR_MAP 715 Link: 2 716 Entries: 717 - Version: 1 718 BBRanges: 719 - BaseAddress: 0x33333 720 BBEntries: 721 - ID: 0 722 AddressOffset: 0x0 723 Size: 0x3 724 Metadata: 0x6 725 - Name: .llvm_bb_addr_map_4 726 Type: SHT_LLVM_BB_ADDR_MAP 727 # Link: 0 (by default, can be overriden) 728 Entries: 729 - Version: 2 730 BBRanges: 731 - BaseAddress: 0x44444 732 BBEntries: 733 - ID: 0 734 AddressOffset: 0x0 735 Size: 0x4 736 Metadata: 0x18 737 )"); 738 739 BBAddrMap E1 = { 740 {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}}; 741 BBAddrMap E2 = { 742 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}, 743 {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}}}}}}; 744 BBAddrMap E3 = { 745 {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}}}; 746 BBAddrMap E4 = { 747 {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}}}; 748 749 std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; 750 std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 751 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 752 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; 753 754 auto DoCheckSucceeds = [&](StringRef YamlString, 755 std::optional<unsigned> TextSectionIndex, 756 std::vector<BBAddrMap> ExpectedResult) { 757 SCOPED_TRACE("for TextSectionIndex: " + 758 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 759 " and object yaml:\n" + YamlString); 760 SmallString<0> Storage; 761 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 762 toBinary<ELF64LE>(Storage, YamlString); 763 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 764 765 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 766 ElfOrErr->getELFFile().getSection(1); 767 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 768 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 769 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 770 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 771 }; 772 773 auto DoCheckFails = [&](StringRef YamlString, 774 std::optional<unsigned> TextSectionIndex, 775 const char *ErrMsg) { 776 SCOPED_TRACE("for TextSectionIndex: " + 777 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 778 " and object yaml:\n" + YamlString); 779 SmallString<0> Storage; 780 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 781 toBinary<ELF64LE>(Storage, YamlString); 782 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 783 784 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 785 ElfOrErr->getELFFile().getSection(1); 786 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 787 EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 788 FailedWithMessage(ErrMsg)); 789 }; 790 791 { 792 SCOPED_TRACE("normal sections"); 793 // Check that we can retrieve the data in the normal case. 794 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 795 AllBBAddrMaps); 796 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 797 Section0BBAddrMaps); 798 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 799 Section1BBAddrMaps); 800 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 801 Section2BBAddrMaps); 802 // Check that when no bb-address-map section is found for a text section, 803 // we return an empty result. 804 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}); 805 } 806 807 // Check that we detect when a bb-addr-map section is linked to an invalid 808 // (not present) section. 809 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 810 InvalidLinkedYamlString += R"( 811 Link: 121 812 )"; 813 814 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4, 815 "unable to get the linked-to section for " 816 "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section " 817 "index: 121"); 818 { 819 SCOPED_TRACE("invalid linked section"); 820 // Linked sections are not checked when we don't target a specific text 821 // section. 822 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 823 AllBBAddrMaps); 824 } 825 826 // Check that we can detect when bb-address-map decoding fails. 827 SmallString<128> TruncatedYamlString(CommonYamlString); 828 TruncatedYamlString += R"( 829 ShSize: 0xa 830 )"; 831 832 { 833 SCOPED_TRACE("truncated section"); 834 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 835 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: " 836 "unable to decode LEB128 at offset 0x0000000a: malformed " 837 "uleb128, extends past end"); 838 839 // Check that we can read the other section's bb-address-maps which are 840 // valid. 841 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 842 Section1BBAddrMaps); 843 } 844 } 845 846 // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap 847 // API. 848 TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) { 849 StringRef CommonYamlString(R"( 850 --- !ELF 851 FileHeader: 852 Class: ELFCLASS64 853 Data: ELFDATA2LSB 854 Type: ET_EXEC 855 Sections: 856 - Type: SHT_LLVM_BB_ADDR_MAP 857 Name: .llvm_bb_addr_map 858 Entries: 859 )"); 860 861 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 862 SmallString<0> Storage; 863 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 864 toBinary<ELF64LE>(Storage, YamlString); 865 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 866 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 867 868 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 869 Elf.getSection(1); 870 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 871 872 std::vector<PGOAnalysisMap> PGOAnalyses; 873 EXPECT_THAT_ERROR( 874 Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses) 875 .takeError(), 876 FailedWithMessage(ErrMsg)); 877 }; 878 879 // Check that we can detect unsupported versions that are too old. 880 SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString); 881 UnsupportedLowVersionYamlString += R"( 882 - Version: 1 883 Feature: 0x4 884 BBRanges: 885 - BBEntries: 886 - AddressOffset: 0x0 887 Size: 0x1 888 Metadata: 0x2 889 )"; 890 891 { 892 SCOPED_TRACE("unsupported version"); 893 DoCheck(UnsupportedLowVersionYamlString, 894 "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features " 895 "are enabled: version = 1 feature = 4"); 896 } 897 898 SmallString<128> CommonVersionedYamlString(CommonYamlString); 899 CommonVersionedYamlString += R"( 900 - Version: 2 901 BBRanges: 902 - BBEntries: 903 - ID: 1 904 AddressOffset: 0x0 905 Size: 0x1 906 Metadata: 0x2 907 )"; 908 909 // Check that we fail when function entry count is enabled but not provided. 910 SmallString<128> MissingFuncEntryCount(CommonYamlString); 911 MissingFuncEntryCount += R"( 912 - Version: 2 913 Feature: 0x01 914 )"; 915 916 { 917 SCOPED_TRACE("missing function entry count"); 918 DoCheck(MissingFuncEntryCount, 919 "unexpected end of data at offset 0x2 while reading [0x2, 0xa)"); 920 } 921 922 // Check that we fail when basic block frequency is enabled but not provided. 923 SmallString<128> MissingBBFreq(CommonYamlString); 924 MissingBBFreq += R"( 925 - Version: 2 926 Feature: 0x02 927 BBRanges: 928 - BBEntries: 929 - ID: 1 930 AddressOffset: 0x0 931 Size: 0x1 932 Metadata: 0x2 933 )"; 934 935 { 936 SCOPED_TRACE("missing bb frequency"); 937 DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: " 938 "malformed uleb128, extends past end"); 939 } 940 941 // Check that we fail when branch probability is enabled but not provided. 942 SmallString<128> MissingBrProb(CommonYamlString); 943 MissingBrProb += R"( 944 - Version: 2 945 Feature: 0x04 946 BBRanges: 947 - BBEntries: 948 - ID: 1 949 AddressOffset: 0x0 950 Size: 0x1 951 Metadata: 0x6 952 - ID: 2 953 AddressOffset: 0x1 954 Size: 0x1 955 Metadata: 0x2 956 - ID: 3 957 AddressOffset: 0x2 958 Size: 0x1 959 Metadata: 0x2 960 PGOAnalyses: 961 - PGOBBEntries: 962 - Successors: 963 - ID: 2 964 BrProb: 0x80000000 965 - ID: 3 966 BrProb: 0x80000000 967 - Successors: 968 - ID: 3 969 BrProb: 0xF0000000 970 )"; 971 972 { 973 SCOPED_TRACE("missing branch probability"); 974 DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: " 975 "malformed uleb128, extends past end"); 976 } 977 } 978 979 // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap. 980 TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { 981 StringRef CommonYamlString(R"( 982 --- !ELF 983 FileHeader: 984 Class: ELFCLASS64 985 Data: ELFDATA2LSB 986 Type: ET_EXEC 987 Sections: 988 - Name: .llvm_bb_addr_map_1 989 Type: SHT_LLVM_BB_ADDR_MAP 990 Link: 1 991 Entries: 992 - Version: 2 993 Feature: 0x1 994 BBRanges: 995 - BaseAddress: 0x11111 996 BBEntries: 997 - ID: 1 998 AddressOffset: 0x0 999 Size: 0x1 1000 Metadata: 0x2 1001 PGOAnalyses: 1002 - FuncEntryCount: 892 1003 - Name: .llvm_bb_addr_map_2 1004 Type: SHT_LLVM_BB_ADDR_MAP 1005 Link: 1 1006 Entries: 1007 - Version: 2 1008 Feature: 0x2 1009 BBRanges: 1010 - BaseAddress: 0x22222 1011 BBEntries: 1012 - ID: 2 1013 AddressOffset: 0x0 1014 Size: 0x2 1015 Metadata: 0x4 1016 PGOAnalyses: 1017 - PGOBBEntries: 1018 - BBFreq: 343 1019 - Name: .llvm_bb_addr_map_3 1020 Type: SHT_LLVM_BB_ADDR_MAP 1021 Link: 2 1022 Entries: 1023 - Version: 2 1024 Feature: 0x4 1025 BBRanges: 1026 - BaseAddress: 0x33333 1027 BBEntries: 1028 - ID: 0 1029 AddressOffset: 0x0 1030 Size: 0x3 1031 Metadata: 0x6 1032 - ID: 1 1033 AddressOffset: 0x0 1034 Size: 0x3 1035 Metadata: 0x4 1036 - ID: 2 1037 AddressOffset: 0x0 1038 Size: 0x3 1039 Metadata: 0x0 1040 PGOAnalyses: 1041 - PGOBBEntries: 1042 - Successors: 1043 - ID: 1 1044 BrProb: 0x11111111 1045 - ID: 2 1046 BrProb: 0xeeeeeeee 1047 - Successors: 1048 - ID: 2 1049 BrProb: 0xffffffff 1050 - Successors: [] 1051 - Name: .llvm_bb_addr_map_4 1052 Type: SHT_LLVM_BB_ADDR_MAP 1053 # Link: 0 (by default, can be overriden) 1054 Entries: 1055 - Version: 2 1056 Feature: 0x7 1057 BBRanges: 1058 - BaseAddress: 0x44444 1059 BBEntries: 1060 - ID: 0 1061 AddressOffset: 0x0 1062 Size: 0x4 1063 Metadata: 0x18 1064 - ID: 1 1065 AddressOffset: 0x0 1066 Size: 0x4 1067 Metadata: 0x0 1068 - ID: 2 1069 AddressOffset: 0x0 1070 Size: 0x4 1071 Metadata: 0x0 1072 - ID: 3 1073 AddressOffset: 0x0 1074 Size: 0x4 1075 Metadata: 0x0 1076 PGOAnalyses: 1077 - FuncEntryCount: 1000 1078 PGOBBEntries: 1079 - BBFreq: 1000 1080 Successors: 1081 - ID: 1 1082 BrProb: 0x22222222 1083 - ID: 2 1084 BrProb: 0x33333333 1085 - ID: 3 1086 BrProb: 0xaaaaaaaa 1087 - BBFreq: 133 1088 Successors: 1089 - ID: 2 1090 BrProb: 0x11111111 1091 - ID: 3 1092 BrProb: 0xeeeeeeee 1093 - BBFreq: 18 1094 Successors: 1095 - ID: 3 1096 BrProb: 0xffffffff 1097 - BBFreq: 1000 1098 Successors: [] 1099 - Name: .llvm_bb_addr_map_5 1100 Type: SHT_LLVM_BB_ADDR_MAP 1101 # Link: 0 (by default, can be overriden) 1102 Entries: 1103 - Version: 2 1104 Feature: 0x0 1105 BBRanges: 1106 - BaseAddress: 0x55555 1107 BBEntries: 1108 - ID: 2 1109 AddressOffset: 0x0 1110 Size: 0x2 1111 Metadata: 0x4 1112 PGOAnalyses: [{}] 1113 - Name: .llvm_bb_addr_map_6 1114 Type: SHT_LLVM_BB_ADDR_MAP 1115 # Link: 0 (by default, can be overriden) 1116 Entries: 1117 - Version: 2 1118 Feature: 0xc 1119 BBRanges: 1120 - BaseAddress: 0x66666 1121 BBEntries: 1122 - ID: 0 1123 AddressOffset: 0x0 1124 Size: 0x6 1125 Metadata: 0x6 1126 - ID: 1 1127 AddressOffset: 0x0 1128 Size: 0x6 1129 Metadata: 0x4 1130 - BaseAddress: 0x666661 1131 BBEntries: 1132 - ID: 2 1133 AddressOffset: 0x0 1134 Size: 0x6 1135 Metadata: 0x0 1136 PGOAnalyses: 1137 - PGOBBEntries: 1138 - Successors: 1139 - ID: 1 1140 BrProb: 0x22222222 1141 - ID: 2 1142 BrProb: 0xcccccccc 1143 - Successors: 1144 - ID: 2 1145 BrProb: 0x88888888 1146 - Successors: [] 1147 )"); 1148 1149 BBAddrMap E1 = { 1150 {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}}; 1151 PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false}}; 1152 BBAddrMap E2 = { 1153 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; 1154 PGOAnalysisMap P2 = { 1155 {}, {{BlockFrequency(343), {}}}, {false, true, false, false, false}}; 1156 BBAddrMap E3 = {{{0x33333, 1157 {{0, 0x0, 0x3, {false, true, true, false, false}}, 1158 {1, 0x3, 0x3, {false, false, true, false, false}}, 1159 {2, 0x6, 0x3, {false, false, false, false, false}}}}}}; 1160 PGOAnalysisMap P3 = {{}, 1161 {{{}, 1162 {{1, BranchProbability::getRaw(0x1111'1111)}, 1163 {2, BranchProbability::getRaw(0xeeee'eeee)}}}, 1164 {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, 1165 {{}, {}}}, 1166 {false, false, true, false, false}}; 1167 BBAddrMap E4 = {{{0x44444, 1168 {{0, 0x0, 0x4, {false, false, false, true, true}}, 1169 {1, 0x4, 0x4, {false, false, false, false, false}}, 1170 {2, 0x8, 0x4, {false, false, false, false, false}}, 1171 {3, 0xc, 0x4, {false, false, false, false, false}}}}}}; 1172 PGOAnalysisMap P4 = { 1173 1000, 1174 {{BlockFrequency(1000), 1175 {{1, BranchProbability::getRaw(0x2222'2222)}, 1176 {2, BranchProbability::getRaw(0x3333'3333)}, 1177 {3, BranchProbability::getRaw(0xaaaa'aaaa)}}}, 1178 {BlockFrequency(133), 1179 {{2, BranchProbability::getRaw(0x1111'1111)}, 1180 {3, BranchProbability::getRaw(0xeeee'eeee)}}}, 1181 {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, 1182 {BlockFrequency(1000), {}}}, 1183 {true, true, true, false, false}}; 1184 BBAddrMap E5 = { 1185 {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}}; 1186 PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false}}; 1187 BBAddrMap E6 = { 1188 {{0x66666, 1189 {{0, 0x0, 0x6, {false, true, true, false, false}}, 1190 {1, 0x6, 0x6, {false, false, true, false, false}}}}, 1191 {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}}}}}}; 1192 PGOAnalysisMap P6 = {{}, 1193 {{{}, 1194 {{1, BranchProbability::getRaw(0x2222'2222)}, 1195 {2, BranchProbability::getRaw(0xcccc'cccc)}}}, 1196 {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}}, 1197 {{}, {}}}, 1198 {false, false, true, true, false}}; 1199 1200 std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6}; 1201 std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 1202 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 1203 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4, E5, E6}; 1204 1205 std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4, P5, P6}; 1206 std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3}; 1207 std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2}; 1208 std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4, P5, P6}; 1209 1210 auto DoCheckSucceeds = 1211 [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex, 1212 std::vector<BBAddrMap> ExpectedResult, 1213 std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) { 1214 SCOPED_TRACE( 1215 "for TextSectionIndex: " + 1216 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 1217 " and object yaml:\n" + YamlString); 1218 SmallString<0> Storage; 1219 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1220 toBinary<ELF64LE>(Storage, YamlString); 1221 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1222 1223 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1224 ElfOrErr->getELFFile().getSection(1); 1225 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1226 1227 std::vector<PGOAnalysisMap> PGOAnalyses; 1228 auto BBAddrMaps = ElfOrErr->readBBAddrMap( 1229 TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr); 1230 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 1231 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 1232 if (ExpectedPGO) { 1233 EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size()); 1234 for (const auto &PGO : PGOAnalyses) { 1235 errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n"; 1236 for (const auto &PGOBB : PGO.BBEntries) 1237 errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n"; 1238 } 1239 errs() << " To expected:\n"; 1240 for (const auto &PGO : *ExpectedPGO) { 1241 errs() << "FuncEntryCount: " << PGO.FuncEntryCount << "\n"; 1242 for (const auto &PGOBB : PGO.BBEntries) 1243 errs() << "\tBB: " << PGOBB.BlockFreq.getFrequency() << "\n"; 1244 } 1245 EXPECT_EQ(PGOAnalyses, *ExpectedPGO); 1246 for (auto &&[BB, PGO] : llvm::zip(*BBAddrMaps, PGOAnalyses)) { 1247 if (PGO.FeatEnable.BBFreq || PGO.FeatEnable.BrProb) 1248 EXPECT_EQ(BB.getNumBBEntries(), PGO.BBEntries.size()); 1249 } 1250 } 1251 }; 1252 1253 auto DoCheckFails = [&](StringRef YamlString, 1254 std::optional<unsigned> TextSectionIndex, 1255 const char *ErrMsg) { 1256 SCOPED_TRACE("for TextSectionIndex: " + 1257 (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") + 1258 " and object yaml:\n" + YamlString); 1259 SmallString<0> Storage; 1260 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1261 toBinary<ELF64LE>(Storage, YamlString); 1262 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1263 1264 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1265 ElfOrErr->getELFFile().getSection(1); 1266 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1267 std::vector<PGOAnalysisMap> PGOAnalyses; 1268 EXPECT_THAT_ERROR( 1269 ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(), 1270 FailedWithMessage(ErrMsg)); 1271 }; 1272 1273 { 1274 SCOPED_TRACE("normal sections"); 1275 // Check that we can retrieve the data in the normal case. 1276 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1277 AllBBAddrMaps, std::nullopt); 1278 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 1279 Section0BBAddrMaps, std::nullopt); 1280 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 1281 Section1BBAddrMaps, std::nullopt); 1282 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 1283 Section2BBAddrMaps, std::nullopt); 1284 1285 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1286 AllBBAddrMaps, AllPGOAnalysisMaps); 1287 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, 1288 Section0BBAddrMaps, Section0PGOAnalysisMaps); 1289 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, 1290 Section1BBAddrMaps, Section1PGOAnalysisMaps); 1291 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, 1292 Section2BBAddrMaps, Section2PGOAnalysisMaps); 1293 // Check that when no bb-address-map section is found for a text section, 1294 // we return an empty result. 1295 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt); 1296 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, 1297 std::vector<PGOAnalysisMap>{}); 1298 } 1299 1300 // Check that we detect when a bb-addr-map section is linked to an invalid 1301 // (not present) section. 1302 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 1303 InvalidLinkedYamlString += R"( 1304 Link: 121 1305 )"; 1306 1307 { 1308 SCOPED_TRACE("invalid linked section"); 1309 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/5, 1310 "unable to get the linked-to section for " 1311 "SHT_LLVM_BB_ADDR_MAP section with index 6: invalid section " 1312 "index: 121"); 1313 1314 // Linked sections are not checked when we don't target a specific text 1315 // section. 1316 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1317 AllBBAddrMaps, std::nullopt); 1318 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1319 AllBBAddrMaps, AllPGOAnalysisMaps); 1320 } 1321 1322 // Check that we can detect when bb-address-map decoding fails. 1323 SmallString<128> TruncatedYamlString(CommonYamlString); 1324 TruncatedYamlString += R"( 1325 ShSize: 0xa 1326 )"; 1327 1328 { 1329 SCOPED_TRACE("truncated section"); 1330 DoCheckFails( 1331 TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 1332 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 6: " 1333 "unexpected end of data at offset 0xa while reading [0x3, 0xb)"); 1334 // Check that we can read the other section's bb-address-maps which are 1335 // valid. 1336 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1337 Section1BBAddrMaps, std::nullopt); 1338 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1339 Section1BBAddrMaps, Section1PGOAnalysisMaps); 1340 } 1341 } 1342 1343 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 1344 // section for executable and relocatable files. 1345 TEST(ELFObjectFileTest, ExecutableWithRelocs) { 1346 StringRef HeaderString(R"( 1347 --- !ELF 1348 FileHeader: 1349 Class: ELFCLASS64 1350 Data: ELFDATA2LSB 1351 )"); 1352 StringRef ContentsString(R"( 1353 Sections: 1354 - Name: .text 1355 Type: SHT_PROGBITS 1356 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1357 - Name: .rela.text 1358 Type: SHT_RELA 1359 Flags: [ SHF_INFO_LINK ] 1360 Info: .text 1361 )"); 1362 1363 auto DoCheck = [&](StringRef YamlString) { 1364 SmallString<0> Storage; 1365 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1366 toBinary<ELF64LE>(Storage, YamlString); 1367 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1368 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 1369 1370 bool FoundRela; 1371 1372 for (SectionRef Sec : Obj.sections()) { 1373 Expected<StringRef> SecNameOrErr = Sec.getName(); 1374 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 1375 StringRef SecName = *SecNameOrErr; 1376 if (SecName != ".rela.text") 1377 continue; 1378 FoundRela = true; 1379 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 1380 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 1381 section_iterator RelSec = *RelSecOrErr; 1382 ASSERT_NE(RelSec, Obj.section_end()); 1383 Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 1384 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 1385 StringRef TextSecName = *TextSecNameOrErr; 1386 EXPECT_EQ(TextSecName, ".text"); 1387 } 1388 ASSERT_TRUE(FoundRela); 1389 }; 1390 1391 // Check ET_EXEC file (`ld --emit-relocs` use-case). 1392 SmallString<128> ExecFileYamlString(HeaderString); 1393 ExecFileYamlString += R"( 1394 Type: ET_EXEC 1395 )"; 1396 ExecFileYamlString += ContentsString; 1397 DoCheck(ExecFileYamlString); 1398 1399 // Check ET_REL file. 1400 SmallString<128> RelocatableFileYamlString(HeaderString); 1401 RelocatableFileYamlString += R"( 1402 Type: ET_REL 1403 )"; 1404 RelocatableFileYamlString += ContentsString; 1405 DoCheck(RelocatableFileYamlString); 1406 } 1407 1408 TEST(ELFObjectFileTest, GetSectionAndRelocations) { 1409 StringRef HeaderString(R"( 1410 --- !ELF 1411 FileHeader: 1412 Class: ELFCLASS64 1413 Data: ELFDATA2LSB 1414 Type: ET_EXEC 1415 )"); 1416 1417 using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>; 1418 1419 auto DoCheckSucceeds = [&](StringRef ContentsString, 1420 std::function<Expected<bool>(const Elf_Shdr &)> 1421 Matcher) { 1422 SmallString<0> Storage; 1423 SmallString<128> FullYamlString(HeaderString); 1424 FullYamlString += ContentsString; 1425 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1426 toBinary<ELF64LE>(Storage, FullYamlString); 1427 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1428 1429 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 1430 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 1431 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded()); 1432 1433 // Basic verification to make sure we have the correct section types. 1434 for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) { 1435 ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS); 1436 ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA); 1437 } 1438 }; 1439 1440 auto DoCheckFails = [&](StringRef ContentsString, 1441 std::function<Expected<bool>(const Elf_Shdr &)> 1442 Matcher, 1443 const char *ErrorMessage) { 1444 SmallString<0> Storage; 1445 SmallString<128> FullYamlString(HeaderString); 1446 FullYamlString += ContentsString; 1447 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1448 toBinary<ELF64LE>(Storage, FullYamlString); 1449 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1450 1451 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 1452 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 1453 ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(), 1454 FailedWithMessage(ErrorMessage)); 1455 }; 1456 1457 auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool { 1458 return Sec.sh_type == ELF::SHT_PROGBITS; 1459 }; 1460 1461 StringRef TwoTextSections = R"( 1462 Sections: 1463 - Name: .text 1464 Type: SHT_PROGBITS 1465 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1466 - Name: .rela.text 1467 Type: SHT_RELA 1468 Flags: [ SHF_INFO_LINK ] 1469 Info: .text 1470 - Name: .text2 1471 Type: SHT_PROGBITS 1472 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1473 - Name: .rela.text2 1474 Type: SHT_RELA 1475 Flags: [ SHF_INFO_LINK ] 1476 Info: .text2 1477 )"; 1478 DoCheckSucceeds(TwoTextSections, DefaultMatcher); 1479 1480 StringRef OneTextSection = R"( 1481 Sections: 1482 - Name: .text 1483 Type: SHT_PROGBITS 1484 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1485 )"; 1486 1487 auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> { 1488 if (Sec.sh_type == ELF::SHT_PROGBITS) 1489 return createError("This was supposed to fail."); 1490 return false; 1491 }; 1492 1493 DoCheckFails(OneTextSection, ErroringMatcher, "This was supposed to fail."); 1494 1495 StringRef MissingRelocatableContent = R"( 1496 Sections: 1497 - Name: .rela.text 1498 Type: SHT_RELA 1499 Flags: [ SHF_INFO_LINK ] 1500 Info: 0xFF 1501 )"; 1502 1503 DoCheckFails(MissingRelocatableContent, DefaultMatcher, 1504 "SHT_RELA section with index 1: failed to get a " 1505 "relocated section: invalid section index: 255"); 1506 } 1507 1508 TEST(ELFObjectFileTest, ELFSymbolRefLess) { 1509 SmallString<0> Storage; 1510 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 1511 --- !ELF 1512 FileHeader: 1513 Class: ELFCLASS64 1514 Data: ELFDATA2LSB 1515 Type: ET_DYN 1516 Machine: EM_X86_64 1517 )"); 1518 1519 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1520 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 1521 1522 const uint32_t ValLow = 0x00000001; 1523 const uint32_t ValHigh = 0x00000100; 1524 1525 auto MakeSymbol = [&Obj](size_t SymtabIndex, size_t SymbolIndex) { 1526 DataRefImpl Data; 1527 Data.d.a = SymtabIndex; 1528 Data.d.b = SymbolIndex; 1529 SymbolRef Sym(Data, &Obj); 1530 return ELFSymbolRef(Sym); 1531 }; 1532 1533 ELFSymbolRef ELFSymLowLow = MakeSymbol(ValLow, ValLow); 1534 ELFSymbolRef ELFSymLowHigh = MakeSymbol(ValLow, ValHigh); 1535 ELFSymbolRef ELFSymHighLow = MakeSymbol(ValHigh, ValLow); 1536 ELFSymbolRef ELFSymHighHigh = MakeSymbol(ValHigh, ValHigh); 1537 1538 EXPECT_TRUE(ELFSymLowLow < ELFSymLowHigh); 1539 EXPECT_FALSE(ELFSymLowHigh < ELFSymLowLow); 1540 EXPECT_FALSE(ELFSymLowLow < ELFSymLowLow); 1541 1542 EXPECT_TRUE(ELFSymLowLow < ELFSymHighHigh); 1543 EXPECT_TRUE(ELFSymLowHigh < ELFSymHighLow); 1544 EXPECT_TRUE(ELFSymLowLow < ELFSymHighLow); 1545 1546 EXPECT_FALSE(ELFSymHighLow < ELFSymLowHigh); 1547 EXPECT_FALSE(ELFSymHighHigh < ELFSymLowLow); 1548 EXPECT_FALSE(ELFSymHighLow < ELFSymLowLow); 1549 } 1550