xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 9c3c6f6acadab5c6938013830ccfb61c109417fa)
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 #include "llvm/Support/thread.h"
18 #include "llvm/TargetParser/Host.h"
19 
20 using namespace llvm;
21 using namespace llvm::object;
22 
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();
28 }
29 
30 namespace {
31 
32 // A struct to initialize a buffer to represent an ELF object file.
33 struct DataForTest {
34   std::vector<uint8_t> Data;
35 
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);
51 
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);
58     }
59 
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;
64   }
65 
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);
72     }
73   }
74 };
75 
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());
82 
83   const ObjectFile &File = *(*ELFObjOrErr).get();
84   EXPECT_EQ(Fmt, File.getFileFormatName());
85   EXPECT_EQ(Arch, File.getArch());
86 }
87 
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)};
93 }
94 
95 } // namespace
96 
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);
102 
103   // Test an arbitrary unused EM_* value (255).
104   for (auto [Idx, Data] : enumerate(generateData(255)))
105     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
106 }
107 
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);
113 }
114 
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);
120 }
121 
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);
127 }
128 
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]);
136 }
137 
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);
143 }
144 
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);
150 }
151 
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]);
160 }
161 
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]);
169 }
170 
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]);
178 }
179 
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]);
187 }
188 
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);
194 }
195 
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);
201 }
202 
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);
208 }
209 
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]);
217 }
218 
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]);
226 }
227 
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]);
235 }
236 
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);
242 }
243 
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);
249 }
250 
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);
256 }
257 
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);
263 }
264 
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]);
273 }
274 
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);
280 }
281 
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);
287 }
288 
289 // ELF relative relocation type test.
290 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
291   EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
292 }
293 
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"));
303 }
304 
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 )");
321 
322   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
323 }
324 
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.
328 
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 )");
358 
359   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
360 
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();
368         });
369 
370     if (!DataOrErr) {
371       ADD_FAILURE() << toString(DataOrErr.takeError());
372       return nullptr;
373     }
374 
375     EXPECT_TRUE(WarnString ==
376                 "loadable segments are unsorted by virtual address");
377     WarnString = "";
378     return *DataOrErr;
379   };
380 
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);
386 
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);
392 }
393 
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 )");
409 
410   ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
411   const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
412   const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
413 
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);
417 
418   auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
419     ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
420 
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));
426 
427     // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
428     EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
429                       FailedWithMessage(ErrMsg));
430 
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));
436 
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));
442 
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));
448 
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));
454 
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));
463   };
464 
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)");
469 
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)");
473 }
474 
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 )");
491 
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();
498 
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));
504   };
505 
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
514 )";
515 
516   DoCheck(UnsupportedVersionYamlString,
517           "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
518 
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
527 )";
528 
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
534 )";
535   DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: "
536                                "malformed uleb128, extends past end");
537 
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
547 )";
548 
549   OverInt32LimitYamlStrings[1] += R"(
550           - ID:            2
551             AddressOffset: 0xFFFFFFFF
552             Size:          0x100000000
553             Metadata:      0xFFFFFFFF
554 )";
555 
556   OverInt32LimitYamlStrings[2] += R"(
557           - ID:            3
558             AddressOffset: 0xFFFFFFFF
559             Size:          0xFFFFFFFF
560             Metadata:      0x100000000
561 )";
562 
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)");
569 
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
578 )";
579   // Truncate at the end of the 5-byte field.
580   OverInt32LimitAndTruncated[1] += R"(
581     ShSize: 0x1a
582 )";
583   // Truncate after the end of the 5-byte field.
584   OverInt32LimitAndTruncated[2] += R"(
585     ShSize: 0x1b
586 )";
587 
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)");
595 
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
601 )";
602 
603   DoCheck(OverLimitNumBlocks,
604           "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
605 }
606 
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 )");
663 
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}}}};
668 
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};
673 
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());
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                           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());
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=*/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, {});
714 
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
720 )";
721 
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);
730 
731   // Check that we can detect when bb-address-map decoding fails.
732   SmallString<128> TruncatedYamlString(CommonYamlString);
733   TruncatedYamlString += R"(
734     ShSize: 0x8
735 )";
736 
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);
745 }
746 
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 )");
766 
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;
773 
774     bool FoundRela;
775 
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");
791     }
792     ASSERT_TRUE(FoundRela);
793   };
794 
795   // Check ET_EXEC file (`ld --emit-relocs` use-case).
796   SmallString<128> ExecFileYamlString(HeaderString);
797   ExecFileYamlString += R"(
798   Type:  ET_EXEC
799 )";
800   ExecFileYamlString += ContentsString;
801   DoCheck(ExecFileYamlString);
802 
803   // Check ET_REL file.
804   SmallString<128> RelocatableFileYamlString(HeaderString);
805   RelocatableFileYamlString += R"(
806   Type:  ET_REL
807 )";
808   RelocatableFileYamlString += ContentsString;
809   DoCheck(RelocatableFileYamlString);
810 }
811 
812 TEST(ELFObjectFileTest, GetSectionAndRelocations) {
813   StringRef HeaderString(R"(
814 --- !ELF
815 FileHeader:
816   Class: ELFCLASS64
817   Data:  ELFDATA2LSB
818   Type:  ET_EXEC
819 )");
820 
821   using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>;
822 
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());
832 
833     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
834         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
835     ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded());
836 
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);
841     }
842   };
843 
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());
854 
855     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
856         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
857     ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(),
858                       FailedWithMessage(ErrorMessage));
859   };
860 
861   auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool {
862     return Sec.sh_type == ELF::SHT_PROGBITS;
863   };
864 
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
881 )";
882   DoCheckSucceeds(TwoTextSections, DefaultMatcher);
883 
884   StringRef OneTextSection = R"(
885 Sections:
886   - Name: .text
887     Type: SHT_PROGBITS
888     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
889 )";
890 
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;
895   };
896 
897   DoCheckFails(OneTextSection, ErroringMatcher,
898                "This was supposed to fail.");
899 
900   StringRef MissingRelocatableContent = R"(
901 Sections:
902   - Name: .rela.text
903     Type: SHT_RELA
904     Flags: [ SHF_INFO_LINK ]
905     Info: 0xFF
906 )";
907 
908   DoCheckFails(MissingRelocatableContent, DefaultMatcher,
909                "SHT_RELA section with index 1: failed to get a "
910                "relocated section: invalid section index: 255");
911 }
912