1
0
mirror of synced 2024-11-28 09:30:51 +01:00

feat: Allow Find view to find overlapping occurrences

Closes #653
This commit is contained in:
WerWolv 2022-08-06 12:57:47 +02:00
parent 9c01f3efe3
commit d7accb6916
5 changed files with 76 additions and 63 deletions

View File

@ -180,7 +180,7 @@ macro(createPackage)
get_target_property(PLUGIN_LOCATION ${plugin} LOCATION) get_target_property(PLUGIN_LOCATION ${plugin} LOCATION)
install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}") install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
else () else ()
if (WIN32) if (WIN32)
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION}) install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})

View File

@ -101,6 +101,10 @@ namespace hex::prv {
return this->m_address; return this->m_address;
} }
void setAddress(u64 address) {
this->m_address = address;
}
difference_type operator-(const Iterator &other) const { difference_type operator-(const Iterator &other) const {
return this->m_address - other.m_address; return this->m_address - other.m_address;
} }
@ -172,6 +176,10 @@ namespace hex::prv {
return this->m_address; return this->m_address;
} }
void setAddress(u64 address) {
this->m_address = address;
}
difference_type operator-(const ReverseIterator &other) const { difference_type operator-(const ReverseIterator &other) const {
return other.m_address - this->m_address; return other.m_address - this->m_address;
} }

View File

@ -8,6 +8,8 @@
#include <atomic> #include <atomic>
#include <vector> #include <vector>
#include <IntervalTree.h>
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
class ViewFind : public View { class ViewFind : public View {
@ -66,7 +68,11 @@ namespace hex::plugin::builtin {
} binaryPattern; } binaryPattern;
} m_searchSettings, m_decodeSettings; } m_searchSettings, m_decodeSettings;
using OccurrenceTree = interval_tree::IntervalTree<u64, Occurrence>;
std::map<prv::Provider*, std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences; std::map<prv::Provider*, std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences;
std::map<prv::Provider*, OccurrenceTree> m_occurrenceTree;
std::atomic<bool> m_searchRunning; std::atomic<bool> m_searchRunning;
bool m_settingsValid = false; bool m_settingsValid = false;

View File

