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