diff options
author | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-15 15:45:15 +0300 |
---|---|---|
committer | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-16 13:14:23 +0300 |
commit | 407d42002904ce541f732ce4300913ef57cff232 (patch) | |
tree | ab845530cd316fa895087a054f337a13a7a983d5 /llvm/unittests/Object/ELFObjectFileTest.cpp | |
parent | 78aea98308a85c061a87952e9842bf1e6fe097d5 (diff) | |
download | llvm-407d42002904ce541f732ce4300913ef57cff232.zip llvm-407d42002904ce541f732ce4300913ef57cff232.tar.gz llvm-407d42002904ce541f732ce4300913ef57cff232.tar.bz2 |
[lib/Object] - Make ELFObjectFile::getSymbol() return Expected<>.
This was requested in comments for D93209:
https://reviews.llvm.org/D93209#inline-871192
D93209 fixes an issue with `ELFFile<ELFT>::getEntry`,
after what `getSymbol` starts calling `report_fatal_error` for previously
missed invalid cases.
This patch makes it return `Expected<>` and updates callers.
For few of them I had to add new `report_fatal_error` calls. But I see no
way to avoid it currently. The change would affects too many places, e.g:
`getSymbolBinding` and other methods are used from `ELFSymbolRef`
which is used in too many places across LLVM.
Differential revision: https://reviews.llvm.org/D93297
Diffstat (limited to 'llvm/unittests/Object/ELFObjectFileTest.cpp')
-rw-r--r-- | llvm/unittests/Object/ELFObjectFileTest.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index 30be24c..aabb07c 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -397,3 +397,75 @@ ProgramHeaders: EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); EXPECT_EQ(Data[0], 0x99); } + +// This is a test for API that is related to symbols. +// We check that errors are properly reported here. +TEST(ELFObjectFileTest, InvalidSymbolTest) { + SmallString<0> Storage; + Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .symtab + Type: SHT_SYMTAB +)"); + + ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded()); + const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile(); + const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr; + + Expected<const typename ELF64LE::Shdr *> SymtabSecOrErr = Elf.getSection(1); + ASSERT_THAT_EXPECTED(SymtabSecOrErr, Succeeded()); + ASSERT_EQ((*SymtabSecOrErr)->sh_type, ELF::SHT_SYMTAB); + + // We create a symbol with an index that is too large to exist in the object. + constexpr unsigned BrokenSymIndex = 0xFFFFFFFF; + ELFSymbolRef BrokenSym = Obj.toSymbolRef(*SymtabSecOrErr, BrokenSymIndex); + + const char *ErrMsg = "unable to access section [index 1] data at " + "0x1800000028: offset goes past the end of file"; + // 1) Check the behavior of ELFObjectFile<ELFT>::getSymbolName(). + // SymbolRef::getName() calls it internally. We can't test it directly, + // because it is protected. + EXPECT_THAT_ERROR(BrokenSym.getName().takeError(), FailedWithMessage(ErrMsg)); + + // 2) Check the behavior of ELFObjectFile<ELFT>::getSymbol(). + EXPECT_THAT_ERROR(Obj.getSymbol(BrokenSym.getRawDataRefImpl()).takeError(), + FailedWithMessage(ErrMsg)); + + // 3) Check the behavior of ELFObjectFile<ELFT>::getSymbolSection(). + // SymbolRef::getSection() calls it internally. We can't test it directly, + // because it is protected. + EXPECT_THAT_ERROR(BrokenSym.getSection().takeError(), + FailedWithMessage(ErrMsg)); + + // 4) Check the behavior of ELFObjectFile<ELFT>::getSymbolFlags(). + // SymbolRef::getFlags() calls it internally. We can't test it directly, + // because it is protected. + EXPECT_THAT_ERROR(BrokenSym.getFlags().takeError(), + FailedWithMessage(ErrMsg)); + + // 5) Check the behavior of ELFObjectFile<ELFT>::getSymbolType(). + // SymbolRef::getType() calls it internally. We can't test it directly, + // because it is protected. + EXPECT_THAT_ERROR(BrokenSym.getType().takeError(), FailedWithMessage(ErrMsg)); + + // 6) Check the behavior of ELFObjectFile<ELFT>::getSymbolAddress(). + // SymbolRef::getAddress() calls it internally. We can't test it directly, + // because it is protected. + EXPECT_THAT_ERROR(BrokenSym.getAddress().takeError(), + FailedWithMessage(ErrMsg)); + + // Finally, check the `ELFFile<ELFT>::getEntry` API. This is an underlying + // method that generates errors for all cases above. + EXPECT_THAT_EXPECTED(Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, 0), + Succeeded()); + EXPECT_THAT_ERROR( + Elf.getEntry<typename ELF64LE::Sym>(**SymtabSecOrErr, BrokenSymIndex) + .takeError(), + FailedWithMessage(ErrMsg)); +} |