2020-11-15 00:42:43 +00:00
|
|
|
#include "views/view_strings.hpp"
|
|
|
|
|
|
|
|
#include "providers/provider.hpp"
|
2020-11-28 20:55:52 +00:00
|
|
|
#include "helpers/utils.hpp"
|
2020-11-15 00:42:43 +00:00
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
2020-11-24 17:12:08 +00:00
|
|
|
#include <llvm/Demangle/Demangle.h>
|
|
|
|
|
2020-11-23 12:10:14 +00:00
|
|
|
using namespace std::literals::string_literals;
|
|
|
|
|
2020-11-15 00:42:43 +00:00
|
|
|
namespace hex {
|
|
|
|
|
2020-11-23 22:57:19 +00:00
|
|
|
ViewStrings::ViewStrings(prv::Provider* &dataProvider) : View("Strings"), m_dataProvider(dataProvider) {
|
2020-11-17 12:58:50 +00:00
|
|
|
View::subscribeEvent(Events::DataChanged, [this](const void*){
|
2020-11-22 18:43:35 +00:00
|
|
|
this->m_foundStrings.clear();
|
2020-11-15 00:42:43 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
this->m_filter = new char[0xFFFF];
|
|
|
|
std::memset(this->m_filter, 0x00, 0xFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
ViewStrings::~ViewStrings() {
|
|
|
|
View::unsubscribeEvent(Events::DataChanged);
|
|
|
|
delete[] this->m_filter;
|
|
|
|
}
|
|
|
|
|
2020-11-24 01:59:49 +00:00
|
|
|
|
2020-11-24 17:12:08 +00:00
|
|
|
void ViewStrings::createStringContextMenu(const FoundString &foundString) {
|
|
|
|
if (ImGui::TableGetHoveredColumn() == 2 && ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
|
2020-11-24 01:59:49 +00:00
|
|
|
ImGui::OpenPopup("StringContextMenu");
|
2020-11-24 17:12:08 +00:00
|
|
|
this->m_selectedString = foundString.string;
|
|
|
|
}
|
2020-11-24 01:59:49 +00:00
|
|
|
if (ImGui::BeginPopup("StringContextMenu")) {
|
2020-11-24 17:12:08 +00:00
|
|
|
if (ImGui::MenuItem("Copy string")) {
|
|
|
|
ImGui::SetClipboardText(this->m_selectedString.c_str());
|
|
|
|
}
|
2020-11-24 01:59:49 +00:00
|
|
|
ImGui::Separator();
|
2020-11-24 17:12:08 +00:00
|
|
|
if (ImGui::MenuItem("Demangle")) {
|
|
|
|
this->m_demangledName = llvm::demangle(this->m_selectedString);
|
|
|
|
if (!this->m_demangledName.empty())
|
|
|
|
View::doLater([]{ ImGui::OpenPopup("Demangled Name"); });
|
|
|
|
}
|
2020-11-24 01:59:49 +00:00
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-15 00:42:43 +00:00
|
|
|
void ViewStrings::createView() {
|
|
|
|
if (this->m_shouldInvalidate) {
|
|
|
|
this->m_shouldInvalidate = false;
|
|
|
|
|
|
|
|
this->m_foundStrings.clear();
|
|
|
|
|
|
|
|
std::vector<u8> buffer(1024, 0x00);
|
|
|
|
u32 foundCharacters = 0;
|
|
|
|
for (u64 offset = 0; offset < this->m_dataProvider->getSize(); offset += buffer.size()) {
|
2020-11-23 15:19:31 +00:00
|
|
|
size_t readSize = std::min(buffer.size(), this->m_dataProvider->getSize() - offset);
|
|
|
|
this->m_dataProvider->read(offset, buffer.data(), readSize);
|
2020-11-15 00:42:43 +00:00
|
|
|
|
2020-11-23 15:19:31 +00:00
|
|
|
for (u32 i = 0; i < readSize; i++) {
|
2020-11-15 00:42:43 +00:00
|
|
|
if (buffer[i] >= 0x20 && buffer[i] <= 0x7E)
|
|
|
|
foundCharacters++;
|
|
|
|
else {
|
|
|
|
if (foundCharacters >= this->m_minimumLength) {
|
|
|
|
FoundString foundString;
|
|
|
|
|
|
|
|
foundString.offset = offset + i - foundCharacters;
|
|
|
|
foundString.size = foundCharacters;
|
|
|
|
foundString.string.reserve(foundCharacters);
|
|
|
|
foundString.string.resize(foundCharacters);
|
|
|
|
this->m_dataProvider->read(foundString.offset, foundString.string.data(), foundCharacters);
|
|
|
|
|
|
|
|
this->m_foundStrings.push_back(foundString);
|
|
|
|
}
|
|
|
|
|
|
|
|
foundCharacters = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-23 22:57:19 +00:00
|
|
|
if (ImGui::Begin("Strings", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
2020-11-15 02:51:59 +00:00
|
|
|
if (this->m_dataProvider != nullptr && this->m_dataProvider->isReadable()) {
|
|
|
|
if (ImGui::InputInt("Minimum length", &this->m_minimumLength, 1, 0))
|
|
|
|
this->m_shouldInvalidate = true;
|
|
|
|
|
|
|
|
ImGui::InputText("Filter", this->m_filter, 0xFFFF);
|
2020-11-22 18:43:35 +00:00
|
|
|
if (ImGui::Button("Extract"))
|
|
|
|
this->m_shouldInvalidate = true;
|
2020-11-15 02:51:59 +00:00
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
if (ImGui::BeginTable("##strings", 3,
|
|
|
|
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
2020-11-23 14:22:26 +00:00
|
|
|
ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
2020-11-19 23:16:50 +00:00
|
|
|
ImGui::TableSetupColumn("Offset", 0, -1, ImGui::GetID("offset"));
|
2020-11-15 02:51:59 +00:00
|
|
|
ImGui::TableSetupColumn("Size", 0, -1, ImGui::GetID("size"));
|
|
|
|
ImGui::TableSetupColumn("String", 0, -1, ImGui::GetID("string"));
|
|
|
|
|
|
|
|
auto sortSpecs = ImGui::TableGetSortSpecs();
|
|
|
|
|
|
|
|
if (sortSpecs->SpecsDirty) {
|
|
|
|
std::sort(this->m_foundStrings.begin(), this->m_foundStrings.end(),
|
2020-11-15 15:06:10 +00:00
|
|
|
[&sortSpecs](FoundString &left, FoundString &right) -> bool {
|
2020-11-19 23:16:50 +00:00
|
|
|
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("offset")) {
|
2020-11-15 02:51:59 +00:00
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.offset > right.offset;
|
|
|
|
else
|
|
|
|
return left.offset < right.offset;
|
|
|
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.size > right.size;
|
|
|
|
else
|
|
|
|
return left.size < right.size;
|
|
|
|
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("string")) {
|
|
|
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
|
|
|
return left.string > right.string;
|
|
|
|
else
|
|
|
|
return left.string < right.string;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
sortSpecs->SpecsDirty = false;
|
|
|
|
}
|
2020-11-15 00:42:43 +00:00
|
|
|
|
2020-11-15 02:51:59 +00:00
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
2020-11-20 10:56:37 +00:00
|
|
|
clipper.Begin(this->m_foundStrings.size());
|
|
|
|
|
|
|
|
while (clipper.Step()) {
|
|
|
|
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
|
|
|
auto &foundString = this->m_foundStrings[i];
|
|
|
|
|
|
|
|
if (strlen(this->m_filter) != 0 &&
|
|
|
|
foundString.string.find(this->m_filter) == std::string::npos)
|
|
|
|
continue;
|
|
|
|
|
2020-11-23 12:08:24 +00:00
|
|
|
ImGui::TableNextRow();
|
2020-11-20 10:56:37 +00:00
|
|
|
ImGui::TableNextColumn();
|
2020-11-23 12:10:14 +00:00
|
|
|
if (ImGui::Selectable(("##StringLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
|
|
|
|
Region selectRegion = { foundString.offset, foundString.size };
|
|
|
|
View::postEvent(Events::SelectionChangeRequest, &selectRegion);
|
|
|
|
}
|
2020-11-24 17:12:08 +00:00
|
|
|
ImGui::PushID(i + 1);
|
|
|
|
createStringContextMenu(foundString);
|
|
|
|
ImGui::PopID();
|
2020-11-23 12:10:14 +00:00
|
|
|
ImGui::SameLine();
|
2020-11-20 10:56:37 +00:00
|
|
|
ImGui::Text("0x%08lx : 0x%08lx", foundString.offset, foundString.offset + foundString.size);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("0x%04lx", foundString.size);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%s", foundString.string.c_str());
|
|
|
|
}
|
2020-11-15 02:51:59 +00:00
|
|
|
}
|
|
|
|
clipper.End();
|
2020-11-15 00:42:43 +00:00
|
|
|
|
2020-11-15 02:51:59 +00:00
|
|
|
ImGui::EndTable();
|
2020-11-15 00:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::End();
|
2020-11-24 17:12:08 +00:00
|
|
|
|
|
|
|
if (ImGui::BeginPopup("Demangled Name")) {
|
|
|
|
if (ImGui::BeginChild("##scrolling", ImVec2(500, 150))) {
|
|
|
|
ImGui::Text("Demangled Name");
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::TextWrapped("%s", this->m_demangledName.c_str());
|
|
|
|
ImGui::EndChild();
|
|
|
|
ImGui::NewLine();
|
|
|
|
if (ImGui::Button("Copy"))
|
|
|
|
ImGui::SetClipboardText(this->m_demangledName.c_str());
|
|
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
|
|
}
|
2020-11-15 00:42:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ViewStrings::createMenu() {
|
2020-11-23 22:57:19 +00:00
|
|
|
|
2020-11-15 00:42:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|