xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 6ba2c2bb804532e97180d548957bb231d994c8ff)
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     llvm::Triple TheTriple = ELFObj.makeTriple();
314 
315     // The AMDGPU architecture will be unknown on big-endian testers.
316     if (TheTriple.getArch() == Triple::UnknownArch)
317       continue;
318 
319     EXPECT_EQ(Triple, TheTriple.getTriple());
320   }
321 }
322 
323 // ELF relative relocation type test.
324 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
325   EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
326 }
327 
328 template <class ELFT>
329 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
330                                               StringRef Yaml) {
331   raw_svector_ostream OS(Storage);
332   yaml::Input YIn(Yaml);
333   if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
334     return createStringError(std::errc::invalid_argument,
335                              "unable to convert YAML");
336   return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
337 }
338 
339 // Check we are able to create an ELFObjectFile even when the content of the
340 // SHT_SYMTAB_SHNDX section can't be read properly.
341 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
342   SmallString<0> Storage;
343   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
344 --- !ELF
345 FileHeader:
346   Class: ELFCLASS64
347   Data:  ELFDATA2LSB
348   Type:  ET_REL
349 Sections:
350   - Name:    .symtab_shndx
351     Type:    SHT_SYMTAB_SHNDX
352     Entries: [ 0 ]
353     ShSize: 0xFFFFFFFF
354 )");
355 
356   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
357 }
358 
359 // Test that we are able to create an ELFObjectFile even when loadable segments
360 // are unsorted by virtual address.
361 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
362 
363 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
364   SmallString<0> Storage;
365   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
366 --- !ELF
367 FileHeader:
368   Class: ELFCLASS64
369   Data:  ELFDATA2LSB
370   Type:  ET_EXEC
371 Sections:
372   - Name:         .foo
373     Type:         SHT_PROGBITS
374     Address:      0x1000
375     Offset:       0x3000
376     ContentArray: [ 0x11 ]
377   - Name:         .bar
378     Type:         SHT_PROGBITS
379     Address:      0x2000
380     Offset:       0x4000
381     ContentArray: [ 0x99 ]
382 ProgramHeaders:
383   - Type:     PT_LOAD
384     VAddr:    0x2000
385     FirstSec: .bar
386     LastSec:  .bar
387   - Type:     PT_LOAD
388     VAddr:    0x1000
389     FirstSec: .foo
390     LastSec:  .foo
391 )");
392 
393   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
394 
395   std::string WarnString;
396   auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
397     Expected<const uint8_t *> DataOrErr =
398         ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
399           EXPECT_TRUE(WarnString.empty());
400           WarnString = Msg.str();
401           return Error::success();
402         });
403 
404     if (!DataOrErr) {
405       ADD_FAILURE() << toString(DataOrErr.takeError());
406       return nullptr;
407     }
408 
409     EXPECT_TRUE(WarnString ==
410                 "loadable segments are unsorted by virtual address");
411     WarnString = "";
412     return *DataOrErr;
413   };
414 
415   const uint8_t *Data = ToMappedAddr(0x1000);
416   ASSERT_TRUE(Data);
417   MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
418   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
419   EXPECT_EQ(Data[0], 0x11);
420 
421   Data = ToMappedAddr(0x2000);
422   ASSERT_TRUE(Data);
423   Buf = ExpectedFile->getMemoryBufferRef();
424   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
425   EXPECT_EQ(Data[0], 0x99);
426 }
427 
428 // This is a test for API that is related to symbols.
429 // We check that errors are properly reported here.
430 TEST(ELFObjectFileTest, InvalidSymbolTest) {
431   SmallString<0> Storage;
432   Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
433 --- !ELF
434 FileHeader:
435   Class:   ELFCLASS64
436   Data:    ELFDATA2LSB
437   Type:    ET_DYN
438   Machine: EM_X86_64
439 Sections:
440   - Name: .symtab
441     Type: SHT_SYMTAB
442 )");
443 
444   ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
445   const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
446   const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
447 
448   Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
449   ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
450   ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
451 
452   auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
453     ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
454 
455     // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
456     //    SymbolRef::getName() calls it internally. We can't test it directly,
457     //    because it is protected.
458     EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
459                       FailedWithMessage(ErrMsg));
460 
461     // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
462     EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
463                       FailedWithMessage(ErrMsg));
464 
465     // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
466     //    SymbolRef::getSection() calls it internally. We can't test it
467     //    directly, because it is protected.
468     EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
469                       FailedWithMessage(ErrMsg));
470 
471     // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
472     //    SymbolRef::getFlags() calls it internally. We can't test it directly,
473     //    because it is protected.
474     EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
475                       FailedWithMessage(ErrMsg));
476 
477     // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
478     //    SymbolRef::getType() calls it internally. We can't test it directly,
479     //    because it is protected.
480     EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
481                       FailedWithMessage(ErrMsg));
482 
483     // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
484     //    SymbolRef::getAddress() calls it internally. We can't test it
485     //    directly, because it is protected.
486     EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
487                       FailedWithMessage(ErrMsg));
488 
489     // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
490     // method that generates errors for all cases above.
491     EXPECT_THAT_EXPECTED(
492         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
493     EXPECT_THAT_ERROR(
494         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
495             .takeError(),
496         FailedWithMessage(ErrMsg));
497   };
498 
499   // We create a symbol with an index that is too large to exist in the symbol
500   // table.
501   DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
502                "section (0x18)");
503 
504   // We create a symbol with an index that is too large to exist in the object.
505   DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
506                       "end of the section (0x18)");
507 }
508 
509 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
510 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
511   if (IsHostWindows())
512     GTEST_SKIP();
513   StringRef CommonYamlString(R"(
514 --- !ELF
515 FileHeader:
516   Class: ELFCLASS64
517   Data:  ELFDATA2LSB
518   Type:  ET_EXEC
519 Sections:
520   - Type: SHT_LLVM_BB_ADDR_MAP
521     Name: .llvm_bb_addr_map
522     Entries:
523       - Address: 0x11111
524 )");
525 
526   auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
527     SmallString<0> Storage;
528     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
529         toBinary<ELF64LE>(Storage, YamlString);
530     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
531     const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
532 
533     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
534         Elf.getSection(1);
535     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
536     EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
537                       FailedWithMessage(ErrMsg));
538   };
539 
540   // Check that we can detect unsupported versions.
541   SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
542   UnsupportedVersionYamlString += R"(
543         Version: 3
544         BBEntries:
545           - AddressOffset: 0x0
546             Size:          0x1
547             Metadata:      0x2
548 )";
549 
550   {
551     SCOPED_TRACE("unsupported version");
552     DoCheck(UnsupportedVersionYamlString,
553             "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
554   }
555 
556   SmallString<128> CommonVersionedYamlString(CommonYamlString);
557   CommonVersionedYamlString += R"(
558         Version: 2
559         BBEntries:
560           - ID:            1
561             AddressOffset: 0x0
562             Size:          0x1
563             Metadata:      0x2
564 )";
565 
566   // Check that we can detect the malformed encoding when the section is
567   // truncated.
568   SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
569   TruncatedYamlString += R"(
570     ShSize: 0xb
571 )";
572   {
573     SCOPED_TRACE("truncated section");
574     DoCheck(TruncatedYamlString,
575             "unable to decode LEB128 at offset 0x0000000b: "
576             "malformed uleb128, extends past end");
577   }
578 
579   // Check that we can detect when the encoded BB entry fields exceed the UINT32
580   // limit.
581   SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
582       3, CommonVersionedYamlString);
583   OverInt32LimitYamlStrings[0] += R"(
584           - ID:            1
585             AddressOffset: 0x100000000
586             Size:          0xFFFFFFFF
587             Metadata:      0xFFFFFFFF
588 )";
589 
590   OverInt32LimitYamlStrings[1] += R"(
591           - ID:            2
592             AddressOffset: 0xFFFFFFFF
593             Size:          0x100000000
594             Metadata:      0xFFFFFFFF
595 )";
596 
597   OverInt32LimitYamlStrings[2] += R"(
598           - ID:            3
599             AddressOffset: 0xFFFFFFFF
600             Size:          0xFFFFFFFF
601             Metadata:      0x100000000
602 )";
603 
604   {
605     SCOPED_TRACE("overlimit fields");
606     DoCheck(OverInt32LimitYamlStrings[0],
607             "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
608     DoCheck(OverInt32LimitYamlStrings[1],
609             "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
610     DoCheck(OverInt32LimitYamlStrings[2],
611             "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
612   }
613 
614   // Check the proper error handling when the section has fields exceeding
615   // UINT32 and is also truncated. This is for checking that we don't generate
616   // unhandled errors.
617   SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
618       3, OverInt32LimitYamlStrings[1]);
619   // Truncate before the end of the 5-byte field.
620   OverInt32LimitAndTruncated[0] += R"(
621     ShSize: 0x19
622 )";
623   // Truncate at the end of the 5-byte field.
624   OverInt32LimitAndTruncated[1] += R"(
625     ShSize: 0x1a
626 )";
627   // Truncate after the end of the 5-byte field.
628   OverInt32LimitAndTruncated[2] += R"(
629     ShSize: 0x1b
630 )";
631 
632   {
633     SCOPED_TRACE("overlimit fields, truncated section");
634     DoCheck(OverInt32LimitAndTruncated[0],
635             "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
636             "extends past end");
637     DoCheck(OverInt32LimitAndTruncated[1],
638             "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
639     DoCheck(OverInt32LimitAndTruncated[2],
640             "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
641   }
642 
643   // Check for proper error handling when the 'NumBlocks' field is overridden
644   // with an out-of-range value.
645   SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
646   OverLimitNumBlocks += R"(
647         NumBlocks: 0x100000000
648 )";
649 
650   {
651     SCOPED_TRACE("overlimit 'NumBlocks' field");
652     DoCheck(OverLimitNumBlocks,
653             "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
654   }
655 }
656 
657 // Test for the ELFObjectFile::readBBAddrMap API.
658 TEST(ELFObjectFileTest, ReadBBAddrMap) {
659   if (IsHostWindows())
660     GTEST_SKIP();
661   StringRef CommonYamlString(R"(
662 --- !ELF
663 FileHeader:
664   Class: ELFCLASS64
665   Data:  ELFDATA2LSB
666   Type:  ET_EXEC
667 Sections:
668   - Name: .llvm_bb_addr_map_1
669     Type: SHT_LLVM_BB_ADDR_MAP
670     Link: 1
671     Entries:
672       - Version: 2
673         Address: 0x11111
674         BBEntries:
675           - ID:            1
676             AddressOffset: 0x0
677             Size:          0x1
678             Metadata:      0x2
679   - Name: .llvm_bb_addr_map_2
680     Type: SHT_LLVM_BB_ADDR_MAP
681     Link: 1
682     Entries:
683       - Version: 2
684         Address: 0x22222
685         BBEntries:
686           - ID:            2
687             AddressOffset: 0x0
688             Size:          0x2
689             Metadata:      0x4
690   - Name: .llvm_bb_addr_map_3
691     Type: SHT_LLVM_BB_ADDR_MAP
692     Link: 2
693     Entries:
694       - Version: 1
695         Address: 0x33333
696         BBEntries:
697           - ID:            0
698             AddressOffset: 0x0
699             Size:          0x3
700             Metadata:      0x6
701   - Name: .llvm_bb_addr_map_4
702     Type: SHT_LLVM_BB_ADDR_MAP_V0
703   # Link: 0 (by default, can be overriden)
704     Entries:
705       - Version: 0
706         Address: 0x44444
707         BBEntries:
708           - ID:            0
709             AddressOffset: 0x0
710             Size:          0x4
711             Metadata:      0x18
712 )");
713 
714   BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}});
715   BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}});
716   BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}});
717   BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}});
718 
719   std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
720   std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
721   std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
722   std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
723 
724   auto DoCheckSucceeds = [&](StringRef YamlString,
725                              std::optional<unsigned> TextSectionIndex,
726                              std::vector<BBAddrMap> ExpectedResult) {
727     SCOPED_TRACE("for TextSectionIndex: " +
728                  (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +
729                  " and object yaml:\n" + YamlString);
730     SmallString<0> Storage;
731     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
732         toBinary<ELF64LE>(Storage, YamlString);
733     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
734 
735     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
736         ElfOrErr->getELFFile().getSection(1);
737     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
738     auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);
739     ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());
740     EXPECT_EQ(*BBAddrMaps, ExpectedResult);
741   };
742 
743   auto DoCheckFails = [&](StringRef YamlString,
744                           std::optional<unsigned> TextSectionIndex,
745                           const char *ErrMsg) {
746     SCOPED_TRACE("for TextSectionIndex: " +
747                  (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +
748                  " and object yaml:\n" + YamlString);
749     SmallString<0> Storage;
750     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
751         toBinary<ELF64LE>(Storage, YamlString);
752     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
753 
754     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
755         ElfOrErr->getELFFile().getSection(1);
756     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
757     EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(),
758                       FailedWithMessage(ErrMsg));
759   };
760 
761   {
762     SCOPED_TRACE("normal sections");
763     // Check that we can retrieve the data in the normal case.
764     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
765                     AllBBAddrMaps);
766     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,
767                     Section0BBAddrMaps);
768     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,
769                     Section1BBAddrMaps);
770     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,
771                     Section2BBAddrMaps);
772     // Check that when no bb-address-map section is found for a text section,
773     // we return an empty result.
774     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});
775   }
776 
777   // Check that we detect when a bb-addr-map section is linked to an invalid
778   // (not present) section.
779   SmallString<128> InvalidLinkedYamlString(CommonYamlString);
780   InvalidLinkedYamlString += R"(
781     Link: 10
782 )";
783 
784   DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
785                "unable to get the linked-to section for "
786                "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
787                "index: 10");
788   {
789     SCOPED_TRACE("invalid linked section");
790     // Linked sections are not checked when we don't target a specific text
791     // section.
792     DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
793                     AllBBAddrMaps);
794   }
795 
796   // Check that we can detect when bb-address-map decoding fails.
797   SmallString<128> TruncatedYamlString(CommonYamlString);
798   TruncatedYamlString += R"(
799     ShSize: 0x8
800 )";
801 
802   {
803     SCOPED_TRACE("truncated section");
804     DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
805                  "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
806                  "unable to decode LEB128 at offset 0x00000008: malformed "
807                  "uleb128, extends past end");
808 
809     // Check that we can read the other section's bb-address-maps which are
810     // valid.
811     DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
812                     Section1BBAddrMaps);
813   }
814 }
815 
816 // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap
817 // API.
818 TEST(ELFObjectFileTest, InvalidDecodePGOAnalysisMap) {
819   if (IsHostWindows())
820     GTEST_SKIP();
821   StringRef CommonYamlString(R"(
822 --- !ELF
823 FileHeader:
824   Class: ELFCLASS64
825   Data:  ELFDATA2LSB
826   Type:  ET_EXEC
827 Sections:
828   - Type: SHT_LLVM_BB_ADDR_MAP
829     Name: .llvm_bb_addr_map
830     Entries:
831       - Address: 0x11111
832 )");
833 
834   auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
835     SmallString<0> Storage;
836     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
837         toBinary<ELF64LE>(Storage, YamlString);
838     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
839     const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
840 
841     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
842         Elf.getSection(1);
843     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
844 
845     std::vector<PGOAnalysisMap> PGOAnalyses;
846     EXPECT_THAT_ERROR(
847         Elf.decodeBBAddrMap(**BBAddrMapSecOrErr, nullptr, &PGOAnalyses)
848             .takeError(),
849         FailedWithMessage(ErrMsg));
850   };
851 
852   // Check that we can detect unsupported versions that are too old.
853   SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);
854   UnsupportedLowVersionYamlString += R"(
855         Version: 1
856         Feature: 0x4
857         BBEntries:
858           - AddressOffset: 0x0
859             Size:          0x1
860             Metadata:      0x2
861 )";
862 
863   {
864     SCOPED_TRACE("unsupported version");
865     DoCheck(UnsupportedLowVersionYamlString,
866             "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features "
867             "are enabled: version = 1 feature = 4");
868   }
869 
870   SmallString<128> CommonVersionedYamlString(CommonYamlString);
871   CommonVersionedYamlString += R"(
872         Version: 2
873         BBEntries:
874           - ID:            1
875             AddressOffset: 0x0
876             Size:          0x1
877             Metadata:      0x2
878 )";
879 
880   // Check that we fail when function entry count is enabled but not provided.
881   SmallString<128> MissingFuncEntryCount(CommonYamlString);
882   MissingFuncEntryCount += R"(
883         Version: 2
884         Feature: 0x01
885 )";
886 
887   {
888     SCOPED_TRACE("missing function entry count");
889     DoCheck(MissingFuncEntryCount,
890             "unable to decode LEB128 at offset 0x0000000b: malformed uleb128, "
891             "extends past end");
892   }
893 
894   // Check that we fail when basic block frequency is enabled but not provided.
895   SmallString<128> MissingBBFreq(CommonYamlString);
896   MissingBBFreq += R"(
897         Version: 2
898         Feature: 0x02
899         BBEntries:
900           - ID:            1
901             AddressOffset: 0x0
902             Size:          0x1
903             Metadata:      0x2
904 )";
905 
906   {
907     SCOPED_TRACE("missing bb frequency");
908     DoCheck(MissingBBFreq, "unable to decode LEB128 at offset 0x0000000f: "
909                            "malformed uleb128, extends past end");
910   }
911 
912   // Check that we fail when branch probability is enabled but not provided.
913   SmallString<128> MissingBrProb(CommonYamlString);
914   MissingBrProb += R"(
915         Version: 2
916         Feature: 0x04
917         BBEntries:
918           - ID:            1
919             AddressOffset: 0x0
920             Size:          0x1
921             Metadata:      0x6
922           - ID:            2
923             AddressOffset: 0x1
924             Size:          0x1
925             Metadata:      0x2
926           - ID:            3
927             AddressOffset: 0x2
928             Size:          0x1
929             Metadata:      0x2
930     PGOAnalyses:
931       - PGOBBEntries:
932          - Successors:
933             - ID:          2
934               BrProb:      0x80000000
935             - ID:          3
936               BrProb:      0x80000000
937          - Successors:
938             - ID:          3
939               BrProb:      0xF0000000
940 )";
941 
942   {
943     SCOPED_TRACE("missing branch probability");
944     DoCheck(MissingBrProb, "unable to decode LEB128 at offset 0x00000017: "
945                            "malformed uleb128, extends past end");
946   }
947 }
948 
949 // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap.
950 TEST(ELFObjectFileTest, ReadPGOAnalysisMap) {
951   if (IsHostWindows())
952     GTEST_SKIP();
953   StringRef CommonYamlString(R"(
954 --- !ELF
955 FileHeader:
956   Class: ELFCLASS64
957   Data:  ELFDATA2LSB
958   Type:  ET_EXEC
959 Sections:
960   - Name: .llvm_bb_addr_map_1
961     Type: SHT_LLVM_BB_ADDR_MAP
962     Link: 1
963     Entries:
964       - Version: 2
965         Address: 0x11111
966         Feature: 0x1
967         BBEntries:
968           - ID:            1
969             AddressOffset: 0x0
970             Size:          0x1
971             Metadata:      0x2
972     PGOAnalyses:
973       - FuncEntryCount: 892
974   - Name: .llvm_bb_addr_map_2
975     Type: SHT_LLVM_BB_ADDR_MAP
976     Link: 1
977     Entries:
978       - Version: 2
979         Address: 0x22222
980         Feature: 0x2
981         BBEntries:
982           - ID:            2
983             AddressOffset: 0x0
984             Size:          0x2
985             Metadata:      0x4
986     PGOAnalyses:
987       - PGOBBEntries:
988          - BBFreq:         343
989   - Name: .llvm_bb_addr_map_3
990     Type: SHT_LLVM_BB_ADDR_MAP
991     Link: 2
992     Entries:
993       - Version: 2
994         Address: 0x33333
995         Feature: 0x4
996         BBEntries:
997           - ID:            0
998             AddressOffset: 0x0
999             Size:          0x3
1000             Metadata:      0x6
1001           - ID:            1
1002             AddressOffset: 0x0
1003             Size:          0x3
1004             Metadata:      0x4
1005           - ID:            2
1006             AddressOffset: 0x0
1007             Size:          0x3
1008             Metadata:      0x0
1009     PGOAnalyses:
1010       - PGOBBEntries:
1011          - Successors:
1012             - ID:          1
1013               BrProb:      0x11111111
1014             - ID:          2
1015               BrProb:      0xeeeeeeee
1016          - Successors:
1017             - ID:          2
1018               BrProb:      0xffffffff
1019          - Successors:     []
1020   - Name: .llvm_bb_addr_map_4
1021     Type: SHT_LLVM_BB_ADDR_MAP
1022   # Link: 0 (by default, can be overriden)
1023     Entries:
1024       - Version: 2
1025         Address: 0x44444
1026         Feature: 0x7
1027         BBEntries:
1028           - ID:            0
1029             AddressOffset: 0x0
1030             Size:          0x4
1031             Metadata:      0x18
1032           - ID:            1
1033             AddressOffset: 0x0
1034             Size:          0x4
1035             Metadata:      0x0
1036           - ID:            2
1037             AddressOffset: 0x0
1038             Size:          0x4
1039             Metadata:      0x0
1040           - ID:            3
1041             AddressOffset: 0x0
1042             Size:          0x4
1043             Metadata:      0x0
1044     PGOAnalyses:
1045       - FuncEntryCount: 1000
1046         PGOBBEntries:
1047           - BBFreq:         1000
1048             Successors:
1049             - ID:          1
1050               BrProb:      0x22222222
1051             - ID:          2
1052               BrProb:      0x33333333
1053             - ID:          3
1054               BrProb:      0xaaaaaaaa
1055           - BBFreq:         133
1056             Successors:
1057             - ID:          2
1058               BrProb:      0x11111111
1059             - ID:          3
1060               BrProb:      0xeeeeeeee
1061           - BBFreq:         18
1062             Successors:
1063             - ID:          3
1064               BrProb:      0xffffffff
1065           - BBFreq:         1000
1066             Successors:    []
1067   - Name: .llvm_bb_addr_map_5
1068     Type: SHT_LLVM_BB_ADDR_MAP
1069   # Link: 0 (by default, can be overriden)
1070     Entries:
1071       - Version: 2
1072         Address: 0x55555
1073         Feature: 0x0
1074         BBEntries:
1075           - ID:            2
1076             AddressOffset: 0x0
1077             Size:          0x2
1078             Metadata:      0x4
1079     PGOAnalyses: [{}]
1080  )");
1081 
1082   BBAddrMap E1(0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}});
1083   PGOAnalysisMap P1 = {892, {}, {true, false, false}};
1084   BBAddrMap E2(0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}});
1085   PGOAnalysisMap P2 = {{}, {{BlockFrequency(343), {}}}, {false, true, false}};
1086   BBAddrMap E3(0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}},
1087                          {1, 0x3, 0x3, {false, false, true, false, false}},
1088                          {2, 0x6, 0x3, {false, false, false, false, false}}});
1089   PGOAnalysisMap P3 = {{},
1090                        {{{},
1091                          {{1, BranchProbability::getRaw(0x1111'1111)},
1092                           {2, BranchProbability::getRaw(0xeeee'eeee)}}},
1093                         {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}},
1094                         {{}, {}}},
1095                        {false, false, true}};
1096   BBAddrMap E4(0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}},
1097                          {1, 0x4, 0x4, {false, false, false, false, false}},
1098                          {2, 0x8, 0x4, {false, false, false, false, false}},
1099                          {3, 0xc, 0x4, {false, false, false, false, false}}});
1100   PGOAnalysisMap P4 = {
1101       1000,
1102       {{BlockFrequency(1000),
1103         {{1, BranchProbability::getRaw(0x2222'2222)},
1104          {2, BranchProbability::getRaw(0x3333'3333)},
1105          {3, BranchProbability::getRaw(0xaaaa'aaaa)}}},
1106        {BlockFrequency(133),
1107         {{2, BranchProbability::getRaw(0x1111'1111)},
1108          {3, BranchProbability::getRaw(0xeeee'eeee)}}},
1109        {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}},
1110        {BlockFrequency(1000), {}}},
1111       {true, true, true}};
1112   BBAddrMap E5(0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}});
1113   PGOAnalysisMap P5 = {{}, {}, {false, false, false}};
1114 
1115   std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5};
1116   std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
1117   std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
1118   std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4, E5};
1119 
1120   std::vector<PGOAnalysisMap> Section0PGOAnalysisMaps = {P4, P5};
1121   std::vector<PGOAnalysisMap> Section1PGOAnalysisMaps = {P3};
1122   std::vector<PGOAnalysisMap> Section2PGOAnalysisMaps = {P1, P2};
1123   std::vector<PGOAnalysisMap> AllPGOAnalysisMaps = {P1, P2, P3, P4, P5};
1124 
1125   auto DoCheckSucceeds =
1126       [&](StringRef YamlString, std::optional<unsigned> TextSectionIndex,
1127           std::vector<BBAddrMap> ExpectedResult,
1128           std::optional<std::vector<PGOAnalysisMap>> ExpectedPGO) {
1129         SCOPED_TRACE(
1130             "for TextSectionIndex: " +
1131             (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +
1132             " and object yaml:\n" + YamlString);
1133         SmallString<0> Storage;
1134         Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1135             toBinary<ELF64LE>(Storage, YamlString);
1136         ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1137 
1138         Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
1139             ElfOrErr->getELFFile().getSection(1);
1140         ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
1141 
1142         std::vector<PGOAnalysisMap> PGOAnalyses;
1143         auto BBAddrMaps = ElfOrErr->readBBAddrMap(
1144             TextSectionIndex, ExpectedPGO ? &PGOAnalyses : nullptr);
1145         ASSERT_THAT_EXPECTED(BBAddrMaps, Succeeded());
1146         EXPECT_EQ(*BBAddrMaps, ExpectedResult);
1147         if (ExpectedPGO) {
1148           EXPECT_EQ(BBAddrMaps->size(), PGOAnalyses.size());
1149           EXPECT_EQ(PGOAnalyses, *ExpectedPGO);
1150           for (auto &&[BB, PGO] : llvm::zip(*BBAddrMaps, PGOAnalyses)) {
1151             if (PGO.FeatEnable.BBFreq || PGO.FeatEnable.BrProb)
1152               EXPECT_EQ(BB.getBBEntries().size(), PGO.BBEntries.size());
1153           }
1154         }
1155       };
1156 
1157   auto DoCheckFails = [&](StringRef YamlString,
1158                           std::optional<unsigned> TextSectionIndex,
1159                           const char *ErrMsg) {
1160     SCOPED_TRACE("for TextSectionIndex: " +
1161                  (TextSectionIndex ? llvm::Twine(*TextSectionIndex) : "{}") +
1162                  " and object yaml:\n" + YamlString);
1163     SmallString<0> Storage;
1164     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1165         toBinary<ELF64LE>(Storage, YamlString);
1166     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1167 
1168     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
1169         ElfOrErr->getELFFile().getSection(1);
1170     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
1171     std::vector<PGOAnalysisMap> PGOAnalyses;
1172     EXPECT_THAT_ERROR(
1173         ElfOrErr->readBBAddrMap(TextSectionIndex, &PGOAnalyses).takeError(),
1174         FailedWithMessage(ErrMsg));
1175   };
1176 
1177   {
1178     SCOPED_TRACE("normal sections");
1179     // Check that we can retrieve the data in the normal case.
1180     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
1181                     AllBBAddrMaps, std::nullopt);
1182     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,
1183                     Section0BBAddrMaps, std::nullopt);
1184     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,
1185                     Section1BBAddrMaps, std::nullopt);
1186     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,
1187                     Section2BBAddrMaps, std::nullopt);
1188 
1189     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
1190                     AllBBAddrMaps, AllPGOAnalysisMaps);
1191     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0,
1192                     Section0BBAddrMaps, Section0PGOAnalysisMaps);
1193     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2,
1194                     Section1BBAddrMaps, Section1PGOAnalysisMaps);
1195     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1,
1196                     Section2BBAddrMaps, Section2PGOAnalysisMaps);
1197     // Check that when no bb-address-map section is found for a text section,
1198     // we return an empty result.
1199     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {}, std::nullopt);
1200     DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {},
1201                     std::vector<PGOAnalysisMap>{});
1202   }
1203 
1204   // Check that we detect when a bb-addr-map section is linked to an invalid
1205   // (not present) section.
1206   SmallString<128> InvalidLinkedYamlString(CommonYamlString);
1207   InvalidLinkedYamlString += R"(
1208     Link: 10
1209 )";
1210 
1211   {
1212     SCOPED_TRACE("invalid linked section");
1213     DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/5,
1214                  "unable to get the linked-to section for "
1215                  "SHT_LLVM_BB_ADDR_MAP section with index 5: invalid section "
1216                  "index: 10");
1217 
1218     // Linked sections are not checked when we don't target a specific text
1219     // section.
1220     DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
1221                     AllBBAddrMaps, std::nullopt);
1222     DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
1223                     AllBBAddrMaps, AllPGOAnalysisMaps);
1224   }
1225 
1226   // Check that we can detect when bb-address-map decoding fails.
1227   SmallString<128> TruncatedYamlString(CommonYamlString);
1228   TruncatedYamlString += R"(
1229     ShSize: 0xa
1230 )";
1231 
1232   {
1233     SCOPED_TRACE("truncated section");
1234     DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
1235                  "unable to read SHT_LLVM_BB_ADDR_MAP section with index 5: "
1236                  "unable to decode LEB128 at offset 0x0000000a: malformed "
1237                  "uleb128, extends past end");
1238     // Check that we can read the other section's bb-address-maps which are
1239     // valid.
1240     DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
1241                     Section1BBAddrMaps, std::nullopt);
1242     DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
1243                     Section1BBAddrMaps, Section1PGOAnalysisMaps);
1244   }
1245 }
1246 
1247 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
1248 // section for executable and relocatable files.
1249 TEST(ELFObjectFileTest, ExecutableWithRelocs) {
1250   StringRef HeaderString(R"(
1251 --- !ELF
1252 FileHeader:
1253   Class: ELFCLASS64
1254   Data:  ELFDATA2LSB
1255 )");
1256   StringRef ContentsString(R"(
1257 Sections:
1258   - Name:  .text
1259     Type:  SHT_PROGBITS
1260     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1261   - Name:  .rela.text
1262     Type:  SHT_RELA
1263     Flags: [ SHF_INFO_LINK ]
1264     Info:  .text
1265 )");
1266 
1267   auto DoCheck = [&](StringRef YamlString) {
1268     SmallString<0> Storage;
1269     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1270         toBinary<ELF64LE>(Storage, YamlString);
1271     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1272     const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
1273 
1274     bool FoundRela;
1275 
1276     for (SectionRef Sec : Obj.sections()) {
1277       Expected<StringRef> SecNameOrErr = Sec.getName();
1278       ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());
1279       StringRef SecName = *SecNameOrErr;
1280       if (SecName != ".rela.text")
1281         continue;
1282       FoundRela = true;
1283       Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
1284       ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());
1285       section_iterator RelSec = *RelSecOrErr;
1286       ASSERT_NE(RelSec, Obj.section_end());
1287       Expected<StringRef> TextSecNameOrErr = RelSec->getName();
1288       ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());
1289       StringRef TextSecName = *TextSecNameOrErr;
1290       EXPECT_EQ(TextSecName, ".text");
1291     }
1292     ASSERT_TRUE(FoundRela);
1293   };
1294 
1295   // Check ET_EXEC file (`ld --emit-relocs` use-case).
1296   SmallString<128> ExecFileYamlString(HeaderString);
1297   ExecFileYamlString += R"(
1298   Type:  ET_EXEC
1299 )";
1300   ExecFileYamlString += ContentsString;
1301   DoCheck(ExecFileYamlString);
1302 
1303   // Check ET_REL file.
1304   SmallString<128> RelocatableFileYamlString(HeaderString);
1305   RelocatableFileYamlString += R"(
1306   Type:  ET_REL
1307 )";
1308   RelocatableFileYamlString += ContentsString;
1309   DoCheck(RelocatableFileYamlString);
1310 }
1311 
1312 TEST(ELFObjectFileTest, GetSectionAndRelocations) {
1313   StringRef HeaderString(R"(
1314 --- !ELF
1315 FileHeader:
1316   Class: ELFCLASS64
1317   Data:  ELFDATA2LSB
1318   Type:  ET_EXEC
1319 )");
1320 
1321   using Elf_Shdr = Elf_Shdr_Impl<ELF64LE>;
1322 
1323   auto DoCheckSucceeds = [&](StringRef ContentsString,
1324                              std::function<Expected<bool>(const Elf_Shdr &)>
1325                                  Matcher) {
1326     SmallString<0> Storage;
1327     SmallString<128> FullYamlString(HeaderString);
1328     FullYamlString += ContentsString;
1329     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1330         toBinary<ELF64LE>(Storage, FullYamlString);
1331     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1332 
1333     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
1334         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
1335     ASSERT_THAT_EXPECTED(SecToRelocMapOrErr, Succeeded());
1336 
1337     // Basic verification to make sure we have the correct section types.
1338     for (auto const &[Sec, RelaSec] : *SecToRelocMapOrErr) {
1339       ASSERT_EQ(Sec->sh_type, ELF::SHT_PROGBITS);
1340       ASSERT_EQ(RelaSec->sh_type, ELF::SHT_RELA);
1341     }
1342   };
1343 
1344   auto DoCheckFails = [&](StringRef ContentsString,
1345                           std::function<Expected<bool>(const Elf_Shdr &)>
1346                               Matcher,
1347                           const char *ErrorMessage) {
1348     SmallString<0> Storage;
1349     SmallString<128> FullYamlString(HeaderString);
1350     FullYamlString += ContentsString;
1351     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
1352         toBinary<ELF64LE>(Storage, FullYamlString);
1353     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
1354 
1355     Expected<MapVector<const Elf_Shdr *, const Elf_Shdr *>> SecToRelocMapOrErr =
1356         ElfOrErr->getELFFile().getSectionAndRelocations(Matcher);
1357     ASSERT_THAT_ERROR(SecToRelocMapOrErr.takeError(),
1358                       FailedWithMessage(ErrorMessage));
1359   };
1360 
1361   auto DefaultMatcher = [](const Elf_Shdr &Sec) -> bool {
1362     return Sec.sh_type == ELF::SHT_PROGBITS;
1363   };
1364 
1365   StringRef TwoTextSections = R"(
1366 Sections:
1367   - Name: .text
1368     Type: SHT_PROGBITS
1369     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1370   - Name: .rela.text
1371     Type: SHT_RELA
1372     Flags: [ SHF_INFO_LINK ]
1373     Info: .text
1374   - Name: .text2
1375     Type: SHT_PROGBITS
1376     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1377   - Name: .rela.text2
1378     Type: SHT_RELA
1379     Flags: [ SHF_INFO_LINK ]
1380     Info: .text2
1381 )";
1382   DoCheckSucceeds(TwoTextSections, DefaultMatcher);
1383 
1384   StringRef OneTextSection = R"(
1385 Sections:
1386   - Name: .text
1387     Type: SHT_PROGBITS
1388     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1389 )";
1390 
1391   auto ErroringMatcher = [](const Elf_Shdr &Sec) -> Expected<bool> {
1392     if (Sec.sh_type == ELF::SHT_PROGBITS)
1393       return createError("This was supposed to fail.");
1394     return false;
1395   };
1396 
1397   DoCheckFails(OneTextSection, ErroringMatcher, "This was supposed to fail.");
1398 
1399   StringRef MissingRelocatableContent = R"(
1400 Sections:
1401   - Name: .rela.text
1402     Type: SHT_RELA
1403     Flags: [ SHF_INFO_LINK ]
1404     Info: 0xFF
1405 )";
1406 
1407   DoCheckFails(MissingRelocatableContent, DefaultMatcher,
1408                "SHT_RELA section with index 1: failed to get a "
1409                "relocated section: invalid section index: 255");
1410 }
1411