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