From d7d19d75949234d2ef15aea2e317eafbc539cf7b Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 1 Jan 2023 12:26:27 +0100 Subject: [PATCH] feat: Further improve process memory provider --- lib/libimhex/CMakeLists.txt | 1 - lib/libimhex/include/hex/helpers/types.hpp | 31 ++++++++++--- lib/libimhex/source/helpers/types.cpp | 41 ----------------- plugins/builtin/include/ui/hex_editor.hpp | 2 + plugins/builtin/source/ui/hex_editor.cpp | 9 ++-- .../providers/process_memory_provider.hpp | 8 +++- .../providers/process_memory_provider.cpp | 44 +++++++++++++++---- 7 files changed, 72 insertions(+), 64 deletions(-) delete mode 100644 lib/libimhex/source/helpers/types.cpp diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index 5b114a308..479fea153 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -126,7 +126,6 @@ set(LIBIMHEX_SOURCES source/helpers/encoding_file.cpp source/helpers/logger.cpp source/helpers/tar.cpp - source/helpers/types.cpp source/providers/provider.cpp diff --git a/lib/libimhex/include/hex/helpers/types.hpp b/lib/libimhex/include/hex/helpers/types.hpp index 91df7f67a..0df6343f2 100644 --- a/lib/libimhex/include/hex/helpers/types.hpp +++ b/lib/libimhex/include/hex/helpers/types.hpp @@ -23,14 +23,33 @@ namespace hex { u64 address; size_t size; - [[nodiscard]] bool isWithin(const Region &other) const; - [[nodiscard]] bool overlaps(const Region &other) const; + [[nodiscard]] constexpr bool isWithin(const Region &other) const { + if (*this == Invalid() || other == Invalid()) + return false; - [[nodiscard]] u64 getStartAddress() const; - [[nodiscard]] u64 getEndAddress() const; - [[nodiscard]] size_t getSize() const; + if (this->getStartAddress() >= other.getStartAddress() && this->getEndAddress() <= other.getEndAddress()) + return true; - bool operator==(const Region &other) const; + return false; + } + + [[nodiscard]] constexpr bool overlaps(const Region &other) const { + if (*this == Invalid() || other == Invalid()) + return false; + + if (this->getEndAddress() >= other.getStartAddress() && this->getStartAddress() <= other.getEndAddress()) + return true; + + return false; + } + + [[nodiscard]] constexpr u64 getStartAddress() const { return this->address; } + [[nodiscard]] constexpr u64 getEndAddress() const { return this->address + this->size - 1;} + [[nodiscard]] constexpr size_t getSize() const { return this->size; } + + [[nodiscard]] constexpr bool operator==(const Region &other) const { + return this->address == other.address && this->size == other.size; + } constexpr static Region Invalid() { return { 0, 0 }; diff --git a/lib/libimhex/source/helpers/types.cpp b/lib/libimhex/source/helpers/types.cpp deleted file mode 100644 index bcedccb49..000000000 --- a/lib/libimhex/source/helpers/types.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -namespace hex { - - [[nodiscard]] bool Region::isWithin(const Region &other) const { - if (*this == Invalid() || other == Invalid()) - return false; - - if (this->getStartAddress() >= other.getStartAddress() && this->getEndAddress() <= other.getEndAddress()) - return true; - - return false; - } - - [[nodiscard]] bool Region::overlaps(const Region &other) const { - if (*this == Invalid() || other == Invalid()) - return false; - - if (this->getEndAddress() >= other.getStartAddress() && this->getStartAddress() <= other.getEndAddress()) - return true; - - return false; - } - - [[nodiscard]] u64 Region::getStartAddress() const { - return this->address; - } - - [[nodiscard]] u64 Region::getEndAddress() const { - return this->address + this->size - 1; - } - - [[nodiscard]] size_t Region::getSize() const { - return this->size; - } - - bool Region::operator==(const Region &other) const { - return this->address == other.address && this->size == other.size; - } - -} \ No newline at end of file diff --git a/plugins/builtin/include/ui/hex_editor.hpp b/plugins/builtin/include/ui/hex_editor.hpp index 5192e0407..a33a39852 100644 --- a/plugins/builtin/include/ui/hex_editor.hpp +++ b/plugins/builtin/include/ui/hex_editor.hpp @@ -197,6 +197,8 @@ namespace hex::plugin::builtin::ui { std::optional m_currCustomEncoding; + std::pair m_currValidRegion = { Region::Invalid(), false }; + static inline std::optional defaultColorCallback(u64, const u8 *, size_t) { return std::nullopt; } static inline void defaultTooltipCallback(u64, const u8 *, size_t) { } std::function(u64, const u8 *, size_t)> m_foregroundColorCallback = defaultColorCallback, m_backgroundColorCallback = defaultColorCallback; diff --git a/plugins/builtin/source/ui/hex_editor.cpp b/plugins/builtin/source/ui/hex_editor.cpp index f05bc295f..a64b0b0c6 100644 --- a/plugins/builtin/source/ui/hex_editor.cpp +++ b/plugins/builtin/source/ui/hex_editor.cpp @@ -379,11 +379,10 @@ namespace hex::plugin::builtin::ui { if (this->m_provider != nullptr && this->m_provider->isReadable()) { - std::pair validRegion = { Region::Invalid(), false }; - const auto isCurrRegionValid = [this, &validRegion](u64 address){ - auto &[currRegion, currRegionValid] = validRegion; + const auto isCurrRegionValid = [this](u64 address){ + auto &[currRegion, currRegionValid] = this->m_currValidRegion; if (!Region{ address, 1 }.isWithin(currRegion)) { - validRegion = this->m_provider->getRegionValidity(address); + this->m_currValidRegion = this->m_provider->getRegionValidity(address); } return currRegionValid; @@ -541,7 +540,7 @@ namespace hex::plugin::builtin::ui { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushItemWidth(CharacterSize.x); if (!isCurrRegionValid(byteAddress)) - ImGui::TextFormatted("?"); + ImGui::TextDisabled("?"); else this->drawCell(byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII); ImGui::PopItemWidth(); diff --git a/plugins/windows/include/content/providers/process_memory_provider.hpp b/plugins/windows/include/content/providers/process_memory_provider.hpp index 406166108..d5923ad2c 100644 --- a/plugins/windows/include/content/providers/process_memory_provider.hpp +++ b/plugins/windows/include/content/providers/process_memory_provider.hpp @@ -64,15 +64,19 @@ namespace hex::plugin::windows { std::string name; }; - struct Module { + struct MemoryRegion { Region region; std::string name; + + constexpr bool operator<(const MemoryRegion &other) const { + return this->region.getStartAddress() < other.region.getStartAddress(); + } }; std::vector m_processes; std::optional m_selectedProcess; - std::vector m_modules; + std::set m_memoryRegions; HANDLE m_processHandle = nullptr; diff --git a/plugins/windows/source/content/providers/process_memory_provider.cpp b/plugins/windows/source/content/providers/process_memory_provider.cpp index dde17d88d..15591ec1e 100644 --- a/plugins/windows/source/content/providers/process_memory_provider.cpp +++ b/plugins/windows/source/content/providers/process_memory_provider.cpp @@ -5,6 +5,7 @@ #include #include +#include namespace hex::plugin::windows { @@ -35,7 +36,23 @@ namespace hex::plugin::windows { if (GetModuleFileNameExA(this->m_processHandle, module, moduleName, MAX_PATH) == FALSE) continue; - this->m_modules.push_back({ { (u64)moduleInfo.lpBaseOfDll, (u64)moduleInfo.lpBaseOfDll + moduleInfo.SizeOfImage }, std::fs::path(moduleName).filename().string() }); + this->m_memoryRegions.insert({ { (u64)moduleInfo.lpBaseOfDll, (u64)moduleInfo.lpBaseOfDll + moduleInfo.SizeOfImage }, std::fs::path(moduleName).filename().string() }); + } + + MEMORY_BASIC_INFORMATION memoryInfo; + for (u64 address = 0; address < 0xFFFF'FFFF'FFFF; address += memoryInfo.RegionSize) { + if (VirtualQueryEx(this->m_processHandle, (LPCVOID)address, &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) + break; + + std::string name; + if (memoryInfo.State & MEM_IMAGE) continue; + if (memoryInfo.State & MEM_FREE) continue; + if (memoryInfo.State & MEM_COMMIT) name += "Commit "; + if (memoryInfo.State & MEM_RESERVE) name += "Reserve "; + if (memoryInfo.State & MEM_PRIVATE) name += "Private "; + if (memoryInfo.State & MEM_MAPPED) name += "Mapped "; + + this->m_memoryRegions.insert({ { (u64)memoryInfo.BaseAddress, (u64)memoryInfo.BaseAddress + memoryInfo.RegionSize }, name }); } return true; @@ -54,9 +71,18 @@ namespace hex::plugin::windows { } std::pair ProcessMemoryProvider::getRegionValidity(u64 address) const { - for (const auto &module : this->m_modules) { - if (module.region.overlaps({ address, 1 })) - return { module.region, true }; + for (const auto &memoryRegion : this->m_memoryRegions) { + if (memoryRegion.region.overlaps({ address, 1 })) + return { memoryRegion.region, true }; + } + + Region lastRegion = Region::Invalid(); + for (const auto &memoryRegion : this->m_memoryRegions) { + + if (address < memoryRegion.region.getStartAddress()) + return { Region { lastRegion.getEndAddress() + 1, memoryRegion.region.getStartAddress() - lastRegion.getEndAddress() }, false }; + + lastRegion = memoryRegion.region; } return { Region::Invalid(), false }; @@ -127,16 +153,16 @@ namespace hex::plugin::windows { ImGui::TableSetupColumn("Name"); ImGui::TableHeadersRow(); - for (auto &module : this->m_modules) { - ImGui::PushID(module.region.getStartAddress()); + for (auto &memoryRegion : this->m_memoryRegions) { + ImGui::PushID(memoryRegion.region.getStartAddress()); ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("0x%016llX - 0x%016llX", module.region.getStartAddress(), module.region.getEndAddress()); + ImGui::Text("0x%016llX - 0x%016llX", memoryRegion.region.getStartAddress(), memoryRegion.region.getEndAddress()); ImGui::TableNextColumn(); - if (ImGui::Selectable(module.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) - ImHexApi::HexEditor::setSelection(module.region); + if (ImGui::Selectable(memoryRegion.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) + ImHexApi::HexEditor::setSelection(memoryRegion.region); ImGui::PopID(); }