Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / Object / ELFObjectFileTest.cpp
blobfe5ce2154dc7444447781c0447c353c250a0ac56
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 //===----------------------------------------------------------------------===//
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"
17 #include "llvm/Support/thread.h"
18 #include "llvm/TargetParser/Host.h"
20 using namespace llvm;
21 using namespace llvm::object;
23 // Used to skip LLVM_BB_ADDR_MAP tests on windows platforms due to
24 // https://github.com/llvm/llvm-project/issues/60013.
25 bool IsHostWindows() {
26 Triple Host(Triple::normalize(sys::getProcessTriple()));
27 return Host.isOSWindows();
30 namespace {
32 // A struct to initialize a buffer to represent an ELF object file.
33 struct DataForTest {
34 std::vector<uint8_t> Data;
36 template <typename T>
37 std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding,
38 uint16_t Machine) {
39 T Ehdr{}; // Zero-initialise the header.
40 Ehdr.e_ident[ELF::EI_MAG0] = 0x7f;
41 Ehdr.e_ident[ELF::EI_MAG1] = 'E';
42 Ehdr.e_ident[ELF::EI_MAG2] = 'L';
43 Ehdr.e_ident[ELF::EI_MAG3] = 'F';
44 Ehdr.e_ident[ELF::EI_CLASS] = Class;
45 Ehdr.e_ident[ELF::EI_DATA] = Encoding;
46 Ehdr.e_ident[ELF::EI_VERSION] = 1;
47 Ehdr.e_type = ELF::ET_REL;
48 Ehdr.e_machine = Machine;
49 Ehdr.e_version = 1;
50 Ehdr.e_ehsize = sizeof(T);
52 bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB;
53 if (sys::IsLittleEndianHost != IsLittleEndian) {
54 sys::swapByteOrder(Ehdr.e_type);
55 sys::swapByteOrder(Ehdr.e_machine);
56 sys::swapByteOrder(Ehdr.e_version);
57 sys::swapByteOrder(Ehdr.e_ehsize);
60 uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr);
61 std::vector<uint8_t> Bytes;
62 std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes));
63 return Bytes;
66 DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) {
67 if (Class == ELF::ELFCLASS64)
68 Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine);
69 else {
70 assert(Class == ELF::ELFCLASS32);
71 Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine);
76 void checkFormatAndArch(const DataForTest &D, StringRef Fmt,
77 Triple::ArchType Arch) {
78 Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr =
79 object::ObjectFile::createELFObjectFile(
80 MemoryBufferRef(toStringRef(D.Data), "dummyELF"));
81 ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());
83 const ObjectFile &File = *(*ELFObjOrErr).get();
84 EXPECT_EQ(Fmt, File.getFileFormatName());
85 EXPECT_EQ(Arch, File.getArch());
88 std::array<DataForTest, 4> generateData(uint16_t Machine) {
89 return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),
90 DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),
91 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),
92 DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};
95 } // namespace
97 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {
98 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
99 "elf64-unknown", "elf64-unknown"};
100 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE)))
101 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
103 // Test an arbitrary unused EM_* value (255).
104 for (auto [Idx, Data] : enumerate(generateData(255)))
105 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
108 TEST(ELFObjectFileTest, MachineTestForVE) {
109 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
110 "elf64-ve", "elf64-ve"};
111 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE)))
112 checkFormatAndArch(Data, Formats[Idx], Triple::ve);
115 TEST(ELFObjectFileTest, MachineTestForX86_64) {
116 std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",
117 "elf64-x86-64", "elf64-x86-64"};
118 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64)))
119 checkFormatAndArch(Data, Formats[Idx], Triple::x86_64);
122 TEST(ELFObjectFileTest, MachineTestFor386) {
123 std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",
124 "elf64-i386"};
125 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386)))
126 checkFormatAndArch(Data, Formats[Idx], Triple::x86);
129 TEST(ELFObjectFileTest, MachineTestForMIPS) {
130 std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",
131 "elf64-mips"};
132 std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,
133 Triple::mips64el, Triple::mips64};
134 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS)))
135 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
138 TEST(ELFObjectFileTest, MachineTestForAMDGPU) {
139 std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",
140 "elf64-amdgpu", "elf64-amdgpu"};
141 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU)))
142 checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
145 TEST(ELFObjectFileTest, MachineTestForIAMCU) {
146 std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",
147 "elf64-unknown", "elf64-unknown"};
148 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU)))
149 checkFormatAndArch(Data, Formats[Idx], Triple::x86);
152 TEST(ELFObjectFileTest, MachineTestForAARCH64) {
153 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
154 "elf64-littleaarch64",
155 "elf64-bigaarch64"};
156 std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,
157 Triple::aarch64, Triple::aarch64_be};
158 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64)))
159 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
162 TEST(ELFObjectFileTest, MachineTestForPPC64) {
163 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
164 "elf64-powerpcle", "elf64-powerpc"};
165 std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,
166 Triple::ppc64le, Triple::ppc64};
167 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64)))
168 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
171 TEST(ELFObjectFileTest, MachineTestForPPC) {
172 std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",
173 "elf64-unknown", "elf64-unknown"};
174 std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,
175 Triple::ppcle, Triple::ppc};
176 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC)))
177 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
180 TEST(ELFObjectFileTest, MachineTestForRISCV) {
181 std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv",
182 "elf64-littleriscv", "elf64-littleriscv"};
183 std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32,
184 Triple::riscv64, Triple::riscv64};
185 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV)))
186 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
189 TEST(ELFObjectFileTest, MachineTestForARM) {
190 std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",
191 "elf64-unknown", "elf64-unknown"};
192 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM)))
193 checkFormatAndArch(Data, Formats[Idx], Triple::arm);
196 TEST(ELFObjectFileTest, MachineTestForS390) {
197 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
198 "elf64-s390", "elf64-s390"};
199 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390)))
200 checkFormatAndArch(Data, Formats[Idx], Triple::systemz);
203 TEST(ELFObjectFileTest, MachineTestForSPARCV9) {
204 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
205 "elf64-sparc", "elf64-sparc"};
206 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9)))
207 checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9);
210 TEST(ELFObjectFileTest, MachineTestForSPARC) {
211 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
212 "elf64-unknown", "elf64-unknown"};
213 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
214 Triple::sparcel, Triple::sparc};
215 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC)))
216 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
219 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {
220 std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
221 "elf64-unknown", "elf64-unknown"};
222 std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
223 Triple::sparcel, Triple::sparc};
224 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS)))
225 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
228 TEST(ELFObjectFileTest, MachineTestForBPF) {
229 std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
230 "elf64-bpf", "elf64-bpf"};
231 std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,
232 Triple::bpfel, Triple::bpfeb};
233 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF)))
234 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
237 TEST(ELFObjectFileTest, MachineTestForAVR) {
238 std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",
239 "elf64-unknown"};
240 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR)))
241 checkFormatAndArch(Data, Formats[Idx], Triple::avr);
244 TEST(ELFObjectFileTest, MachineTestForHEXAGON) {
245 std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",
246 "elf64-unknown", "elf64-unknown"};
247 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON)))
248 checkFormatAndArch(Data, Formats[Idx], Triple::hexagon);
251 TEST(ELFObjectFileTest, MachineTestForLANAI) {
252 std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",
253 "elf64-unknown", "elf64-unknown"};
254 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI)))
255 checkFormatAndArch(Data, Formats[Idx], Triple::lanai);
258 TEST(ELFObjectFileTest, MachineTestForMSP430) {
259 std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",
260 "elf64-unknown", "elf64-unknown"};
261 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430)))
262 checkFormatAndArch(Data, Formats[Idx], Triple::msp430);
265 TEST(ELFObjectFileTest, MachineTestForLoongArch) {
266 std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch",
267 "elf64-loongarch", "elf64-loongarch"};
268 std::array<Triple::ArchType, 4> Archs = {
269 Triple::loongarch32, Triple::loongarch32, Triple::loongarch64,
270 Triple::loongarch64};
271 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH)))
272 checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
275 TEST(ELFObjectFileTest, MachineTestForCSKY) {
276 std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
277 "elf64-unknown", "elf64-unknown"};
278 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY)))
279 checkFormatAndArch(Data, Formats[Idx], Triple::csky);
282 TEST(ELFObjectFileTest, MachineTestForXtensa) {
283 std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa",
284 "elf64-unknown", "elf64-unknown"};
285 for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA)))
286 checkFormatAndArch(Data, Formats[Idx], Triple::xtensa);
289 // ELF relative relocation type test.
290 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
291 EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
294 template <class ELFT>
295 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
296 StringRef Yaml) {
297 raw_svector_ostream OS(Storage);
298 yaml::Input YIn(Yaml);
299 if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
300 return createStringError(std::errc::invalid_argument,
301 "unable to convert YAML");
302 return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
305 // Check we are able to create an ELFObjectFile even when the content of the
306 // SHT_SYMTAB_SHNDX section can't be read properly.
307 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
308 SmallString<0> Storage;
309 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
310 --- !ELF
311 FileHeader:
312 Class: ELFCLASS64
313 Data: ELFDATA2LSB
314 Type: ET_REL
315 Sections:
316 - Name: .symtab_shndx
317 Type: SHT_SYMTAB_SHNDX
318 Entries: [ 0 ]
319 ShSize: 0xFFFFFFFF
320 )");
322 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
325 // Test that we are able to create an ELFObjectFile even when loadable segments
326 // are unsorted by virtual address.
327 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
329 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
330 SmallString<0> Storage;
331 Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
332 --- !ELF
333 FileHeader:
334 Class: ELFCLASS64
335 Data: ELFDATA2LSB
336 Type: ET_EXEC
337 Sections:
338 - Name: .foo
339 Type: SHT_PROGBITS
340 Address: 0x1000
341 Offset: 0x3000
342 ContentArray: [ 0x11 ]
343 - Name: .bar
344 Type: SHT_PROGBITS
345 Address: 0x2000
346 Offset: 0x4000
347 ContentArray: [ 0x99 ]
348 ProgramHeaders:
349 - Type: PT_LOAD
350 VAddr: 0x2000
351 FirstSec: .bar
352 LastSec: .bar
353 - Type: PT_LOAD
354 VAddr: 0x1000
355 FirstSec: .foo
356 LastSec: .foo
357 )");
359 ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
361 std::string WarnString;
362 auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
363 Expected<const uint8_t *> DataOrErr =
364 ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
365 EXPECT_TRUE(WarnString.empty());
366 WarnString = Msg.str();
367 return Error::success();
370 if (!DataOrErr) {
371 ADD_FAILURE() << toString(DataOrErr.takeError());
372 return nullptr;
375 EXPECT_TRUE(WarnString ==
376 "loadable segments are unsorted by virtual address");
377 WarnString = "";
378 return *DataOrErr;
381 const uint8_t *Data = ToMappedAddr(0x1000);
382 ASSERT_TRUE(Data);
383 MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
384 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
385 EXPECT_EQ(Data[0], 0x11);
387 Data = ToMappedAddr(0x2000);
388 ASSERT_TRUE(Data);
389 Buf = ExpectedFile->getMemoryBufferRef();
390 EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
391 EXPECT_EQ(Data[0], 0x99);
394 // This is a test for API that is related to symbols.
395 // We check that errors are properly reported here.
396 TEST(ELFObjectFileTest, InvalidSymbolTest) {
397 SmallString<0> Storage;
398 Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
399 --- !ELF
400 FileHeader:
401 Class: ELFCLASS64
402 Data: ELFDATA2LSB
403 Type: ET_DYN
404 Machine: EM_X86_64
405 Sections:
406 - Name: .symtab
407 Type: SHT_SYMTAB
408 )");
410 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
411 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
412 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
414 Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
415 ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
416 ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
418 auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
419 ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
421 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
422 // SymbolRef::getName() calls it internally. We can't test it directly,
423 // because it is protected.
424 EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
425 FailedWithMessage(ErrMsg));
427 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
428 EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
429 FailedWithMessage(ErrMsg));
431 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
432 // SymbolRef::getSection() calls it internally. We can't test it
433 // directly, because it is protected.
434 EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
435 FailedWithMessage(ErrMsg));
437 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
438 // SymbolRef::getFlags() calls it internally. We can't test it directly,
439 // because it is protected.
440 EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
441 FailedWithMessage(ErrMsg));
443 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
444 // SymbolRef::getType() calls it internally. We can't test it directly,
445 // because it is protected.
446 EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
447 FailedWithMessage(ErrMsg));
449 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
450 // SymbolRef::getAddress() calls it internally. We can't test it
451 // directly, because it is protected.
452 EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
453 FailedWithMessage(ErrMsg));
455 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
456 // method that generates errors for all cases above.
457 EXPECT_THAT_EXPECTED(
458 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
459 EXPECT_THAT_ERROR(
460 Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
461 .takeError(),
462 FailedWithMessage(ErrMsg));
465 // We create a symbol with an index that is too large to exist in the symbol
466 // table.
467 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
468 "section (0x18)");
470 // We create a symbol with an index that is too large to exist in the object.
471 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
472 "end of the section (0x18)");
475 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
476 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
477 if (IsHostWindows())
478 GTEST_SKIP();
479 StringRef CommonYamlString(R"(
480 --- !ELF
481 FileHeader:
482 Class: ELFCLASS64
483 Data: ELFDATA2LSB
484 Type: ET_EXEC
485 Sections:
486 - Type: SHT_LLVM_BB_ADDR_MAP
487 Name: .llvm_bb_addr_map
488 Entries:
489 - Address: 0x11111
490 )");
492 auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
493 SmallString<0> Storage;
494 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
495 toBinary<ELF64LE>(Storage, YamlString);
496 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
497 const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
499 Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
500 Elf.getSection(1);
501 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
502 EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
503 FailedWithMessage(ErrMsg));
506 // Check that we can detect unsupported versions.
507 SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
508 UnsupportedVersionYamlString += R"(
509 Version: 3
510 BBEntries:
511 - AddressOffset: 0x0
512 Size: 0x1
513 Metadata: 0x2
516 DoCheck(UnsupportedVersionYamlString,
517 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
519 SmallString<128> CommonVersionedYamlString(CommonYamlString);
520 CommonVersionedYamlString += R"(
521 Version: 2
522 BBEntries:
523 - ID: 1
524 AddressOffset: 0x0
525 Size: 0x1
526 Metadata: 0x2
529 // Check that we can detect the malformed encoding when the section is
530 // truncated.
531 SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
532 TruncatedYamlString += R"(
533 ShSize: 0xb
535 DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: "
536 "malformed uleb128, extends past end");
538 // Check that we can detect when the encoded BB entry fields exceed the UINT32
539 // limit.
540 SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
541 3, CommonVersionedYamlString);
542 OverInt32LimitYamlStrings[0] += R"(
543 - ID: 1
544 AddressOffset: 0x100000000
545 Size: 0xFFFFFFFF
546 Metadata: 0xFFFFFFFF
549 OverInt32LimitYamlStrings[1] += R"(
550 - ID: 2
551 AddressOffset: 0xFFFFFFFF
552 Size: 0x100000000
553 Metadata: 0xFFFFFFFF
556 OverInt32LimitYamlStrings[2] += R"(
557 - ID: 3
558 AddressOffset: 0xFFFFFFFF
559 Size: 0xFFFFFFFF
560 Metadata: 0x100000000
563 DoCheck(OverInt32LimitYamlStrings[0],
564 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
565 DoCheck(OverInt32LimitYamlStrings[1],
566 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
567 DoCheck(OverInt32LimitYamlStrings[2],
568 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
570 // Check the proper error handling when the section has fields exceeding
571 // UINT32 and is also truncated. This is for checking that we don't generate
572 // unhandled errors.
573 SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
574 3, OverInt32LimitYamlStrings[1]);
575 // Truncate before the end of the 5-byte field.
576 OverInt32LimitAndTruncated[0] += R"(
577 ShSize: 0x19
579 // Truncate at the end of the 5-byte field.
580 OverInt32LimitAndTruncated[1] += R"(
581 ShSize: 0x1a
583 // Truncate after the end of the 5-byte field.
584 OverInt32LimitAndTruncated[2] += R"(
585 ShSize: 0x1b
588 DoCheck(OverInt32LimitAndTruncated[0],
589 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
590 "extends past end");
591 DoCheck(OverInt32LimitAndTruncated[1],
592 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
593 DoCheck(OverInt32LimitAndTruncated[2],
594 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
596 // Check for proper error handling when the 'NumBlocks' field is overridden
597 // with an out-of-range value.
598 SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
599 OverLimitNumBlocks += R"(
600 NumBlocks: 0x100000000
603 DoCheck(OverLimitNumBlocks,
604 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
607 // Test for the ELFObjectFile::readBBAddrMap API.
608 TEST(ELFObjectFileTest, ReadBBAddrMap) {
609 if (IsHostWindows())
610 GTEST_SKIP();
611 StringRef CommonYamlString(R"(
612 --- !ELF
613 FileHeader:
614 Class: ELFCLASS64
615 Data: ELFDATA2LSB
616 Type: ET_EXEC
617 Sections:
618 - Name: .llvm_bb_addr_map_1
619 Type: SHT_LLVM_BB_ADDR_MAP
620 Link: 1
621 Entries:
622 - Version: 2
623 Address: 0x11111
624 BBEntries:
625 - ID: 1
626 AddressOffset: 0x0
627 Size: 0x1
628 Metadata: 0x2
629 - Name: .llvm_bb_addr_map_2
630 Type: SHT_LLVM_BB_ADDR_MAP
631 Link: 1
632 Entries:
633 - Version: 2
634 Address: 0x22222
635 BBEntries:
636 - ID: 2
637 AddressOffset: 0x0
638 Size: 0x2
639 Metadata: 0x4
640 - Name: .llvm_bb_addr_map_3
641 Type: SHT_LLVM_BB_ADDR_MAP
642 Link: 2
643 Entries:
644 - Version: 1
645 Address: 0x33333
646 BBEntries:
647 - ID: 0
648 AddressOffset: 0x0
649 Size: 0x3
650 Metadata: 0x6
651 - Name: .llvm_bb_addr_map_4
652 Type: SHT_LLVM_BB_ADDR_MAP_V0
653 # Link: 0 (by default, can be overriden)
654 Entries:
655 - Version: 0
656 Address: 0x44444
657 BBEntries:
658 - ID: 0
659 AddressOffset: 0x0
660 Size: 0x4
661 Metadata: 0x18
662 )");
664 BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}};
665 BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}};
666 BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}};
667 BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}};
669 std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
670 std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
671 std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
672 std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
674 auto DoCheckSucceeds = [&](StringRef YamlString,
675 std::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());
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);
690 auto DoCheckFails = [&](StringRef YamlString,
691 std::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());
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));
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=*/2, Section1BBAddrMaps);
710 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps);
711 // Check that when no bb-address-map section is found for a text section,
712 // we return an empty result.
713 DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});
715 // Check that we detect when a bb-addr-map section is linked to an invalid
716 // (not present) section.
717 SmallString<128> InvalidLinkedYamlString(CommonYamlString);
718 InvalidLinkedYamlString += R"(
719 Link: 10
722 DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
723 "unable to get the linked-to section for "
724 "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
725 "index: 10");
726 // Linked sections are not checked when we don't target a specific text
727 // section.
728 DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
729 AllBBAddrMaps);
731 // Check that we can detect when bb-address-map decoding fails.
732 SmallString<128> TruncatedYamlString(CommonYamlString);
733 TruncatedYamlString += R"(
734 ShSize: 0x8
737 DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
738 "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
739 "unable to decode LEB128 at offset 0x00000008: malformed "
740 "uleb128, extends past end");
741 // Check that we can read the other section's bb-address-maps which are
742 // valid.
743 DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
744 Section1BBAddrMaps);
747 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
748 // section for executable and relocatable files.
749 TEST(ELFObjectFileTest, ExecutableWithRelocs) {
750 StringRef HeaderString(R"(
751 --- !ELF
752 FileHeader:
753 Class: ELFCLASS64
754 Data: ELFDATA2LSB
755 )");
756 StringRef ContentsString(R"(
757 Sections:
758 - Name: .text
759 Type: SHT_PROGBITS
760 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
761 - Name: .rela.text
762 Type: SHT_RELA
763 Flags: [ SHF_INFO_LINK ]
764 Info: .text
765 )");
767 auto DoCheck = [&](StringRef YamlString) {
768 SmallString<0> Storage;
769 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
770 toBinary<ELF64LE>(Storage, YamlString);
771 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
772 const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
774 bool FoundRela;
776 for (SectionRef Sec : Obj.sections()) {
777 Expected<StringRef> SecNameOrErr = Sec.getName();
778 ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());
779 StringRef SecName = *SecNameOrErr;
780 if (SecName != ".rela.text")
781 continue;
782 FoundRela = true;
783 Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
784 ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());
785 section_iterator RelSec = *RelSecOrErr;
786 ASSERT_NE(RelSec, Obj.section_end());
787 Expected<StringRef> TextSecNameOrErr = RelSec->getName();
788 ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());
789 StringRef TextSecName = *TextSecNameOrErr;
790 EXPECT_EQ(TextSecName, ".text");
792 ASSERT_TRUE(FoundRela);
795 // Check ET_EXEC file (`ld --emit-relocs` use-case).
796 SmallString<128> ExecFileYamlString(HeaderString);
797 ExecFileYamlString += R"(
798 Type: ET_EXEC
800 ExecFileYamlString += ContentsString;
801 DoCheck(ExecFileYamlString);
803 // Check ET_REL file.
804 SmallString<128> RelocatableFileYamlString(HeaderString);
805 RelocatableFileYamlString += R"(
806 Type: ET_REL
808 RelocatableFileYamlString += ContentsString;
809 DoCheck(RelocatableFileYamlString);
812 TEST(ELFObjectFileTest, GetSectionAndRelocations) {
813 StringRef HeaderString(R"(
814 --- !ELF
815 FileHeader:
816 Class: ELFCLASS64
817 Data: ELFDATA2LSB
818 Type: ET_EXEC
819 )");
821 using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>;
823 auto DoCheckSucceeds = [&](StringRef ContentsString,
824 std::function<Expected<bool>(const Elf_Shdr &)>
825 Matcher) {
826 SmallString<0> Storage;
827 SmallString<128> FullYamlString(HeaderString);
828 FullYamlString += ContentsString;
829 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
830 toBinary<ELF64LE>(Storage, FullYamlString);
831 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
833 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
834 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
835 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded());
837 // Basic verification to make sure we have the correct section types.
838 for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) {
839 ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS);
840 ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA);
844 auto DoCheckFails = [&](StringRef ContentsString,
845 std::function<Expected<bool>(const Elf_Shdr &)>
846 Matcher,
847 const char *ErrorMessage) {
848 SmallString<0> Storage;
849 SmallString<128> FullYamlString(HeaderString);
850 FullYamlString += ContentsString;
851 Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
852 toBinary<ELF64LE>(Storage, FullYamlString);
853 ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
855 Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
856 ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
857 ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(),
858 FailedWithMessage(ErrorMessage));
861 auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool {
862 return Sec.sh_type == ELF::SHT_PROGBITS;
865 StringRef TwoTextSections = R"(
866 Sections:
867 - Name: .text
868 Type: SHT_PROGBITS
869 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
870 - Name: .rela.text
871 Type: SHT_RELA
872 Flags: [ SHF_INFO_LINK ]
873 Info: .text
874 - Name: .text2
875 Type: SHT_PROGBITS
876 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
877 - Name: .rela.text2
878 Type: SHT_RELA
879 Flags: [ SHF_INFO_LINK ]
880 Info: .text2
882 DoCheckSucceeds(TwoTextSections, DefaultMatcher);
884 StringRef OneTextSection = R"(
885 Sections:
886 - Name: .text
887 Type: SHT_PROGBITS
888 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
891 auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> {
892 if(Sec.sh_type == ELF::SHT_PROGBITS)
893 return createError("This was supposed to fail.");
894 return false;
897 DoCheckFails(OneTextSection, ErroringMatcher,
898 "This was supposed to fail.");
900 StringRef MissingRelocatableContent = R"(
901 Sections:
902 - Name: .rela.text
903 Type: SHT_RELA
904 Flags: [ SHF_INFO_LINK ]
905 Info: 0xFF
908 DoCheckFails(MissingRelocatableContent, DefaultMatcher,
909 "SHT_RELA section with index 1: failed to get a "
910 "relocated section: invalid section index: 255");