summaryrefslogtreecommitdiff
path: root/plugins/warp/ui/plugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/warp/ui/plugin.cpp')
-rw-r--r--plugins/warp/ui/plugin.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/plugins/warp/ui/plugin.cpp b/plugins/warp/ui/plugin.cpp
new file mode 100644
index 00000000..69aaaf34
--- /dev/null
+++ b/plugins/warp/ui/plugin.cpp
@@ -0,0 +1,198 @@
+#include "plugin.h"
+
+#include <QToolBar>
+
+#include "matched.h"
+#include "matches.h"
+#include "symbollist.h"
+#include "viewframe.h"
+
+using namespace BinaryNinja;
+
+QIcon GetColoredIcon(const QString &iconPath, const QColor &color)
+{
+ auto pixmap = QPixmap(iconPath);
+ auto mask = pixmap.createMaskFromColor(QColor(0, 0, 0), Qt::MaskInColor);
+ pixmap.fill(color);
+ pixmap.setMask(mask);
+ return QIcon(pixmap);
+}
+
+Ref<BackgroundTask> GetMatcherTask()
+{
+ // TODO: What happens if we have multiple views open matching? This fails.
+ // Look for the matcher background task to determine if we are stopping or starting it.
+ Ref<BackgroundTask> matcherTask = nullptr;
+ for (const auto &task: BackgroundTask::GetRunningTasks())
+ {
+ std::string progressText = task->GetProgressText();
+ if (progressText.find("Matching on WARP") != std::string::npos)
+ matcherTask = task;
+ }
+ return matcherTask;
+}
+
+WarpSidebarWidget::WarpSidebarWidget(BinaryViewRef data) : SidebarWidget("WARP"), m_data(data)
+{
+ m_logger = LogRegistry::CreateLogger("WARPUI");
+ m_currentFrame = nullptr;
+
+ m_headerWidget = new QWidget();
+ QHBoxLayout *headerLayout = new QHBoxLayout();
+ headerLayout->setContentsMargins(0, 0, 0, 0);
+ headerLayout->setSpacing(0);
+
+ QToolBar *headerToolbar = new QToolBar(this);
+ headerToolbar->setContentsMargins(0, 0, 0, 0);
+ headerToolbar->setIconSize(QSize(20, 20));
+
+ static auto matcherStopIcon = GetColoredIcon(":/icons/images/stop.png", getThemeColor(RedStandardHighlightColor));
+ static auto matcherStartIcon = GetColoredIcon(":/icons/images/start.png",
+ getThemeColor(GreenStandardHighlightColor));
+ m_matcherAction = headerToolbar->addAction(matcherStartIcon, "Run Matcher", [this]() {
+ UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ if (Ref<BackgroundTask> matcherTask = GetMatcherTask())
+ matcherTask->Cancel();
+ else if (!isMatcherRunning)
+ {
+ handler->executeAction("WARP\\Run Matcher");
+ setMatcherActionIcon(true);
+ }
+ });
+ m_matcherAction->setToolTip("Run the matcher on all functions");
+
+ auto loadIcon = GetColoredIcon(":/icons/images/file-add.png", getThemeColor(BlueStandardHighlightColor));
+ auto loadAction = headerToolbar->addAction(loadIcon, "Load Signature File", [this]() {
+ UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ handler->executeAction("WARP\\Load File");
+ });
+ loadAction->setToolTip("Load a signature file to match against");
+
+ auto saveIcon = GetColoredIcon(":/icons/images/edit.png", getThemeColor(BlueStandardHighlightColor));
+ auto saveAction = headerToolbar->addAction(saveIcon, "Create Signature File", [this]() {
+ UIActionHandler *handler = m_currentFrame->getCurrentViewInterface()->actionHandler();
+ handler->executeAction("WARP\\Create\\From Current View");
+ });
+ saveAction->setToolTip("Save data to a signature file");
+
+ auto refreshIcon = GetColoredIcon(":/icons/images/refresh.png", getThemeColor(BlueStandardHighlightColor));
+ auto refreshAction = headerToolbar->addAction(refreshIcon, "Refresh the view data", [this]() {
+ Update();
+ });
+ refreshAction->setToolTip("Refresh the sidebar data");
+
+ // TODO: Add action for pushing to network sources.
+
+ // Push the toolbar to the right using a stretch space.
+ headerLayout->addStretch();
+ headerLayout->addWidget(headerToolbar, 0);
+ m_headerWidget->setLayout(headerLayout);
+
+ QFrame *currentFunctionFrame = new QFrame(this);
+ m_currentFunctionWidget = new WarpCurrentFunctionWidget(nullptr);
+ QVBoxLayout *currentFunctionLayout = new QVBoxLayout();
+ currentFunctionLayout->setContentsMargins(0, 0, 0, 0);
+ currentFunctionLayout->setSpacing(0);
+ currentFunctionLayout->addWidget(m_currentFunctionWidget);
+ currentFunctionFrame->setLayout(currentFunctionLayout);
+
+ QFrame *matchedFrame = new QFrame(this);
+ m_matchedWidget = new WarpMatchedWidget(m_data);
+ QVBoxLayout *matchedLayout = new QVBoxLayout();
+ matchedLayout->setContentsMargins(0, 0, 0, 0);
+ matchedLayout->setSpacing(0);
+ matchedLayout->addWidget(m_matchedWidget);
+ matchedFrame->setLayout(matchedLayout);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ auto tabWidget = new QTabWidget(this);
+ tabWidget->addTab(currentFunctionFrame, "Current Function");
+ tabWidget->addTab(matchedFrame, "Matched Functions");
+
+ m_analysisEvent = new AnalysisCompletionEvent(m_data, [this]() {
+ ExecuteOnMainThread([this]() {
+ Update();
+ });
+ });
+
+ layout->addWidget(tabWidget);
+ this->setLayout(layout);
+}
+
+WarpSidebarWidget::~WarpSidebarWidget()
+{
+ m_analysisEvent->Cancel();
+}
+
+void WarpSidebarWidget::focus()
+{
+}
+
+void WarpSidebarWidget::Update()
+{
+ m_matchedWidget->Update();
+ if (!GetMatcherTask())
+ setMatcherActionIcon(false);
+}
+
+void WarpSidebarWidget::setMatcherActionIcon(bool running)
+{
+ static auto matcherStopIcon = GetColoredIcon(":/icons/images/stop.png", getThemeColor(RedStandardHighlightColor));
+ static auto matcherStartIcon = GetColoredIcon(":/icons/images/start.png",
+ getThemeColor(GreenStandardHighlightColor));
+ isMatcherRunning = running;
+ if (running)
+ {
+ m_matcherAction->setIcon(matcherStopIcon);
+ m_matcherAction->setToolTip("Stop the matcher");
+ m_matcherAction->setIconText("Stop Matcher");
+ } else
+ {
+ m_matcherAction->setIcon(matcherStartIcon);
+ m_matcherAction->setToolTip("Run the matcher on all functions");
+ m_matcherAction->setIconText("Run Matcher");
+ }
+}
+
+void WarpSidebarWidget::notifyViewChanged(ViewFrame *view)
+{
+ if (!view)
+ return;
+
+ if (view == m_currentFrame)
+ return;
+ m_currentFrame = view;
+ // TODO: We need to set some stuff here prolly.
+}
+
+void WarpSidebarWidget::notifyViewLocationChanged(View *view, const ViewLocation &location)
+{
+ auto function = location.getFunction();
+ // TODO: Only update if the function exists?
+ // NOTE: The function called will exit early if it is the same function.
+ m_currentFunctionWidget->SetCurrentFunction(function);
+}
+
+WarpSidebarWidgetType::WarpSidebarWidgetType() : SidebarWidgetType(QImage(":/icons/images/warp.png"), "WARP")
+{
+}
+
+
+extern "C" {
+BN_DECLARE_UI_ABI_VERSION
+
+BINARYNINJAPLUGIN void CorePluginDependencies()
+{
+ // We must have WARP to enable this plugin!
+ AddRequiredPluginDependency("warp_ninja");
+}
+
+BINARYNINJAPLUGIN bool UIPluginInit()
+{
+ Sidebar::addSidebarWidgetType(new WarpSidebarWidgetType());
+ return true;
+}
+}