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/Support/MemoryBuffer.h" 11 #include "llvm/ObjectYAML/yaml2obj.h" 12 #include "llvm/Support/YAMLTraits.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "gtest/gtest.h" 15 16 using namespace llvm; 17 using namespace llvm::object; 18 19 namespace { 20 21 // A struct to initialize a buffer to represent an ELF object file. 22 struct DataForTest { 23 std::vector<uint8_t> Data; 24 25 template <typename T> 26 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding, 27 uint16_t Machine) { 28 T Ehdr{}; // Zero-initialise the header. 29 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f; 30 Ehdr.e_ident[ELF::EI_MAG1] = 'E'; 31 Ehdr.e_ident[ELF::EI_MAG2] = 'L'; 32 Ehdr.e_ident[ELF::EI_MAG3] = 'F'; 33 Ehdr.e_ident[ELF::EI_CLASS] = Class; 34 Ehdr.e_ident[ELF::EI_DATA] = Encoding; 35 Ehdr.e_ident[ELF::EI_VERSION] = 1; 36 Ehdr.e_type = ELF::ET_REL; 37 Ehdr.e_machine = Machine; 38 Ehdr.e_version = 1; 39 Ehdr.e_ehsize = sizeof(T); 40 41 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB; 42 if (sys::IsLittleEndianHost != IsLittleEndian) { 43 sys::swapByteOrder(Ehdr.e_type); 44 sys::swapByteOrder(Ehdr.e_machine); 45 sys::swapByteOrder(Ehdr.e_version); 46 sys::swapByteOrder(Ehdr.e_ehsize); 47 } 48 49 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr); 50 std::vector<uint8_t> Bytes; 51 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes)); 52 return Bytes; 53 } 54 55 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) { 56 if (Class == ELF::ELFCLASS64) 57 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine); 58 else { 59 assert(Class == ELF::ELFCLASS32); 60 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine); 61 } 62 } 63 }; 64 65 void checkFormatAndArch(const DataForTest &D, StringRef Fmt, 66 Triple::ArchType Arch) { 67 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr = 68 object::ObjectFile::createELFObjectFile( 69 MemoryBufferRef(toStringRef(D.Data), "dummyELF")); 70 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded()); 71 72 const ObjectFile &File = *(*ELFObjOrErr).get(); 73 EXPECT_EQ(Fmt, File.getFileFormatName()); 74 EXPECT_EQ(Arch, File.getArch()); 75 } 76 77 std::array<DataForTest, 4> generateData(uint16_t Machine) { 78 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine), 79 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine), 80 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine), 81 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)}; 82 } 83 84 } // namespace 85 86 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) { 87 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 88 "elf64-unknown", "elf64-unknown"}; 89 size_t I = 0; 90 for (const DataForTest &D : generateData(ELF::EM_NONE)) 91 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 92 93 // Test an arbitrary unused EM_* value (255). 94 I = 0; 95 for (const DataForTest &D : generateData(255)) 96 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 97 } 98 99 TEST(ELFObjectFileTest, MachineTestForVE) { 100 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 101 "elf64-ve", "elf64-ve"}; 102 size_t I = 0; 103 for (const DataForTest &D : generateData(ELF::EM_VE)) 104 checkFormatAndArch(D, Formats[I++], Triple::ve); 105 } 106 107 TEST(ELFObjectFileTest, MachineTestForX86_64) { 108 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64", 109 "elf64-x86-64", "elf64-x86-64"}; 110 size_t I = 0; 111 for (const DataForTest &D : generateData(ELF::EM_X86_64)) 112 checkFormatAndArch(D, Formats[I++], Triple::x86_64); 113 } 114 115 TEST(ELFObjectFileTest, MachineTestFor386) { 116 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386", 117 "elf64-i386"}; 118 size_t I = 0; 119 for (const DataForTest &D : generateData(ELF::EM_386)) 120 checkFormatAndArch(D, Formats[I++], Triple::x86); 121 } 122 123 TEST(ELFObjectFileTest, MachineTestForMIPS) { 124 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips", 125 "elf64-mips"}; 126 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips, 127 Triple::mips64el, Triple::mips64}; 128 size_t I = 0; 129 for (const DataForTest &D : generateData(ELF::EM_MIPS)) { 130 checkFormatAndArch(D, Formats[I], Archs[I]); 131 ++I; 132 } 133 } 134 135 TEST(ELFObjectFileTest, MachineTestForAMDGPU) { 136 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu", 137 "elf64-amdgpu", "elf64-amdgpu"}; 138 size_t I = 0; 139 for (const DataForTest &D : generateData(ELF::EM_AMDGPU)) 140 checkFormatAndArch(D, Formats[I++], Triple::UnknownArch); 141 } 142 143 TEST(ELFObjectFileTest, MachineTestForIAMCU) { 144 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu", 145 "elf64-unknown", "elf64-unknown"}; 146 size_t I = 0; 147 for (const DataForTest &D : generateData(ELF::EM_IAMCU)) 148 checkFormatAndArch(D, Formats[I++], Triple::x86); 149 } 150 151 TEST(ELFObjectFileTest, MachineTestForAARCH64) { 152 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 153 "elf64-littleaarch64", 154 "elf64-bigaarch64"}; 155 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be, 156 Triple::aarch64, Triple::aarch64_be}; 157 size_t I = 0; 158 for (const DataForTest &D : generateData(ELF::EM_AARCH64)) { 159 checkFormatAndArch(D, Formats[I], Archs[I]); 160 ++I; 161 } 162 } 163 164 TEST(ELFObjectFileTest, MachineTestForPPC64) { 165 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 166 "elf64-powerpcle", "elf64-powerpc"}; 167 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64, 168 Triple::ppc64le, Triple::ppc64}; 169 size_t I = 0; 170 for (const DataForTest &D : generateData(ELF::EM_PPC64)) { 171 checkFormatAndArch(D, Formats[I], Archs[I]); 172 ++I; 173 } 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 size_t I = 0; 182 for (const DataForTest &D : generateData(ELF::EM_PPC)) { 183 checkFormatAndArch(D, Formats[I], Archs[I]); 184 ++I; 185 } 186 } 187 188 TEST(ELFObjectFileTest, MachineTestForRISCV) { 189 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", 190 "elf64-littleriscv", "elf64-littleriscv"}; 191 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, 192 Triple::riscv64, Triple::riscv64}; 193 size_t I = 0; 194 for (const DataForTest &D : generateData(ELF::EM_RISCV)) { 195 checkFormatAndArch(D, Formats[I], Archs[I]); 196 ++I; 197 } 198 } 199 200 TEST(ELFObjectFileTest, MachineTestForARM) { 201 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm", 202 "elf64-unknown", "elf64-unknown"}; 203 size_t I = 0; 204 for (const DataForTest &D : generateData(ELF::EM_ARM)) 205 checkFormatAndArch(D, Formats[I++], Triple::arm); 206 } 207 208 TEST(ELFObjectFileTest, MachineTestForS390) { 209 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 210 "elf64-s390", "elf64-s390"}; 211 size_t I = 0; 212 for (const DataForTest &D : generateData(ELF::EM_S390)) 213 checkFormatAndArch(D, Formats[I++], Triple::systemz); 214 } 215 216 TEST(ELFObjectFileTest, MachineTestForSPARCV9) { 217 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 218 "elf64-sparc", "elf64-sparc"}; 219 size_t I = 0; 220 for (const DataForTest &D : generateData(ELF::EM_SPARCV9)) 221 checkFormatAndArch(D, Formats[I++], Triple::sparcv9); 222 } 223 224 TEST(ELFObjectFileTest, MachineTestForSPARC) { 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 size_t I = 0; 230 for (const DataForTest &D : generateData(ELF::EM_SPARC)) { 231 checkFormatAndArch(D, Formats[I], Archs[I]); 232 ++I; 233 } 234 } 235 236 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) { 237 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc", 238 "elf64-unknown", "elf64-unknown"}; 239 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc, 240 Triple::sparcel, Triple::sparc}; 241 size_t I = 0; 242 for (const DataForTest &D : generateData(ELF::EM_SPARC32PLUS)) { 243 checkFormatAndArch(D, Formats[I], Archs[I]); 244 ++I; 245 } 246 } 247 248 TEST(ELFObjectFileTest, MachineTestForBPF) { 249 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown", 250 "elf64-bpf", "elf64-bpf"}; 251 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb, 252 Triple::bpfel, Triple::bpfeb}; 253 size_t I = 0; 254 for (const DataForTest &D : generateData(ELF::EM_BPF)) { 255 checkFormatAndArch(D, Formats[I], Archs[I]); 256 ++I; 257 } 258 } 259 260 TEST(ELFObjectFileTest, MachineTestForAVR) { 261 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown", 262 "elf64-unknown"}; 263 size_t I = 0; 264 for (const DataForTest &D : generateData(ELF::EM_AVR)) 265 checkFormatAndArch(D, Formats[I++], Triple::avr); 266 } 267 268 TEST(ELFObjectFileTest, MachineTestForHEXAGON) { 269 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon", 270 "elf64-unknown", "elf64-unknown"}; 271 size_t I = 0; 272 for (const DataForTest &D : generateData(ELF::EM_HEXAGON)) 273 checkFormatAndArch(D, Formats[I++], Triple::hexagon); 274 } 275 276 TEST(ELFObjectFileTest, MachineTestForLANAI) { 277 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai", 278 "elf64-unknown", "elf64-unknown"}; 279 size_t I = 0; 280 for (const DataForTest &D : generateData(ELF::EM_LANAI)) 281 checkFormatAndArch(D, Formats[I++], Triple::lanai); 282 } 283 284 TEST(ELFObjectFileTest, MachineTestForMSP430) { 285 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430", 286 "elf64-unknown", "elf64-unknown"}; 287 size_t I = 0; 288 for (const DataForTest &D : generateData(ELF::EM_MSP430)) 289 checkFormatAndArch(D, Formats[I++], Triple::msp430); 290 } 291 292 TEST(ELFObjectFileTest, MachineTestForLoongArch) { 293 std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch", 294 "elf64-loongarch", "elf64-loongarch"}; 295 std::array<Triple::ArchType, 4> Archs = { 296 Triple::loongarch32, Triple::loongarch32, Triple::loongarch64, 297 Triple::loongarch64}; 298 size_t I = 0; 299 for (const DataForTest &D : generateData(ELF::EM_LOONGARCH)) { 300 checkFormatAndArch(D, Formats[I], Archs[I]); 301 ++I; 302 } 303 } 304 305 TEST(ELFObjectFileTest, MachineTestForCSKY) { 306 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 307 "elf64-unknown", "elf64-unknown"}; 308 size_t I = 0; 309 for (const DataForTest &D : generateData(ELF::EM_CSKY)) 310 checkFormatAndArch(D, Formats[I++], Triple::csky); 311 } 312 313 // ELF relative relocation type test. 314 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 315 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 316 } 317 318 template <class ELFT> 319 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 320 StringRef Yaml) { 321 raw_svector_ostream OS(Storage); 322 yaml::Input YIn(Yaml); 323 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 324 return createStringError(std::errc::invalid_argument, 325 "unable to convert YAML"); 326 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 327 } 328 329 // Check we are able to create an ELFObjectFile even when the content of the 330 // SHT_SYMTAB_SHNDX section can't be read properly. 331 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 332 SmallString<0> Storage; 333 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 334 --- !ELF 335 FileHeader: 336 Class: ELFCLASS64 337 Data: ELFDATA2LSB 338 Type: ET_REL 339 Sections: 340 - Name: .symtab_shndx 341 Type: SHT_SYMTAB_SHNDX 342 Entries: [ 0 ] 343 ShSize: 0xFFFFFFFF 344 )"); 345 346 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 347 } 348 349 // Test that we are able to create an ELFObjectFile even when loadable segments 350 // are unsorted by virtual address. 351 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 352 353 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 354 SmallString<0> Storage; 355 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 356 --- !ELF 357 FileHeader: 358 Class: ELFCLASS64 359 Data: ELFDATA2LSB 360 Type: ET_EXEC 361 Sections: 362 - Name: .foo 363 Type: SHT_PROGBITS 364 Address: 0x1000 365 Offset: 0x3000 366 ContentArray: [ 0x11 ] 367 - Name: .bar 368 Type: SHT_PROGBITS 369 Address: 0x2000 370 Offset: 0x4000 371 ContentArray: [ 0x99 ] 372 ProgramHeaders: 373 - Type: PT_LOAD 374 VAddr: 0x2000 375 FirstSec: .bar 376 LastSec: .bar 377 - Type: PT_LOAD 378 VAddr: 0x1000 379 FirstSec: .foo 380 LastSec: .foo 381 )"); 382 383 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 384 385 std::string WarnString; 386 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 387 Expected<const uint8_t *> DataOrErr = 388 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 389 EXPECT_TRUE(WarnString.empty()); 390 WarnString = Msg.str(); 391 return Error::success(); 392 }); 393 394 if (!DataOrErr) { 395 ADD_FAILURE() << toString(DataOrErr.takeError()); 396 return nullptr; 397 } 398 399 EXPECT_TRUE(WarnString == 400 "loadable segments are unsorted by virtual address"); 401 WarnString = ""; 402 return *DataOrErr; 403 }; 404 405 const uint8_t *Data = ToMappedAddr(0x1000); 406 ASSERT_TRUE(Data); 407 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 408 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 409 EXPECT_EQ(Data[0], 0x11); 410 411 Data = ToMappedAddr(0x2000); 412 ASSERT_TRUE(Data); 413 Buf = ExpectedFile->getMemoryBufferRef(); 414 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 415 EXPECT_EQ(Data[0], 0x99); 416 } 417 418 // This is a test for API that is related to symbols. 419 // We check that errors are properly reported here. 420 TEST(ELFObjectFileTest, InvalidSymbolTest) { 421 SmallString<0> Storage; 422 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 423 --- !ELF 424 FileHeader: 425 Class: ELFCLASS64 426 Data: ELFDATA2LSB 427 Type: ET_DYN 428 Machine: EM_X86_64 429 Sections: 430 - Name: .symtab 431 Type: SHT_SYMTAB 432 )"); 433 434 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 435 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 436 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 437 438 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 439 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 440 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 441 442 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 443 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 444 445 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 446 // SymbolRef::getName() calls it internally. We can't test it directly, 447 // because it is protected. 448 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 449 FailedWithMessage(ErrMsg)); 450 451 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 452 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 453 FailedWithMessage(ErrMsg)); 454 455 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 456 // SymbolRef::getSection() calls it internally. We can't test it 457 // directly, because it is protected. 458 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 459 FailedWithMessage(ErrMsg)); 460 461 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 462 // SymbolRef::getFlags() calls it internally. We can't test it directly, 463 // because it is protected. 464 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 465 FailedWithMessage(ErrMsg)); 466 467 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 468 // SymbolRef::getType() calls it internally. We can't test it directly, 469 // because it is protected. 470 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 471 FailedWithMessage(ErrMsg)); 472 473 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 474 // SymbolRef::getAddress() calls it internally. We can't test it 475 // directly, because it is protected. 476 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 477 FailedWithMessage(ErrMsg)); 478 479 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 480 // method that generates errors for all cases above. 481 EXPECT_THAT_EXPECTED( 482 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 483 EXPECT_THAT_ERROR( 484 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 485 .takeError(), 486 FailedWithMessage(ErrMsg)); 487 }; 488 489 // We create a symbol with an index that is too large to exist in the symbol 490 // table. 491 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 492 "section (0x18)"); 493 494 // We create a symbol with an index that is too large to exist in the object. 495 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 496 "end of the section (0x18)"); 497 } 498 499 // Tests for error paths of the ELFFile::decodeBBAddrMap API. 500 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) { 501 StringRef CommonYamlString(R"( 502 --- !ELF 503 FileHeader: 504 Class: ELFCLASS64 505 Data: ELFDATA2LSB 506 Type: ET_EXEC 507 Sections: 508 - Type: SHT_LLVM_BB_ADDR_MAP 509 Name: .llvm_bb_addr_map 510 Entries: 511 - Address: 0x11111 512 )"); 513 514 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 515 SmallString<0> Storage; 516 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 517 toBinary<ELF64LE>(Storage, YamlString); 518 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 519 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 520 521 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 522 Elf.getSection(1); 523 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 524 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 525 FailedWithMessage(ErrMsg)); 526 }; 527 528 // Check that we can detect unsupported versions. 529 SmallString<128> UnsupportedVersionYamlString(CommonYamlString); 530 UnsupportedVersionYamlString += R"( 531 Version: 3 532 BBEntries: 533 - AddressOffset: 0x0 534 Size: 0x1 535 Metadata: 0x2 536 )"; 537 538 DoCheck(UnsupportedVersionYamlString, 539 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3"); 540 541 SmallString<128> CommonVersionedYamlString(CommonYamlString); 542 CommonVersionedYamlString += R"( 543 Version: 2 544 BBEntries: 545 - ID: 1 546 AddressOffset: 0x0 547 Size: 0x1 548 Metadata: 0x2 549 )"; 550 551 // Check that we can detect the malformed encoding when the section is 552 // truncated. 553 SmallString<128> TruncatedYamlString(CommonVersionedYamlString); 554 TruncatedYamlString += R"( 555 ShSize: 0xb 556 )"; 557 DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: " 558 "malformed uleb128, extends past end"); 559 560 // Check that we can detect when the encoded BB entry fields exceed the UINT32 561 // limit. 562 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings( 563 3, CommonVersionedYamlString); 564 OverInt32LimitYamlStrings[0] += R"( 565 - ID: 1 566 AddressOffset: 0x100000000 567 Size: 0xFFFFFFFF 568 Metadata: 0xFFFFFFFF 569 )"; 570 571 OverInt32LimitYamlStrings[1] += R"( 572 - ID: 2 573 AddressOffset: 0xFFFFFFFF 574 Size: 0x100000000 575 Metadata: 0xFFFFFFFF 576 )"; 577 578 OverInt32LimitYamlStrings[2] += R"( 579 - ID: 3 580 AddressOffset: 0xFFFFFFFF 581 Size: 0xFFFFFFFF 582 Metadata: 0x100000000 583 )"; 584 585 DoCheck(OverInt32LimitYamlStrings[0], 586 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)"); 587 DoCheck(OverInt32LimitYamlStrings[1], 588 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 589 DoCheck(OverInt32LimitYamlStrings[2], 590 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)"); 591 592 // Check the proper error handling when the section has fields exceeding 593 // UINT32 and is also truncated. This is for checking that we don't generate 594 // unhandled errors. 595 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 596 3, OverInt32LimitYamlStrings[1]); 597 // Truncate before the end of the 5-byte field. 598 OverInt32LimitAndTruncated[0] += R"( 599 ShSize: 0x19 600 )"; 601 // Truncate at the end of the 5-byte field. 602 OverInt32LimitAndTruncated[1] += R"( 603 ShSize: 0x1a 604 )"; 605 // Truncate after the end of the 5-byte field. 606 OverInt32LimitAndTruncated[2] += R"( 607 ShSize: 0x1b 608 )"; 609 610 DoCheck(OverInt32LimitAndTruncated[0], 611 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, " 612 "extends past end"); 613 DoCheck(OverInt32LimitAndTruncated[1], 614 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 615 DoCheck(OverInt32LimitAndTruncated[2], 616 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)"); 617 618 // Check for proper error handling when the 'NumBlocks' field is overridden 619 // with an out-of-range value. 620 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString); 621 OverLimitNumBlocks += R"( 622 NumBlocks: 0x100000000 623 )"; 624 625 DoCheck(OverLimitNumBlocks, 626 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)"); 627 } 628 629 // Test for the ELFObjectFile::readBBAddrMap API. 630 TEST(ELFObjectFileTest, ReadBBAddrMap) { 631 StringRef CommonYamlString(R"( 632 --- !ELF 633 FileHeader: 634 Class: ELFCLASS64 635 Data: ELFDATA2LSB 636 Type: ET_EXEC 637 Sections: 638 - Name: .llvm_bb_addr_map_1 639 Type: SHT_LLVM_BB_ADDR_MAP 640 Link: 1 641 Entries: 642 - Version: 2 643 Address: 0x11111 644 BBEntries: 645 - ID: 1 646 AddressOffset: 0x0 647 Size: 0x1 648 Metadata: 0x2 649 - Name: .llvm_bb_addr_map_2 650 Type: SHT_LLVM_BB_ADDR_MAP 651 Link: 1 652 Entries: 653 - Version: 2 654 Address: 0x22222 655 BBEntries: 656 - ID: 2 657 AddressOffset: 0x0 658 Size: 0x2 659 Metadata: 0x4 660 - Name: .llvm_bb_addr_map_3 661 Type: SHT_LLVM_BB_ADDR_MAP 662 Link: 2 663 Entries: 664 - Version: 1 665 Address: 0x33333 666 BBEntries: 667 - ID: 0 668 AddressOffset: 0x0 669 Size: 0x3 670 Metadata: 0x6 671 - Name: .llvm_bb_addr_map_4 672 Type: SHT_LLVM_BB_ADDR_MAP_V0 673 # Link: 0 (by default, can be overriden) 674 Entries: 675 - Version: 0 676 Address: 0x44444 677 BBEntries: 678 - ID: 0 679 AddressOffset: 0x0 680 Size: 0x4 681 Metadata: 0x8 682 )"); 683 684 BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, 0x2}}}; 685 BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, 0x4}}}; 686 BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, 0x6}}}; 687 BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, 0x8}}}; 688 689 std::vector<BBAddrMap> Section0BBAddrMaps = {E4}; 690 std::vector<BBAddrMap> Section1BBAddrMaps = {E3}; 691 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2}; 692 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4}; 693 694 auto DoCheckSucceeds = [&](StringRef YamlString, 695 std::optional<unsigned> TextSectionIndex, 696 std::vector<BBAddrMap> ExpectedResult) { 697 SmallString<0> Storage; 698 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 699 toBinary<ELF64LE>(Storage, YamlString); 700 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 701 702 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 703 ElfOrErr->getELFFile().getSection(1); 704 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 705 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 706 EXPECT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 707 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 708 }; 709 710 auto DoCheckFails = [&](StringRef YamlString, 711 std::optional<unsigned> TextSectionIndex, 712 const char *ErrMsg) { 713 SmallString<0> Storage; 714 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 715 toBinary<ELF64LE>(Storage, YamlString); 716 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 717 718 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 719 ElfOrErr->getELFFile().getSection(1); 720 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 721 EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 722 FailedWithMessage(ErrMsg)); 723 }; 724 725 // Check that we can retrieve the data in the normal case. 726 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 727 AllBBAddrMaps); 728 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); 729 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps); 730 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps); 731 // Check that when no bb-address-map section is found for a text section, 732 // we return an empty result. 733 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}); 734 735 // Check that we detect when a bb-addr-map section is linked to an invalid 736 // (not present) section. 737 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 738 InvalidLinkedYamlString += R"( 739 Link: 10 740 )"; 741 742 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4, 743 "unable to get the linked-to section for " 744 "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section " 745 "index: 10"); 746 // Linked sections are not checked when we don't target a specific text 747 // section. 748 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 749 AllBBAddrMaps); 750 751 // Check that we can detect when bb-address-map decoding fails. 752 SmallString<128> TruncatedYamlString(CommonYamlString); 753 TruncatedYamlString += R"( 754 ShSize: 0x8 755 )"; 756 757 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 758 "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: " 759 "unable to decode LEB128 at offset 0x00000008: malformed " 760 "uleb128, extends past end"); 761 // Check that we can read the other section's bb-address-maps which are 762 // valid. 763 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2, 764 Section1BBAddrMaps); 765 } 766 767 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 768 // section for executable and relocatable files. 769 TEST(ELFObjectFileTest, ExecutableWithRelocs) { 770 StringRef HeaderString(R"( 771 --- !ELF 772 FileHeader: 773 Class: ELFCLASS64 774 Data: ELFDATA2LSB 775 )"); 776 StringRef ContentsString(R"( 777 Sections: 778 - Name: .text 779 Type: SHT_PROGBITS 780 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 781 - Name: .rela.text 782 Type: SHT_RELA 783 Flags: [ SHF_INFO_LINK ] 784 Info: .text 785 )"); 786 787 auto DoCheck = [&](StringRef YamlString) { 788 SmallString<0> Storage; 789 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 790 toBinary<ELF64LE>(Storage, YamlString); 791 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 792 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 793 794 bool FoundRela; 795 796 for (SectionRef Sec : Obj.sections()) { 797 Expected<StringRef> SecNameOrErr = Sec.getName(); 798 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 799 StringRef SecName = *SecNameOrErr; 800 if (SecName != ".rela.text") 801 continue; 802 FoundRela = true; 803 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 804 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 805 section_iterator RelSec = *RelSecOrErr; 806 ASSERT_NE(RelSec, Obj.section_end()); 807 Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 808 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 809 StringRef TextSecName = *TextSecNameOrErr; 810 EXPECT_EQ(TextSecName, ".text"); 811 } 812 ASSERT_TRUE(FoundRela); 813 }; 814 815 // Check ET_EXEC file (`ld --emit-relocs` use-case). 816 SmallString<128> ExecFileYamlString(HeaderString); 817 ExecFileYamlString += R"( 818 Type: ET_EXEC 819 )"; 820 ExecFileYamlString += ContentsString; 821 DoCheck(ExecFileYamlString); 822 823 // Check ET_REL file. 824 SmallString<128> RelocatableFileYamlString(HeaderString); 825 RelocatableFileYamlString += R"( 826 Type: ET_REL 827 )"; 828 RelocatableFileYamlString += ContentsString; 829 DoCheck(RelocatableFileYamlString); 830 } 831