1 //===- ELFObjectFileTest.cpp - Tests for ELFObjectFile --------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
17 #include "llvm/Support/thread.h"
18 #include "llvm/TargetParser/Host.h"
21 using namespace llvm::object
;
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();
32 // A struct to initialize a buffer to represent an ELF object file.
34 std::vector
<uint8_t> Data
;
37 std::vector
<uint8_t> makeElfData(uint8_t Class
, uint8_t Encoding
,
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
;
50 Ehdr
.e_ehsize
= sizeof(T
);
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
);
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
));
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
);
70 assert(Class
== ELF::ELFCLASS32
);
71 Data
= makeElfData
<ELF::Elf32_Ehdr
>(Class
, Encoding
, Machine
);
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());
83 const ObjectFile
&File
= *(*ELFObjOrErr
).get();
84 EXPECT_EQ(Fmt
, File
.getFileFormatName());
85 EXPECT_EQ(Arch
, File
.getArch());
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
)};
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
);
103 // Test an arbitrary unused EM_* value (255).
104 for (auto [Idx
, Data
] : enumerate(generateData(255)))
105 checkFormatAndArch(Data
, Formats
[Idx
], Triple::UnknownArch
);
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
);
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
);
122 TEST(ELFObjectFileTest
, MachineTestFor386
) {
123 std::array
<StringRef
, 4> Formats
= {"elf32-i386", "elf32-i386", "elf64-i386",
125 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_386
)))
126 checkFormatAndArch(Data
, Formats
[Idx
], Triple::x86
);
129 TEST(ELFObjectFileTest
, MachineTestForMIPS
) {
130 std::array
<StringRef
, 4> Formats
= {"elf32-mips", "elf32-mips", "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
]);
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
);
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
);
152 TEST(ELFObjectFileTest
, MachineTestForAARCH64
) {
153 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
154 "elf64-littleaarch64",
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
]);
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
]);
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
]);
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
]);
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
);
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
);
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
);
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
]);
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
]);
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
]);
237 TEST(ELFObjectFileTest
, MachineTestForAVR
) {
238 std::array
<StringRef
, 4> Formats
= {"elf32-avr", "elf32-avr", "elf64-unknown",
240 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_AVR
)))
241 checkFormatAndArch(Data
, Formats
[Idx
], Triple::avr
);
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
);
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
);
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
);
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
]);
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
);
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
);
289 // ELF relative relocation type test.
290 TEST(ELFObjectFileTest
, RelativeRelocationTypeTest
) {
291 EXPECT_EQ(ELF::R_CKCORE_RELATIVE
, getELFRelativeRelocationType(ELF::EM_CSKY
));
294 template <class ELFT
>
295 static Expected
<ELFObjectFile
<ELFT
>> toBinary(SmallVectorImpl
<char> &Storage
,
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"));
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
"(
316 - Name: .symtab_shndx
317 Type: SHT_SYMTAB_SHNDX
322 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
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.
329 TEST(ELFObjectFileTest
, InvalidLoadSegmentsOrderTest
) {
330 SmallString
<0> Storage
;
331 Expected
<ELFObjectFile
<ELF64LE
>> ExpectedFile
= toBinary
<ELF64LE
>(Storage
, R
"(
342 ContentArray: [ 0x11 ]
347 ContentArray: [ 0x99 ]
359 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
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();
371 ADD_FAILURE() << toString(DataOrErr
.takeError());
375 EXPECT_TRUE(WarnString
==
376 "loadable segments are unsorted by virtual address");
381 const uint8_t *Data
= ToMappedAddr(0x1000);
383 MemoryBufferRef Buf
= ExpectedFile
->getMemoryBufferRef();
384 EXPECT_EQ((const char *)Data
- Buf
.getBufferStart(), 0x3000);
385 EXPECT_EQ(Data
[0], 0x11);
387 Data
= ToMappedAddr(0x2000);
389 Buf
= ExpectedFile
->getMemoryBufferRef();
390 EXPECT_EQ((const char *)Data
- Buf
.getBufferStart(), 0x4000);
391 EXPECT_EQ(Data
[0], 0x99);
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
"(
410 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
411 const ELFFile
<ELF64LE
> &Elf
= ElfOrErr
->getELFFile();
412 const ELFObjectFile
<ELF64LE
> &Obj
= *ElfOrErr
;
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
);
418 auto DoCheck
= [&](unsigned BrokenSymIndex
, const char *ErrMsg
) {
419 ELFSymbolRef BrokenSym
= Obj
.toSymbolRef(*SymtabSecOrErr
, BrokenSymIndex
);
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
));
427 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
428 EXPECT_THAT_ERROR(Obj
.getSymbol(BrokenSym
.getRawDataRefImpl()).takeError(),
429 FailedWithMessage(ErrMsg
));
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
));
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
));
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
));
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
));
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());
460 Elf
.getEntry
<typename
ELF64LE::Sym
>(**SymtabSecOrErr
, BrokenSymIndex
)
462 FailedWithMessage(ErrMsg
));
465 // We create a symbol with an index that is too large to exist in the symbol
467 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
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)");
475 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
476 TEST(ELFObjectFileTest
, InvalidDecodeBBAddrMap
) {
479 StringRef
CommonYamlString(R
"(
486 - Type: SHT_LLVM_BB_ADDR_MAP
487 Name: .llvm_bb_addr_map
492 auto DoCheck
= [&](StringRef YamlString
, const char *ErrMsg
) {
493 SmallString
<0> Storage
;
494 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
495 toBinary
<ELF64LE
>(Storage
, YamlString
);
496 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
497 const ELFFile
<ELF64LE
> &Elf
= ElfOrErr
->getELFFile();
499 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
501 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
502 EXPECT_THAT_ERROR(Elf
.decodeBBAddrMap(**BBAddrMapSecOrErr
).takeError(),
503 FailedWithMessage(ErrMsg
));
506 // Check that we can detect unsupported versions.
507 SmallString
<128> UnsupportedVersionYamlString(CommonYamlString
);
508 UnsupportedVersionYamlString
+= R
"(
516 DoCheck(UnsupportedVersionYamlString
,
517 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
519 SmallString
<128> CommonVersionedYamlString(CommonYamlString
);
520 CommonVersionedYamlString
+= R
"(
529 // Check that we can detect the malformed encoding when the section is
531 SmallString
<128> TruncatedYamlString(CommonVersionedYamlString
);
532 TruncatedYamlString
+= R
"(
535 DoCheck(TruncatedYamlString
, "unable to decode LEB128 at offset 0x0000000b: "
536 "malformed uleb128, extends past end");
538 // Check that we can detect when the encoded BB entry fields exceed the UINT32
540 SmallVector
<SmallString
<128>, 3> OverInt32LimitYamlStrings(
541 3, CommonVersionedYamlString
);
542 OverInt32LimitYamlStrings
[0] += R
"(
544 AddressOffset: 0x100000000
549 OverInt32LimitYamlStrings
[1] += R
"(
551 AddressOffset: 0xFFFFFFFF
556 OverInt32LimitYamlStrings
[2] += R
"(
558 AddressOffset: 0xFFFFFFFF
560 Metadata: 0x100000000
563 DoCheck(OverInt32LimitYamlStrings
[0],
564 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
565 DoCheck(OverInt32LimitYamlStrings
[1],
566 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
567 DoCheck(OverInt32LimitYamlStrings
[2],
568 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
570 // Check the proper error handling when the section has fields exceeding
571 // UINT32 and is also truncated. This is for checking that we don't generate
573 SmallVector
<SmallString
<128>, 3> OverInt32LimitAndTruncated(
574 3, OverInt32LimitYamlStrings
[1]);
575 // Truncate before the end of the 5-byte field.
576 OverInt32LimitAndTruncated
[0] += R
"(
579 // Truncate at the end of the 5-byte field.
580 OverInt32LimitAndTruncated
[1] += R
"(
583 // Truncate after the end of the 5-byte field.
584 OverInt32LimitAndTruncated
[2] += R
"(
588 DoCheck(OverInt32LimitAndTruncated
[0],
589 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
591 DoCheck(OverInt32LimitAndTruncated
[1],
592 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
593 DoCheck(OverInt32LimitAndTruncated
[2],
594 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
596 // Check for proper error handling when the 'NumBlocks' field is overridden
597 // with an out-of-range value.
598 SmallString
<128> OverLimitNumBlocks(CommonVersionedYamlString
);
599 OverLimitNumBlocks
+= R
"(
600 NumBlocks: 0x100000000
603 DoCheck(OverLimitNumBlocks
,
604 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
607 // Test for the ELFObjectFile::readBBAddrMap API.
608 TEST(ELFObjectFileTest
, ReadBBAddrMap
) {
611 StringRef
CommonYamlString(R
"(
618 - Name: .llvm_bb_addr_map_1
619 Type: SHT_LLVM_BB_ADDR_MAP
629 - Name: .llvm_bb_addr_map_2
630 Type: SHT_LLVM_BB_ADDR_MAP
640 - Name: .llvm_bb_addr_map_3
641 Type: SHT_LLVM_BB_ADDR_MAP
651 - Name: .llvm_bb_addr_map_4
652 Type: SHT_LLVM_BB_ADDR_MAP_V0
653 # Link: 0 (by default, can be overriden)
664 BBAddrMap E1
= {0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}};
665 BBAddrMap E2
= {0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}};
666 BBAddrMap E3
= {0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}};
667 BBAddrMap E4
= {0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}};
669 std::vector
<BBAddrMap
> Section0BBAddrMaps
= {E4
};
670 std::vector
<BBAddrMap
> Section1BBAddrMaps
= {E3
};
671 std::vector
<BBAddrMap
> Section2BBAddrMaps
= {E1
, E2
};
672 std::vector
<BBAddrMap
> AllBBAddrMaps
= {E1
, E2
, E3
, E4
};
674 auto DoCheckSucceeds
= [&](StringRef YamlString
,
675 std::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());
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
);
690 auto DoCheckFails
= [&](StringRef YamlString
,
691 std::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());
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
));
705 // Check that we can retrieve the data in the normal case.
706 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/std::nullopt
,
708 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/0, Section0BBAddrMaps
);
709 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/2, Section1BBAddrMaps
);
710 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/1, Section2BBAddrMaps
);
711 // Check that when no bb-address-map section is found for a text section,
712 // we return an empty result.
713 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/3, {});
715 // Check that we detect when a bb-addr-map section is linked to an invalid
716 // (not present) section.
717 SmallString
<128> InvalidLinkedYamlString(CommonYamlString
);
718 InvalidLinkedYamlString
+= R
"(
722 DoCheckFails(InvalidLinkedYamlString
, /*TextSectionIndex=*/4,
723 "unable to get the linked-to section for "
724 "SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: invalid section "
726 // Linked sections are not checked when we don't target a specific text
728 DoCheckSucceeds(InvalidLinkedYamlString
, /*TextSectionIndex=*/std::nullopt
,
731 // Check that we can detect when bb-address-map decoding fails.
732 SmallString
<128> TruncatedYamlString(CommonYamlString
);
733 TruncatedYamlString
+= R
"(
737 DoCheckFails(TruncatedYamlString
, /*TextSectionIndex=*/std::nullopt
,
738 "unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 4: "
739 "unable to decode LEB128 at offset 0x00000008: malformed "
740 "uleb128, extends past end");
741 // Check that we can read the other section's bb-address-maps which are
743 DoCheckSucceeds(TruncatedYamlString
, /*TextSectionIndex=*/2,
747 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
748 // section for executable and relocatable files.
749 TEST(ELFObjectFileTest
, ExecutableWithRelocs
) {
750 StringRef
HeaderString(R
"(
756 StringRef
ContentsString(R
"(
760 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
763 Flags: [ SHF_INFO_LINK ]
767 auto DoCheck
= [&](StringRef YamlString
) {
768 SmallString
<0> Storage
;
769 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
770 toBinary
<ELF64LE
>(Storage
, YamlString
);
771 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
772 const ELFObjectFile
<ELF64LE
> &Obj
= *ElfOrErr
;
776 for (SectionRef Sec
: Obj
.sections()) {
777 Expected
<StringRef
> SecNameOrErr
= Sec
.getName();
778 ASSERT_THAT_EXPECTED(SecNameOrErr
, Succeeded());
779 StringRef SecName
= *SecNameOrErr
;
780 if (SecName
!= ".rela.text")
783 Expected
<section_iterator
> RelSecOrErr
= Sec
.getRelocatedSection();
784 ASSERT_THAT_EXPECTED(RelSecOrErr
, Succeeded());
785 section_iterator RelSec
= *RelSecOrErr
;
786 ASSERT_NE(RelSec
, Obj
.section_end());
787 Expected
<StringRef
> TextSecNameOrErr
= RelSec
->getName();
788 ASSERT_THAT_EXPECTED(TextSecNameOrErr
, Succeeded());
789 StringRef TextSecName
= *TextSecNameOrErr
;
790 EXPECT_EQ(TextSecName
, ".text");
792 ASSERT_TRUE(FoundRela
);
795 // Check ET_EXEC file (`ld --emit-relocs` use-case).
796 SmallString
<128> ExecFileYamlString(HeaderString
);
797 ExecFileYamlString
+= R
"(
800 ExecFileYamlString
+= ContentsString
;
801 DoCheck(ExecFileYamlString
);
803 // Check ET_REL file.
804 SmallString
<128> RelocatableFileYamlString(HeaderString
);
805 RelocatableFileYamlString
+= R
"(
808 RelocatableFileYamlString
+= ContentsString
;
809 DoCheck(RelocatableFileYamlString
);
812 TEST(ELFObjectFileTest
, GetSectionAndRelocations
) {
813 StringRef
HeaderString(R
"(
821 using Elf_Shdr
= Elf_Shdr_Impl
<ELF64LE
>;
823 auto DoCheckSucceeds
= [&](StringRef ContentsString
,
824 std::function
<Expected
<bool>(const Elf_Shdr
&)>
826 SmallString
<0> Storage
;
827 SmallString
<128> FullYamlString(HeaderString
);
828 FullYamlString
+= ContentsString
;
829 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
830 toBinary
<ELF64LE
>(Storage
, FullYamlString
);
831 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
833 Expected
<MapVector
<const Elf_Shdr
*, const Elf_Shdr
*>> SecToRelocMapOrErr
=
834 ElfOrErr
->getELFFile().getSectionAndRelocations(Matcher
);
835 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr
, Succeeded());
837 // Basic verification to make sure we have the correct section types.
838 for (auto const &[Sec
, RelaSec
] : *SecToRelocMapOrErr
) {
839 ASSERT_EQ(Sec
->sh_type
, ELF::SHT_PROGBITS
);
840 ASSERT_EQ(RelaSec
->sh_type
, ELF::SHT_RELA
);
844 auto DoCheckFails
= [&](StringRef ContentsString
,
845 std::function
<Expected
<bool>(const Elf_Shdr
&)>
847 const char *ErrorMessage
) {
848 SmallString
<0> Storage
;
849 SmallString
<128> FullYamlString(HeaderString
);
850 FullYamlString
+= ContentsString
;
851 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
852 toBinary
<ELF64LE
>(Storage
, FullYamlString
);
853 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
855 Expected
<MapVector
<const Elf_Shdr
*, const Elf_Shdr
*>> SecToRelocMapOrErr
=
856 ElfOrErr
->getELFFile().getSectionAndRelocations(Matcher
);
857 ASSERT_THAT_ERROR(SecToRelocMapOrErr
.takeError(),
858 FailedWithMessage(ErrorMessage
));
861 auto DefaultMatcher
= [](const Elf_Shdr
&Sec
) -> bool {
862 return Sec
.sh_type
== ELF::SHT_PROGBITS
;
865 StringRef TwoTextSections
= R
"(
869 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
872 Flags: [ SHF_INFO_LINK ]
876 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
879 Flags: [ SHF_INFO_LINK ]
882 DoCheckSucceeds(TwoTextSections
, DefaultMatcher
);
884 StringRef OneTextSection
= R
"(
888 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
891 auto ErroringMatcher
= [](const Elf_Shdr
&Sec
) -> Expected
<bool> {
892 if(Sec
.sh_type
== ELF::SHT_PROGBITS
)
893 return createError("This was supposed to fail.");
897 DoCheckFails(OneTextSection
, ErroringMatcher
,
898 "This was supposed to fail.");
900 StringRef MissingRelocatableContent
= R
"(
904 Flags: [ SHF_INFO_LINK ]
908 DoCheckFails(MissingRelocatableContent
, DefaultMatcher
,
909 "SHT_RELA section with index 1: failed to get a "
910 "relocated section: invalid section index: 255");