aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/ELF.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/lib/Object/ELF.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/lib/Object/ELF.cpp')
-rw-r--r--llvm/lib/Object/ELF.cpp14
1 files changed, 13 insertions, 1 deletions
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 116856a..28a6914 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -566,7 +566,8 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const {
}
template <class ELFT>
-Expected<const uint8_t *> ELFFile<ELFT>::toMappedAddr(uint64_t VAddr) const {
+Expected<const uint8_t *>
+ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const {
auto ProgramHeadersOrError = program_headers();
if (!ProgramHeadersOrError)
return ProgramHeadersOrError.takeError();
@@ -577,6 +578,17 @@ Expected<const uint8_t *> ELFFile<ELFT>::toMappedAddr(uint64_t VAddr) const {
if (Phdr.p_type == ELF::PT_LOAD)
LoadSegments.push_back(const_cast<Elf_Phdr *>(&Phdr));
+ auto SortPred = [](const Elf_Phdr_Impl<ELFT> *A,
+ const Elf_Phdr_Impl<ELFT> *B) {
+ return A->p_vaddr < B->p_vaddr;
+ };
+ if (!llvm::is_sorted(LoadSegments, SortPred)) {
+ if (Error E =
+ WarnHandler("loadable segments are unsorted by virtual address"))
+ return std::move(E);
+ llvm::stable_sort(LoadSegments, SortPred);
+ }
+
const Elf_Phdr *const *I =
std::upper_bound(LoadSegments.begin(), LoadSegments.end(), VAddr,
[](uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {