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