xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 105adf2cd9588b4839fbdc7287bb76a962fdb8ca)
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/BlockFrequency.h"
13 #include "llvm/Support/MemoryBuffer.h"
14 #include "llvm/Support/YAMLTraits.h"
15 #include "llvm/Testing/Support/Error.h"
16 #include "gtest/gtest.h"
17 
18 #include "llvm/Support/thread.h"
19 #include "llvm/TargetParser/Host.h"
20 
21 using namespace llvm;
22 using namespace llvm::object;
23 
24 // Used to skip LLVM_BB_ADDR_MAP tests on windows platforms due to
25 // https://github.com/llvm/llvm-project/issues/60013.
26 bool IsHostWindows() {
27   Triple Host(Triple::normalize(sys::getProcessTriple()));
28   return Host.isOSWindows();
29 }
30 
31 namespace {
32 
33 // A struct to initialize a buffer to represent an ELF object file.
34 struct DataForTest {
35   std::vector<uint8_t> Data;
36 
37   template <typename T>
38   std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding,
39                                    uint16_t Machine) {
40     T Ehdr{}; // Zero-initialise the header.
41     Ehdr.e_ident[ELF::EI_MAG0] = 0x7f;
42     Ehdr.e_ident[ELF::EI_MAG1] = 'E';
43     Ehdr.e_ident[ELF::EI_MAG2] = 'L';
44     Ehdr.e_ident[ELF::EI_MAG3] = 'F';
45     Ehdr.e_ident[ELF::EI_CLASS] = Class;
46     Ehdr.e_ident[ELF::EI_DATA] = Encoding;
47     Ehdr.e_ident[ELF::EI_VERSION] = 1;
48     Ehdr.e_type = ELF::ET_REL;
49     Ehdr.e_machine = Machine;
50     Ehdr.e_version = 1;
51     Ehdr.e_ehsize = sizeof(T);
52 
53     bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB;
54     if (sys::IsLittleEndianHost != IsLittleEndian) {
55       sys::swapByteOrder(Ehdr.e_type);
56       sys::swapByteOrder(Ehdr.e_machine);
57       sys::swapByteOrder(Ehdr.e_version);
58       sys::swapByteOrder(Ehdr.e_ehsize);
59     }
60 
61     uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr);
62     std::vector<uint8_t> Bytes;
63     std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes));
64     return Bytes;
65   }
66 
67   DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) {
68     if (Class == ELF::ELFCLASS64)
69       Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine);
70     else {
71       assert(Class == ELF::ELFCLASS32);
72       Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine);
73     }
74   }
75 };
76 
77 void checkFormatAndArch(const DataForTest &D, StringRef Fmt,
78                         Triple::ArchType Arch) {
79   Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr =
80       object::ObjectFile::createELFObjectFile(
81           MemoryBufferRef(toStringRef(D.Data), "dummyELF"));
82   ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());
83 
84   const ObjectFile &File = *(*ELFObjOrErr).get();
85   EXPECT_EQ(Fmt, File.getFileFormatName());
86   EXPECT_EQ(Arch, File.getArch());
87 }
88 
89 std::array<DataForTest, 4> generateData(uint16_t Machine) {
90   return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),
91           DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),
92           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),
93           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};
94 }
95 
96 } // namespace
97 
98 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {
99   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
100                                       "elf64-unknown", "elf64-unknown"};
101   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE)))
102     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
103 
104   // Test an arbitrary unused EM_* value (255).
105   for (auto [Idx, Data] : enumerate(generateData(255)))
106     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
107 }
108 
109 TEST(ELFObjectFileTest, MachineTestForVE) {
110   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
111                                       "elf64-ve", "elf64-ve"};
112   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE)))
113     checkFormatAndArch(Data, Formats[Idx], Triple::ve);
114 }
115 
116 TEST(ELFObjectFileTest, MachineTestForX86_64) {
117   std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",
118                                       "elf64-x86-64", "elf64-x86-64"};
119   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64)))
120     checkFormatAndArch(Data, Formats[Idx], Triple::x86_64);
121 }
122 
123 TEST(ELFObjectFileTest, MachineTestFor386) {
124   std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",
125                                       "elf64-i386"};
126   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386)))
127     checkFormatAndArch(Data, Formats[Idx], Triple::x86);
128 }
129 
130 TEST(ELFObjectFileTest, MachineTestForMIPS) {
131   std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",
132                                       "elf64-mips"};
133   std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,
134                                            Triple::mips64el, Triple::mips64};
135   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS)))
136     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
137 }
138 
139 TEST(ELFObjectFileTest, MachineTestForAMDGPU) {
140   std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",
141                                       "elf64-amdgpu", "elf64-amdgpu"};
142   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU)))
143     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
144 }
145 
146 TEST(ELFObjectFileTest, MachineTestForIAMCU) {
147   std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",
148                                       "elf64-unknown", "elf64-unknown"};
149   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU)))
150     checkFormatAndArch(Data, Formats[Idx], Triple::x86);
151 }
152 
153 TEST(ELFObjectFileTest, MachineTestForAARCH64) {
154   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
155                                       "elf64-littleaarch64",
156                                       "elf64-bigaarch64"};
157   std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,
158                                            Triple::aarch64, Triple::aarch64_be};
159   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64)))
160     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
161 }
162 
163 TEST(ELFObjectFileTest, MachineTestForPPC64) {
164   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
165                                       "elf64-powerpcle", "elf64-powerpc"};
166   std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,
167                                            Triple::ppc64le, Triple::ppc64};
168   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64)))
169     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
170 }
171 
172 TEST(ELFObjectFileTest, MachineTestForPPC) {
173   std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",
174                                       "elf64-unknown", "elf64-unknown"};
175   std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,
176                                            Triple::ppcle, Triple::ppc};
177   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC)))
178     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
179 }
180 
181 TEST(ELFObjectFileTest, MachineTestForRISCV) {
182   std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv",
183                                       "elf64-littleriscv", "elf64-littleriscv"};
184   std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32,
185                                            Triple::riscv64, Triple::riscv64};
186   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV)))
187     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
188 }
189 
190 TEST(ELFObjectFileTest, MachineTestForARM) {
191   std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",
192                                       "elf64-unknown", "elf64-unknown"};
193   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM)))
194     checkFormatAndArch(Data, Formats[Idx], Triple::arm);
195 }
196 
197 TEST(ELFObjectFileTest, MachineTestForS390) {
198   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
199                                       "elf64-s390", "elf64-s390"};
200   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390)))
201     checkFormatAndArch(Data, Formats[Idx], Triple::systemz);
202 }
203 
204 TEST(ELFObjectFileTest, MachineTestForSPARCV9) {
205   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
206                                       "elf64-sparc", "elf64-sparc"};
207   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9)))
208     checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9);
209 }
210 
211 TEST(ELFObjectFileTest, MachineTestForSPARC) {
212   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
213                                       "elf64-unknown", "elf64-unknown"};
214   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
215                                            Triple::sparcel, Triple::sparc};
216   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC)))
217     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
218 }
219 
220 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {
221   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
222                                       "elf64-unknown", "elf64-unknown"};
223   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
224                                            Triple::sparcel, Triple::sparc};
225   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS)))
226     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
227 }
228 
229 TEST(ELFObjectFileTest, MachineTestForBPF) {
230   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
231                                       "elf64-bpf", "elf64-bpf"};
232   std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,
233                                            Triple::bpfel, Triple::bpfeb};
234   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF)))
235     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
236 }
237 
238 TEST(ELFObjectFileTest, MachineTestForAVR) {
239   std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",
240                                       "elf64-unknown"};
241   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR)))
242     checkFormatAndArch(Data, Formats[Idx], Triple::avr);
243 }
244 
245 TEST(ELFObjectFileTest, MachineTestForHEXAGON) {
246   std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",
247                                       "elf64-unknown", "elf64-unknown"};
248   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON)))
249     checkFormatAndArch(Data, Formats[Idx], Triple::hexagon);
250 }
251 
252 TEST(ELFObjectFileTest, MachineTestForLANAI) {
253   std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",
254                                       "elf64-unknown", "elf64-unknown"};
255   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI)))
256     checkFormatAndArch(Data, Formats[Idx], Triple::lanai);
257 }
258 
259 TEST(ELFObjectFileTest, MachineTestForMSP430) {
260   std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",
261                                       "elf64-unknown", "elf64-unknown"};
262   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430)))
263     checkFormatAndArch(Data, Formats[Idx], Triple::msp430);
264 }
265 
266 TEST(ELFObjectFileTest, MachineTestForLoongArch) {
267   std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch",
268                                       "elf64-loongarch", "elf64-loongarch"};
269   std::array<Triple::ArchType, 4> Archs = {
270       Triple::loongarch32, Triple::loongarch32, Triple::loongarch64,
271       Triple::loongarch64};
272   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH)))
273     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
274 }
275 
276 TEST(ELFObjectFileTest, MachineTestForCSKY) {
277   std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
278                                       "elf64-unknown", "elf64-unknown"};
279   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY)))
280     checkFormatAndArch(Data, Formats[Idx], Triple::csky);
281 }
282 
283 TEST(ELFObjectFileTest, MachineTestForXtensa) {
284   std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa",
285                                       "elf64-unknown", "elf64-unknown"};
286   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA)))
287     checkFormatAndArch(Data, Formats[Idx], Triple::xtensa);
288 }
289 
290 // ELF relative relocation type test.
291 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
292   EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
293 }
294 
295 template <class ELFT>
296 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
297                                               StringRef Yaml) {
298   raw_svector_ostream OS(Storage);
299   yaml::Input YIn(Yaml);
300   if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
301     return createStringError(std::errc::invalid_argument,
302                              "unable to convert YAML");
303   return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
304 }
305 
306 // Check we are able to create an ELFObjectFile even when the content of the
307 // SHT_SYMTAB_SHNDX section can't be read properly.
308 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
309   SmallString<0> Storage;
310   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
311 --- !ELF
312 FileHeader:
313   Class: ELFCLASS64
314   Data:  ELFDATA2LSB
315   Type:  ET_REL
316 Sections:
317   - Name:    .symtab_shndx
318     Type:    SHT_SYMTAB_SHNDX
319     Entries: [ 0 ]
320     ShSize: 0xFFFFFFFF
321 )");
322 
323   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
324 }
325 
326 // Test that we are able to create an ELFObjectFile even when loadable segments
327 // are unsorted by virtual address.
328 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
329 
330 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
331   SmallString<0> Storage;
332   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
333 --- !ELF
334 FileHeader:
335   Class: ELFCLASS64
336   Data:  ELFDATA2LSB
337   Type:  ET_EXEC
338 Sections:
339   - Name:         .foo
340     Type:         SHT_PROGBITS
341     Address:      0x1000
342     Offset:       0x3000
343     ContentArray: [ 0x11 ]
344   - Name:         .bar
345     Type:         SHT_PROGBITS
346     Address:      0x2000
347     Offset:       0x4000
348     ContentArray: [ 0x99 ]
349 ProgramHeaders:
350   - Type:     PT_LOAD
351     VAddr:    0x2000
352     FirstSec: .bar
353     LastSec:  .bar
354   - Type:     PT_LOAD
355     VAddr:    0x1000
356     FirstSec: .foo
357     LastSec:  .foo
358 )");
359 
360   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
361 
362   std::string WarnString;
363   auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
364     Expected<const uint8_t *> DataOrErr =
365         ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
366           EXPECT_TRUE(WarnString.empty());
367           WarnString = Msg.str();
368           return Error::success();
369         });
370 
371     if (!DataOrErr) {
372       ADD_FAILURE() << toString(DataOrErr.takeError());
373       return nullptr;
374     }
375 
376     EXPECT_TRUE(WarnString ==
377                 "loadable segments are unsorted by virtual address");
378     WarnString = "";
379     return *DataOrErr;
380   };
381 
382   const uint8_t *Data = ToMappedAddr(0x1000);
383   ASSERT_TRUE(Data);
384   MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
385   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
386   EXPECT_EQ(Data[0], 0x11);
387 
388   Data = ToMappedAddr(0x2000);
389   ASSERT_TRUE(Data);
390   Buf = ExpectedFile->getMemoryBufferRef();
391   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
392   EXPECT_EQ(Data[0], 0x99);
393 }
394 
395 // This is a test for API that is related to symbols.
396 // We check that errors are properly reported here.
397 TEST(ELFObjectFileTest, InvalidSymbolTest) {
398   SmallString<0> Storage;
399   Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
400 --- !ELF
401 FileHeader:
402   Class:   ELFCLASS64
403   Data:    ELFDATA2LSB
404   Type:    ET_DYN
405   Machine: EM_X86_64
406 Sections:
407   - Name: .symtab
408     Type: SHT_SYMTAB
409 )");
410 
411   ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
412   const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
413   const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
414 
415   Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
416   ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
417   ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
418 
419   auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
420     ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
421 
422     // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
423     //    SymbolRef::getName() calls it internally. We can't test it directly,
424     //    because it is protected.
425     EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
426                       FailedWithMessage(ErrMsg));
427 
428     // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
429     EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
430                       FailedWithMessage(ErrMsg));
431 
432     // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
433     //    SymbolRef::getSection() calls it internally. We can't test it
434     //    directly, because it is protected.
435     EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
436                       FailedWithMessage(ErrMsg));
437 
438     // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
439     //    SymbolRef::getFlags() calls it internally. We can't test it directly,
440     //    because it is protected.
441     EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
442                       FailedWithMessage(ErrMsg));
443 
444     // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
445     //    SymbolRef::getType() calls it internally. We can't test it directly,
446     //    because it is protected.
447     EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
448                       FailedWithMessage(ErrMsg));
449 
450     // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
451     //    SymbolRef::getAddress() calls it internally. We can't test it
452     //    directly, because it is protected.
453     EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
454                       FailedWithMessage(ErrMsg));
455 
456     // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
457     // method that generates errors for all cases above.
458     EXPECT_THAT_EXPECTED(
459         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
460     EXPECT_THAT_ERROR(
461         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
462             .takeError(),
463         FailedWithMessage(ErrMsg));
464   };
465 
466   // We create a symbol with an index that is too large to exist in the symbol
467   // table.
468   DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
469                "section (0x18)");
470 
471   // We create a symbol with an index that is too large to exist in the object.
472   DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
473                       "end of the section (0x18)");
474 }
475 
476 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
477 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
478   if (IsHostWindows())
479     GTEST_SKIP();
480   StringRef CommonYamlString(R"(
481 --- !ELF
482 FileHeader:
483   Class: ELFCLASS64
484   Data:  ELFDATA2LSB
485   Type:  ET_EXEC
486 Sections:
487   - Type: SHT_LLVM_BB_ADDR_MAP
488     Name: .llvm_bb_addr_map
489     Entries:
490       - Address: 0x11111
491 )");
492 
493   auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
494     SmallString<0> Storage;
495     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
496         toBinary<ELF64LE>(Storage, YamlString);
497     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
498     const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
499 
500     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
501         Elf.getSection(1);
502     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
503     EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
504                       FailedWithMessage(ErrMsg));
505   };
506 
507   // Check that we can detect unsupported versions.
508   SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
509   UnsupportedVersionYamlString += R"(
510         Version: 3
511         BBEntries:
512           - AddressOffset: 0x0
513             Size:          0x1
514             Metadata:      0x2
515 )";
516 
517   DoCheck(UnsupportedVersionYamlString,
518           "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
519 
520   SmallString<128> CommonVersionedYamlString(CommonYamlString);
521   CommonVersionedYamlString += R"(
522         Version: 2
523         BBEntries:
524           - ID:            1
525             AddressOffset: 0x0
526             Size:          0x1
527             Metadata:      0x2
528 )";
529 
530   // Check that we can detect the malformed encoding when the section is
531   // truncated.
532   SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
533   TruncatedYamlString += R"(
534     ShSize: 0xb
535 )";
536   DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: "
537                                "malformed uleb128, extends past end");
538 
539   // Check that we can detect when the encoded BB entry fields exceed the UINT32
540   // limit.
541   SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
542       3, CommonVersionedYamlString);
543   OverInt32LimitYamlStrings[0] += R"(
544           - ID:            1
545             AddressOffset: 0x100000000
546             Size:          0xFFFFFFFF
547             Metadata:      0xFFFFFFFF
548 )";
549 
550   OverInt32LimitYamlStrings[1] += R"(
551           - ID:            2
552             AddressOffset: 0xFFFFFFFF
553             Size:          0x100000000
554             Metadata:      0xFFFFFFFF
555 )";
556 
557   OverInt32LimitYamlStrings[2] += R"(
558           - ID:            3
559             AddressOffset: 0xFFFFFFFF
560             Size:          0xFFFFFFFF
561             Metadata:      0x100000000
562 )";
563 
564   DoCheck(OverInt32LimitYamlStrings[0],
565           "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
566   DoCheck(OverInt32LimitYamlStrings[1],
567           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
568   DoCheck(OverInt32LimitYamlStrings[2],
569           "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
570 
571   // Check the proper error handling when the section has fields exceeding
572   // UINT32 and is also truncated. This is for checking that we don't generate
573   // unhandled errors.
574   SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
575       3, OverInt32LimitYamlStrings[1]);
576   // Truncate before the end of the 5-byte field.
577   OverInt32LimitAndTruncated[0] += R"(
578     ShSize: 0x19
579 )";
580   // Truncate at the end of the 5-byte field.
581   OverInt32LimitAndTruncated[1] += R"(
582     ShSize: 0x1a
583 )";
584   // Truncate after the end of the 5-byte field.
585   OverInt32LimitAndTruncated[2] += R"(
586     ShSize: 0x1b
587 )";
588 
589   DoCheck(OverInt32LimitAndTruncated[0],
590           "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
591           "extends past end");
592   DoCheck(OverInt32LimitAndTruncated[1],
593           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
594   DoCheck(OverInt32LimitAndTruncated[2],
595           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
596 
597   // Check for proper error handling when the 'NumBlocks' field is overridden
598   // with an out-of-range value.
599   SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
600   OverLimitNumBlocks += R"(
601         NumBlocks: 0x100000000
602 )";
603 
604   DoCheck(OverLimitNumBlocks,
605           "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
606 }
607 
608 // Test for the ELFObjectFile::readBBAddrMap API.
609 TEST(ELFObjectFileTest, ReadBBAddrMap) {
610   if (IsHostWindows())
611     GTEST_SKIP();
612   StringRef CommonYamlString(R"(
613 --- !ELF
614 FileHeader:
615   Class: ELFCLASS64
616   Data:  ELFDATA2LSB
617   Type:  ET_EXEC
618 Sections:
619   - Name: .llvm_bb_addr_map_1
620     Type: SHT_LLVM_BB_ADDR_MAP
621     Link: 1
622     Entries:
623       - Version: 2
624         Address: 0x11111
625         BBEntries:
626           - ID:            1
627             AddressOffset: 0x0
628             Size:          0x1
629             Metadata:      0x2
630   - Name: .llvm_bb_addr_map_2
631     Type: SHT_LLVM_BB_ADDR_MAP
632     Link: 1
633     Entries:
634       - Version: 2
635         Address: 0x22222
636         BBEntries:
637           - ID:            2
638             AddressOffset: 0x0
639             Size:          0x2
640             Metadata:      0x4
641   - Name: .llvm_bb_addr_map_3
642     Type: SHT_LLVM_BB_ADDR_MAP
643     Link: 2
644     Entries:
645       - Version: 1
646         Address: 0x33333
647         BBEntries:
648           - ID:            0
649             AddressOffset: 0x0
650             Size:          0x3
651             Metadata:      0x6
652   - Name: .llvm_bb_addr_map_4
653     Type: SHT_LLVM_BB_ADDR_MAP_V0
654   # Link: 0 (by default, can be overriden)
655     Entries:
656       - Version: 0
657         Address: 0x44444
658         BBEntries:
659           - ID:            0
660             AddressOffset: 0x0
661             Size:          0x4
662             Metadata:      0x18
663 )");
664 
665   BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}});
666   BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}});
667   BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}});
668   BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}});
669 
670   std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
671   std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
672   std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
673   std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
674 
675   auto DoCheckSucceeds = [&](StringRef YamlString,
676                              std::optional<unsigned> TextSectionIndex,
677                              std::vector<BBAddrMap> ExpectedResult) {
678     SmallString<0> Storage;
679     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
680         toBinary<ELF64LE>(Storage, YamlString);
681     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
682 
683     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
684         ElfOrErr->getELFFile().getSection(1);
685     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
686     auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);
687     ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());
688     EXPECT_EQ(*BBAddrMaps, ExpectedResult);
689   };
690 
691   auto DoCheckFails = [&](StringRef YamlString,
692                           std::optional<unsigned> TextSectionIndex,
693                           const char *ErrMsg) {
694     SmallString<0> Storage;
695     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
696         toBinary<ELF64LE>(Storage, YamlString);
697     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
698 
699     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
700         ElfOrErr->getELFFile().getSection(1);
701     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
702     EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(),
703                       FailedWithMessage(ErrMsg));
704   };
705 
706   // Check that we can retrieve the data in the normal case.
707   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
708                   AllBBAddrMaps);
709   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps);
710   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps);
711   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps);
712   // Check that when no bb-address-map section is found for a text section,
713   // we return an empty result.
714   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});
715 
716   // Check that we detect when a bb-addr-map section is linked to an invalid
717   // (not present) section.
718   SmallString<128> InvalidLinkedYamlString(CommonYamlString);
719   InvalidLinkedYamlString += R"(
720     Link: 10
721 )";
722 
723   DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
724                "unable to get the linked-to section for "
725                "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
726                "index: 10");
727   // Linked sections are not checked when we don't target a specific text
728   // section.
729   DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
730                   AllBBAddrMaps);
731 
732   // Check that we can detect when bb-address-map decoding fails.
733   SmallString<128> TruncatedYamlString(CommonYamlString);
734   TruncatedYamlString += R"(
735     ShSize: 0x8
736 )";
737 
738   DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
739                "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
740                "unable to decode LEB128 at offset 0x00000008: malformed "
741                "uleb128, extends past end");
742   // Check that we can read the other section's bb-address-maps which are
743   // valid.
744   DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
745                   Section1BBAddrMaps);
746 }
747 
748 // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap
749 // API.
750 TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) {
751   if (IsHostWindows())
752     GTEST_SKIP();
753   StringRef CommonYamlString(R"(
754 --- !ELF
755 FileHeader:
756   Class: ELFCLASS64
757   Data:  ELFDATA2LSB
758   Type:  ET_EXEC
759 Sections:
760   - Type: SHT_LLVM_BB_ADDR_MAP
761     Name: .llvm_bb_addr_map
762     Entries:
763       - Address: 0x11111
764 )");
765 
766   auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
767     SmallString<0> Storage;
768     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
769         toBinary<ELF64LE>(Storage, YamlString);
770     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
771     const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
772 
773     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
774         Elf.getSection(1);
775     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
776 
777     std::vector<PGOAnalysisMap> PGOAnalyses;
778     EXPECT_THAT_ERROR(
779         Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses)
780             .takeError(),
781         FailedWithMessage(ErrMsg));
782   };
783 
784   // Check that we can detect unsupported versions that are too old.
785   SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);
786   UnsupportedLowVersionYamlString += R"(
787         Version: 1
788         Feature: 0x4
789         BBEntries:
790           - AddressOffset: 0x0
791             Size:          0x1
792             Metadata:      0x2
793 )";
794 
795   DoCheck(UnsupportedLowVersionYamlString,
796           "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features "
797           "are enabled: version = 1 feature = 4");
798 
799   SmallString<128> CommonVersionedYamlString(CommonYamlString);
800   CommonVersionedYamlString += R"(
801         Version: 2
802         BBEntries:
803           - ID:            1
804             AddressOffset: 0x0
805             Size:          0x1
806             Metadata:      0x2
807 )";
808 
809   // Check that we fail when function entry count is enabled but not provided.
810   SmallString<128> MissingFuncEntryCount(CommonYamlString);
811   MissingFuncEntryCount += R"(
812         Version: 2
813         Feature: 0x01
814 )";
815 
816   DoCheck(MissingFuncEntryCount,
817           "unable to decode LEB128 at offset 0x0000000b: malformed uleb128, "
818           "extends past end");
819 
820   // Check that we fail when basic block frequency is enabled but not provided.
821   SmallString<128> MissingBBFreq(CommonYamlString);
822   MissingBBFreq += R"(
823         Version: 2
824         Feature: 0x02
825         BBEntries:
826           - ID:            1
827             AddressOffset: 0x0
828             Size:          0x1
829             Metadata:      0x2
830 )";
831 
832   DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: "
833                          "malformed uleb128, extends past end");
834 
835   // Check that we fail when branch probability is enabled but not provided.
836   SmallString<128> MissingBrProb(CommonYamlString);
837   MissingBrProb += R"(
838         Version: 2
839         Feature: 0x04
840         BBEntries:
841           - ID:            1
842             AddressOffset: 0x0
843             Size:          0x1
844             Metadata:      0x6
845           - ID:            2
846             AddressOffset: 0x1
847             Size:          0x1
848             Metadata:      0x2
849           - ID:            3
850             AddressOffset: 0x2
851             Size:          0x1
852             Metadata:      0x2
853     PGOAnalyses:
854       - PGOBBEntries:
855          - Successors:
856             - ID:          2
857               BrProb:      0x80000000
858             - ID:          3
859               BrProb:      0x80000000
860          - Successors:
861             - ID:          3
862               BrProb:      0xF0000000
863 )";
864 
865   DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: "
866                          "malformed uleb128, extends past end");
867 }
868 
869 // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap.
870 TEST(ELFObjectFileTest, ReadPGOAnalysisMap) {
871   if (IsHostWindows())
872     GTEST_SKIP();
873   StringRef CommonYamlString(R"(
874 --- !ELF
875 FileHeader:
876   Class: ELFCLASS64
877   Data:  ELFDATA2LSB
878   Type:  ET_EXEC
879 Sections:
880   - Name: .llvm_bb_addr_map_1
881     Type: SHT_LLVM_BB_ADDR_MAP
882     Link: 1
883     Entries:
884       - Version: 2
885         Address: 0x11111
886         Feature: 0x1
887         BBEntries:
888           - ID:            1
889             AddressOffset: 0x0
890             Size:          0x1
891             Metadata:      0x2
892     PGOAnalyses:
893       - FuncEntryCount: 892
894   - Name: .llvm_bb_addr_map_2
895     Type: SHT_LLVM_BB_ADDR_MAP
896     Link: 1
897     Entries:
898       - Version: 2
899         Address: 0x22222
900         Feature: 0x2
901         BBEntries:
902           - ID:            2
903             AddressOffset: 0x0
904             Size:          0x2
905             Metadata:      0x4
906     PGOAnalyses:
907       - PGOBBEntries:
908          - BBFreq:         343
909   - Name: .llvm_bb_addr_map_3
910     Type: SHT_LLVM_BB_ADDR_MAP
911     Link: 2
912     Entries:
913       - Version: 2
914         Address: 0x33333
915         Feature: 0x4
916         BBEntries:
917           - ID:            0
918             AddressOffset: 0x0
919             Size:          0x3
920             Metadata:      0x6
921           - ID:            1
922             AddressOffset: 0x0
923             Size:          0x3
924             Metadata:      0x4
925           - ID:            2
926             AddressOffset: 0x0
927             Size:          0x3
928             Metadata:      0x0
929     PGOAnalyses:
930       - PGOBBEntries:
931          - Successors:
932             - ID:          1
933               BrProb:      0x11111111
934             - ID:          2
935               BrProb:      0xeeeeeeee
936          - Successors:
937             - ID:          2
938               BrProb:      0xffffffff
939          - Successors:     []
940   - Name: .llvm_bb_addr_map_4
941     Type: SHT_LLVM_BB_ADDR_MAP
942   # Link: 0 (by default, can be overriden)
943     Entries:
944       - Version: 2
945         Address: 0x44444
946         Feature: 0x7
947         BBEntries:
948           - ID:            0
949             AddressOffset: 0x0
950             Size:          0x4
951             Metadata:      0x18
952           - ID:            1
953             AddressOffset: 0x0
954             Size:          0x4
955             Metadata:      0x0
956           - ID:            2
957             AddressOffset: 0x0
958             Size:          0x4
959             Metadata:      0x0
960           - ID:            3
961             AddressOffset: 0x0
962             Size:          0x4
963             Metadata:      0x0
964     PGOAnalyses:
965       - FuncEntryCount: 1000
966         PGOBBEntries:
967           - BBFreq:         1000
968             Successors:
969             - ID:          1
970               BrProb:      0x22222222
971             - ID:          2
972               BrProb:      0x33333333
973             - ID:          3
974               BrProb:      0xaaaaaaaa
975           - BBFreq:         133
976             Successors:
977             - ID:          2
978               BrProb:      0x11111111
979             - ID:          3
980               BrProb:      0xeeeeeeee
981           - BBFreq:         18
982             Successors:
983             - ID:          3
984               BrProb:      0xffffffff
985           - BBFreq:         1000
986             Successors:    []
987 )");
988 
989   BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}});
990   PGOAnalysisMap P1 = {892, {{}}, {true, false, false}};
991   BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}});
992   PGOAnalysisMap P2 = {{}, {{BlockFrequency(343), {}}}, {false, true, false}};
993   BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}},
994                          {1, 0x3, 0x3, {false, false, true, false, false}},
995                          {2, 0x6, 0x3, {false, false, false, false, false}}});
996   PGOAnalysisMap P3 = {{},
997                        {{{},
998                          {{1, BranchProbability::getRaw(0x1111'1111)},
999                           {2, BranchProbability::getRaw(0xeeee'eeee)}}},
1000                         {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}},
1001                         {{}, {}}},
1002                        {false, false, true}};
1003   BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}},
1004                          {1, 0x4, 0x4, {false, false, false, false, false}},
1005                          {2, 0x8, 0x4, {false, false, false, false, false}},
1006                          {3, 0xc, 0x4, {false, false, false, false, false}}});
1007   PGOAnalysisMap P4 = {
1008       1000,
1009       {{BlockFrequency(1000),
1010         {{1, BranchProbability::getRaw(0x2222'2222)},
1011          {2, BranchProbability::getRaw(0x3333'3333)},
1012          {3, BranchProbability::getRaw(0xaaaa'aaaa)}}},
1013        {BlockFrequency(133),
1014         {{2, BranchProbability::getRaw(0x1111'1111)},
1015          {3, BranchProbability::getRaw(0xeeee'eeee)}}},
1016        {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}},
1017        {BlockFrequency(1000), {}}},
1018       {true, true, true}};
1019 
1020   std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
1021   std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
1022   std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
1023   std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
1024 
1025   std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4};
1026   std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3};
1027   std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2};
1028   std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4};
1029 
1030   auto DoCheckSucceeds =
1031       [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex,
1032           std::vector<BBAddrMap> ExpectedResult,
1033           std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) {
1034         SmallString<0> Storage;
1035         Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1036             toBinary<ELF64LE>(Storage, YamlString);
1037         ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1038 
1039         Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
1040             ElfOrErr->getELFFile().getSection(1);
1041         ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
1042 
1043         std::vector<PGOAnalysisMap> PGOAnalyses;
1044         auto BBAddrMaps = ElfOrErr->readBBAddrMap(
1045             TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr);
1046         ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());
1047         EXPECT_EQ(*BBAddrMaps, ExpectedResult);
1048         if (ExpectedPGO) {
1049           EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size());
1050           EXPECT_EQ(PGOAnalyses, *ExpectedPGO);
1051         }
1052       };
1053 
1054   auto DoCheckFails = [&](StringRef YamlString,
1055                           std::optional<unsigned> TextSectionIndex,
1056                           const char *ErrMsg) {
1057     SmallString<0> Storage;
1058     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1059         toBinary<ELF64LE>(Storage, YamlString);
1060     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1061 
1062     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
1063         ElfOrErr->getELFFile().getSection(1);
1064     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
1065     std::vector<PGOAnalysisMap> PGOAnalyses;
1066     EXPECT_THAT_ERROR(
1067         ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(),
1068         FailedWithMessage(ErrMsg));
1069   };
1070 
1071   // Check that we can retrieve the data in the normal case.
1072   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
1073                   AllBBAddrMaps, std::nullopt);
1074   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps,
1075                   std::nullopt);
1076   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps,
1077                   std::nullopt);
1078   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps,
1079                   std::nullopt);
1080 
1081   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
1082                   AllBBAddrMaps, AllPGOAnalysisMaps);
1083   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps,
1084                   Section0PGOAnalysisMaps);
1085   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps,
1086                   Section1PGOAnalysisMaps);
1087   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps,
1088                   Section2PGOAnalysisMaps);
1089   // Check that when no bb-address-map section is found for a text section,
1090   // we return an empty result.
1091   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt);
1092   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {},
1093                   std::vector<PGOAnalysisMap>{});
1094 
1095   // Check that we detect when a bb-addr-map section is linked to an invalid
1096   // (not present) section.
1097   SmallString<128> InvalidLinkedYamlString(CommonYamlString);
1098   InvalidLinkedYamlString += R"(
1099     Link: 10
1100 )";
1101 
1102   DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
1103                "unable to get the linked-to section for "
1104                "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section "
1105                "index: 10");
1106   // Linked sections are not checked when we don't target a specific text
1107   // section.
1108   DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
1109                   AllBBAddrMaps, std::nullopt);
1110   DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
1111                   AllBBAddrMaps, AllPGOAnalysisMaps);
1112 
1113   // Check that we can detect when bb-address-map decoding fails.
1114   SmallString<128> TruncatedYamlString(CommonYamlString);
1115   TruncatedYamlString += R"(
1116     ShSize: 0xa
1117 )";
1118 
1119   DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
1120                "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: "
1121                "unable to decode LEB128 at offset 0x0000000a: malformed "
1122                "uleb128, extends past end");
1123   // Check that we can read the other section's bb-address-maps which are
1124   // valid.
1125   DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
1126                   Section1BBAddrMaps, std::nullopt);
1127   DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
1128                   Section1BBAddrMaps, Section1PGOAnalysisMaps);
1129 }
1130 
1131 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
1132 // section for executable and relocatable files.
1133 TEST(ELFObjectFileTest, ExecutableWithRelocs) {
1134   StringRef HeaderString(R"(
1135 --- !ELF
1136 FileHeader:
1137   Class: ELFCLASS64
1138   Data:  ELFDATA2LSB
1139 )");
1140   StringRef ContentsString(R"(
1141 Sections:
1142   - Name:  .text
1143     Type:  SHT_PROGBITS
1144     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1145   - Name:  .rela.text
1146     Type:  SHT_RELA
1147     Flags: [ SHF_INFO_LINK ]
1148     Info:  .text
1149 )");
1150 
1151   auto DoCheck = [&](StringRef YamlString) {
1152     SmallString<0> Storage;
1153     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1154         toBinary<ELF64LE>(Storage, YamlString);
1155     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1156     const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
1157 
1158     bool FoundRela;
1159 
1160     for (SectionRef Sec : Obj.sections()) {
1161       Expected<StringRef> SecNameOrErr = Sec.getName();
1162       ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());
1163       StringRef SecName = *SecNameOrErr;
1164       if (SecName != ".rela.text")
1165         continue;
1166       FoundRela = true;
1167       Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
1168       ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());
1169       section_iterator RelSec = *RelSecOrErr;
1170       ASSERT_NE(RelSec, Obj.section_end());
1171       Expected<StringRef> TextSecNameOrErr = RelSec->getName();
1172       ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());
1173       StringRef TextSecName = *TextSecNameOrErr;
1174       EXPECT_EQ(TextSecName, ".text");
1175     }
1176     ASSERT_TRUE(FoundRela);
1177   };
1178 
1179   // Check ET_EXEC file (`ld --emit-relocs` use-case).
1180   SmallString<128> ExecFileYamlString(HeaderString);
1181   ExecFileYamlString += R"(
1182   Type:  ET_EXEC
1183 )";
1184   ExecFileYamlString += ContentsString;
1185   DoCheck(ExecFileYamlString);
1186 
1187   // Check ET_REL file.
1188   SmallString<128> RelocatableFileYamlString(HeaderString);
1189   RelocatableFileYamlString += R"(
1190   Type:  ET_REL
1191 )";
1192   RelocatableFileYamlString += ContentsString;
1193   DoCheck(RelocatableFileYamlString);
1194 }
1195 
1196 TEST(ELFObjectFileTest, GetSectionAndRelocations) {
1197   StringRef HeaderString(R"(
1198 --- !ELF
1199 FileHeader:
1200   Class: ELFCLASS64
1201   Data:  ELFDATA2LSB
1202   Type:  ET_EXEC
1203 )");
1204 
1205   using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>;
1206 
1207   auto DoCheckSucceeds = [&](StringRef ContentsString,
1208                              std::function<Expected<bool>(const Elf_Shdr &)>
1209                                  Matcher) {
1210     SmallString<0> Storage;
1211     SmallString<128> FullYamlString(HeaderString);
1212     FullYamlString += ContentsString;
1213     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1214         toBinary<ELF64LE>(Storage, FullYamlString);
1215     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1216 
1217     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
1218         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
1219     ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded());
1220 
1221     // Basic verification to make sure we have the correct section types.
1222     for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) {
1223       ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS);
1224       ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA);
1225     }
1226   };
1227 
1228   auto DoCheckFails = [&](StringRef ContentsString,
1229                           std::function<Expected<bool>(const Elf_Shdr &)>
1230                               Matcher,
1231                           const char *ErrorMessage) {
1232     SmallString<0> Storage;
1233     SmallString<128> FullYamlString(HeaderString);
1234     FullYamlString += ContentsString;
1235     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1236         toBinary<ELF64LE>(Storage, FullYamlString);
1237     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1238 
1239     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
1240         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
1241     ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(),
1242                       FailedWithMessage(ErrorMessage));
1243   };
1244 
1245   auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool {
1246     return Sec.sh_type == ELF::SHT_PROGBITS;
1247   };
1248 
1249   StringRef TwoTextSections = R"(
1250 Sections:
1251   - Name: .text
1252     Type: SHT_PROGBITS
1253     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1254   - Name: .rela.text
1255     Type: SHT_RELA
1256     Flags: [ SHF_INFO_LINK ]
1257     Info: .text
1258   - Name: .text2
1259     Type: SHT_PROGBITS
1260     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1261   - Name: .rela.text2
1262     Type: SHT_RELA
1263     Flags: [ SHF_INFO_LINK ]
1264     Info: .text2
1265 )";
1266   DoCheckSucceeds(TwoTextSections, DefaultMatcher);
1267 
1268   StringRef OneTextSection = R"(
1269 Sections:
1270   - Name: .text
1271     Type: SHT_PROGBITS
1272     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1273 )";
1274 
1275   auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> {
1276     if(Sec.sh_type == ELF::SHT_PROGBITS)
1277       return createError("This was supposed to fail.");
1278     return false;
1279   };
1280 
1281   DoCheckFails(OneTextSection, ErroringMatcher,
1282                "This was supposed to fail.");
1283 
1284   StringRef MissingRelocatableContent = R"(
1285 Sections:
1286   - Name: .rela.text
1287     Type: SHT_RELA
1288     Flags: [ SHF_INFO_LINK ]
1289     Info: 0xFF
1290 )";
1291 
1292   DoCheckFails(MissingRelocatableContent, DefaultMatcher,
1293                "SHT_RELA section with index 1: failed to get a "
1294                "relocated section: invalid section index: 255");
1295 }
1296