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