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