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