@ -16,26 +16,12 @@ namespace hex::plugin::builtin {
ViewFind::ViewFind() : View("hex.builtin.view.find.name") { ViewFind::ViewFind() : View("hex.builtin.view.find.name") {
const static auto HighlightColor = [] { return (ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarPurple) & 0x00FFFFFF) | 0x70000000; }; const static auto HighlightColor = [] { return (ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarPurple) & 0x00FFFFFF) | 0x70000000; };
const static auto FindOccurrence = [this](u64 address) -> std::optional<Occurrence> { ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8* data, size_t size) -> std::optional<color_t> {
auto &occurrences = this->m_foundOccurrences[ImHexApi::Provider::get()];
auto it = std::upper_bound(occurrences.begin(), occurrences.end(), address, [](u64 address, Occurrence &occurrence) {
return address < occurrence.region.getStartAddress();
});
if (it != occurrences.begin())
it--;
if (it != occurrences.end() && it->region.getStartAddress() <= address && address <= it->region.getEndAddress())
return *it;
else
return std::nullopt;
};
ImHexApi::HexEditor::addBackgroundHighlightingProvider([](u64 address, const u8* data, size_t size) -> std::optional<color_t> {
hex::unused(data, size); hex::unused(data, size);
if (FindOccurrence(address).has_value()) auto provider = ImHexApi::Provider::get();
if (!this->m_occurrenceTree[provider].findOverlapping(address, address).empty())
return HighlightColor(); return HighlightColor();
else else
return std::nullopt; return std::nullopt;
@ -44,19 +30,22 @@ namespace hex::plugin::builtin {
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8* data, size_t size) { ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8* data, size_t size) {
hex::unused(data, size); hex::unused(data, size);
auto occurrence = FindOccurrence(address); auto provider = ImHexApi::Provider::get();
if (!occurrence.has_value())
auto occurrences = this->m_occurrenceTree[provider].findOverlapping(address, address);
if (occurrences.empty())
return; return;
ImGui::BeginTooltip(); ImGui::BeginTooltip();
for (const auto &occurrence : occurrences) {
ImGui::PushID(&occurrence); ImGui::PushID(&occurrence);
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
{ {
const auto value = this->decodeValue(ImHexApi::Provider::get(), occurrence.value()); const auto value = this->decodeValue(ImHexApi::Provider::get(), occurrence.value);
ImGui::ColorButton("##color", ImColor(HighlightColor())); ImGui::ColorButton("##color", ImColor(HighlightColor()));
ImGui::SameLine(0, 10); ImGui::SameLine(0, 10);
@ -70,7 +59,7 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormatted("{}: ", "hex.builtin.common.region"_lang.get()); ImGui::TextFormatted("{}: ", "hex.builtin.common.region"_lang.get());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextFormatted("[ 0x{:08X} - 0x{:08X} ]", occurrence->region.getStartAddress(), occurrence->region.getEndAddress()); ImGui::TextFormatted("[ 0x{:08X} - 0x{:08X} ]", occurrence.value.region.getStartAddress(), occurrence.value.region.getEndAddress());
auto demangledValue = llvm::demangle(value); auto demangledValue = llvm::demangle(value);
@ -95,6 +84,7 @@ namespace hex::plugin::builtin {
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
} }
ImGui::PopID(); ImGui::PopID();
}
ImGui::EndTooltip(); ImGui::EndTooltip();
}); });
@ -252,7 +242,7 @@ namespace hex::plugin::builtin {
break; break;
auto address = occurrence.getAddress(); auto address = occurrence.getAddress();
reader.seek(address + sequence.size()); reader.seek(address + 1);
results.push_back(Occurrence{ Region { address, sequence.size() }, Occurrence::DecodeType::Binary }); results.push_back(Occurrence{ Region { address, sequence.size() }, Occurrence::DecodeType::Binary });
task.update(address - searchRegion.getStartAddress()); task.update(address - searchRegion.getStartAddress());
} }
@ -294,21 +284,24 @@ namespace hex::plugin::builtin {
reader.setEndAddress(searchRegion.getEndAddress()); reader.setEndAddress(searchRegion.getEndAddress());
u32 matchedBytes = 0; u32 matchedBytes = 0;
u64 address = searchRegion.getStartAddress();
const size_t patternSize = settings.pattern.size(); const size_t patternSize = settings.pattern.size();
for (u8 byte : reader) {
for (auto it = reader.begin(); it != reader.end(); ++it) {
auto byte = *it;
if ((byte & settings.pattern[matchedBytes].mask) == settings.pattern[matchedBytes].value) { if ((byte & settings.pattern[matchedBytes].mask) == settings.pattern[matchedBytes].value) {
matchedBytes++; matchedBytes++;
if (matchedBytes == settings.pattern.size()) { if (matchedBytes == settings.pattern.size()) {
results.push_back(Occurrence { Region { address - (patternSize - 1), patternSize }, Occurrence::DecodeType::Binary }); auto occurrenceAddress = it.getAddress() - (patternSize - 1);
task.update(address);
results.push_back(Occurrence { Region { occurrenceAddress, patternSize }, Occurrence::DecodeType::Binary });
task.update(occurrenceAddress);
it.setAddress(occurrenceAddress);
matchedBytes = 0; matchedBytes = 0;
} }
} else { } else {
matchedBytes = 0; matchedBytes = 0;
} }
address++;
} }
return results; return results;
@ -345,7 +338,13 @@ namespace hex::plugin::builtin {
break; break;
} }
this->m_sortedOccurrences = this->m_foundOccurrences; this->m_sortedOccurrences[provider] = this->m_foundOccurrences[provider];
OccurrenceTree::interval_vector intervals;
for (const auto &occurrence : this->m_foundOccurrences[provider])
intervals.push_back(OccurrenceTree::interval(occurrence.region.getStartAddress(), occurrence.region.getEndAddress(), occurrence));
this->m_occurrenceTree[provider] = std::move(intervals);
this->m_searchRunning = false; this->m_searchRunning = false;
}).detach(); }).detach();
} }