summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorXusheng <xusheng@vector35.com>2021-02-05 20:28:13 +0800
committerXusheng <xusheng@vector35.com>2021-04-22 10:52:39 +0800
commitc4b1dd712783e7474570705e6d95183a0c02a76e (patch)
tree0393986e0078cb20610c8ad091db061f8f41a08b /ui
parenta355d5c9aa1978d10f378931bfd5f06be60bae98 (diff)
add persistent search result
Diffstat (limited to 'ui')
-rw-r--r--ui/addressdialog.h26
-rw-r--r--ui/expandablegroup.h27
-rw-r--r--ui/getsymbolslistthread.h37
-rw-r--r--ui/searchresult.h267
-rw-r--r--ui/typeview.h2
-rw-r--r--ui/viewframe.h50
-rw-r--r--ui/xreflist.h25
7 files changed, 372 insertions, 62 deletions
diff --git a/ui/addressdialog.h b/ui/addressdialog.h
index eee9d836..1f67664d 100644
--- a/ui/addressdialog.h
+++ b/ui/addressdialog.h
@@ -11,31 +11,7 @@
#endif
#include "binaryninjaapi.h"
#include "uitypes.h"
-
-#ifdef BINARYNINJAUI_BINDINGS
-// QThread has issues working in the bindings on some platforms
-class GetSymbolsListThread;
-#else
-class BINARYNINJAUIAPI GetSymbolsListThread: public QThread
-{
- Q_OBJECT
-
- QStringList m_allSymbols;
- std::function<void()> m_completeFunc;
- std::mutex m_mutex;
- bool m_done;
- BinaryViewRef m_view;
-
-protected:
- virtual void run() override;
-
-public:
- GetSymbolsListThread(BinaryViewRef view, const std::function<void()>& completeFunc);
- void cancel();
-
- const QStringList& getSymbols() const { return m_allSymbols; }
-};
-#endif
+#include "getsymbolslistthread.h"
class BINARYNINJAUIAPI AddressDialogWithPreview: public QDialog
diff --git a/ui/expandablegroup.h b/ui/expandablegroup.h
new file mode 100644
index 00000000..164651f6
--- /dev/null
+++ b/ui/expandablegroup.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "uitypes.h"
+#include <QtWidgets/QToolButton>
+#include <QtCore/QParallelAnimationGroup>
+#include <QtWidgets/QScrollArea>
+#include <QtCore/QPropertyAnimation>
+
+class BINARYNINJAUIAPI ExpandableGroup : public QWidget
+{
+ Q_OBJECT
+
+private:
+ QToolButton* m_button;
+ QParallelAnimationGroup* m_animation;
+ QScrollArea* m_content;
+ int m_duration = 100;
+
+private Q_SLOTS:
+ void toggled(bool expanded);
+
+public:
+ explicit ExpandableGroup(const QString& title = "", QWidget* parent = nullptr);
+ void setContentLayout(QLayout* contentLayout);
+ void setTitle(const QString& title) { m_button->setText(title); }
+ void toggle(bool expanded);
+};
diff --git a/ui/getsymbolslistthread.h b/ui/getsymbolslistthread.h
new file mode 100644
index 00000000..b806448a
--- /dev/null
+++ b/ui/getsymbolslistthread.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#ifndef BINARYNINJAUI_BINDINGS
+#include <QtCore/QThread>
+#include <QtCore/QEvent>
+#endif
+#include "binaryninjaapi.h"
+#include "uitypes.h"
+
+
+#ifdef BINARYNINJAUI_BINDINGS
+// QThread has issues working in the bindings on some platforms
+class GetSymbolsListThread;
+#else
+class BINARYNINJAUIAPI GetSymbolsListThread: public QThread
+{
+ Q_OBJECT
+
+ QStringList m_allSymbols;
+ std::function<void()> m_completeFunc;
+ std::mutex m_mutex;
+ bool m_done;
+ BinaryViewRef m_view;
+
+protected:
+ virtual void run() override;
+
+public:
+ GetSymbolsListThread(BinaryViewRef view, const std::function<void()>& completeFunc);
+ void cancel();
+
+ static int m_eventType;
+ int GetEventType() { return GetSymbolsListThread::m_eventType; }
+
+ const QStringList& getSymbols() const { return m_allSymbols; }
+};
+#endif
diff --git a/ui/searchresult.h b/ui/searchresult.h
new file mode 100644
index 00000000..5905ae0d
--- /dev/null
+++ b/ui/searchresult.h
@@ -0,0 +1,267 @@
+#pragma once
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QItemSelectionModel>
+#include <QtCore/QSortFilterProxyModel>
+#include <QtCore/QModelIndex>
+#include <QtCore/QThread>
+#include <QtWidgets/QTableView>
+#include <QtWidgets/QTabWidget>
+#include <QtWidgets/QStyledItemDelegate>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QProgressBar>
+#include <QtWidgets/QToolButton>
+#include "binaryninjaapi.h"
+#include "dockhandler.h"
+#include "viewframe.h"
+#include "filter.h"
+#include "expandablegroup.h"
+
+#define FIND_RESULT_LIST_UPDATE_INTERVAL 250
+#define COLUMN_MIN_WIDTH_IN_CHAR 10
+#define COLUMN_MAX_WIDTH_IN_CHAR 30
+
+class CachedTokens
+{
+public:
+ QVariant tokens;
+ QVariant flattenedTokens;
+ bool valid;
+
+ CachedTokens(): valid(false) {}
+ CachedTokens(const CachedTokens& other):
+ tokens(other.tokens), flattenedTokens(other.flattenedTokens), valid(other.valid)
+ {}
+};
+
+
+class SearchResultItem
+{
+private:
+ uint64_t m_addr;
+ BinaryNinja::DataBuffer m_buffer;
+ FunctionRef m_func;
+ CachedTokens m_tokensCache[4];
+
+public:
+ SearchResultItem();
+ SearchResultItem(uint64_t addr, const BinaryNinja::DataBuffer& buffer,
+ FunctionRef func);
+ SearchResultItem(uint64_t addr, const BinaryNinja::DataBuffer& buffer,
+ FunctionRef func, const BinaryNinja::DisassemblyTextLine& line, QWidget* owner);
+ SearchResultItem(const SearchResultItem& other);
+ uint64_t addr() const { return m_addr; }
+ BinaryNinja::DataBuffer buffer() const { return m_buffer; }
+ FunctionRef func() const { return m_func; }
+ bool operator==(const SearchResultItem& other) const { return m_addr == other.addr(); }
+ bool operator!=(const SearchResultItem& other) const { return m_addr != other.addr(); }
+ bool operator<(const SearchResultItem& other) const { return m_addr < other.addr(); }
+
+ CachedTokens getCachedTokens(size_t i) const;
+ CachedTokens& getCachedTokens(size_t i);
+ void setCachedTokens(size_t i, QVariant tokens, QVariant flattenedTokens);
+};
+
+Q_DECLARE_METATYPE(SearchResultItem);
+
+
+class BINARYNINJAUIAPI SearchResultModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+protected:
+ QWidget* m_owner;
+ BinaryViewRef m_data;
+ ViewFrame* m_view;
+ BinaryNinja::FindParameters m_params;
+ std::vector<SearchResultItem> m_refs;
+ mutable size_t m_columnWidths[4];
+ // if this value is true, it means the user has overriden the automatically calculated width
+ // of the coumn, and we should not resize it anymore
+ bool m_userColumnWidth[4];
+
+ std::mutex m_updateMutex;
+ std::set<SearchResultItem> m_pendingSearchResults;
+
+public:
+ enum ColumnHeaders
+ {
+ AddressColumn = 0,
+ DataColumn = 1,
+ FunctionColumn = 2,
+ PreviewColumn = 3,
+ EndOfColumn = 4
+ };
+
+ SearchResultModel(QWidget* parent, BinaryViewRef data, ViewFrame* view);
+ virtual ~SearchResultModel();
+
+ virtual QModelIndex index(int row, int col, const QModelIndex& parent = QModelIndex()) const override;
+
+ void reset();
+ virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override { (void) parent; return (int)m_refs.size(); }
+ virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override { (void) parent; return 4; }
+ SearchResultItem getRow(int row) const;
+ virtual QVariant data(const QModelIndex& i, int role) const override;
+ virtual QVariant headerData(int column, Qt::Orientation orientation, int role) const override;
+ void addItem(const SearchResultItem& addr);
+ void clear();
+ void updateFindParameters(const BinaryNinja::FindParameters params);
+ void updateSearchResults();
+
+ size_t getColumnWidth(size_t column) const;
+ // This function is marked as const, but it actually modifies the mutable member m_columnWidths.
+ // It is called in SearchResultModel::data(), which is const. So it has to be const as well.
+ void updateColumnWidth(size_t column, size_t size) const;
+ void resetColumnWidth();
+
+ bool isUserColumnWidth(size_t column) const;
+ void setUserColumnWidth(size_t column);
+};
+
+
+class BINARYNINJAUIAPI SearchResultFilterProxyModel: public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ SearchResultFilterProxyModel(QObject* parent);
+ virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
+ virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
+ virtual QVariant data(const QModelIndex& idx, int role) const override;
+};
+
+
+class BINARYNINJAUIAPI SearchResultItemDelegate: public QStyledItemDelegate
+{
+ Q_OBJECT
+
+ QFont m_font;
+ int m_baseline, m_charWidth, m_charHeight, m_charOffset;
+
+public:
+ SearchResultItemDelegate(QWidget* parent);
+ void updateFonts();
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& idx) const;
+};
+
+class SearchResultWidget;
+class BINARYNINJAUIAPI SearchResultTable: public QTableView
+{
+ Q_OBJECT
+
+ ViewFrame* m_view;
+ SearchResultModel* m_table;
+ SearchResultFilterProxyModel* m_model;
+ SearchResultItemDelegate* m_itemDelegate;
+ BinaryViewRef m_data;
+ BinaryNinja::FindParameters m_params;
+ UIActionHandler m_actionHandler;
+ QTimer* m_updateTimer;
+
+ int m_charWidth, m_charHeight;
+
+ bool m_cacheThreadShouldExit;
+
+public:
+ SearchResultTable(SearchResultWidget* parent, ViewFrame* view, BinaryViewRef data);
+ virtual ~SearchResultTable();
+
+ void addSearchResult(const SearchResultItem& addr);
+ void updateFindParameters(const BinaryNinja::FindParameters& params);
+ void clearSearchResult();
+
+ void updateFonts();
+ void updateHeaderFontAndSize();
+
+ virtual void keyPressEvent(QKeyEvent* e) override;
+
+ virtual bool hasSelection() const { return selectionModel()->selectedRows().size() != 0; }
+ virtual QModelIndexList selectedRows() const { return selectionModel()->selectedRows(); }
+
+ void goToResult(const QModelIndex& idx);
+
+ int rowCount() const;
+ int filteredCount() const;
+
+ void updateColumnWidth();
+ void resetColumnWidth();
+
+ void cacheTokens();
+ void terminateCacheThread() { m_cacheThreadShouldExit = true; }
+
+ SearchResultModel* model() const { return m_table; }
+
+public Q_SLOTS:
+ void resultActivated(const QModelIndex& idx);
+ void updateFilter(const QString& filterText);
+ void updateTimerEvent();
+ void columnResized(int logicalIndex, int oldSize, int newSize);
+
+Q_SIGNALS:
+ void newSelection();
+};
+
+class SearchProgressBar;
+class BINARYNINJAUIAPI SearchResultWidget: public QWidget, public DockContextHandler
+{
+ Q_OBJECT
+ Q_INTERFACES(DockContextHandler)
+
+ ViewFrame* m_view;
+ BinaryViewRef m_data;
+ SearchResultTable* m_table;
+ QLabel* m_label;
+ QLineEdit* m_lineEdit;
+ ExpandableGroup* m_group;
+ SearchProgressBar* m_progress;
+ BinaryNinja::FindParameters m_params;
+ QThread* m_tokenCacheThread = nullptr;
+
+ virtual void contextMenuEvent(QContextMenuEvent* event) override;
+
+public:
+ SearchResultWidget(ViewFrame* frame, BinaryViewRef data);
+ ~SearchResultWidget();
+
+ virtual void notifyFontChanged() override;
+
+ void startNewFind(const BinaryNinja::FindParameters& params);
+ virtual QString getHeaderText();
+
+ void addSearchResult(uint64_t addr, const BinaryNinja::DataBuffer& match);
+ void addSearchResult(uint64_t addr, const BinaryNinja::DataBuffer& match,
+ const BinaryNinja::LinearDisassemblyLine& line);
+ void clearSearchResult();
+ bool updateProgress(uint64_t cur, uint64_t total);
+ void notifySearchCompleted();
+ void cacheTokens();
+ void terminateCacheThread();
+ bool isSearchActive() const;
+
+public Q_SLOTS:
+ void updateTotal();
+};
+
+
+class BINARYNINJAUIAPI SearchProgressBar: public QWidget
+{
+ Q_OBJECT
+
+private:
+ QProgressBar* m_progress;
+ QToolButton* m_cancel;
+ bool m_maxSet;
+ bool m_running;
+ // The minimal duration (in milliseconds) the progress bar must last, before it is displayed
+ int m_minimalDuration;
+ std::chrono::steady_clock::time_point m_lastUpdate;
+
+public:
+ explicit SearchProgressBar(QWidget* parent = nullptr);
+ bool updateProgress(uint64_t cur, uint64_t total);
+ void init();
+ void reset();
+ void show();
+ bool isRunning() const { return m_running; }
+};
diff --git a/ui/typeview.h b/ui/typeview.h
index b24e3df9..b9dab368 100644
--- a/ui/typeview.h
+++ b/ui/typeview.h
@@ -159,7 +159,7 @@ public:
virtual bool findNextData(uint64_t start, uint64_t end, const BinaryNinja::DataBuffer& data, uint64_t& addr, BNFindFlag flags,
const std::function<bool (size_t current, size_t total)>& cb) override;
virtual bool findNextText(uint64_t start, uint64_t end, const std::string& text, uint64_t& addr,
- DisassemblySettingsRef settings, BNFindFlag flags,
+ DisassemblySettingsRef settings, BNFindFlag flags, BNFunctionGraphType graph,
const std::function<bool (size_t current, size_t total)>& cb) override;
virtual BinaryViewRef getData() override { return m_data; }
virtual uint64_t getCurrentOffset() override;
diff --git a/ui/viewframe.h b/ui/viewframe.h
index 36072430..4d1ebf32 100644
--- a/ui/viewframe.h
+++ b/ui/viewframe.h
@@ -14,6 +14,7 @@
#include <stack>
#include <utility>
#include <vector>
+#include "binaryninjaapi.h"
#include "filecontext.h"
#include "viewtype.h"
#include "action.h"
@@ -78,6 +79,7 @@ class FeatureMap;
class StatusBarWidget;
class ViewNavigationMode;
class TransformParameterDialog;
+// struct BinaryNinjaCore::LinearDisassemblyLine;
class BINARYNINJAUIAPI View
@@ -109,14 +111,31 @@ public:
virtual bool canAssemble() { return false; }
virtual bool canCompile() { return false; }
- virtual bool findNextData(uint64_t start, uint64_t end, const BinaryNinja::DataBuffer& data, uint64_t& addr, BNFindFlag flags,
+ virtual bool findNextData(uint64_t start, uint64_t end, const BinaryNinja::DataBuffer& data,
+ uint64_t& addr, BNFindFlag flags,
const std::function<bool (size_t current, size_t total)>& cb);
- virtual bool findNextText(uint64_t start, uint64_t end, const std::string& text, uint64_t& addr,
- DisassemblySettingsRef settings, BNFindFlag flags,
+ virtual bool findNextText(uint64_t start, uint64_t end, const std::string& text,
+ uint64_t& addr, DisassemblySettingsRef settings, BNFindFlag flags,
+ BNFunctionGraphType graph,
const std::function<bool (size_t current, size_t total)>& cb);
- virtual bool findNextConstant(uint64_t start, uint64_t end, uint64_t constant, uint64_t& addr, DisassemblySettingsRef settings,
+ virtual bool findNextConstant(uint64_t start, uint64_t end, uint64_t constant,
+ uint64_t& addr, DisassemblySettingsRef settings, BNFunctionGraphType graph,
const std::function<bool (size_t current, size_t total)>& cb);
+ virtual bool findAllData(uint64_t start, uint64_t end, const BinaryNinja::DataBuffer& data, BNFindFlag flags,
+ const std::function<bool (size_t current, size_t total)>& cb,
+ const std::function<bool (uint64_t addr, const BinaryNinja::DataBuffer& match)>& matchCallback);
+ virtual bool findAllText(uint64_t start, uint64_t end, const std::string& data,
+ DisassemblySettingsRef settings, BNFindFlag flags, BNFunctionGraphType graph,
+ const std::function<bool (size_t current, size_t total)>& cb,
+ const std::function<bool (uint64_t addr, const std::string& match,
+ const BinaryNinja::LinearDisassemblyLine& line)>& matchCallback);
+ virtual bool findAllConstant(uint64_t start, uint64_t end, uint64_t constant,
+ DisassemblySettingsRef settings, BNFunctionGraphType graph,
+ const std::function<bool (size_t current, size_t total)>& cb,
+ const std::function<bool (uint64_t addr,
+ const BinaryNinja::LinearDisassemblyLine& line)>& matchCallback);
+
virtual BinaryViewRef getData() = 0;
virtual uint64_t getCurrentOffset() = 0;
virtual BNAddressRange getSelectionOffsets();
@@ -307,12 +326,12 @@ public:
QString getShortFileName();
std::vector<QString> getAvailableTypes() const;
- QString getCurrentView();
- QString getCurrentDataType();
- uint64_t getCurrentOffset();
- BNAddressRange getSelectionOffsets();
+ QString getCurrentView() const;
+ QString getCurrentDataType() const;
+ uint64_t getCurrentOffset() const;
+ BNAddressRange getSelectionOffsets() const;
- ViewLocation getViewLocation();
+ ViewLocation getViewLocation() const;
void setViewLocation(const ViewLocation& viewLocation);
View* getCurrentViewInterface() const { return View::getViewFromWidget(m_view); }
@@ -335,9 +354,9 @@ public:
bool goToReference(BinaryViewRef data, FunctionRef func, uint64_t source, uint64_t target, bool addHistoryEntry = true);
bool navigateToViewLocation(BinaryViewRef data, const ViewLocation& viewLocation,
bool addHistoryEntry = true);
- QString getTypeForView(QWidget* view);
- QString getDataTypeForView(const QString& type);
- QString getDataTypeForView(QWidget* view);
+ QString getTypeForView(QWidget* view) const;
+ QString getDataTypeForView(const QString& type) const;
+ QString getDataTypeForView(QWidget* view) const;
bool closeRequest();
void closing();
@@ -367,6 +386,13 @@ public:
void nextTag();
void prevTag();
+ void startNewFind(const BinaryNinja::FindParameters& params);
+ bool updateSearchProgress(uint64_t cur, uint64_t total);
+ void notifySearchCompleted();
+ void addSearchResult(uint64_t addr, const BinaryNinja::DataBuffer& match);
+ void addSearchResult(uint64_t addr, const BinaryNinja::DataBuffer& match,
+ const BinaryNinja::LinearDisassemblyLine& line);
+
virtual UIActionContext actionContext();
void bindActions();
static void registerActions();
diff --git a/ui/xreflist.h b/ui/xreflist.h
index 625d384e..d603c599 100644
--- a/ui/xreflist.h
+++ b/ui/xreflist.h
@@ -5,7 +5,6 @@
#include <QtCore/QSortFilterProxyModel>
#include <QtCore/QModelIndex>
#include <QtGui/QImage>
-#include <QtCore/QParallelAnimationGroup>
#include <QtWidgets/QListView>
#include <QtWidgets/QStyledItemDelegate>
#include <QtWidgets/QTreeView>
@@ -15,8 +14,6 @@
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QFrame>
#include <QtWidgets/QGridLayout>
-#include <QtWidgets/QScrollArea>
-#include <QtWidgets/QToolButton>
#include <vector>
#include <deque>
@@ -26,6 +23,7 @@
#include "dockhandler.h"
#include "viewframe.h"
#include "fontsettings.h"
+#include "expandablegroup.h"
class XrefHeader;
class XrefItem
@@ -524,27 +522,6 @@ public Q_SLOTS:
};
-class BINARYNINJAUIAPI ExpandableGroup : public QWidget
-{
- Q_OBJECT
-
-private:
- QToolButton* m_button;
- QParallelAnimationGroup* m_animation;
- QScrollArea* m_content;
- int m_duration = 100;
-
-private Q_SLOTS:
- void toggled(bool expanded);
-
-public:
- explicit ExpandableGroup(const QString& title = "", QWidget* parent = nullptr);
- void setContentLayout(QLayout* contentLayout);
- void setTitle(const QString& title) { m_button->setText(title); }
- void toggle(bool expanded);
-};
-
-
// https://github.com/CuriousCrow/QCheckboxCombo
/*
* QCheckboxCombo is a combobox widget that contains items with checkboxes