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