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