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: 2 532 BBEntries: 533 - AddressOffset: 0x0 534 Size: 0x1 535 Metadata: 0x2 536 )"; 537 538 DoCheck(UnsupportedVersionYamlString, 539 "unsupported SHT_LLVM_BB_ADDR_MAP version: 2"); 540 541 SmallString<128> CommonVersionedYamlString(CommonYamlString); 542 CommonVersionedYamlString += R"( 543 Version: 1 544 BBEntries: 545 - AddressOffset: 0x0 546 Size: 0x1 547 Metadata: 0x2 548 )"; 549 550 // Check that we can detect the malformed encoding when the section is 551 // truncated. 552 SmallString<128> TruncatedYamlString(CommonVersionedYamlString); 553 TruncatedYamlString += R"( 554 ShSize: 0xa 555 )"; 556 DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000a: " 557 "malformed uleb128, extends past end"); 558 559 // Check that we can detect when the encoded BB entry fields exceed the UINT32 560 // limit. 561 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings( 562 3, CommonVersionedYamlString); 563 OverInt32LimitYamlStrings[0] += R"( 564 - AddressOffset: 0x100000000 565 Size: 0xFFFFFFFF 566 Metadata: 0xFFFFFFFF 567 )"; 568 569 OverInt32LimitYamlStrings[1] += R"( 570 - AddressOffset: 0xFFFFFFFF 571 Size: 0x100000000 572 Metadata: 0xFFFFFFFF 573 )"; 574 575 OverInt32LimitYamlStrings[2] += R"( 576 - AddressOffset: 0xFFFFFFFF 577 Size: 0xFFFFFFFF 578 Metadata: 0x100000000 579 )"; 580 581 DoCheck(OverInt32LimitYamlStrings[0], 582 "ULEB128 value at offset 0xe exceeds UINT32_MAX (0x100000000)"); 583 DoCheck(OverInt32LimitYamlStrings[1], 584 "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); 585 DoCheck(OverInt32LimitYamlStrings[2], 586 "ULEB128 value at offset 0x18 exceeds UINT32_MAX (0x100000000)"); 587 588 // Check the proper error handling when the section has fields exceeding 589 // UINT32 and is also truncated. This is for checking that we don't generate 590 // unhandled errors. 591 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 592 3, OverInt32LimitYamlStrings[1]); 593 // Truncate before the end of the 5-byte field. 594 OverInt32LimitAndTruncated[0] += R"( 595 ShSize: 0x17 596 )"; 597 // Truncate at the end of the 5-byte field. 598 OverInt32LimitAndTruncated[1] += R"( 599 ShSize: 0x18 600 )"; 601 // Truncate after the end of the 5-byte field. 602 OverInt32LimitAndTruncated[2] += R"( 603 ShSize: 0x19 604 )"; 605 606 DoCheck(OverInt32LimitAndTruncated[0], 607 "unable to decode LEB128 at offset 0x00000013: malformed uleb128, " 608 "extends past end"); 609 DoCheck(OverInt32LimitAndTruncated[1], 610 "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); 611 DoCheck(OverInt32LimitAndTruncated[2], 612 "ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)"); 613 614 // Check for proper error handling when the 'NumBlocks' field is overridden 615 // with an out-of-range value. 616 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString); 617 OverLimitNumBlocks += R"( 618 NumBlocks: 0x100000000 619 )"; 620 621 DoCheck(OverLimitNumBlocks, 622 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)"); 623 } 624 625 // Test for the ELFObjectFile::readBBAddrMap API. 626 TEST(ELFObjectFileTest, ReadBBAddrMap) { 627 StringRef CommonYamlString(R"( 628 --- !ELF 629 FileHeader: 630 Class: ELFCLASS64 631 Data: ELFDATA2LSB 632 Type: ET_EXEC 633 Sections: 634 - Name: .llvm_bb_addr_map_1 635 Type: SHT_LLVM_BB_ADDR_MAP 636 Link: 1 637 Entries: 638 - Version: 1 639 Address: 0x11111 640 BBEntries: 641 - AddressOffset: 0x0 642 Size: 0x1 643 Metadata: 0x2 644 - Name: .llvm_bb_addr_map_2 645 Type: SHT_LLVM_BB_ADDR_MAP 646 Link: 1 647 Entries: 648 - Version: 1 649 Address: 0x22222 650 BBEntries: 651 - AddressOffset: 0x0 652 Size: 0x2 653 Metadata: 0x4 654 - Name: .llvm_bb_addr_map 655 Type: SHT_LLVM_BB_ADDR_MAP_V0 656 # Link: 0 (by default) 657 Entries: 658 - Version: 0 659 Address: 0x33333 660 BBEntries: 661 - AddressOffset: 0x0 662 Size: 0x3 663 Metadata: 0x6 664 )"); 665 666 BBAddrMap E1 = {0x11111, {{0x0, 0x1, 0x2}}}; 667 BBAddrMap E2 = {0x22222, {{0x0, 0x2, 0x4}}}; 668 BBAddrMap E3 = {0x33333, {{0x0, 0x3, 0x6}}}; 669 670 std::vector<BBAddrMap> Section0BBAddrMaps = {E3}; 671 std::vector<BBAddrMap> Section1BBAddrMaps = {E1, E2}; 672 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3}; 673 674 auto DoCheckSucceeds = [&](StringRef YamlString, 675 Optional<unsigned> TextSectionIndex, 676 std::vector<BBAddrMap> ExpectedResult) { 677 SmallString<0> Storage; 678 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 679 toBinary<ELF64LE>(Storage, YamlString); 680 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 681 682 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 683 ElfOrErr->getELFFile().getSection(1); 684 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 685 auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex); 686 EXPECT_THAT_EXPECTED(BBAddrMaps, Succeeded()); 687 EXPECT_EQ(*BBAddrMaps, ExpectedResult); 688 }; 689 690 auto DoCheckFails = [&](StringRef YamlString, 691 Optional<unsigned> TextSectionIndex, 692 const char *ErrMsg) { 693 SmallString<0> Storage; 694 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 695 toBinary<ELF64LE>(Storage, YamlString); 696 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 697 698 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 699 ElfOrErr->getELFFile().getSection(1); 700 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 701 EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(), 702 FailedWithMessage(ErrMsg)); 703 }; 704 705 // Check that we can retrieve the data in the normal case. 706 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt, 707 AllBBAddrMaps); 708 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps); 709 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section1BBAddrMaps); 710 // Check that when no bb-address-map section is found for a text section, 711 // we return an empty result. 712 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, {}); 713 714 // Check that we detect when a bb-addr-map section is linked to an invalid 715 // (not present) section. 716 SmallString<128> InvalidLinkedYamlString(CommonYamlString); 717 InvalidLinkedYamlString += R"( 718 Link: 10 719 )"; 720 721 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/1, 722 "unable to get the linked-to section for " 723 "SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: invalid section " 724 "index: 10"); 725 // Linked sections are not checked when we don't target a specific text 726 // section. 727 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt, 728 AllBBAddrMaps); 729 730 // Check that we can detect when bb-address-map decoding fails. 731 SmallString<128> TruncatedYamlString(CommonYamlString); 732 TruncatedYamlString += R"( 733 ShSize: 0x8 734 )"; 735 736 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt, 737 "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: " 738 "unable to decode LEB128 at offset 0x00000008: malformed " 739 "uleb128, extends past end"); 740 // Check that we can read the other section's bb-address-maps which are 741 // valid. 742 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/1, 743 Section1BBAddrMaps); 744 } 745 746 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 747 // section for executable and relocatable files. 748 TEST(ELFObjectFileTest, ExecutableWithRelocs) { 749 StringRef HeaderString(R"( 750 --- !ELF 751 FileHeader: 752 Class: ELFCLASS64 753 Data: ELFDATA2LSB 754 )"); 755 StringRef ContentsString(R"( 756 Sections: 757 - Name: .text 758 Type: SHT_PROGBITS 759 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 760 - Name: .rela.text 761 Type: SHT_RELA 762 Flags: [ SHF_INFO_LINK ] 763 Info: .text 764 )"); 765 766 auto DoCheck = [&](StringRef YamlString) { 767 SmallString<0> Storage; 768 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 769 toBinary<ELF64LE>(Storage, YamlString); 770 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 771 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 772 773 bool FoundRela; 774 775 for (SectionRef Sec : Obj.sections()) { 776 Expected<StringRef> SecNameOrErr = Sec.getName(); 777 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 778 StringRef SecName = *SecNameOrErr; 779 if (SecName != ".rela.text") 780 continue; 781 FoundRela = true; 782 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 783 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 784 section_iterator RelSec = *RelSecOrErr; 785 ASSERT_NE(RelSec, Obj.section_end()); 786 Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 787 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 788 StringRef TextSecName = *TextSecNameOrErr; 789 EXPECT_EQ(TextSecName, ".text"); 790 } 791 ASSERT_TRUE(FoundRela); 792 }; 793 794 // Check ET_EXEC file (`ld --emit-relocs` use-case). 795 SmallString<128> ExecFileYamlString(HeaderString); 796 ExecFileYamlString += R"( 797 Type: ET_EXEC 798 )"; 799 ExecFileYamlString += ContentsString; 800 DoCheck(ExecFileYamlString); 801 802 // Check ET_REL file. 803 SmallString<128> RelocatableFileYamlString(HeaderString); 804 RelocatableFileYamlString += R"( 805 Type: ET_REL 806 )"; 807 RelocatableFileYamlString += ContentsString; 808 DoCheck(RelocatableFileYamlString); 809 } 810