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 EXPECT_EQ(Triple, ELFObj.makeTriple().getTriple()); 314 } 315 } 316 317 // ELF relative relocation type test. 318 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 319 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 320 } 321 322 template <class ELFT> 323 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 324 StringRef Yaml) { 325 raw_svector_ostream OS(Storage); 326 yaml::Input YIn(Yaml); 327 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 328 return createStringError(std::errc::invalid_argument, 329 "unable to convert YAML"); 330 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 331 } 332 333 // Check we are able to create an ELFObjectFile even when the content of the 334 // SHT_SYMTAB_SHNDX section can't be read properly. 335 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 336 SmallString<0> Storage; 337 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 338 --- !ELF 339 FileHeader: 340 Class: ELFCLASS64 341 Data: ELFDATA2LSB 342 Type: ET_REL 343 Sections: 344 - Name: .symtab_shndx 345 Type: SHT_SYMTAB_SHNDX 346 Entries: [ 0 ] 347 ShSize: 0xFFFFFFFF 348 )"); 349 350 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 351 } 352 353 // Test that we are able to create an ELFObjectFile even when loadable segments 354 // are unsorted by virtual address. 355 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 356 357 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 358 SmallString<0> Storage; 359 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 360 --- !ELF 361 FileHeader: 362 Class: ELFCLASS64 363 Data: ELFDATA2LSB 364 Type: ET_EXEC 365 Sections: 366 - Name: .foo 367 Type: SHT_PROGBITS 368 Address: 0x1000 369 Offset: 0x3000 370 ContentArray: [ 0x11 ] 371 - Name: .bar 372 Type: SHT_PROGBITS 373 Address: 0x2000 374 Offset: 0x4000 375 ContentArray: [ 0x99 ] 376 ProgramHeaders: 377 - Type: PT_LOAD 378 VAddr: 0x2000 379 FirstSec: .bar 380 LastSec: .bar 381 - Type: PT_LOAD 382 VAddr: 0x1000 383 FirstSec: .foo 384 LastSec: .foo 385 )"); 386 387 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 388 389 std::string WarnString; 390 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 391 Expected<const uint8_t *> DataOrErr = 392 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 393 EXPECT_TRUE(WarnString.empty()); 394 WarnString = Msg.str(); 395 return Error::success(); 396 }); 397 398 if (!DataOrErr) { 399 ADD_FAILURE() << toString(DataOrErr.takeError()); 400 return nullptr; 401 } 402 403 EXPECT_TRUE(WarnString == 404 "loadable segments are unsorted by virtual address"); 405 WarnString = ""; 406 return *DataOrErr; 407 }; 408 409 const uint8_t *Data = ToMappedAddr(0x1000); 410 ASSERT_TRUE(Data); 411 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 412 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 413 EXPECT_EQ(Data[0], 0x11); 414 415 Data = ToMappedAddr(0x2000); 416 ASSERT_TRUE(Data); 417 Buf = ExpectedFile->getMemoryBufferRef(); 418 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 419 EXPECT_EQ(Data[0], 0x99); 420 } 421 422 // This is a test for API that is related to symbols. 423 // We check that errors are properly reported here. 424 TEST(ELFObjectFileTest, InvalidSymbolTest) { 425 SmallString<0> Storage; 426 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 427 --- !ELF 428 FileHeader: 429 Class: ELFCLASS64 430 Data: ELFDATA2LSB 431 Type: ET_DYN 432 Machine: EM_X86_64 433 Sections: 434 - Name: .symtab 435 Type: SHT_SYMTAB 436 )"); 437 438 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 439 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 440 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 441 442 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 443 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 444 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 445 446 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 447 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 448 449 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 450 // SymbolRef::getName() calls it internally. We can't test it directly, 451 // because it is protected. 452 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 453 FailedWithMessage(ErrMsg)); 454 455 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 456 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 457 FailedWithMessage(ErrMsg)); 458 459 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 460 // SymbolRef::getSection() calls it internally. We can't test it 461 // directly, because it is protected. 462 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 463 FailedWithMessage(ErrMsg)); 464 465 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 466 // SymbolRef::getFlags() calls it internally. We can't test it directly, 467 // because it is protected. 468 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 469 FailedWithMessage(ErrMsg)); 470 471 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 472 // SymbolRef::getType() calls it internally. We can't test it directly, 473 // because it is protected. 474 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 475 FailedWithMessage(ErrMsg)); 476 477 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 478 // SymbolRef::getAddress() calls it internally. We can't test it 479 // directly, because it is protected. 480 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 481 FailedWithMessage(ErrMsg)); 482 483 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 484 // method that generates errors for all cases above. 485 EXPECT_THAT_EXPECTED( 486 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 487 EXPECT_THAT_ERROR( 488 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 489 .takeError(), 490 FailedWithMessage(ErrMsg)); 491 }; 492 493 // We create a symbol with an index that is too large to exist in the symbol 494 // table. 495 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 496 "section (0x18)"); 497 498 // We create a symbol with an index that is too large to exist in the object. 499 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 500 "end of the section (0x18)"); 501 } 502 503 // Tests for error paths of the ELFFile::decodeBBAddrMap API. 504 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { 505 if (IsHostWindows()) 506 GTEST_SKIP(); 507 StringRef CommonYamlString(R"( 508 --- !ELF 509 FileHeader: 510 Class: ELFCLASS64 511 Data: ELFDATA2LSB 512 Type: ET_EXEC 513 Sections: 514 - Type: SHT_LLVM_BB_ADDR_MAP 515 Name: .llvm_bb_addr_map 516 Entries: 517 - Address: 0x11111 518 )"); 519 520 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 521 SmallString<0> Storage; 522 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 523 toBinary<ELF64LE>(Storage, YamlString); 524 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 525 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 526 527 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 528 Elf.getSection(1); 529 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 530 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 531 FailedWithMessage(ErrMsg)); 532 }; 533 534 // Check that we can detect unsupported versions. 535 SmallString<128> UnsupportedVersionYamlString(CommonYamlString); 536 UnsupportedVersionYamlString += R"( 537 Version: 3 538 BBEntries: 539 - AddressOffset: 0x0 540 Size: 0x1 541 Metadata: 0x2 542 )"; 543 544 DoCheck(UnsupportedVersionYamlString, 545 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3"); 546 547 SmallString<128> CommonVersionedYamlString(CommonYamlString); 548 CommonVersionedYamlString += R"( 549 Version: 2 550 BBEntries: 551 - ID: 1 552 AddressOffset: 0x0 553 Size: 0x1 554 Metadata: 0x2 555 )"; 556 557 // Check that we can detect the malformed encoding when the section is 558 // truncated. 559 SmallString<128> TruncatedYamlString(CommonVersionedYamlString); 560 TruncatedYamlString += R"( 561 ShSize: 0xb 562 )"; 563 DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: " 564 "malformed uleb128, extends past end"); 565 566 // Check that we can detect when the encoded BB entry fields exceed the UINT32 567 // limit. 568 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings( 569 3, CommonVersionedYamlString); 570 OverInt32LimitYamlStrings[0] += R"( 571 - ID: 1 572 AddressOffset: 0x100000000 573 Size: 0xFFFFFFFF 574 Metadata: 0xFFFFFFFF 575 )"; 576 577 OverInt32LimitYamlStrings[1] += R"( 578 - ID: 2 579 AddressOffset: 0xFFFFFFFF 580 Size: 0x100000000 581 Metadata: 0xFFFFFFFF 582 )"; 583 584 OverInt32LimitYamlStrings[2] += R"( 585 - ID: 3 586 AddressOffset: 0xFFFFFFFF 587 Size: 0xFFFFFFFF 588 Metadata: 0x100000000 589 )"; 590 591 DoCheck(OverInt32LimitYamlStrings[0], 592 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)"); 593 DoCheck(OverInt32LimitYamlStrings[1], 594 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 595 DoCheck(OverInt32LimitYamlStrings[2], 596 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)"); 597 598 // Check the proper error handling when the section has fields exceeding 599 // UINT32 and is also truncated. This is for checking that we don't generate 600 // unhandled errors. 601 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 602 3, OverInt32LimitYamlStrings[1]); 603 // Truncate before the end of the 5-byte field. 604 OverInt32LimitAndTruncated[0] += R"( 605 ShSize: 0x19 606 )"; 607 // Truncate at the end of the 5-byte field. 608 OverInt32LimitAndTruncated[1] += R"( 609 ShSize: 0x1a 610 )"; 611 // Truncate after the end of the 5-byte field. 612 OverInt32LimitAndTruncated[2] += R"( 613 ShSize: 0x1b 614 )"; 615 616 DoCheck(OverInt32LimitAndTruncated[0], 617 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, " 618 "extends past end"); 619 DoCheck(OverInt32LimitAndTruncated[1], 620 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 621 DoCheck(OverInt32LimitAndTruncated[2], 622 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 623 624 // Check for proper error handling when the 'NumBlocks' field is overridden 625 // with an out-of-range value. 626 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString); 627 OverLimitNumBlocks += R"( 628 NumBlocks: 0x100000000 629 )"; 630 631 DoCheck(OverLimitNumBlocks, 632 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)"); 633 } 634 635 // Test for the ELFObjectFile::readBBAddrMap API. 636 TEST(ELFObjectFileTest, ReadBBAddrMap) { 637 if (IsHostWindows()) 638 GTEST_SKIP(); 639 StringRef CommonYamlString(R"( 640 --- !ELF 641 FileHeader: 642 Class: ELFCLASS64 643 Data: ELFDATA2LSB 644 Type: ET_EXEC 645 Sections: 646 - Name: .llvm_bb_addr_map_1 647 Type: SHT_LLVM_BB_ADDR_MAP 648 Link: 1 649 Entries: 650 - Version: 2 651 Address: 0x11111 652 BBEntries: 653 - ID: 1 654 AddressOffset: 0x0 655 Size: 0x1 656 Metadata: 0x2 657 - Name: .llvm_bb_addr_map_2 658 Type: SHT_LLVM_BB_ADDR_MAP 659 Link: 1 660 Entries: 661 - Version: 2 662 Address: 0x22222 663 BBEntries: 664 - ID: 2 665 AddressOffset: 0x0 666 Size: 0x2 667 Metadata: 0x4 668 - Name: .llvm_bb_addr_map_3 669 Type: SHT_LLVM_BB_ADDR_MAP 670 Link: 2 671 Entries: 672 - Version: 1 673 Address: 0x33333 674 BBEntries: 675 - ID: 0 676 AddressOffset: 0x0 677 Size: 0x3 678 Metadata: 0x6 679 - Name: .llvm_bb_addr_map_4 680 Type: SHT_LLVM_BB_ADDR_MAP_V0 681 # Link: 0 (by default, can be overriden) 682 Entries: 683 - Version: 0 684 Address: 0x44444 685 BBEntries: 686 - ID: 0 687 AddressOffset: 0x0 688 Size: 0x4 689 Metadata: 0x18 690 )"); 691 692 BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}); 693 BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}); 694 BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}); 695 BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}); 696 697 std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; 698 std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 699 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 700 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; 701 702 auto DoCheckSucceeds = [&](StringRef YamlString, 703 std::optional<unsigned> TextSectionIndex, 704 std::vector<BBAddrMap> ExpectedResult) { 705 SmallString<0> Storage; 706 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 707 toBinary<ELF64LE>(Storage, YamlString); 708 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 709 710 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 711 ElfOrErr->getELFFile().getSection(1); 712 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 713 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 714 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 715 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 716 }; 717 718 auto DoCheckFails = [&](StringRef YamlString, 719 std::optional<unsigned> TextSectionIndex, 720 const char *ErrMsg) { 721 SmallString<0> Storage; 722 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 723 toBinary<ELF64LE>(Storage, YamlString); 724 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 725 726 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 727 ElfOrErr->getELFFile().getSection(1); 728 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 729 EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 730 FailedWithMessage(ErrMsg)); 731 }; 732 733 // Check that we can retrieve the data in the normal case. 734 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 735 AllBBAddrMaps); 736 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); 737 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps); 738 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps); 739 // Check that when no bb-address-map section is found for a text section, 740 // we return an empty result. 741 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}); 742 743 // Check that we detect when a bb-addr-map section is linked to an invalid 744 // (not present) section. 745 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 746 InvalidLinkedYamlString += R"( 747 Link: 10 748 )"; 749 750 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4, 751 "unable to get the linked-to section for " 752 "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section " 753 "index: 10"); 754 // Linked sections are not checked when we don't target a specific text 755 // section. 756 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 757 AllBBAddrMaps); 758 759 // Check that we can detect when bb-address-map decoding fails. 760 SmallString<128> TruncatedYamlString(CommonYamlString); 761 TruncatedYamlString += R"( 762 ShSize: 0x8 763 )"; 764 765 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 766 "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: " 767 "unable to decode LEB128 at offset 0x00000008: malformed " 768 "uleb128, extends past end"); 769 // Check that we can read the other section's bb-address-maps which are 770 // valid. 771 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 772 Section1BBAddrMaps); 773 } 774 775 // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap 776 // API. 777 TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) { 778 if (IsHostWindows()) 779 GTEST_SKIP(); 780 StringRef CommonYamlString(R"( 781 --- !ELF 782 FileHeader: 783 Class: ELFCLASS64 784 Data: ELFDATA2LSB 785 Type: ET_EXEC 786 Sections: 787 - Type: SHT_LLVM_BB_ADDR_MAP 788 Name: .llvm_bb_addr_map 789 Entries: 790 - Address: 0x11111 791 )"); 792 793 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 794 SmallString<0> Storage; 795 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 796 toBinary<ELF64LE>(Storage, YamlString); 797 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 798 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 799 800 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 801 Elf.getSection(1); 802 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 803 804 std::vector<PGOAnalysisMap> PGOAnalyses; 805 EXPECT_THAT_ERROR( 806 Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses) 807 .takeError(), 808 FailedWithMessage(ErrMsg)); 809 }; 810 811 // Check that we can detect unsupported versions that are too old. 812 SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString); 813 UnsupportedLowVersionYamlString += R"( 814 Version: 1 815 Feature: 0x4 816 BBEntries: 817 - AddressOffset: 0x0 818 Size: 0x1 819 Metadata: 0x2 820 )"; 821 822 DoCheck(UnsupportedLowVersionYamlString, 823 "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features " 824 "are enabled: version = 1 feature = 4"); 825 826 SmallString<128> CommonVersionedYamlString(CommonYamlString); 827 CommonVersionedYamlString += R"( 828 Version: 2 829 BBEntries: 830 - ID: 1 831 AddressOffset: 0x0 832 Size: 0x1 833 Metadata: 0x2 834 )"; 835 836 // Check that we fail when function entry count is enabled but not provided. 837 SmallString<128> MissingFuncEntryCount(CommonYamlString); 838 MissingFuncEntryCount += R"( 839 Version: 2 840 Feature: 0x01 841 )"; 842 843 DoCheck(MissingFuncEntryCount, 844 "unable to decode LEB128 at offset 0x0000000b: malformed uleb128, " 845 "extends past end"); 846 847 // Check that we fail when basic block frequency is enabled but not provided. 848 SmallString<128> MissingBBFreq(CommonYamlString); 849 MissingBBFreq += R"( 850 Version: 2 851 Feature: 0x02 852 BBEntries: 853 - ID: 1 854 AddressOffset: 0x0 855 Size: 0x1 856 Metadata: 0x2 857 )"; 858 859 DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: " 860 "malformed uleb128, extends past end"); 861 862 // Check that we fail when branch probability is enabled but not provided. 863 SmallString<128> MissingBrProb(CommonYamlString); 864 MissingBrProb += R"( 865 Version: 2 866 Feature: 0x04 867 BBEntries: 868 - ID: 1 869 AddressOffset: 0x0 870 Size: 0x1 871 Metadata: 0x6 872 - ID: 2 873 AddressOffset: 0x1 874 Size: 0x1 875 Metadata: 0x2 876 - ID: 3 877 AddressOffset: 0x2 878 Size: 0x1 879 Metadata: 0x2 880 PGOAnalyses: 881 - PGOBBEntries: 882 - Successors: 883 - ID: 2 884 BrProb: 0x80000000 885 - ID: 3 886 BrProb: 0x80000000 887 - Successors: 888 - ID: 3 889 BrProb: 0xF0000000 890 )"; 891 892 DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: " 893 "malformed uleb128, extends past end"); 894 } 895 896 // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap. 897 TEST(ELFObjectFileTest, ReadPGOAnalysisMap) { 898 if (IsHostWindows()) 899 GTEST_SKIP(); 900 StringRef CommonYamlString(R"( 901 --- !ELF 902 FileHeader: 903 Class: ELFCLASS64 904 Data: ELFDATA2LSB 905 Type: ET_EXEC 906 Sections: 907 - Name: .llvm_bb_addr_map_1 908 Type: SHT_LLVM_BB_ADDR_MAP 909 Link: 1 910 Entries: 911 - Version: 2 912 Address: 0x11111 913 Feature: 0x1 914 BBEntries: 915 - ID: 1 916 AddressOffset: 0x0 917 Size: 0x1 918 Metadata: 0x2 919 PGOAnalyses: 920 - FuncEntryCount: 892 921 - Name: .llvm_bb_addr_map_2 922 Type: SHT_LLVM_BB_ADDR_MAP 923 Link: 1 924 Entries: 925 - Version: 2 926 Address: 0x22222 927 Feature: 0x2 928 BBEntries: 929 - ID: 2 930 AddressOffset: 0x0 931 Size: 0x2 932 Metadata: 0x4 933 PGOAnalyses: 934 - PGOBBEntries: 935 - BBFreq: 343 936 - Name: .llvm_bb_addr_map_3 937 Type: SHT_LLVM_BB_ADDR_MAP 938 Link: 2 939 Entries: 940 - Version: 2 941 Address: 0x33333 942 Feature: 0x4 943 BBEntries: 944 - ID: 0 945 AddressOffset: 0x0 946 Size: 0x3 947 Metadata: 0x6 948 - ID: 1 949 AddressOffset: 0x0 950 Size: 0x3 951 Metadata: 0x4 952 - ID: 2 953 AddressOffset: 0x0 954 Size: 0x3 955 Metadata: 0x0 956 PGOAnalyses: 957 - PGOBBEntries: 958 - Successors: 959 - ID: 1 960 BrProb: 0x11111111 961 - ID: 2 962 BrProb: 0xeeeeeeee 963 - Successors: 964 - ID: 2 965 BrProb: 0xffffffff 966 - Successors: [] 967 - Name: .llvm_bb_addr_map_4 968 Type: SHT_LLVM_BB_ADDR_MAP 969 # Link: 0 (by default, can be overriden) 970 Entries: 971 - Version: 2 972 Address: 0x44444 973 Feature: 0x7 974 BBEntries: 975 - ID: 0 976 AddressOffset: 0x0 977 Size: 0x4 978 Metadata: 0x18 979 - ID: 1 980 AddressOffset: 0x0 981 Size: 0x4 982 Metadata: 0x0 983 - ID: 2 984 AddressOffset: 0x0 985 Size: 0x4 986 Metadata: 0x0 987 - ID: 3 988 AddressOffset: 0x0 989 Size: 0x4 990 Metadata: 0x0 991 PGOAnalyses: 992 - FuncEntryCount: 1000 993 PGOBBEntries: 994 - BBFreq: 1000 995 Successors: 996 - ID: 1 997 BrProb: 0x22222222 998 - ID: 2 999 BrProb: 0x33333333 1000 - ID: 3 1001 BrProb: 0xaaaaaaaa 1002 - BBFreq: 133 1003 Successors: 1004 - ID: 2 1005 BrProb: 0x11111111 1006 - ID: 3 1007 BrProb: 0xeeeeeeee 1008 - BBFreq: 18 1009 Successors: 1010 - ID: 3 1011 BrProb: 0xffffffff 1012 - BBFreq: 1000 1013 Successors: [] 1014 )"); 1015 1016 BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}); 1017 PGOAnalysisMap P1 = {892, {{}}, {true, false, false}}; 1018 BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}); 1019 PGOAnalysisMap P2 = {{}, {{BlockFrequency(343), {}}}, {false, true, false}}; 1020 BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}, 1021 {1, 0x3, 0x3, {false, false, true, false, false}}, 1022 {2, 0x6, 0x3, {false, false, false, false, false}}}); 1023 PGOAnalysisMap P3 = {{}, 1024 {{{}, 1025 {{1, BranchProbability::getRaw(0x1111'1111)}, 1026 {2, BranchProbability::getRaw(0xeeee'eeee)}}}, 1027 {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}}, 1028 {{}, {}}}, 1029 {false, false, true}}; 1030 BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}, 1031 {1, 0x4, 0x4, {false, false, false, false, false}}, 1032 {2, 0x8, 0x4, {false, false, false, false, false}}, 1033 {3, 0xc, 0x4, {false, false, false, false, false}}}); 1034 PGOAnalysisMap P4 = { 1035 1000, 1036 {{BlockFrequency(1000), 1037 {{1, BranchProbability::getRaw(0x2222'2222)}, 1038 {2, BranchProbability::getRaw(0x3333'3333)}, 1039 {3, BranchProbability::getRaw(0xaaaa'aaaa)}}}, 1040 {BlockFrequency(133), 1041 {{2, BranchProbability::getRaw(0x1111'1111)}, 1042 {3, BranchProbability::getRaw(0xeeee'eeee)}}}, 1043 {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}}, 1044 {BlockFrequency(1000), {}}}, 1045 {true, true, true}}; 1046 1047 std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; 1048 std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 1049 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 1050 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; 1051 1052 std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4}; 1053 std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3}; 1054 std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2}; 1055 std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4}; 1056 1057 auto DoCheckSucceeds = 1058 [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex, 1059 std::vector<BBAddrMap> ExpectedResult, 1060 std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) { 1061 SmallString<0> Storage; 1062 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1063 toBinary<ELF64LE>(Storage, YamlString); 1064 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1065 1066 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1067 ElfOrErr->getELFFile().getSection(1); 1068 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1069 1070 std::vector<PGOAnalysisMap> PGOAnalyses; 1071 auto BBAddrMaps = ElfOrErr->readBBAddrMap( 1072 TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr); 1073 ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 1074 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 1075 if (ExpectedPGO) { 1076 EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size()); 1077 EXPECT_EQ(PGOAnalyses, *ExpectedPGO); 1078 } 1079 }; 1080 1081 auto DoCheckFails = [&](StringRef YamlString, 1082 std::optional<unsigned> TextSectionIndex, 1083 const char *ErrMsg) { 1084 SmallString<0> Storage; 1085 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1086 toBinary<ELF64LE>(Storage, YamlString); 1087 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1088 1089 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 1090 ElfOrErr->getELFFile().getSection(1); 1091 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 1092 std::vector<PGOAnalysisMap> PGOAnalyses; 1093 EXPECT_THAT_ERROR( 1094 ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(), 1095 FailedWithMessage(ErrMsg)); 1096 }; 1097 1098 // Check that we can retrieve the data in the normal case. 1099 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1100 AllBBAddrMaps, std::nullopt); 1101 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps, 1102 std::nullopt); 1103 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps, 1104 std::nullopt); 1105 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps, 1106 std::nullopt); 1107 1108 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 1109 AllBBAddrMaps, AllPGOAnalysisMaps); 1110 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps, 1111 Section0PGOAnalysisMaps); 1112 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps, 1113 Section1PGOAnalysisMaps); 1114 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps, 1115 Section2PGOAnalysisMaps); 1116 // Check that when no bb-address-map section is found for a text section, 1117 // we return an empty result. 1118 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt); 1119 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, 1120 std::vector<PGOAnalysisMap>{}); 1121 1122 // Check that we detect when a bb-addr-map section is linked to an invalid 1123 // (not present) section. 1124 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 1125 InvalidLinkedYamlString += R"( 1126 Link: 10 1127 )"; 1128 1129 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4, 1130 "unable to get the linked-to section for " 1131 "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section " 1132 "index: 10"); 1133 // Linked sections are not checked when we don't target a specific text 1134 // section. 1135 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1136 AllBBAddrMaps, std::nullopt); 1137 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 1138 AllBBAddrMaps, AllPGOAnalysisMaps); 1139 1140 // Check that we can detect when bb-address-map decoding fails. 1141 SmallString<128> TruncatedYamlString(CommonYamlString); 1142 TruncatedYamlString += R"( 1143 ShSize: 0xa 1144 )"; 1145 1146 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 1147 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: " 1148 "unable to decode LEB128 at offset 0x0000000a: malformed " 1149 "uleb128, extends past end"); 1150 // Check that we can read the other section's bb-address-maps which are 1151 // valid. 1152 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1153 Section1BBAddrMaps, std::nullopt); 1154 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 1155 Section1BBAddrMaps, Section1PGOAnalysisMaps); 1156 } 1157 1158 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 1159 // section for executable and relocatable files. 1160 TEST(ELFObjectFileTest, ExecutableWithRelocs) { 1161 StringRef HeaderString(R"( 1162 --- !ELF 1163 FileHeader: 1164 Class: ELFCLASS64 1165 Data: ELFDATA2LSB 1166 )"); 1167 StringRef ContentsString(R"( 1168 Sections: 1169 - Name: .text 1170 Type: SHT_PROGBITS 1171 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1172 - Name: .rela.text 1173 Type: SHT_RELA 1174 Flags: [ SHF_INFO_LINK ] 1175 Info: .text 1176 )"); 1177 1178 auto DoCheck = [&](StringRef YamlString) { 1179 SmallString<0> Storage; 1180 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1181 toBinary<ELF64LE>(Storage, YamlString); 1182 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1183 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 1184 1185 bool FoundRela; 1186 1187 for (SectionRef Sec : Obj.sections()) { 1188 Expected<StringRef> SecNameOrErr = Sec.getName(); 1189 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 1190 StringRef SecName = *SecNameOrErr; 1191 if (SecName != ".rela.text") 1192 continue; 1193 FoundRela = true; 1194 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 1195 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 1196 section_iterator RelSec = *RelSecOrErr; 1197 ASSERT_NE(RelSec, Obj.section_end()); 1198 Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 1199 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 1200 StringRef TextSecName = *TextSecNameOrErr; 1201 EXPECT_EQ(TextSecName, ".text"); 1202 } 1203 ASSERT_TRUE(FoundRela); 1204 }; 1205 1206 // Check ET_EXEC file (`ld --emit-relocs` use-case). 1207 SmallString<128> ExecFileYamlString(HeaderString); 1208 ExecFileYamlString += R"( 1209 Type: ET_EXEC 1210 )"; 1211 ExecFileYamlString += ContentsString; 1212 DoCheck(ExecFileYamlString); 1213 1214 // Check ET_REL file. 1215 SmallString<128> RelocatableFileYamlString(HeaderString); 1216 RelocatableFileYamlString += R"( 1217 Type: ET_REL 1218 )"; 1219 RelocatableFileYamlString += ContentsString; 1220 DoCheck(RelocatableFileYamlString); 1221 } 1222 1223 TEST(ELFObjectFileTest, GetSectionAndRelocations) { 1224 StringRef HeaderString(R"( 1225 --- !ELF 1226 FileHeader: 1227 Class: ELFCLASS64 1228 Data: ELFDATA2LSB 1229 Type: ET_EXEC 1230 )"); 1231 1232 using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>; 1233 1234 auto DoCheckSucceeds = [&](StringRef ContentsString, 1235 std::function<Expected<bool>(const Elf_Shdr &)> 1236 Matcher) { 1237 SmallString<0> Storage; 1238 SmallString<128> FullYamlString(HeaderString); 1239 FullYamlString += ContentsString; 1240 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1241 toBinary<ELF64LE>(Storage, FullYamlString); 1242 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1243 1244 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 1245 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 1246 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded()); 1247 1248 // Basic verification to make sure we have the correct section types. 1249 for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) { 1250 ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS); 1251 ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA); 1252 } 1253 }; 1254 1255 auto DoCheckFails = [&](StringRef ContentsString, 1256 std::function<Expected<bool>(const Elf_Shdr &)> 1257 Matcher, 1258 const char *ErrorMessage) { 1259 SmallString<0> Storage; 1260 SmallString<128> FullYamlString(HeaderString); 1261 FullYamlString += ContentsString; 1262 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 1263 toBinary<ELF64LE>(Storage, FullYamlString); 1264 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 1265 1266 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr = 1267 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher); 1268 ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(), 1269 FailedWithMessage(ErrorMessage)); 1270 }; 1271 1272 auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool { 1273 return Sec.sh_type == ELF::SHT_PROGBITS; 1274 }; 1275 1276 StringRef TwoTextSections = R"( 1277 Sections: 1278 - Name: .text 1279 Type: SHT_PROGBITS 1280 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1281 - Name: .rela.text 1282 Type: SHT_RELA 1283 Flags: [ SHF_INFO_LINK ] 1284 Info: .text 1285 - Name: .text2 1286 Type: SHT_PROGBITS 1287 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1288 - Name: .rela.text2 1289 Type: SHT_RELA 1290 Flags: [ SHF_INFO_LINK ] 1291 Info: .text2 1292 )"; 1293 DoCheckSucceeds(TwoTextSections, DefaultMatcher); 1294 1295 StringRef OneTextSection = R"( 1296 Sections: 1297 - Name: .text 1298 Type: SHT_PROGBITS 1299 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 1300 )"; 1301 1302 auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> { 1303 if (Sec.sh_type == ELF::SHT_PROGBITS) 1304 return createError("This was supposed to fail."); 1305 return false; 1306 }; 1307 1308 DoCheckFails(OneTextSection, ErroringMatcher, "This was supposed to fail."); 1309 1310 StringRef MissingRelocatableContent = R"( 1311 Sections: 1312 - Name: .rela.text 1313 Type: SHT_RELA 1314 Flags: [ SHF_INFO_LINK ] 1315 Info: 0xFF 1316 )"; 1317 1318 DoCheckFails(MissingRelocatableContent, DefaultMatcher, 1319 "SHT_RELA section with index 1: failed to get a " 1320 "relocated section: invalid section index: 255"); 1321 } 1322