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