diff options
| author | Xusheng <xusheng@vector35.com> | 2021-02-05 20:28:13 +0800 |
|---|---|---|
| committer | Xusheng <xusheng@vector35.com> | 2021-04-22 10:52:39 +0800 |
| commit | c4b1dd712783e7474570705e6d95183a0c02a76e (patch) | |
| tree | 0393986e0078cb20610c8ad091db061f8f41a08b /ui | |
| parent | a355d5c9aa1978d10f378931bfd5f06be60bae98 (diff) | |
add persistent search result
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/addressdialog.h | 26 | ||||
| -rw-r--r-- | ui/expandablegroup.h | 27 | ||||
| -rw-r--r-- | ui/getsymbolslistthread.h | 37 | ||||
| -rw-r--r-- | ui/searchresult.h | 267 | ||||
| -rw-r--r-- | ui/typeview.h | 2 | ||||
| -rw-r--r-- | ui/viewframe.h | 50 | ||||
| -rw-r--r-- | ui/xreflist.h | 25 |
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 |
