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/lib/Object/ELF.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/lib/Object/ELF.cpp')
-rw-r--r-- | llvm/lib/Object/ELF.cpp | 14 |
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) { |