aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Object/ELFObjectFileTest.cpp
diff options
context:
space:
mode:
authorGeorgii Rymar <grimar@accesssoftek.com>2020-12-04 11:54:03 +0300
committerGeorgii Rymar <grimar@accesssoftek.com>2020-12-16 12:59:32 +0300
commit78aea98308a85c061a87952e9842bf1e6fe097d5 (patch)
tree7996cbd5e1cc88706741016ed51aa5d1f4ffa695 /llvm/unittests/Object/ELFObjectFileTest.cpp
parent0da240c2d050303c99564f1901b0d1548ffe2323 (diff)
downloadllvm-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.cpp69
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);
+}