xref: /llvm-project/llvm/unittests/Object/ELFObjectFileTest.cpp (revision 3d6841b2b1a138b5b19fd57950079822565a3786)
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/MemoryBuffer.h"
13 #include "llvm/Support/YAMLTraits.h"
14 #include "llvm/Testing/Support/Error.h"
15 #include "gtest/gtest.h"
16 
17 #include "llvm/Support/Host.h"
18 #include "llvm/Support/thread.h"
19 
20 using namespace llvm;
21 using namespace llvm::object;
22 
23 // Used to skip LLVM_BB_ADDR_MAP tests on windows platforms due to
24 // https://github.com/llvm/llvm-project/issues/60013.
25 bool IsHostWindows() {
26   Triple Host(Triple::normalize(sys::getProcessTriple()));
27   return Host.isOSWindows();
28 }
29 
30 namespace {
31 
32 // A struct to initialize a buffer to represent an ELF object file.
33 struct DataForTest {
34   std::vector<uint8_t> Data;
35 
36   template <typename T>
37   std::vector<uint8_t> makeElfData(uint8_t Class, uint8_t Encoding,
38                                    uint16_t Machine) {
39     T Ehdr{}; // Zero-initialise the header.
40     Ehdr.e_ident[ELF::EI_MAG0] = 0x7f;
41     Ehdr.e_ident[ELF::EI_MAG1] = 'E';
42     Ehdr.e_ident[ELF::EI_MAG2] = 'L';
43     Ehdr.e_ident[ELF::EI_MAG3] = 'F';
44     Ehdr.e_ident[ELF::EI_CLASS] = Class;
45     Ehdr.e_ident[ELF::EI_DATA] = Encoding;
46     Ehdr.e_ident[ELF::EI_VERSION] = 1;
47     Ehdr.e_type = ELF::ET_REL;
48     Ehdr.e_machine = Machine;
49     Ehdr.e_version = 1;
50     Ehdr.e_ehsize = sizeof(T);
51 
52     bool IsLittleEndian = Encoding == ELF::ELFDATA2LSB;
53     if (sys::IsLittleEndianHost != IsLittleEndian) {
54       sys::swapByteOrder(Ehdr.e_type);
55       sys::swapByteOrder(Ehdr.e_machine);
56       sys::swapByteOrder(Ehdr.e_version);
57       sys::swapByteOrder(Ehdr.e_ehsize);
58     }
59 
60     uint8_t *EhdrBytes = reinterpret_cast<uint8_t *>(&Ehdr);
61     std::vector<uint8_t> Bytes;
62     std::copy(EhdrBytes, EhdrBytes + sizeof(Ehdr), std::back_inserter(Bytes));
63     return Bytes;
64   }
65 
66   DataForTest(uint8_t Class, uint8_t Encoding, uint16_t Machine) {
67     if (Class == ELF::ELFCLASS64)
68       Data = makeElfData<ELF::Elf64_Ehdr>(Class, Encoding, Machine);
69     else {
70       assert(Class == ELF::ELFCLASS32);
71       Data = makeElfData<ELF::Elf32_Ehdr>(Class, Encoding, Machine);
72     }
73   }
74 };
75 
76 void checkFormatAndArch(const DataForTest &D, StringRef Fmt,
77                         Triple::ArchType Arch) {
78   Expected<std::unique_ptr<ObjectFile>> ELFObjOrErr =
79       object::ObjectFile::createELFObjectFile(
80           MemoryBufferRef(toStringRef(D.Data), "dummyELF"));
81   ASSERT_THAT_EXPECTED(ELFObjOrErr, Succeeded());
82 
83   const ObjectFile &File = *(*ELFObjOrErr).get();
84   EXPECT_EQ(Fmt, File.getFileFormatName());
85   EXPECT_EQ(Arch, File.getArch());
86 }
87 
88 std::array<DataForTest, 4> generateData(uint16_t Machine) {
89   return {DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2LSB, Machine),
90           DataForTest(ELF::ELFCLASS32, ELF::ELFDATA2MSB, Machine),
91           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2LSB, Machine),
92           DataForTest(ELF::ELFCLASS64, ELF::ELFDATA2MSB, Machine)};
93 }
94 
95 } // namespace
96 
97 TEST(ELFObjectFileTest, MachineTestForNoneOrUnused) {
98   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
99                                       "elf64-unknown", "elf64-unknown"};
100   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_NONE)))
101     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
102 
103   // Test an arbitrary unused EM_* value (255).
104   for (auto [Idx, Data] : enumerate(generateData(255)))
105     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
106 }
107 
108 TEST(ELFObjectFileTest, MachineTestForVE) {
109   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
110                                       "elf64-ve", "elf64-ve"};
111   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_VE)))
112     checkFormatAndArch(Data, Formats[Idx], Triple::ve);
113 }
114 
115 TEST(ELFObjectFileTest, MachineTestForX86_64) {
116   std::array<StringRef, 4> Formats = {"elf32-x86-64", "elf32-x86-64",
117                                       "elf64-x86-64", "elf64-x86-64"};
118   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_X86_64)))
119     checkFormatAndArch(Data, Formats[Idx], Triple::x86_64);
120 }
121 
122 TEST(ELFObjectFileTest, MachineTestFor386) {
123   std::array<StringRef, 4> Formats = {"elf32-i386", "elf32-i386", "elf64-i386",
124                                       "elf64-i386"};
125   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_386)))
126     checkFormatAndArch(Data, Formats[Idx], Triple::x86);
127 }
128 
129 TEST(ELFObjectFileTest, MachineTestForMIPS) {
130   std::array<StringRef, 4> Formats = {"elf32-mips", "elf32-mips", "elf64-mips",
131                                       "elf64-mips"};
132   std::array<Triple::ArchType, 4> Archs = {Triple::mipsel, Triple::mips,
133                                            Triple::mips64el, Triple::mips64};
134   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MIPS)))
135     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
136 }
137 
138 TEST(ELFObjectFileTest, MachineTestForAMDGPU) {
139   std::array<StringRef, 4> Formats = {"elf32-amdgpu", "elf32-amdgpu",
140                                       "elf64-amdgpu", "elf64-amdgpu"};
141   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AMDGPU)))
142     checkFormatAndArch(Data, Formats[Idx], Triple::UnknownArch);
143 }
144 
145 TEST(ELFObjectFileTest, MachineTestForIAMCU) {
146   std::array<StringRef, 4> Formats = {"elf32-iamcu", "elf32-iamcu",
147                                       "elf64-unknown", "elf64-unknown"};
148   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_IAMCU)))
149     checkFormatAndArch(Data, Formats[Idx], Triple::x86);
150 }
151 
152 TEST(ELFObjectFileTest, MachineTestForAARCH64) {
153   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
154                                       "elf64-littleaarch64",
155                                       "elf64-bigaarch64"};
156   std::array<Triple::ArchType, 4> Archs = {Triple::aarch64, Triple::aarch64_be,
157                                            Triple::aarch64, Triple::aarch64_be};
158   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AARCH64)))
159     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
160 }
161 
162 TEST(ELFObjectFileTest, MachineTestForPPC64) {
163   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
164                                       "elf64-powerpcle", "elf64-powerpc"};
165   std::array<Triple::ArchType, 4> Archs = {Triple::ppc64le, Triple::ppc64,
166                                            Triple::ppc64le, Triple::ppc64};
167   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC64)))
168     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
169 }
170 
171 TEST(ELFObjectFileTest, MachineTestForPPC) {
172   std::array<StringRef, 4> Formats = {"elf32-powerpcle", "elf32-powerpc",
173                                       "elf64-unknown", "elf64-unknown"};
174   std::array<Triple::ArchType, 4> Archs = {Triple::ppcle, Triple::ppc,
175                                            Triple::ppcle, Triple::ppc};
176   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_PPC)))
177     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
178 }
179 
180 TEST(ELFObjectFileTest, MachineTestForRISCV) {
181   std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv",
182                                       "elf64-littleriscv", "elf64-littleriscv"};
183   std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32,
184                                            Triple::riscv64, Triple::riscv64};
185   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV)))
186     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
187 }
188 
189 TEST(ELFObjectFileTest, MachineTestForARM) {
190   std::array<StringRef, 4> Formats = {"elf32-littlearm", "elf32-bigarm",
191                                       "elf64-unknown", "elf64-unknown"};
192   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_ARM)))
193     checkFormatAndArch(Data, Formats[Idx], Triple::arm);
194 }
195 
196 TEST(ELFObjectFileTest, MachineTestForS390) {
197   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
198                                       "elf64-s390", "elf64-s390"};
199   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_S390)))
200     checkFormatAndArch(Data, Formats[Idx], Triple::systemz);
201 }
202 
203 TEST(ELFObjectFileTest, MachineTestForSPARCV9) {
204   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
205                                       "elf64-sparc", "elf64-sparc"};
206   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARCV9)))
207     checkFormatAndArch(Data, Formats[Idx], Triple::sparcv9);
208 }
209 
210 TEST(ELFObjectFileTest, MachineTestForSPARC) {
211   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
212                                       "elf64-unknown", "elf64-unknown"};
213   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
214                                            Triple::sparcel, Triple::sparc};
215   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC)))
216     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
217 }
218 
219 TEST(ELFObjectFileTest, MachineTestForSPARC32PLUS) {
220   std::array<StringRef, 4> Formats = {"elf32-sparc", "elf32-sparc",
221                                       "elf64-unknown", "elf64-unknown"};
222   std::array<Triple::ArchType, 4> Archs = {Triple::sparcel, Triple::sparc,
223                                            Triple::sparcel, Triple::sparc};
224   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_SPARC32PLUS)))
225     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
226 }
227 
228 TEST(ELFObjectFileTest, MachineTestForBPF) {
229   std::array<StringRef, 4> Formats = {"elf32-unknown", "elf32-unknown",
230                                       "elf64-bpf", "elf64-bpf"};
231   std::array<Triple::ArchType, 4> Archs = {Triple::bpfel, Triple::bpfeb,
232                                            Triple::bpfel, Triple::bpfeb};
233   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_BPF)))
234     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
235 }
236 
237 TEST(ELFObjectFileTest, MachineTestForAVR) {
238   std::array<StringRef, 4> Formats = {"elf32-avr", "elf32-avr", "elf64-unknown",
239                                       "elf64-unknown"};
240   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_AVR)))
241     checkFormatAndArch(Data, Formats[Idx], Triple::avr);
242 }
243 
244 TEST(ELFObjectFileTest, MachineTestForHEXAGON) {
245   std::array<StringRef, 4> Formats = {"elf32-hexagon", "elf32-hexagon",
246                                       "elf64-unknown", "elf64-unknown"};
247   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_HEXAGON)))
248     checkFormatAndArch(Data, Formats[Idx], Triple::hexagon);
249 }
250 
251 TEST(ELFObjectFileTest, MachineTestForLANAI) {
252   std::array<StringRef, 4> Formats = {"elf32-lanai", "elf32-lanai",
253                                       "elf64-unknown", "elf64-unknown"};
254   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LANAI)))
255     checkFormatAndArch(Data, Formats[Idx], Triple::lanai);
256 }
257 
258 TEST(ELFObjectFileTest, MachineTestForMSP430) {
259   std::array<StringRef, 4> Formats = {"elf32-msp430", "elf32-msp430",
260                                       "elf64-unknown", "elf64-unknown"};
261   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_MSP430)))
262     checkFormatAndArch(Data, Formats[Idx], Triple::msp430);
263 }
264 
265 TEST(ELFObjectFileTest, MachineTestForLoongArch) {
266   std::array<StringRef, 4> Formats = {"elf32-loongarch", "elf32-loongarch",
267                                       "elf64-loongarch", "elf64-loongarch"};
268   std::array<Triple::ArchType, 4> Archs = {
269       Triple::loongarch32, Triple::loongarch32, Triple::loongarch64,
270       Triple::loongarch64};
271   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_LOONGARCH)))
272     checkFormatAndArch(Data, Formats[Idx], Archs[Idx]);
273 }
274 
275 TEST(ELFObjectFileTest, MachineTestForCSKY) {
276   std::array<StringRef, 4> Formats = {"elf32-csky", "elf32-csky",
277                                       "elf64-unknown", "elf64-unknown"};
278   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_CSKY)))
279     checkFormatAndArch(Data, Formats[Idx], Triple::csky);
280 }
281 
282 TEST(ELFObjectFileTest, MachineTestForXtensa) {
283   std::array<StringRef, 4> Formats = {"elf32-xtensa", "elf32-xtensa",
284                                       "elf64-unknown", "elf64-unknown"};
285   for (auto [Idx, Data] : enumerate(generateData(ELF::EM_XTENSA)))
286     checkFormatAndArch(Data, Formats[Idx], Triple::xtensa);
287 }
288 
289 // ELF relative relocation type test.
290 TEST(ELFObjectFileTest, RelativeRelocationTypeTest) {
291   EXPECT_EQ(ELF::R_CKCORE_RELATIVE, getELFRelativeRelocationType(ELF::EM_CSKY));
292 }
293 
294 template <class ELFT>
295 static Expected<ELFObjectFile<ELFT>> toBinary(SmallVectorImpl<char> &Storage,
296                                               StringRef Yaml) {
297   raw_svector_ostream OS(Storage);
298   yaml::Input YIn(Yaml);
299   if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
300     return createStringError(std::errc::invalid_argument,
301                              "unable to convert YAML");
302   return ELFObjectFile<ELFT>::create(MemoryBufferRef(OS.str(), "dummyELF"));
303 }
304 
305 // Check we are able to create an ELFObjectFile even when the content of the
306 // SHT_SYMTAB_SHNDX section can't be read properly.
307 TEST(ELFObjectFileTest, InvalidSymtabShndxTest) {
308   SmallString<0> Storage;
309   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
310 --- !ELF
311 FileHeader:
312   Class: ELFCLASS64
313   Data:  ELFDATA2LSB
314   Type:  ET_REL
315 Sections:
316   - Name:    .symtab_shndx
317     Type:    SHT_SYMTAB_SHNDX
318     Entries: [ 0 ]
319     ShSize: 0xFFFFFFFF
320 )");
321 
322   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
323 }
324 
325 // Test that we are able to create an ELFObjectFile even when loadable segments
326 // are unsorted by virtual address.
327 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
328 
329 TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) {
330   SmallString<0> Storage;
331   Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"(
332 --- !ELF
333 FileHeader:
334   Class: ELFCLASS64
335   Data:  ELFDATA2LSB
336   Type:  ET_EXEC
337 Sections:
338   - Name:         .foo
339     Type:         SHT_PROGBITS
340     Address:      0x1000
341     Offset:       0x3000
342     ContentArray: [ 0x11 ]
343   - Name:         .bar
344     Type:         SHT_PROGBITS
345     Address:      0x2000
346     Offset:       0x4000
347     ContentArray: [ 0x99 ]
348 ProgramHeaders:
349   - Type:     PT_LOAD
350     VAddr:    0x2000
351     FirstSec: .bar
352     LastSec:  .bar
353   - Type:     PT_LOAD
354     VAddr:    0x1000
355     FirstSec: .foo
356     LastSec:  .foo
357 )");
358 
359   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());
360 
361   std::string WarnString;
362   auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * {
363     Expected<const uint8_t *> DataOrErr =
364         ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) {
365           EXPECT_TRUE(WarnString.empty());
366           WarnString = Msg.str();
367           return Error::success();
368         });
369 
370     if (!DataOrErr) {
371       ADD_FAILURE() << toString(DataOrErr.takeError());
372       return nullptr;
373     }
374 
375     EXPECT_TRUE(WarnString ==
376                 "loadable segments are unsorted by virtual address");
377     WarnString = "";
378     return *DataOrErr;
379   };
380 
381   const uint8_t *Data = ToMappedAddr(0x1000);
382   ASSERT_TRUE(Data);
383   MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef();
384   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000);
385   EXPECT_EQ(Data[0], 0x11);
386 
387   Data = ToMappedAddr(0x2000);
388   ASSERT_TRUE(Data);
389   Buf = ExpectedFile->getMemoryBufferRef();
390   EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000);
391   EXPECT_EQ(Data[0], 0x99);
392 }
393 
394 // This is a test for API that is related to symbols.
395 // We check that errors are properly reported here.
396 TEST(ELFObjectFileTest, InvalidSymbolTest) {
397   SmallString<0> Storage;
398   Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
399 --- !ELF
400 FileHeader:
401   Class:   ELFCLASS64
402   Data:    ELFDATA2LSB
403   Type:    ET_DYN
404   Machine: EM_X86_64
405 Sections:
406   - Name: .symtab
407     Type: SHT_SYMTAB
408 )");
409 
410   ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
411   const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
412   const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
413 
414   Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1);
415   ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded());
416   ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB);
417 
418   auto DoCheck = [&](unsigned BrokenSymIndex, const char *ErrMsg) {
419     ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex);
420 
421     // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
422     //    SymbolRef::getName() calls it internally. We can't test it directly,
423     //    because it is protected.
424     EXPECT_THAT_ERROR(BrokenSym.getName().takeError(),
425                       FailedWithMessage(ErrMsg));
426 
427     // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
428     EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(),
429                       FailedWithMessage(ErrMsg));
430 
431     // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
432     //    SymbolRef::getSection() calls it internally. We can't test it
433     //    directly, because it is protected.
434     EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(),
435                       FailedWithMessage(ErrMsg));
436 
437     // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
438     //    SymbolRef::getFlags() calls it internally. We can't test it directly,
439     //    because it is protected.
440     EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(),
441                       FailedWithMessage(ErrMsg));
442 
443     // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
444     //    SymbolRef::getType() calls it internally. We can't test it directly,
445     //    because it is protected.
446     EXPECT_THAT_ERROR(BrokenSym.getType().takeError(),
447                       FailedWithMessage(ErrMsg));
448 
449     // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
450     //    SymbolRef::getAddress() calls it internally. We can't test it
451     //    directly, because it is protected.
452     EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(),
453                       FailedWithMessage(ErrMsg));
454 
455     // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
456     // method that generates errors for all cases above.
457     EXPECT_THAT_EXPECTED(
458         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), Succeeded());
459     EXPECT_THAT_ERROR(
460         Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex)
461             .takeError(),
462         FailedWithMessage(ErrMsg));
463   };
464 
465   // We create a symbol with an index that is too large to exist in the symbol
466   // table.
467   DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
468                "section (0x18)");
469 
470   // We create a symbol with an index that is too large to exist in the object.
471   DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
472                       "end of the section (0x18)");
473 }
474 
475 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
476 TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
477   if (IsHostWindows()) return;
478   StringRef CommonYamlString(R"(
479 --- !ELF
480 FileHeader:
481   Class: ELFCLASS64
482   Data:  ELFDATA2LSB
483   Type:  ET_EXEC
484 Sections:
485   - Type: SHT_LLVM_BB_ADDR_MAP
486     Name: .llvm_bb_addr_map
487     Entries:
488       - Address: 0x11111
489 )");
490 
491   auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
492     SmallString<0> Storage;
493     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
494         toBinary<ELF64LE>(Storage, YamlString);
495     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
496     const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
497 
498     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
499         Elf.getSection(1);
500     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
501     EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
502                       FailedWithMessage(ErrMsg));
503   };
504 
505   // Check that we can detect unsupported versions.
506   SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
507   UnsupportedVersionYamlString += R"(
508         Version: 3
509         BBEntries:
510           - AddressOffset: 0x0
511             Size:          0x1
512             Metadata:      0x2
513 )";
514 
515   DoCheck(UnsupportedVersionYamlString,
516           "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
517 
518   SmallString<128> CommonVersionedYamlString(CommonYamlString);
519   CommonVersionedYamlString += R"(
520         Version: 2
521         BBEntries:
522           - ID:            1
523             AddressOffset: 0x0
524             Size:          0x1
525             Metadata:      0x2
526 )";
527 
528   // Check that we can detect the malformed encoding when the section is
529   // truncated.
530   SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
531   TruncatedYamlString += R"(
532     ShSize: 0xb
533 )";
534   DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000b: "
535                                "malformed uleb128, extends past end");
536 
537   // Check that we can detect when the encoded BB entry fields exceed the UINT32
538   // limit.
539   SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
540       3, CommonVersionedYamlString);
541   OverInt32LimitYamlStrings[0] += R"(
542           - ID:            1
543             AddressOffset: 0x100000000
544             Size:          0xFFFFFFFF
545             Metadata:      0xFFFFFFFF
546 )";
547 
548   OverInt32LimitYamlStrings[1] += R"(
549           - ID:            2
550             AddressOffset: 0xFFFFFFFF
551             Size:          0x100000000
552             Metadata:      0xFFFFFFFF
553 )";
554 
555   OverInt32LimitYamlStrings[2] += R"(
556           - ID:            3
557             AddressOffset: 0xFFFFFFFF
558             Size:          0xFFFFFFFF
559             Metadata:      0x100000000
560 )";
561 
562   DoCheck(OverInt32LimitYamlStrings[0],
563           "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
564   DoCheck(OverInt32LimitYamlStrings[1],
565           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
566   DoCheck(OverInt32LimitYamlStrings[2],
567           "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
568 
569   // Check the proper error handling when the section has fields exceeding
570   // UINT32 and is also truncated. This is for checking that we don't generate
571   // unhandled errors.
572   SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
573       3, OverInt32LimitYamlStrings[1]);
574   // Truncate before the end of the 5-byte field.
575   OverInt32LimitAndTruncated[0] += R"(
576     ShSize: 0x19
577 )";
578   // Truncate at the end of the 5-byte field.
579   OverInt32LimitAndTruncated[1] += R"(
580     ShSize: 0x1a
581 )";
582   // Truncate after the end of the 5-byte field.
583   OverInt32LimitAndTruncated[2] += R"(
584     ShSize: 0x1b
585 )";
586 
587   DoCheck(OverInt32LimitAndTruncated[0],
588           "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
589           "extends past end");
590   DoCheck(OverInt32LimitAndTruncated[1],
591           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
592   DoCheck(OverInt32LimitAndTruncated[2],
593           "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
594 
595   // Check for proper error handling when the 'NumBlocks' field is overridden
596   // with an out-of-range value.
597   SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
598   OverLimitNumBlocks += R"(
599         NumBlocks: 0x100000000
600 )";
601 
602   DoCheck(OverLimitNumBlocks,
603           "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
604 }
605 
606 // Test for the ELFObjectFile::readBBAddrMap API.
607 TEST(ELFObjectFileTest, ReadBBAddrMap) {
608   if (IsHostWindows()) return;
609   StringRef CommonYamlString(R"(
610 --- !ELF
611 FileHeader:
612   Class: ELFCLASS64
613   Data:  ELFDATA2LSB
614   Type:  ET_EXEC
615 Sections:
616   - Name: .llvm_bb_addr_map_1
617     Type: SHT_LLVM_BB_ADDR_MAP
618     Link: 1
619     Entries:
620       - Version: 2
621         Address: 0x11111
622         BBEntries:
623           - ID:            1
624             AddressOffset: 0x0
625             Size:          0x1
626             Metadata:      0x2
627   - Name: .llvm_bb_addr_map_2
628     Type: SHT_LLVM_BB_ADDR_MAP
629     Link: 1
630     Entries:
631       - Version: 2
632         Address: 0x22222
633         BBEntries:
634           - ID:            2
635             AddressOffset: 0x0
636             Size:          0x2
637             Metadata:      0x4
638   - Name: .llvm_bb_addr_map_3
639     Type: SHT_LLVM_BB_ADDR_MAP
640     Link: 2
641     Entries:
642       - Version: 1
643         Address: 0x33333
644         BBEntries:
645           - ID:            0
646             AddressOffset: 0x0
647             Size:          0x3
648             Metadata:      0x6
649   - Name: .llvm_bb_addr_map_4
650     Type: SHT_LLVM_BB_ADDR_MAP_V0
651   # Link: 0 (by default, can be overriden)
652     Entries:
653       - Version: 0
654         Address: 0x44444
655         BBEntries:
656           - ID:            0
657             AddressOffset: 0x0
658             Size:          0x4
659             Metadata:      0x8
660 )");
661 
662   BBAddrMap E1 = {0x11111, {{1, 0x0, 0x1, 0x2}}};
663   BBAddrMap E2 = {0x22222, {{2, 0x0, 0x2, 0x4}}};
664   BBAddrMap E3 = {0x33333, {{0, 0x0, 0x3, 0x6}}};
665   BBAddrMap E4 = {0x44444, {{0, 0x0, 0x4, 0x8}}};
666 
667   std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
668   std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
669   std::vector<BBAddrMap> Section2BBAddrMaps = {E1, E2};
670   std::vector<BBAddrMap> AllBBAddrMaps = {E1, E2, E3, E4};
671 
672   auto DoCheckSucceeds = [&](StringRef YamlString,
673                              std::optional<unsigned> TextSectionIndex,
674                              std::vector<BBAddrMap> ExpectedResult) {
675     SmallString<0> Storage;
676     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
677         toBinary<ELF64LE>(Storage, YamlString);
678     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
679 
680     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
681         ElfOrErr->getELFFile().getSection(1);
682     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
683     auto BBAddrMaps = ElfOrErr->readBBAddrMap(TextSectionIndex);
684     EXPECT_THAT_EXPECTED(BBAddrMaps, Succeeded());
685     EXPECT_EQ(*BBAddrMaps, ExpectedResult);
686   };
687 
688   auto DoCheckFails = [&](StringRef YamlString,
689                           std::optional<unsigned> TextSectionIndex,
690                           const char *ErrMsg) {
691     SmallString<0> Storage;
692     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
693         toBinary<ELF64LE>(Storage, YamlString);
694     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
695 
696     Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
697         ElfOrErr->getELFFile().getSection(1);
698     ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
699     EXPECT_THAT_ERROR(ElfOrErr->readBBAddrMap(TextSectionIndex).takeError(),
700                       FailedWithMessage(ErrMsg));
701   };
702 
703   // Check that we can retrieve the data in the normal case.
704   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/std::nullopt,
705                   AllBBAddrMaps);
706   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/0, Section0BBAddrMaps);
707   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/2, Section1BBAddrMaps);
708   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/1, Section2BBAddrMaps);
709   // Check that when no bb-address-map section is found for a text section,
710   // we return an empty result.
711   DoCheckSucceeds(CommonYamlString, /*TextSectionIndex=*/3, {});
712 
713   // Check that we detect when a bb-addr-map section is linked to an invalid
714   // (not present) section.
715   SmallString<128> InvalidLinkedYamlString(CommonYamlString);
716   InvalidLinkedYamlString += R"(
717     Link: 10
718 )";
719 
720   DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/4,
721                "unable to get the linked-to section for "
722                "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
723                "index: 10");
724   // Linked sections are not checked when we don't target a specific text
725   // section.
726   DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/std::nullopt,
727                   AllBBAddrMaps);
728 
729   // Check that we can detect when bb-address-map decoding fails.
730   SmallString<128> TruncatedYamlString(CommonYamlString);
731   TruncatedYamlString += R"(
732     ShSize: 0x8
733 )";
734 
735   DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/std::nullopt,
736                "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
737                "unable to decode LEB128 at offset 0x00000008: malformed "
738                "uleb128, extends past end");
739   // Check that we can read the other section's bb-address-maps which are
740   // valid.
741   DoCheckSucceeds(TruncatedYamlString, /*TextSectionIndex=*/2,
742                   Section1BBAddrMaps);
743 }
744 
745 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
746 // section for executable and relocatable files.
747 TEST(ELFObjectFileTest, ExecutableWithRelocs) {
748   StringRef HeaderString(R"(
749 --- !ELF
750 FileHeader:
751   Class: ELFCLASS64
752   Data:  ELFDATA2LSB
753 )");
754   StringRef ContentsString(R"(
755 Sections:
756   - Name:  .text
757     Type:  SHT_PROGBITS
758     Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
759   - Name:  .rela.text
760     Type:  SHT_RELA
761     Flags: [ SHF_INFO_LINK ]
762     Info:  .text
763 )");
764 
765   auto DoCheck = [&](StringRef YamlString) {
766     SmallString<0> Storage;
767     Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
768         toBinary<ELF64LE>(Storage, YamlString);
769     ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
770     const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
771 
772     bool FoundRela;
773 
774     for (SectionRef Sec : Obj.sections()) {
775       Expected<StringRef> SecNameOrErr = Sec.getName();
776       ASSERT_THAT_EXPECTED(SecNameOrErr, Succeeded());
777       StringRef SecName = *SecNameOrErr;
778       if (SecName != ".rela.text")
779         continue;
780       FoundRela = true;
781       Expected<section_iterator> RelSecOrErr = Sec.getRelocatedSection();
782       ASSERT_THAT_EXPECTED(RelSecOrErr, Succeeded());
783       section_iterator RelSec = *RelSecOrErr;
784       ASSERT_NE(RelSec, Obj.section_end());
785       Expected<StringRef> TextSecNameOrErr = RelSec->getName();
786       ASSERT_THAT_EXPECTED(TextSecNameOrErr, Succeeded());
787       StringRef TextSecName = *TextSecNameOrErr;
788       EXPECT_EQ(TextSecName, ".text");
789     }
790     ASSERT_TRUE(FoundRela);
791   };
792 
793   // Check ET_EXEC file (`ld --emit-relocs` use-case).
794   SmallString<128> ExecFileYamlString(HeaderString);
795   ExecFileYamlString += R"(
796   Type:  ET_EXEC
797 )";
798   ExecFileYamlString += ContentsString;
799   DoCheck(ExecFileYamlString);
800 
801   // Check ET_REL file.
802   SmallString<128> RelocatableFileYamlString(HeaderString);
803   RelocatableFileYamlString += R"(
804   Type:  ET_REL
805 )";
806   RelocatableFileYamlString += ContentsString;
807   DoCheck(RelocatableFileYamlString);
808 }
809