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/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"
18 #include "llvm/Support/thread.h"
19 #include "llvm/TargetParser/Host.h"
22 using namespace llvm::object
;
26 // A struct to initialize a buffer to represent an ELF object file.
28 std::vector
<uint8_t> Data
;
31 std::vector
<uint8_t> makeElfData(uint8_t Class
, uint8_t Encoding
,
32 uint16_t Machine
, uint8_t OS
,
34 T Ehdr
{}; // Zero-initialise the header.
35 Ehdr
.e_ident
[ELF::EI_MAG0
] = 0x7f;
36 Ehdr
.e_ident
[ELF::EI_MAG1
] = 'E';
37 Ehdr
.e_ident
[ELF::EI_MAG2
] = 'L';
38 Ehdr
.e_ident
[ELF::EI_MAG3
] = 'F';
39 Ehdr
.e_ident
[ELF::EI_CLASS
] = Class
;
40 Ehdr
.e_ident
[ELF::EI_DATA
] = Encoding
;
41 Ehdr
.e_ident
[ELF::EI_VERSION
] = 1;
42 Ehdr
.e_ident
[ELF::EI_OSABI
] = OS
;
43 Ehdr
.e_type
= ELF::ET_REL
;
44 Ehdr
.e_machine
= Machine
;
47 Ehdr
.e_ehsize
= sizeof(T
);
49 bool IsLittleEndian
= Encoding
== ELF::ELFDATA2LSB
;
50 if (sys::IsLittleEndianHost
!= IsLittleEndian
) {
51 sys::swapByteOrder(Ehdr
.e_type
);
52 sys::swapByteOrder(Ehdr
.e_machine
);
53 sys::swapByteOrder(Ehdr
.e_version
);
54 sys::swapByteOrder(Ehdr
.e_ehsize
);
57 uint8_t *EhdrBytes
= reinterpret_cast<uint8_t *>(&Ehdr
);
58 std::vector
<uint8_t> Bytes
;
59 std::copy(EhdrBytes
, EhdrBytes
+ sizeof(Ehdr
), std::back_inserter(Bytes
));
63 DataForTest(uint8_t Class
, uint8_t Encoding
, uint16_t Machine
,
64 uint8_t OS
= ELF::ELFOSABI_NONE
, uint16_t Flags
= 0) {
65 if (Class
== ELF::ELFCLASS64
)
66 Data
= makeElfData
<ELF::Elf64_Ehdr
>(Class
, Encoding
, Machine
, OS
, Flags
);
68 assert(Class
== ELF::ELFCLASS32
);
69 Data
= makeElfData
<ELF::Elf32_Ehdr
>(Class
, Encoding
, Machine
, OS
, Flags
);
74 void checkFormatAndArch(const DataForTest
&D
, StringRef Fmt
,
75 Triple::ArchType Arch
) {
76 Expected
<std::unique_ptr
<ObjectFile
>> ELFObjOrErr
=
77 object::ObjectFile::createELFObjectFile(
78 MemoryBufferRef(toStringRef(D
.Data
), "dummyELF"));
79 ASSERT_THAT_EXPECTED(ELFObjOrErr
, Succeeded());
81 const ObjectFile
&File
= *(*ELFObjOrErr
).get();
82 EXPECT_EQ(Fmt
, File
.getFileFormatName());
83 EXPECT_EQ(Arch
, File
.getArch());
86 std::array
<DataForTest
, 4> generateData(uint16_t Machine
) {
87 return {DataForTest(ELF::ELFCLASS32
, ELF::ELFDATA2LSB
, Machine
),
88 DataForTest(ELF::ELFCLASS32
, ELF::ELFDATA2MSB
, Machine
),
89 DataForTest(ELF::ELFCLASS64
, ELF::ELFDATA2LSB
, Machine
),
90 DataForTest(ELF::ELFCLASS64
, ELF::ELFDATA2MSB
, Machine
)};
95 TEST(ELFObjectFileTest
, MachineTestForNoneOrUnused
) {
96 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
97 "elf64-unknown", "elf64-unknown"};
98 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_NONE
)))
99 checkFormatAndArch(Data
, Formats
[Idx
], Triple::UnknownArch
);
101 // Test an arbitrary unused EM_* value (255).
102 for (auto [Idx
, Data
] : enumerate(generateData(255)))
103 checkFormatAndArch(Data
, Formats
[Idx
], Triple::UnknownArch
);
106 TEST(ELFObjectFileTest
, MachineTestForVE
) {
107 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
108 "elf64-ve", "elf64-ve"};
109 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_VE
)))
110 checkFormatAndArch(Data
, Formats
[Idx
], Triple::ve
);
113 TEST(ELFObjectFileTest
, MachineTestForX86_64
) {
114 std::array
<StringRef
, 4> Formats
= {"elf32-x86-64", "elf32-x86-64",
115 "elf64-x86-64", "elf64-x86-64"};
116 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_X86_64
)))
117 checkFormatAndArch(Data
, Formats
[Idx
], Triple::x86_64
);
120 TEST(ELFObjectFileTest
, MachineTestFor386
) {
121 std::array
<StringRef
, 4> Formats
= {"elf32-i386", "elf32-i386", "elf64-i386",
123 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_386
)))
124 checkFormatAndArch(Data
, Formats
[Idx
], Triple::x86
);
127 TEST(ELFObjectFileTest
, MachineTestForMIPS
) {
128 std::array
<StringRef
, 4> Formats
= {"elf32-mips", "elf32-mips", "elf64-mips",
130 std::array
<Triple::ArchType
, 4> Archs
= {Triple::mipsel
, Triple::mips
,
131 Triple::mips64el
, Triple::mips64
};
132 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_MIPS
)))
133 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
136 TEST(ELFObjectFileTest
, MachineTestForAMDGPU
) {
137 std::array
<StringRef
, 4> Formats
= {"elf32-amdgpu", "elf32-amdgpu",
138 "elf64-amdgpu", "elf64-amdgpu"};
139 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_AMDGPU
)))
140 checkFormatAndArch(Data
, Formats
[Idx
], Triple::UnknownArch
);
143 TEST(ELFObjectFileTest
, MachineTestForIAMCU
) {
144 std::array
<StringRef
, 4> Formats
= {"elf32-iamcu", "elf32-iamcu",
145 "elf64-unknown", "elf64-unknown"};
146 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_IAMCU
)))
147 checkFormatAndArch(Data
, Formats
[Idx
], Triple::x86
);
150 TEST(ELFObjectFileTest
, MachineTestForAARCH64
) {
151 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
152 "elf64-littleaarch64",
154 std::array
<Triple::ArchType
, 4> Archs
= {Triple::aarch64
, Triple::aarch64_be
,
155 Triple::aarch64
, Triple::aarch64_be
};
156 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_AARCH64
)))
157 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
160 TEST(ELFObjectFileTest
, MachineTestForPPC64
) {
161 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
162 "elf64-powerpcle", "elf64-powerpc"};
163 std::array
<Triple::ArchType
, 4> Archs
= {Triple::ppc64le
, Triple::ppc64
,
164 Triple::ppc64le
, Triple::ppc64
};
165 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_PPC64
)))
166 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
169 TEST(ELFObjectFileTest
, MachineTestForPPC
) {
170 std::array
<StringRef
, 4> Formats
= {"elf32-powerpcle", "elf32-powerpc",
171 "elf64-unknown", "elf64-unknown"};
172 std::array
<Triple::ArchType
, 4> Archs
= {Triple::ppcle
, Triple::ppc
,
173 Triple::ppcle
, Triple::ppc
};
174 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_PPC
)))
175 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
178 TEST(ELFObjectFileTest
, MachineTestForRISCV
) {
179 std::array
<StringRef
, 4> Formats
= {"elf32-littleriscv", "elf32-littleriscv",
180 "elf64-littleriscv", "elf64-littleriscv"};
181 std::array
<Triple::ArchType
, 4> Archs
= {Triple::riscv32
, Triple::riscv32
,
182 Triple::riscv64
, Triple::riscv64
};
183 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_RISCV
)))
184 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
187 TEST(ELFObjectFileTest
, MachineTestForARM
) {
188 std::array
<StringRef
, 4> Formats
= {"elf32-littlearm", "elf32-bigarm",
189 "elf64-unknown", "elf64-unknown"};
190 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_ARM
)))
191 checkFormatAndArch(Data
, Formats
[Idx
], Triple::arm
);
194 TEST(ELFObjectFileTest
, MachineTestForS390
) {
195 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
196 "elf64-s390", "elf64-s390"};
197 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_S390
)))
198 checkFormatAndArch(Data
, Formats
[Idx
], Triple::systemz
);
201 TEST(ELFObjectFileTest
, MachineTestForSPARCV9
) {
202 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
203 "elf64-sparc", "elf64-sparc"};
204 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_SPARCV9
)))
205 checkFormatAndArch(Data
, Formats
[Idx
], Triple::sparcv9
);
208 TEST(ELFObjectFileTest
, MachineTestForSPARC
) {
209 std::array
<StringRef
, 4> Formats
= {"elf32-sparc", "elf32-sparc",
210 "elf64-unknown", "elf64-unknown"};
211 std::array
<Triple::ArchType
, 4> Archs
= {Triple::sparcel
, Triple::sparc
,
212 Triple::sparcel
, Triple::sparc
};
213 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_SPARC
)))
214 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
217 TEST(ELFObjectFileTest
, MachineTestForSPARC32PLUS
) {
218 std::array
<StringRef
, 4> Formats
= {"elf32-sparc", "elf32-sparc",
219 "elf64-unknown", "elf64-unknown"};
220 std::array
<Triple::ArchType
, 4> Archs
= {Triple::sparcel
, Triple::sparc
,
221 Triple::sparcel
, Triple::sparc
};
222 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_SPARC32PLUS
)))
223 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
226 TEST(ELFObjectFileTest
, MachineTestForBPF
) {
227 std::array
<StringRef
, 4> Formats
= {"elf32-unknown", "elf32-unknown",
228 "elf64-bpf", "elf64-bpf"};
229 std::array
<Triple::ArchType
, 4> Archs
= {Triple::bpfel
, Triple::bpfeb
,
230 Triple::bpfel
, Triple::bpfeb
};
231 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_BPF
)))
232 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
235 TEST(ELFObjectFileTest
, MachineTestForAVR
) {
236 std::array
<StringRef
, 4> Formats
= {"elf32-avr", "elf32-avr", "elf64-unknown",
238 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_AVR
)))
239 checkFormatAndArch(Data
, Formats
[Idx
], Triple::avr
);
242 TEST(ELFObjectFileTest
, MachineTestForHEXAGON
) {
243 std::array
<StringRef
, 4> Formats
= {"elf32-hexagon", "elf32-hexagon",
244 "elf64-unknown", "elf64-unknown"};
245 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_HEXAGON
)))
246 checkFormatAndArch(Data
, Formats
[Idx
], Triple::hexagon
);
249 TEST(ELFObjectFileTest
, MachineTestForLANAI
) {
250 std::array
<StringRef
, 4> Formats
= {"elf32-lanai", "elf32-lanai",
251 "elf64-unknown", "elf64-unknown"};
252 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_LANAI
)))
253 checkFormatAndArch(Data
, Formats
[Idx
], Triple::lanai
);
256 TEST(ELFObjectFileTest
, MachineTestForMSP430
) {
257 std::array
<StringRef
, 4> Formats
= {"elf32-msp430", "elf32-msp430",
258 "elf64-unknown", "elf64-unknown"};
259 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_MSP430
)))
260 checkFormatAndArch(Data
, Formats
[Idx
], Triple::msp430
);
263 TEST(ELFObjectFileTest
, MachineTestForLoongArch
) {
264 std::array
<StringRef
, 4> Formats
= {"elf32-loongarch", "elf32-loongarch",
265 "elf64-loongarch", "elf64-loongarch"};
266 std::array
<Triple::ArchType
, 4> Archs
= {
267 Triple::loongarch32
, Triple::loongarch32
, Triple::loongarch64
,
268 Triple::loongarch64
};
269 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_LOONGARCH
)))
270 checkFormatAndArch(Data
, Formats
[Idx
], Archs
[Idx
]);
273 TEST(ELFObjectFileTest
, MachineTestForCSKY
) {
274 std::array
<StringRef
, 4> Formats
= {"elf32-csky", "elf32-csky",
275 "elf64-unknown", "elf64-unknown"};
276 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_CSKY
)))
277 checkFormatAndArch(Data
, Formats
[Idx
], Triple::csky
);
280 TEST(ELFObjectFileTest
, MachineTestForXtensa
) {
281 std::array
<StringRef
, 4> Formats
= {"elf32-xtensa", "elf32-xtensa",
282 "elf64-unknown", "elf64-unknown"};
283 for (auto [Idx
, Data
] : enumerate(generateData(ELF::EM_XTENSA
)))
284 checkFormatAndArch(Data
, Formats
[Idx
], Triple::xtensa
);
287 TEST(ELFObjectFileTest
, CheckOSAndTriple
) {
288 std::tuple
<uint16_t, uint8_t, StringRef
> Formats
[] = {
289 {ELF::EM_AMDGPU
, ELF::ELFOSABI_AMDGPU_HSA
, "amdgcn-amd-amdhsa"},
290 {ELF::EM_X86_64
, ELF::ELFOSABI_LINUX
, "x86_64--linux"},
291 {ELF::EM_X86_64
, ELF::ELFOSABI_NETBSD
, "x86_64--netbsd"},
292 {ELF::EM_X86_64
, ELF::ELFOSABI_HURD
, "x86_64--hurd"},
293 {ELF::EM_X86_64
, ELF::ELFOSABI_SOLARIS
, "x86_64--solaris"},
294 {ELF::EM_X86_64
, ELF::ELFOSABI_AIX
, "x86_64--aix"},
295 {ELF::EM_X86_64
, ELF::ELFOSABI_FREEBSD
, "x86_64--freebsd"},
296 {ELF::EM_X86_64
, ELF::ELFOSABI_OPENBSD
, "x86_64--openbsd"},
297 {ELF::EM_CUDA
, ELF::ELFOSABI_CUDA
, "nvptx64-nvidia-cuda"}};
298 for (auto [Machine
, OS
, Triple
] : Formats
) {
299 const DataForTest
D(ELF::ELFCLASS64
, ELF::ELFDATA2LSB
, Machine
, OS
,
300 ELF::EF_AMDGPU_MACH_AMDGCN_LAST
);
301 Expected
<ELF64LEObjectFile
> ELFObjOrErr
= ELF64LEObjectFile::create(
302 MemoryBufferRef(toStringRef(D
.Data
), "dummyELF"));
303 ASSERT_THAT_EXPECTED(ELFObjOrErr
, Succeeded());
305 auto &ELFObj
= *ELFObjOrErr
;
306 llvm::Triple TheTriple
= ELFObj
.makeTriple();
308 // The AMDGPU architecture will be unknown on big-endian testers.
309 if (TheTriple
.getArch() == Triple::UnknownArch
)
312 EXPECT_EQ(Triple
, TheTriple
.getTriple());
316 // ELF relative relocation type test.
317 TEST(ELFObjectFileTest
, RelativeRelocationTypeTest
) {
318 EXPECT_EQ(ELF::R_CKCORE_RELATIVE
, getELFRelativeRelocationType(ELF::EM_CSKY
));
321 template <class ELFT
>
322 static Expected
<ELFObjectFile
<ELFT
>> toBinary(SmallVectorImpl
<char> &Storage
,
324 raw_svector_ostream
OS(Storage
);
325 yaml::Input
YIn(Yaml
);
326 if (!yaml::convertYAML(YIn
, OS
, [](const Twine
&Msg
) {}))
327 return createStringError(std::errc::invalid_argument
,
328 "unable to convert YAML");
329 return ELFObjectFile
<ELFT
>::create(MemoryBufferRef(OS
.str(), "dummyELF"));
332 // Check we are able to create an ELFObjectFile even when the content of the
333 // SHT_SYMTAB_SHNDX section can't be read properly.
334 TEST(ELFObjectFileTest
, InvalidSymtabShndxTest
) {
335 SmallString
<0> Storage
;
336 Expected
<ELFObjectFile
<ELF64LE
>> ExpectedFile
= toBinary
<ELF64LE
>(Storage
, R
"(
343 - Name: .symtab_shndx
344 Type: SHT_SYMTAB_SHNDX
349 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
352 // Test that we are able to create an ELFObjectFile even when loadable segments
353 // are unsorted by virtual address.
354 // Test that ELFFile<ELFT>::toMappedAddr works properly in this case.
356 TEST(ELFObjectFileTest
, InvalidLoadSegmentsOrderTest
) {
357 SmallString
<0> Storage
;
358 Expected
<ELFObjectFile
<ELF64LE
>> ExpectedFile
= toBinary
<ELF64LE
>(Storage
, R
"(
369 ContentArray: [ 0x11 ]
374 ContentArray: [ 0x99 ]
386 ASSERT_THAT_EXPECTED(ExpectedFile
, Succeeded());
388 std::string WarnString
;
389 auto ToMappedAddr
= [&](uint64_t Addr
) -> const uint8_t * {
390 Expected
<const uint8_t *> DataOrErr
=
391 ExpectedFile
->getELFFile().toMappedAddr(Addr
, [&](const Twine
&Msg
) {
392 EXPECT_TRUE(WarnString
.empty());
393 WarnString
= Msg
.str();
394 return Error::success();
398 ADD_FAILURE() << toString(DataOrErr
.takeError());
402 EXPECT_TRUE(WarnString
==
403 "loadable segments are unsorted by virtual address");
408 const uint8_t *Data
= ToMappedAddr(0x1000);
410 MemoryBufferRef Buf
= ExpectedFile
->getMemoryBufferRef();
411 EXPECT_EQ((const char *)Data
- Buf
.getBufferStart(), 0x3000);
412 EXPECT_EQ(Data
[0], 0x11);
414 Data
= ToMappedAddr(0x2000);
416 Buf
= ExpectedFile
->getMemoryBufferRef();
417 EXPECT_EQ((const char *)Data
- Buf
.getBufferStart(), 0x4000);
418 EXPECT_EQ(Data
[0], 0x99);
421 // This is a test for API that is related to symbols.
422 // We check that errors are properly reported here.
423 TEST(ELFObjectFileTest
, InvalidSymbolTest
) {
424 SmallString
<0> Storage
;
425 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
= toBinary
<ELF64LE
>(Storage
, R
"(
437 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
438 const ELFFile
<ELF64LE
> &Elf
= ElfOrErr
->getELFFile();
439 const ELFObjectFile
<ELF64LE
> &Obj
= *ElfOrErr
;
441 Expected
<const typename
ELF64LE::Shdr
*> SymtabSecOrErr
= Elf
.getSection(1);
442 ASSERT_THAT_EXPECTED(SymtabSecOrErr
, Succeeded());
443 ASSERT_EQ((*SymtabSecOrErr
)->sh_type
, ELF::SHT_SYMTAB
);
445 auto DoCheck
= [&](unsigned BrokenSymIndex
, const char *ErrMsg
) {
446 ELFSymbolRef BrokenSym
= Obj
.toSymbolRef(*SymtabSecOrErr
, BrokenSymIndex
);
448 // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName().
449 // SymbolRef::getName() calls it internally. We can't test it directly,
450 // because it is protected.
451 EXPECT_THAT_ERROR(BrokenSym
.getName().takeError(),
452 FailedWithMessage(ErrMsg
));
454 // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol().
455 EXPECT_THAT_ERROR(Obj
.getSymbol(BrokenSym
.getRawDataRefImpl()).takeError(),
456 FailedWithMessage(ErrMsg
));
458 // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection().
459 // SymbolRef::getSection() calls it internally. We can't test it
460 // directly, because it is protected.
461 EXPECT_THAT_ERROR(BrokenSym
.getSection().takeError(),
462 FailedWithMessage(ErrMsg
));
464 // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags().
465 // SymbolRef::getFlags() calls it internally. We can't test it directly,
466 // because it is protected.
467 EXPECT_THAT_ERROR(BrokenSym
.getFlags().takeError(),
468 FailedWithMessage(ErrMsg
));
470 // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType().
471 // SymbolRef::getType() calls it internally. We can't test it directly,
472 // because it is protected.
473 EXPECT_THAT_ERROR(BrokenSym
.getType().takeError(),
474 FailedWithMessage(ErrMsg
));
476 // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress().
477 // SymbolRef::getAddress() calls it internally. We can't test it
478 // directly, because it is protected.
479 EXPECT_THAT_ERROR(BrokenSym
.getAddress().takeError(),
480 FailedWithMessage(ErrMsg
));
482 // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying
483 // method that generates errors for all cases above.
484 EXPECT_THAT_EXPECTED(
485 Elf
.getEntry
<typename
ELF64LE::Sym
>(**SymtabSecOrErr
, 0), Succeeded());
487 Elf
.getEntry
<typename
ELF64LE::Sym
>(**SymtabSecOrErr
, BrokenSymIndex
)
489 FailedWithMessage(ErrMsg
));
492 // We create a symbol with an index that is too large to exist in the symbol
494 DoCheck(0x1, "can't read an entry at 0x18: it goes past the end of the "
497 // We create a symbol with an index that is too large to exist in the object.
498 DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
499 "end of the section (0x18)");
502 // Tests for error paths of the ELFFile::decodeBBAddrMap API.
503 TEST(ELFObjectFileTest
, InvalidDecodeBBAddrMap
) {
504 StringRef
CommonYamlString(R
"(
511 - Type: SHT_LLVM_BB_ADDR_MAP
512 Name: .llvm_bb_addr_map
516 auto DoCheck
= [&](StringRef YamlString
, const char *ErrMsg
) {
517 SmallString
<0> Storage
;
518 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
519 toBinary
<ELF64LE
>(Storage
, YamlString
);
520 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
521 const ELFFile
<ELF64LE
> &Elf
= ElfOrErr
->getELFFile();
523 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
525 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
526 EXPECT_THAT_ERROR(Elf
.decodeBBAddrMap(**BBAddrMapSecOrErr
).takeError(),
527 FailedWithMessage(ErrMsg
));
530 // Check that we can detect unsupported versions.
531 SmallString
<128> UnsupportedVersionYamlString(CommonYamlString
);
532 UnsupportedVersionYamlString
+= R
"(
535 - BaseAddress: 0x11111
543 SCOPED_TRACE("unsupported version");
544 DoCheck(UnsupportedVersionYamlString
,
545 "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
548 SmallString
<128> ZeroBBRangesYamlString(CommonYamlString
);
549 ZeroBBRangesYamlString
+= R
"(
555 SCOPED_TRACE("zero bb ranges");
556 DoCheck(ZeroBBRangesYamlString
,
557 "invalid zero number of BB ranges at offset 3 in "
558 "SHT_LLVM_BB_ADDR_MAP section with index 1");
561 SmallString
<128> CommonVersionedYamlString(CommonYamlString
);
562 CommonVersionedYamlString
+= R
"(
565 - BaseAddress: 0x11111
572 // Check that we can detect the malformed encoding when the section is
574 SmallString
<128> TruncatedYamlString(CommonVersionedYamlString
);
575 TruncatedYamlString
+= R
"(
579 SCOPED_TRACE("truncated section");
580 DoCheck(TruncatedYamlString
,
581 "unable to decode LEB128 at offset 0x0000000b: "
582 "malformed uleb128, extends past end");
585 // Check that we can detect when the encoded BB entry fields exceed the UINT32
587 SmallVector
<SmallString
<128>, 3> OverInt32LimitYamlStrings(
588 3, CommonVersionedYamlString
);
589 OverInt32LimitYamlStrings
[0] += R
"(
591 AddressOffset: 0x100000000
596 OverInt32LimitYamlStrings
[1] += R
"(
598 AddressOffset: 0xFFFFFFFF
603 OverInt32LimitYamlStrings
[2] += R
"(
605 AddressOffset: 0xFFFFFFFF
607 Metadata: 0x100000000
611 SCOPED_TRACE("overlimit fields");
612 DoCheck(OverInt32LimitYamlStrings
[0],
613 "ULEB128 value at offset 0x10 exceeds UINT32_MAX (0x100000000)");
614 DoCheck(OverInt32LimitYamlStrings
[1],
615 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
616 DoCheck(OverInt32LimitYamlStrings
[2],
617 "ULEB128 value at offset 0x1a exceeds UINT32_MAX (0x100000000)");
620 // Check the proper error handling when the section has fields exceeding
621 // UINT32 and is also truncated. This is for checking that we don't generate
623 SmallVector
<SmallString
<128>, 3> OverInt32LimitAndTruncated(
624 3, OverInt32LimitYamlStrings
[1]);
625 // Truncate before the end of the 5-byte field.
626 OverInt32LimitAndTruncated
[0] += R
"(
629 // Truncate at the end of the 5-byte field.
630 OverInt32LimitAndTruncated
[1] += R
"(
633 // Truncate after the end of the 5-byte field.
634 OverInt32LimitAndTruncated
[2] += R
"(
639 SCOPED_TRACE("overlimit fields, truncated section");
640 DoCheck(OverInt32LimitAndTruncated
[0],
641 "unable to decode LEB128 at offset 0x00000015: malformed uleb128, "
643 DoCheck(OverInt32LimitAndTruncated
[1],
644 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
645 DoCheck(OverInt32LimitAndTruncated
[2],
646 "ULEB128 value at offset 0x15 exceeds UINT32_MAX (0x100000000)");
649 // Check for proper error handling when the 'NumBlocks' field is overridden
650 // with an out-of-range value.
651 SmallString
<128> OverLimitNumBlocks(CommonVersionedYamlString
);
652 OverLimitNumBlocks
+= R
"(
653 NumBlocks: 0x100000000
657 SCOPED_TRACE("overlimit 'NumBlocks' field");
658 DoCheck(OverLimitNumBlocks
,
659 "ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
662 // Check for proper error handling when the 'NumBBRanges' field is overridden
663 // with an out-of-range value.
664 SmallString
<128> OverLimitNumBBRanges(CommonVersionedYamlString
);
665 OverLimitNumBBRanges
+= R
"(
666 NumBBRanges: 0x100000000
669 DoCheck(OverLimitNumBBRanges
,
670 "ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)");
673 // Test for the ELFObjectFile::readBBAddrMap API.
674 TEST(ELFObjectFileTest
, ReadBBAddrMap
) {
675 StringRef
CommonYamlString(R
"(
682 - Name: .llvm_bb_addr_map_1
683 Type: SHT_LLVM_BB_ADDR_MAP
688 - BaseAddress: 0x11111
694 - Name: .llvm_bb_addr_map_2
695 Type: SHT_LLVM_BB_ADDR_MAP
701 - BaseAddress: 0x22222
707 - BaseAddress: 0xFFFFF
713 - Name: .llvm_bb_addr_map_3
714 Type: SHT_LLVM_BB_ADDR_MAP
719 - BaseAddress: 0x33333
725 - Name: .llvm_bb_addr_map_4
726 Type: SHT_LLVM_BB_ADDR_MAP
727 # Link: 0 (by default, can be overriden)
731 - BaseAddress: 0x44444
740 {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
742 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}},
743 {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}}}}}};
745 {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}}};
747 {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}}};
749 std::vector
<BBAddrMap
> Section0BBAddrMaps
= {E4
};
750 std::vector
<BBAddrMap
> Section1BBAddrMaps
= {E3
};
751 std::vector
<BBAddrMap
> Section2BBAddrMaps
= {E1
, E2
};
752 std::vector
<BBAddrMap
> AllBBAddrMaps
= {E1
, E2
, E3
, E4
};
754 auto DoCheckSucceeds
= [&](StringRef YamlString
,
755 std::optional
<unsigned> TextSectionIndex
,
756 std::vector
<BBAddrMap
> ExpectedResult
) {
757 SCOPED_TRACE("for TextSectionIndex: " +
758 (TextSectionIndex
? llvm::Twine(*TextSectionIndex
) : "{}") +
759 " and object yaml:\n" + YamlString
);
760 SmallString
<0> Storage
;
761 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
762 toBinary
<ELF64LE
>(Storage
, YamlString
);
763 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
765 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
766 ElfOrErr
->getELFFile().getSection(1);
767 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
768 auto BBAddrMaps
= ElfOrErr
->readBBAddrMap(TextSectionIndex
);
769 ASSERT_THAT_EXPECTED(BBAddrMaps
, Succeeded());
770 EXPECT_EQ(*BBAddrMaps
, ExpectedResult
);
773 auto DoCheckFails
= [&](StringRef YamlString
,
774 std::optional
<unsigned> TextSectionIndex
,
775 const char *ErrMsg
) {
776 SCOPED_TRACE("for TextSectionIndex: " +
777 (TextSectionIndex
? llvm::Twine(*TextSectionIndex
) : "{}") +
778 " and object yaml:\n" + YamlString
);
779 SmallString
<0> Storage
;
780 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
781 toBinary
<ELF64LE
>(Storage
, YamlString
);
782 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
784 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
785 ElfOrErr
->getELFFile().getSection(1);
786 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
787 EXPECT_THAT_ERROR(ElfOrErr
->readBBAddrMap(TextSectionIndex
).takeError(),
788 FailedWithMessage(ErrMsg
));
792 SCOPED_TRACE("normal sections");
793 // Check that we can retrieve the data in the normal case.
794 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/std::nullopt
,
796 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/0,
798 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/2,
800 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/1,
802 // Check that when no bb-address-map section is found for a text section,
803 // we return an empty result.
804 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/3, {});
807 // Check that we detect when a bb-addr-map section is linked to an invalid
808 // (not present) section.
809 SmallString
<128> InvalidLinkedYamlString(CommonYamlString
);
810 InvalidLinkedYamlString
+= R
"(
814 DoCheckFails(InvalidLinkedYamlString
, /*TextSectionIndex=*/4,
815 "unable to get the linked-to section for "
816 "SHT_LLVM_BB_ADDR_MAP section with index 4: invalid section "
819 SCOPED_TRACE("invalid linked section");
820 // Linked sections are not checked when we don't target a specific text
822 DoCheckSucceeds(InvalidLinkedYamlString
, /*TextSectionIndex=*/std::nullopt
,
826 // Check that we can detect when bb-address-map decoding fails.
827 SmallString
<128> TruncatedYamlString(CommonYamlString
);
828 TruncatedYamlString
+= R
"(
833 SCOPED_TRACE("truncated section");
834 DoCheckFails(TruncatedYamlString
, /*TextSectionIndex=*/std::nullopt
,
835 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 4: "
836 "unable to decode LEB128 at offset 0x0000000a: malformed "
837 "uleb128, extends past end");
839 // Check that we can read the other section's bb-address-maps which are
841 DoCheckSucceeds(TruncatedYamlString
, /*TextSectionIndex=*/2,
846 // Tests for error paths of the ELFFile::decodeBBAddrMap with PGOAnalysisMap
848 TEST(ELFObjectFileTest
, InvalidDecodePGOAnalysisMap
) {
849 StringRef
CommonYamlString(R
"(
856 - Type: SHT_LLVM_BB_ADDR_MAP
857 Name: .llvm_bb_addr_map
861 auto DoCheck
= [&](StringRef YamlString
, const char *ErrMsg
) {
862 SmallString
<0> Storage
;
863 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
864 toBinary
<ELF64LE
>(Storage
, YamlString
);
865 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
866 const ELFFile
<ELF64LE
> &Elf
= ElfOrErr
->getELFFile();
868 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
870 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
872 std::vector
<PGOAnalysisMap
> PGOAnalyses
;
874 Elf
.decodeBBAddrMap(**BBAddrMapSecOrErr
, nullptr, &PGOAnalyses
)
876 FailedWithMessage(ErrMsg
));
879 // Check that we can detect unsupported versions that are too old.
880 SmallString
<128> UnsupportedLowVersionYamlString(CommonYamlString
);
881 UnsupportedLowVersionYamlString
+= R
"(
892 SCOPED_TRACE("unsupported version");
893 DoCheck(UnsupportedLowVersionYamlString
,
894 "version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when PGO features "
895 "are enabled: version = 1 feature = 4");
898 SmallString
<128> CommonVersionedYamlString(CommonYamlString
);
899 CommonVersionedYamlString
+= R
"(
909 // Check that we fail when function entry count is enabled but not provided.
910 SmallString
<128> MissingFuncEntryCount(CommonYamlString
);
911 MissingFuncEntryCount
+= R
"(
917 SCOPED_TRACE("missing function entry count");
918 DoCheck(MissingFuncEntryCount
,
919 "unexpected end of data at offset 0x2 while reading [0x2, 0xa)");
922 // Check that we fail when basic block frequency is enabled but not provided.
923 SmallString
<128> MissingBBFreq(CommonYamlString
);
936 SCOPED_TRACE("missing bb frequency");
937 DoCheck(MissingBBFreq
, "unable to decode LEB128 at offset 0x0000000f: "
938 "malformed uleb128, extends past end");
941 // Check that we fail when branch probability is enabled but not provided.
942 SmallString
<128> MissingBrProb(CommonYamlString
);
973 SCOPED_TRACE("missing branch probability");
974 DoCheck(MissingBrProb
, "unable to decode LEB128 at offset 0x00000017: "
975 "malformed uleb128, extends past end");
979 // Test for the ELFObjectFile::readBBAddrMap API with PGOAnalysisMap.
980 TEST(ELFObjectFileTest
, ReadPGOAnalysisMap
) {
981 StringRef
CommonYamlString(R
"(
988 - Name: .llvm_bb_addr_map_1
989 Type: SHT_LLVM_BB_ADDR_MAP
995 - BaseAddress: 0x11111
1002 - FuncEntryCount: 892
1003 - Name: .llvm_bb_addr_map_2
1004 Type: SHT_LLVM_BB_ADDR_MAP
1010 - BaseAddress: 0x22222
1019 - Name: .llvm_bb_addr_map_3
1020 Type: SHT_LLVM_BB_ADDR_MAP
1026 - BaseAddress: 0x33333
1051 - Name: .llvm_bb_addr_map_4
1052 Type: SHT_LLVM_BB_ADDR_MAP
1053 # Link: 0 (by default, can be overriden)
1058 - BaseAddress: 0x44444
1077 - FuncEntryCount: 1000
1099 - Name: .llvm_bb_addr_map_5
1100 Type: SHT_LLVM_BB_ADDR_MAP
1101 # Link: 0 (by default, can be overriden)
1106 - BaseAddress: 0x55555
1113 - Name: .llvm_bb_addr_map_6
1114 Type: SHT_LLVM_BB_ADDR_MAP
1115 # Link: 0 (by default, can be overriden)
1120 - BaseAddress: 0x66666
1130 - BaseAddress: 0x666661
1150 {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
1151 PGOAnalysisMap P1
= {892, {}, {true, false, false, false}};
1153 {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
1154 PGOAnalysisMap P2
= {
1155 {}, {{BlockFrequency(343), {}}}, {false, true, false, false}};
1156 BBAddrMap E3
= {{{0x33333,
1157 {{0, 0x0, 0x3, {false, true, true, false, false}},
1158 {1, 0x3, 0x3, {false, false, true, false, false}},
1159 {2, 0x6, 0x3, {false, false, false, false, false}}}}}};
1160 PGOAnalysisMap P3
= {{},
1162 {{1, BranchProbability::getRaw(0x1111'1111)},
1163 {2, BranchProbability::getRaw(0xeeee'eeee)}}},
1164 {{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}},
1166 {false, false, true, false}};
1167 BBAddrMap E4
= {{{0x44444,
1168 {{0, 0x0, 0x4, {false, false, false, true, true}},
1169 {1, 0x4, 0x4, {false, false, false, false, false}},
1170 {2, 0x8, 0x4, {false, false, false, false, false}},
1171 {3, 0xc, 0x4, {false, false, false, false, false}}}}}};
1172 PGOAnalysisMap P4
= {
1174 {{BlockFrequency(1000),
1175 {{1, BranchProbability::getRaw(0x2222'2222)},
1176 {2, BranchProbability::getRaw(0x3333'3333)},
1177 {3, BranchProbability::getRaw(0xaaaa'aaaa)}}},
1178 {BlockFrequency(133),
1179 {{2, BranchProbability::getRaw(0x1111'1111)},
1180 {3, BranchProbability::getRaw(0xeeee'eeee)}}},
1181 {BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}},
1182 {BlockFrequency(1000), {}}},
1183 {true, true, true, false}};
1185 {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
1186 PGOAnalysisMap P5
= {{}, {}, {false, false, false, false}};
1189 {{0, 0x0, 0x6, {false, true, true, false, false}},
1190 {1, 0x6, 0x6, {false, false, true, false, false}}}},
1191 {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}}}}}};
1192 PGOAnalysisMap P6
= {{},
1194 {{1, BranchProbability::getRaw(0x2222'2222)},
1195 {2, BranchProbability::getRaw(0xcccc'cccc)}}},
1196 {{}, {{2, BranchProbability::getRaw(0x8888'8888)}}},
1198 {false, false, true, true}};
1200 std::vector
<BBAddrMap
> Section0BBAddrMaps
= {E4
, E5
, E6
};
1201 std::vector
<BBAddrMap
> Section1BBAddrMaps
= {E3
};
1202 std::vector
<BBAddrMap
> Section2BBAddrMaps
= {E1
, E2
};
1203 std::vector
<BBAddrMap
> AllBBAddrMaps
= {E1
, E2
, E3
, E4
, E5
, E6
};
1205 std::vector
<PGOAnalysisMap
> Section0PGOAnalysisMaps
= {P4
, P5
, P6
};
1206 std::vector
<PGOAnalysisMap
> Section1PGOAnalysisMaps
= {P3
};
1207 std::vector
<PGOAnalysisMap
> Section2PGOAnalysisMaps
= {P1
, P2
};
1208 std::vector
<PGOAnalysisMap
> AllPGOAnalysisMaps
= {P1
, P2
, P3
, P4
, P5
, P6
};
1210 auto DoCheckSucceeds
=
1211 [&](StringRef YamlString
, std::optional
<unsigned> TextSectionIndex
,
1212 std::vector
<BBAddrMap
> ExpectedResult
,
1213 std::optional
<std::vector
<PGOAnalysisMap
>> ExpectedPGO
) {
1215 "for TextSectionIndex: " +
1216 (TextSectionIndex
? llvm::Twine(*TextSectionIndex
) : "{}") +
1217 " and object yaml:\n" + YamlString
);
1218 SmallString
<0> Storage
;
1219 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
1220 toBinary
<ELF64LE
>(Storage
, YamlString
);
1221 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1223 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
1224 ElfOrErr
->getELFFile().getSection(1);
1225 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
1227 std::vector
<PGOAnalysisMap
> PGOAnalyses
;
1228 auto BBAddrMaps
= ElfOrErr
->readBBAddrMap(
1229 TextSectionIndex
, ExpectedPGO
? &PGOAnalyses
: nullptr);
1230 ASSERT_THAT_EXPECTED(BBAddrMaps
, Succeeded());
1231 EXPECT_EQ(*BBAddrMaps
, ExpectedResult
);
1233 EXPECT_EQ(BBAddrMaps
->size(), PGOAnalyses
.size());
1234 for (const auto &PGO
: PGOAnalyses
) {
1235 errs() << "FuncEntryCount: " << PGO
.FuncEntryCount
<< "\n";
1236 for (const auto &PGOBB
: PGO
.BBEntries
)
1237 errs() << "\tBB: " << PGOBB
.BlockFreq
.getFrequency() << "\n";
1239 errs() << " To expected:\n";
1240 for (const auto &PGO
: *ExpectedPGO
) {
1241 errs() << "FuncEntryCount: " << PGO
.FuncEntryCount
<< "\n";
1242 for (const auto &PGOBB
: PGO
.BBEntries
)
1243 errs() << "\tBB: " << PGOBB
.BlockFreq
.getFrequency() << "\n";
1245 EXPECT_EQ(PGOAnalyses
, *ExpectedPGO
);
1246 for (auto &&[BB
, PGO
] : llvm::zip(*BBAddrMaps
, PGOAnalyses
)) {
1247 if (PGO
.FeatEnable
.BBFreq
|| PGO
.FeatEnable
.BrProb
)
1248 EXPECT_EQ(BB
.getNumBBEntries(), PGO
.BBEntries
.size());
1253 auto DoCheckFails
= [&](StringRef YamlString
,
1254 std::optional
<unsigned> TextSectionIndex
,
1255 const char *ErrMsg
) {
1256 SCOPED_TRACE("for TextSectionIndex: " +
1257 (TextSectionIndex
? llvm::Twine(*TextSectionIndex
) : "{}") +
1258 " and object yaml:\n" + YamlString
);
1259 SmallString
<0> Storage
;
1260 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
1261 toBinary
<ELF64LE
>(Storage
, YamlString
);
1262 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1264 Expected
<const typename
ELF64LE::Shdr
*> BBAddrMapSecOrErr
=
1265 ElfOrErr
->getELFFile().getSection(1);
1266 ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr
, Succeeded());
1267 std::vector
<PGOAnalysisMap
> PGOAnalyses
;
1269 ElfOrErr
->readBBAddrMap(TextSectionIndex
, &PGOAnalyses
).takeError(),
1270 FailedWithMessage(ErrMsg
));
1274 SCOPED_TRACE("normal sections");
1275 // Check that we can retrieve the data in the normal case.
1276 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/std::nullopt
,
1277 AllBBAddrMaps
, std::nullopt
);
1278 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/0,
1279 Section0BBAddrMaps
, std::nullopt
);
1280 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/2,
1281 Section1BBAddrMaps
, std::nullopt
);
1282 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/1,
1283 Section2BBAddrMaps
, std::nullopt
);
1285 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/std::nullopt
,
1286 AllBBAddrMaps
, AllPGOAnalysisMaps
);
1287 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/0,
1288 Section0BBAddrMaps
, Section0PGOAnalysisMaps
);
1289 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/2,
1290 Section1BBAddrMaps
, Section1PGOAnalysisMaps
);
1291 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/1,
1292 Section2BBAddrMaps
, Section2PGOAnalysisMaps
);
1293 // Check that when no bb-address-map section is found for a text section,
1294 // we return an empty result.
1295 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/3, {}, std::nullopt
);
1296 DoCheckSucceeds(CommonYamlString
, /*TextSectionIndex=*/3, {},
1297 std::vector
<PGOAnalysisMap
>{});
1300 // Check that we detect when a bb-addr-map section is linked to an invalid
1301 // (not present) section.
1302 SmallString
<128> InvalidLinkedYamlString(CommonYamlString
);
1303 InvalidLinkedYamlString
+= R
"(
1308 SCOPED_TRACE("invalid linked section");
1309 DoCheckFails(InvalidLinkedYamlString
, /*TextSectionIndex=*/5,
1310 "unable to get the linked-to section for "
1311 "SHT_LLVM_BB_ADDR_MAP section with index 6: invalid section "
1314 // Linked sections are not checked when we don't target a specific text
1316 DoCheckSucceeds(InvalidLinkedYamlString
, /*TextSectionIndex=*/std::nullopt
,
1317 AllBBAddrMaps
, std::nullopt
);
1318 DoCheckSucceeds(InvalidLinkedYamlString
, /*TextSectionIndex=*/std::nullopt
,
1319 AllBBAddrMaps
, AllPGOAnalysisMaps
);
1322 // Check that we can detect when bb-address-map decoding fails.
1323 SmallString
<128> TruncatedYamlString(CommonYamlString
);
1324 TruncatedYamlString
+= R
"(
1329 SCOPED_TRACE("truncated section");
1331 TruncatedYamlString
, /*TextSectionIndex=*/std::nullopt
,
1332 "unable to read SHT_LLVM_BB_ADDR_MAP section with index 6: "
1333 "unexpected end of data at offset 0xa while reading [0x3, 0xb)");
1334 // Check that we can read the other section's bb-address-maps which are
1336 DoCheckSucceeds(TruncatedYamlString
, /*TextSectionIndex=*/2,
1337 Section1BBAddrMaps
, std::nullopt
);
1338 DoCheckSucceeds(TruncatedYamlString
, /*TextSectionIndex=*/2,
1339 Section1BBAddrMaps
, Section1PGOAnalysisMaps
);
1343 // Test for ObjectFile::getRelocatedSection: check that it returns a relocated
1344 // section for executable and relocatable files.
1345 TEST(ELFObjectFileTest
, ExecutableWithRelocs
) {
1346 StringRef
HeaderString(R
"(
1352 StringRef
ContentsString(R
"(
1356 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1359 Flags: [ SHF_INFO_LINK ]
1363 auto DoCheck
= [&](StringRef YamlString
) {
1364 SmallString
<0> Storage
;
1365 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
1366 toBinary
<ELF64LE
>(Storage
, YamlString
);
1367 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1368 const ELFObjectFile
<ELF64LE
> &Obj
= *ElfOrErr
;
1372 for (SectionRef Sec
: Obj
.sections()) {
1373 Expected
<StringRef
> SecNameOrErr
= Sec
.getName();
1374 ASSERT_THAT_EXPECTED(SecNameOrErr
, Succeeded());
1375 StringRef SecName
= *SecNameOrErr
;
1376 if (SecName
!= ".rela.text")
1379 Expected
<section_iterator
> RelSecOrErr
= Sec
.getRelocatedSection();
1380 ASSERT_THAT_EXPECTED(RelSecOrErr
, Succeeded());
1381 section_iterator RelSec
= *RelSecOrErr
;
1382 ASSERT_NE(RelSec
, Obj
.section_end());
1383 Expected
<StringRef
> TextSecNameOrErr
= RelSec
->getName();
1384 ASSERT_THAT_EXPECTED(TextSecNameOrErr
, Succeeded());
1385 StringRef TextSecName
= *TextSecNameOrErr
;
1386 EXPECT_EQ(TextSecName
, ".text");
1388 ASSERT_TRUE(FoundRela
);
1391 // Check ET_EXEC file (`ld --emit-relocs` use-case).
1392 SmallString
<128> ExecFileYamlString(HeaderString
);
1393 ExecFileYamlString
+= R
"(
1396 ExecFileYamlString
+= ContentsString
;
1397 DoCheck(ExecFileYamlString
);
1399 // Check ET_REL file.
1400 SmallString
<128> RelocatableFileYamlString(HeaderString
);
1401 RelocatableFileYamlString
+= R
"(
1404 RelocatableFileYamlString
+= ContentsString
;
1405 DoCheck(RelocatableFileYamlString
);
1408 TEST(ELFObjectFileTest
, GetSectionAndRelocations
) {
1409 StringRef
HeaderString(R
"(
1417 using Elf_Shdr
= Elf_Shdr_Impl
<ELF64LE
>;
1419 auto DoCheckSucceeds
= [&](StringRef ContentsString
,
1420 std::function
<Expected
<bool>(const Elf_Shdr
&)>
1422 SmallString
<0> Storage
;
1423 SmallString
<128> FullYamlString(HeaderString
);
1424 FullYamlString
+= ContentsString
;
1425 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
1426 toBinary
<ELF64LE
>(Storage
, FullYamlString
);
1427 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1429 Expected
<MapVector
<const Elf_Shdr
*, const Elf_Shdr
*>> SecToRelocMapOrErr
=
1430 ElfOrErr
->getELFFile().getSectionAndRelocations(Matcher
);
1431 ASSERT_THAT_EXPECTED(SecToRelocMapOrErr
, Succeeded());
1433 // Basic verification to make sure we have the correct section types.
1434 for (auto const &[Sec
, RelaSec
] : *SecToRelocMapOrErr
) {
1435 ASSERT_EQ(Sec
->sh_type
, ELF::SHT_PROGBITS
);
1436 ASSERT_EQ(RelaSec
->sh_type
, ELF::SHT_RELA
);
1440 auto DoCheckFails
= [&](StringRef ContentsString
,
1441 std::function
<Expected
<bool>(const Elf_Shdr
&)>
1443 const char *ErrorMessage
) {
1444 SmallString
<0> Storage
;
1445 SmallString
<128> FullYamlString(HeaderString
);
1446 FullYamlString
+= ContentsString
;
1447 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
=
1448 toBinary
<ELF64LE
>(Storage
, FullYamlString
);
1449 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1451 Expected
<MapVector
<const Elf_Shdr
*, const Elf_Shdr
*>> SecToRelocMapOrErr
=
1452 ElfOrErr
->getELFFile().getSectionAndRelocations(Matcher
);
1453 ASSERT_THAT_ERROR(SecToRelocMapOrErr
.takeError(),
1454 FailedWithMessage(ErrorMessage
));
1457 auto DefaultMatcher
= [](const Elf_Shdr
&Sec
) -> bool {
1458 return Sec
.sh_type
== ELF::SHT_PROGBITS
;
1461 StringRef TwoTextSections
= R
"(
1465 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1468 Flags: [ SHF_INFO_LINK ]
1472 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1475 Flags: [ SHF_INFO_LINK ]
1478 DoCheckSucceeds(TwoTextSections
, DefaultMatcher
);
1480 StringRef OneTextSection
= R
"(
1484 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
1487 auto ErroringMatcher
= [](const Elf_Shdr
&Sec
) -> Expected
<bool> {
1488 if (Sec
.sh_type
== ELF::SHT_PROGBITS
)
1489 return createError("This was supposed to fail.");
1493 DoCheckFails(OneTextSection
, ErroringMatcher
, "This was supposed to fail.");
1495 StringRef MissingRelocatableContent
= R
"(
1499 Flags: [ SHF_INFO_LINK ]
1503 DoCheckFails(MissingRelocatableContent
, DefaultMatcher
,
1504 "SHT_RELA section with index 1: failed to get a "
1505 "relocated section: invalid section index: 255");
1508 TEST(ELFObjectFileTest
, ELFSymbolRefLess
) {
1509 SmallString
<0> Storage
;
1510 Expected
<ELFObjectFile
<ELF64LE
>> ElfOrErr
= toBinary
<ELF64LE
>(Storage
, R
"(
1519 ASSERT_THAT_EXPECTED(ElfOrErr
, Succeeded());
1520 const ELFObjectFile
<ELF64LE
> &Obj
= *ElfOrErr
;
1522 const uint32_t ValLow
= 0x00000001;
1523 const uint32_t ValHigh
= 0x00000100;
1525 auto MakeSymbol
= [&Obj
](size_t SymtabIndex
, size_t SymbolIndex
) {
1527 Data
.d
.a
= SymtabIndex
;
1528 Data
.d
.b
= SymbolIndex
;
1529 SymbolRef
Sym(Data
, &Obj
);
1530 return ELFSymbolRef(Sym
);
1533 ELFSymbolRef ELFSymLowLow
= MakeSymbol(ValLow
, ValLow
);
1534 ELFSymbolRef ELFSymLowHigh
= MakeSymbol(ValLow
, ValHigh
);
1535 ELFSymbolRef ELFSymHighLow
= MakeSymbol(ValHigh
, ValLow
);
1536 ELFSymbolRef ELFSymHighHigh
= MakeSymbol(ValHigh
, ValHigh
);
1538 EXPECT_TRUE(ELFSymLowLow
< ELFSymLowHigh
);
1539 EXPECT_FALSE(ELFSymLowHigh
< ELFSymLowLow
);
1540 EXPECT_FALSE(ELFSymLowLow
< ELFSymLowLow
);
1542 EXPECT_TRUE(ELFSymLowLow
< ELFSymHighHigh
);
1543 EXPECT_TRUE(ELFSymLowHigh
< ELFSymHighLow
);
1544 EXPECT_TRUE(ELFSymLowLow
< ELFSymHighLow
);
1546 EXPECT_FALSE(ELFSymHighLow
< ELFSymLowHigh
);
1547 EXPECT_FALSE(ELFSymHighHigh
< ELFSymLowLow
);
1548 EXPECT_FALSE(ELFSymHighLow
< ELFSymLowLow
);