1
0
mirror of synced 2025-02-17 18:59:21 +01:00

sys: Added support for providers with unreadable regions

This commit is contained in:
WerWolv 2022-08-10 09:26:48 +02:00
parent 19a0dc80db
commit 5c13cf9dbf
8 changed files with 111 additions and 18 deletions

@ -1 +1 @@
Subproject commit f1c58564f32b23e52a57ef2c1263223b3b773ddf
Subproject commit 15f42da03ff501d5e1c66794a508ef9a452236e3

View File

@ -21,11 +21,11 @@ namespace hex {
size_t size;
[[nodiscard]] constexpr bool isWithin(const Region &other) const {
return (this->getStartAddress() >= other.getStartAddress()) && (this->getEndAddress() <= other.getEndAddress());
return (this->getStartAddress() >= other.getStartAddress()) && (this->getEndAddress() <= other.getEndAddress()) && *this != Invalid() && other != Invalid();
}
[[nodiscard]] constexpr bool overlaps(const Region &other) const {
return (this->getEndAddress() >= other.getStartAddress()) && (this->getStartAddress() < other.getEndAddress());
return (this->getEndAddress() >= other.getStartAddress()) && (this->getStartAddress() < other.getEndAddress()) && *this != Invalid() && other != Invalid();
}
[[nodiscard]] constexpr u64 getStartAddress() const {
@ -39,6 +39,14 @@ namespace hex {
[[nodiscard]] constexpr size_t getSize() const {
return this->size;
}
constexpr bool operator==(const Region &other) const {
return this->address == other.address && this->size == other.size;
}
constexpr static Region Invalid() {
return { 0, 0 };
}
};
}

View File

@ -99,6 +99,8 @@ namespace hex::prv {
void markDirty(bool dirty = true) { this->m_dirty = dirty; }
[[nodiscard]] bool isDirty() const { return this->m_dirty; }
virtual std::pair<Region, bool> getRegionValidity(u64 address) const;
protected:
u32 m_currPage = 0;
u64 m_baseAddress = 0;

View File

@ -244,9 +244,11 @@ namespace hex {
std::unique_ptr<pl::PatternLanguage> createDefaultRuntime(prv::Provider *provider) {
auto runtime = std::make_unique<pl::PatternLanguage>();
runtime->setDataSource([provider](u64 offset, u8 *buffer, size_t size) {
provider->read(offset, buffer, size);
}, 0, 0);
if (provider != nullptr) {
runtime->setDataSource([provider](u64 offset, u8 *buffer, size_t size) {
provider->read(offset, buffer, size);
}, provider->getBaseAddress(), provider->getActualSize());
}
runtime->setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude));

View File

@ -254,4 +254,36 @@ namespace hex::prv {
this->m_currPage = settings["currPage"];
}
std::pair<Region, bool> Provider::getRegionValidity(u64 address) const {
if (address > this->getActualSize())
return { Region::Invalid(), false };
bool insideValidRegion = false;
std::optional<u64> nextRegionAddress;
for (const auto &overlay : this->m_overlays) {
Region overlayRegion = { overlay->getAddress(), overlay->getSize() };
if (!nextRegionAddress.has_value() || overlay->getAddress() < nextRegionAddress) {
nextRegionAddress = overlayRegion.getStartAddress();
}
if (Region { address, 1 }.overlaps(overlayRegion)) {
insideValidRegion = true;
}
}
for (const auto &[patchAddress, value] : this->m_patches.back()) {
if (!nextRegionAddress.has_value() || patchAddress < nextRegionAddress)
nextRegionAddress = patchAddress;
if (address == patchAddress)
insideValidRegion = true;
}
if (!nextRegionAddress.has_value())
return { Region { address, this->getActualSize() - address }, true };
else
return { Region { address, *nextRegionAddress - address }, insideValidRegion };
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <hex/providers/provider.hpp>
namespace hex::plugin::builtin::prv {
class NullProvider : public hex::prv::Provider {
public:
explicit NullProvider() = default;
~NullProvider() override = default;
[[nodiscard]] bool isAvailable() const override { return true; }
[[nodiscard]] bool isReadable() const override { return true; }
[[nodiscard]] bool isWritable() const override { return false; }
[[nodiscard]] bool isResizable() const override { return false; }
[[nodiscard]] bool isSavable() const override { return false; }
void readRaw(u64 offset, void *buffer, size_t size) override { hex::unused(offset, buffer, size); }
void writeRaw(u64 offset, const void *buffer, size_t size) override { hex::unused(offset, buffer, size); }
[[nodiscard]] size_t getActualSize() const override { return 0x00; }
[[nodiscard]] std::string getName() const override { return "None"; }
[[nodiscard]] std::vector<std::pair<std::string, std::string>> getDataInformation() const override { return { }; }
void loadSettings(const nlohmann::json &settings) override { hex::unused(settings); }
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override { return settings; }
[[nodiscard]] std::string getTypeName() const override {
return "hex.builtin.provider.null";
}
};
}

View File

@ -2,6 +2,7 @@
#include "content/providers/gdb_provider.hpp"
#include "content/providers/file_provider.hpp"
#include "content/providers/null_provider.hpp"
#include "content/providers/disk_provider.hpp"
#include <hex/api/project_file_manager.hpp>
@ -13,8 +14,9 @@ namespace hex::plugin::builtin {
void registerProviders() {
ContentRegistry::Provider::add<prv::FileProvider>(false);
ContentRegistry::Provider::add<prv::GDBProvider>();
ContentRegistry::Provider::add<prv::NullProvider>(false);
ContentRegistry::Provider::add<prv::DiskProvider>();
ContentRegistry::Provider::add<prv::GDBProvider>();
ProjectFile::registerHandler({
.basePath = "providers",
@ -53,9 +55,7 @@ namespace hex::plugin::builtin {
}
tar.write(basePath / "providers.json",
nlohmann::json({
{"providers", providerIds}
}).dump(4)
nlohmann::json({ {"providers", providerIds } }).dump(4)
);
return true;

View File

@ -728,6 +728,16 @@ namespace hex::plugin::builtin {
if (ImHexApi::Provider::isValid()) {
auto provider = ImHexApi::Provider::get();
std::pair<Region, bool> validRegion = { Region::Invalid(), false };
const auto isCurrRegionValid = [&validRegion, &provider](u64 address){
auto &[currRegion, currRegionValid] = validRegion;
if (!Region{ address, 1 }.isWithin(currRegion)) {
validRegion = provider->getRegionValidity(address);
}
return currRegionValid;
};
ImGuiListClipper clipper;
clipper.Begin(std::ceil(provider->getSize() / (long double)(this->m_bytesPerRow)), CharacterSize.y);
@ -735,7 +745,7 @@ namespace hex::plugin::builtin {
this->m_visibleRowCount = clipper.DisplayEnd - clipper.DisplayStart;
// Loop over rows
for (i128 y = clipper.DisplayStart; y < u64(clipper.DisplayEnd); y++) {
for (u64 y = u64(clipper.DisplayStart); y < u64(clipper.DisplayEnd); y++) {
// Draw address column
ImGui::TableNextRow();
@ -800,13 +810,14 @@ namespace hex::plugin::builtin {
if (x < std::ceil(float(validBytes) / bytesPerCell)) {
auto cellStartPos = getCellPosition();
auto cellSize = (CharacterSize * ImVec2(this->m_currDataVisualizer->getMaxCharsPerCell(), 1) + (ImVec2(3, 2) * ImGui::GetStyle().CellPadding) - ImVec2(1, 0) * ImGui::GetStyle().CellPadding) + ImVec2(1, 0);
auto maxCharsPerCell = this->m_currDataVisualizer->getMaxCharsPerCell();
auto [foregroundColor, backgroundColor] = cellColors[x];
if (isColumnSeparatorColumn(x + 1, columnCount) && selectionMax != x + y * columnCount) {
cellSize.x += SeparatorColumWidth + 1;
}
if (y == clipper.DisplayStart)
if (y == u64(clipper.DisplayStart))
cellSize.y -= (ImGui::GetStyle().CellPadding.y + 1);
// Draw highlights and selection
@ -830,8 +841,11 @@ namespace hex::plugin::builtin {
// Draw cell content
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushItemWidth((CharacterSize * this->m_currDataVisualizer->getMaxCharsPerCell()).x);
this->drawCell(byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered);
ImGui::PushItemWidth((CharacterSize * maxCharsPerCell).x);
if (isCurrRegionValid(byteAddress))
this->drawCell(byteAddress, &bytes[x * bytesPerCell], bytesPerCell, cellHovered);
else
ImGui::TextFormatted("{}", std::string(maxCharsPerCell, '?'));
ImGui::PopItemWidth();
ImGui::PopStyleVar();
@ -875,7 +889,9 @@ namespace hex::plugin::builtin {
this->drawSelectionFrame(x, y, byteAddress, 1, cellStartPos, cellSize);
}
if (std::isprint(bytes[x]))
if (!isCurrRegionValid(byteAddress))
ImGui::TextFormatted("?");
else if (std::isprint(bytes[x]))
ImGui::TextFormatted("{:c}", bytes[x]);
else
ImGui::TextDisabled(".");
@ -917,7 +933,7 @@ namespace hex::plugin::builtin {
const auto x = address % this->m_bytesPerRow;
if (x < validBytes) {
if (x < validBytes && isCurrRegionValid(address)) {
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
// Draw highlights and selection
@ -951,13 +967,13 @@ namespace hex::plugin::builtin {
if ((ImGui::IsMouseDown(ImGuiMouseButton_Left) && this->m_selectionStart != this->m_selectionEnd)) {
auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1);
if (y == clipper.DisplayStart + 2) {
if (y == u64(clipper.DisplayStart + 2)) {
if (i128(this->m_selectionEnd - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 2) * this->m_bytesPerRow)) {
this->m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(fractionPerLine * 4);
}
} else if (y == (clipper.DisplayEnd - 2)) {
} else if (y == u64(clipper.DisplayEnd - 2)) {
if (i128(this->m_selectionEnd - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) {
this->m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(fractionPerLine * (this->m_visibleRowCount - 1));