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, MachineTestForCSKY) { 293 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky", 294 "elf64-unknown", "elf64-unknown"}; 295 size_t I = 0; 296 for (const DataForTest &D : generateData(ELF::EM_CSKY)) 297 checkFormatAndArch(D, Formats[I++], Triple::csky); 298 } 299 300 // ELF relative relocation type test. 301 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) { 302 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY)); 303 } 304 305 template <class ELFT> 306 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage, 307 StringRef Yaml) { 308 raw_svector_ostream OS(Storage); 309 yaml::Input YIn(Yaml); 310 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {})) 311 return createStringError(std::errc::invalid_argument, 312 "unable to convert YAML"); 313 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF")); 314 } 315 316 // Check we are able to create an ELFObjectFile even when the content of the 317 // SHT_SYMTAB_SHNDX section can't be read properly. 318 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) { 319 SmallString<0> Storage; 320 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 321 --- !ELF 322 FileHeader: 323 Class: ELFCLASS64 324 Data: ELFDATA2LSB 325 Type: ET_REL 326 Sections: 327 - Name: .symtab_shndx 328 Type: SHT_SYMTAB_SHNDX 329 Entries: [ 0 ] 330 ShSize: 0xFFFFFFFF 331 )"); 332 333 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 334 } 335 336 // Test that we are able to create an ELFObjectFile even when loadable segments 337 // are unsorted by virtual address. 338 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case. 339 340 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { 341 SmallString<0> Storage; 342 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( 343 --- !ELF 344 FileHeader: 345 Class: ELFCLASS64 346 Data: ELFDATA2LSB 347 Type: ET_EXEC 348 Sections: 349 - Name: .foo 350 Type: SHT_PROGBITS 351 Address: 0x1000 352 Offset: 0x3000 353 ContentArray: [ 0x11 ] 354 - Name: .bar 355 Type: SHT_PROGBITS 356 Address: 0x2000 357 Offset: 0x4000 358 ContentArray: [ 0x99 ] 359 ProgramHeaders: 360 - Type: PT_LOAD 361 VAddr: 0x2000 362 FirstSec: .bar 363 LastSec: .bar 364 - Type: PT_LOAD 365 VAddr: 0x1000 366 FirstSec: .foo 367 LastSec: .foo 368 )"); 369 370 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); 371 372 std::string WarnString; 373 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { 374 Expected<const uint8_t *> DataOrErr = 375 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { 376 EXPECT_TRUE(WarnString.empty()); 377 WarnString = Msg.str(); 378 return Error::success(); 379 }); 380 381 if (!DataOrErr) { 382 ADD_FAILURE() << toString(DataOrErr.takeError()); 383 return nullptr; 384 } 385 386 EXPECT_TRUE(WarnString == 387 "loadable segments are unsorted by virtual address"); 388 WarnString = ""; 389 return *DataOrErr; 390 }; 391 392 const uint8_t *Data = ToMappedAddr(0x1000); 393 ASSERT_TRUE(Data); 394 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); 395 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); 396 EXPECT_EQ(Data[0], 0x11); 397 398 Data = ToMappedAddr(0x2000); 399 ASSERT_TRUE(Data); 400 Buf = ExpectedFile->getMemoryBufferRef(); 401 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); 402 EXPECT_EQ(Data[0], 0x99); 403 } 404 405 // This is a test for API that is related to symbols. 406 // We check that errors are properly reported here. 407 TEST(ELFObjectFileTest, InvalidSymbolTest) { 408 SmallString<0> Storage; 409 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( 410 --- !ELF 411 FileHeader: 412 Class: ELFCLASS64 413 Data: ELFDATA2LSB 414 Type: ET_DYN 415 Machine: EM_X86_64 416 Sections: 417 - Name: .symtab 418 Type: SHT_SYMTAB 419 )"); 420 421 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 422 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 423 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 424 425 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); 426 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); 427 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); 428 429 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) { 430 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); 431 432 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). 433 // SymbolRef::getName() calls it internally. We can't test it directly, 434 // because it is protected. 435 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), 436 FailedWithMessage(ErrMsg)); 437 438 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). 439 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), 440 FailedWithMessage(ErrMsg)); 441 442 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). 443 // SymbolRef::getSection() calls it internally. We can't test it 444 // directly, because it is protected. 445 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), 446 FailedWithMessage(ErrMsg)); 447 448 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). 449 // SymbolRef::getFlags() calls it internally. We can't test it directly, 450 // because it is protected. 451 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), 452 FailedWithMessage(ErrMsg)); 453 454 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). 455 // SymbolRef::getType() calls it internally. We can't test it directly, 456 // because it is protected. 457 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), 458 FailedWithMessage(ErrMsg)); 459 460 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). 461 // SymbolRef::getAddress() calls it internally. We can't test it 462 // directly, because it is protected. 463 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), 464 FailedWithMessage(ErrMsg)); 465 466 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying 467 // method that generates errors for all cases above. 468 EXPECT_THAT_EXPECTED( 469 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded()); 470 EXPECT_THAT_ERROR( 471 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) 472 .takeError(), 473 FailedWithMessage(ErrMsg)); 474 }; 475 476 // We create a symbol with an index that is too large to exist in the symbol 477 // table. 478 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the " 479 "section (0x18)"); 480 481 // We create a symbol with an index that is too large to exist in the object. 482 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the " 483 "end of the section (0x18)"); 484 } 485 486 // Tests for error paths of the ELFFile::decodeBBAddrMap API. 487 TEST(ELFObjectFileTest, InvalidBBAddrMap) { 488 StringRef CommonYamlString(R"( 489 --- !ELF 490 FileHeader: 491 Class: ELFCLASS64 492 Data: ELFDATA2LSB 493 Type: ET_EXEC 494 Sections: 495 - Name: .llvm_bb_addr_map 496 Type: SHT_LLVM_BB_ADDR_MAP 497 Entries: 498 - Address: 0x11111 499 BBEntries: 500 - AddressOffset: 0x0 501 Size: 0x1 502 Metadata: 0x2 503 )"); 504 505 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) { 506 SmallString<0> Storage; 507 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 508 toBinary<ELF64LE>(Storage, YamlString); 509 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 510 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); 511 512 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr = 513 Elf.getSection(1); 514 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded()); 515 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(), 516 FailedWithMessage(ErrMsg)); 517 }; 518 519 // Check that we can detect the malformed encoding when the section is 520 // truncated. 521 SmallString<128> TruncatedYamlString(CommonYamlString); 522 TruncatedYamlString += R"( 523 ShSize: 0x8 524 )"; 525 DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x00000008: " 526 "malformed uleb128, extends past end"); 527 528 // Check that we can detect when the encoded BB entry fields exceed the UINT32 529 // limit. 530 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(3, 531 CommonYamlString); 532 OverInt32LimitYamlStrings[0] += R"( 533 - AddressOffset: 0x100000000 534 Size: 0xFFFFFFFF 535 Metadata: 0xFFFFFFFF 536 )"; 537 538 OverInt32LimitYamlStrings[1] += R"( 539 - AddressOffset: 0xFFFFFFFF 540 Size: 0x100000000 541 Metadata: 0xFFFFFFFF 542 )"; 543 544 OverInt32LimitYamlStrings[2] += R"( 545 - AddressOffset: 0xFFFFFFFF 546 Size: 0xFFFFFFFF 547 Metadata: 0x100000000 548 )"; 549 550 DoCheck(OverInt32LimitYamlStrings[0], 551 "ULEB128 value at offset 0xc exceeds UINT32_MAX (0x100000000)"); 552 DoCheck(OverInt32LimitYamlStrings[1], 553 "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 554 DoCheck(OverInt32LimitYamlStrings[2], 555 "ULEB128 value at offset 0x16 exceeds UINT32_MAX (0x100000000)"); 556 557 // Check the proper error handling when the section has fields exceeding 558 // UINT32 and is also truncated. This is for checking that we don't generate 559 // unhandled errors. 560 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated( 561 3, OverInt32LimitYamlStrings[1]); 562 // Truncate before the end of the 5-byte field. 563 OverInt32LimitAndTruncated[0] += R"( 564 ShSize: 0x15 565 )"; 566 // Truncate at the end of the 5-byte field. 567 OverInt32LimitAndTruncated[1] += R"( 568 ShSize: 0x16 569 )"; 570 // Truncate after the end of the 5-byte field. 571 OverInt32LimitAndTruncated[2] += R"( 572 ShSize: 0x17 573 )"; 574 575 DoCheck(OverInt32LimitAndTruncated[0], 576 "unable to decode LEB128 at offset 0x00000011: malformed uleb128, " 577 "extends past end"); 578 DoCheck(OverInt32LimitAndTruncated[1], 579 "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 580 DoCheck(OverInt32LimitAndTruncated[2], 581 "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)"); 582 583 // Check for proper error handling when the 'NumBlocks' field is overridden 584 // with an out-of-range value. 585 SmallString<128> OverLimitNumBlocks(CommonYamlString); 586 OverLimitNumBlocks += R"( 587 NumBlocks: 0x100000000 588 )"; 589 590 DoCheck(OverLimitNumBlocks, 591 "ULEB128 value at offset 0x8 exceeds UINT32_MAX (0x100000000)"); 592 } 593 594 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated 595 // section for executable and relocatable files. 596 TEST(ELFObjectFileTest, ExecutableWithRelocs) { 597 StringRef HeaderString(R"( 598 --- !ELF 599 FileHeader: 600 Class: ELFCLASS64 601 Data: ELFDATA2LSB 602 )"); 603 StringRef ContentsString(R"( 604 Sections: 605 - Name: .text 606 Type: SHT_PROGBITS 607 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 608 - Name: .rela.text 609 Type: SHT_RELA 610 Flags: [ SHF_INFO_LINK ] 611 Info: .text 612 )"); 613 614 auto DoCheck = [&](StringRef YamlString) { 615 SmallString<0> Storage; 616 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = 617 toBinary<ELF64LE>(Storage, YamlString); 618 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); 619 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; 620 621 bool FoundRela; 622 623 for (SectionRef Sec : Obj.sections()) { 624 Expected<StringRef> SecNameOrErr = Sec.getName(); 625 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded()); 626 StringRef SecName = *SecNameOrErr; 627 if (SecName != ".rela.text") 628 continue; 629 FoundRela = true; 630 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection(); 631 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded()); 632 section_iterator RelSec = *RelSecOrErr; 633 ASSERT_NE(RelSec, Obj.section_end()); 634 Expected<StringRef> TextSecNameOrErr = RelSec->getName(); 635 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded()); 636 StringRef TextSecName = *TextSecNameOrErr; 637 EXPECT_EQ(TextSecName, ".text"); 638 } 639 ASSERT_TRUE(FoundRela); 640 }; 641 642 // Check ET_EXEC file (`ld --emit-relocs` use-case). 643 SmallString<128> ExecFileYamlString(HeaderString); 644 ExecFileYamlString += R"( 645 Type: ET_EXEC 646 )"; 647 ExecFileYamlString += ContentsString; 648 DoCheck(ExecFileYamlString); 649 650 // Check ET_REL file. 651 SmallString<128> RelocatableFileYamlString(HeaderString); 652 RelocatableFileYamlString += R"( 653 Type: ET_REL 654 )"; 655 RelocatableFileYamlString += ContentsString; 656 DoCheck(RelocatableFileYamlString); 657 } 658