diff options
author | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-04 11:54:03 +0300 |
---|---|---|
committer | Georgii Rymar <grimar@accesssoftek.com> | 2020-12-16 12:59:32 +0300 |
commit | 78aea98308a85c061a87952e9842bf1e6fe097d5 (patch) | |
tree | 7996cbd5e1cc88706741016ed51aa5d1f4ffa695 /llvm/unittests/Object/ELFObjectFileTest.cpp | |
parent | 0da240c2d050303c99564f1901b0d1548ffe2323 (diff) | |
download | llvm-78aea98308a85c061a87952e9842bf1e6fe097d5.zip llvm-78aea98308a85c061a87952e9842bf1e6fe097d5.tar.gz llvm-78aea98308a85c061a87952e9842bf1e6fe097d5.tar.bz2 |
[llvm-readelf/obj] - Handle out-of-order PT_LOADs better.
This is https://bugs.llvm.org/show_bug.cgi?id=45698.
Specification says that
"Loadable segment entries in the program header table appear
in ascending order, sorted on the p_vaddr member."
Our `toMappedAddr()` relies on this condition. This patch
adds a warning when the sorting order of loadable segments is wrong.
In this case we force segments sorting and that allows
`toMappedAddr()` to work as expected.
Differential revision: https://reviews.llvm.org/D92641
Diffstat (limited to 'llvm/unittests/Object/ELFObjectFileTest.cpp')
-rw-r--r-- | llvm/unittests/Object/ELFObjectFileTest.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index 5b7a298..30be24c 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -328,3 +328,72 @@ Sections: ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); } + +// Test that we are able to create an ELFObjectFile even when loadable segments +// are unsorted by virtual address. +// Test that ELFFile<ELFT>::toMappedAddr works properly in this case. + +TEST(ELFObjectFileTest, InvalidLoadSegmentsOrderTest) { + SmallString<0> Storage; + Expected<ELFObjectFile<ELF64LE>> ExpectedFile = toBinary<ELF64LE>(Storage, R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .foo + Type: SHT_PROGBITS + Address: 0x1000 + Offset: 0x3000 + ContentArray: [ 0x11 ] + - Name: .bar + Type: SHT_PROGBITS + Address: 0x2000 + Offset: 0x4000 + ContentArray: [ 0x99 ] +ProgramHeaders: + - Type: PT_LOAD + VAddr: 0x2000 + FirstSec: .bar + LastSec: .bar + - Type: PT_LOAD + VAddr: 0x1000 + FirstSec: .foo + LastSec: .foo +)"); + + ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded()); + + std::string WarnString; + auto ToMappedAddr = [&](uint64_t Addr) -> const uint8_t * { + Expected<const uint8_t *> DataOrErr = + ExpectedFile->getELFFile().toMappedAddr(Addr, [&](const Twine &Msg) { + EXPECT_TRUE(WarnString.empty()); + WarnString = Msg.str(); + return Error::success(); + }); + + if (!DataOrErr) { + ADD_FAILURE() << toString(DataOrErr.takeError()); + return nullptr; + } + + EXPECT_TRUE(WarnString == + "loadable segments are unsorted by virtual address"); + WarnString = ""; + return *DataOrErr; + }; + + const uint8_t *Data = ToMappedAddr(0x1000); + ASSERT_TRUE(Data); + MemoryBufferRef Buf = ExpectedFile->getMemoryBufferRef(); + EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x3000); + EXPECT_EQ(Data[0], 0x11); + + Data = ToMappedAddr(0x2000); + ASSERT_TRUE(Data); + Buf = ExpectedFile->getMemoryBufferRef(); + EXPECT_EQ((const char *)Data - Buf.getBufferStart(), 0x4000); + EXPECT_EQ(Data[0], 0x99); +} |