diff options
| author | Peter LaFosse <peter@vector35.com> | 2019-07-05 11:29:28 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2019-07-14 14:42:52 -0400 |
| commit | a096663fc17d08af0bf2581150b618a1a8f09767 (patch) | |
| tree | a865bc30f99da2612ed4aa61d46e0c483fb35b19 | |
| parent | c061061966ee12a7d6ace672b7798257eeb22cfd (diff) | |
Add support for sorting the symbol list by name or address
Refactoring Function List to support Symbols and Data Variables too
Renaming FunctionList and FunctionsView to SymbolList/SymbolsView
Keep track of current selection and scroll position between model resets
| -rw-r--r-- | binaryninjaapi.h | 2 | ||||
| -rw-r--r-- | binaryninjacore.h | 2 | ||||
| -rw-r--r-- | binaryview.cpp | 12 | ||||
| -rw-r--r-- | python/binaryview.py | 10 | ||||
| -rw-r--r-- | ui/action.h | 1 | ||||
| -rw-r--r-- | ui/dockhandler.h | 4 | ||||
| -rw-r--r-- | ui/functionlist.h | 138 | ||||
| -rw-r--r-- | ui/symbollist.h | 294 | ||||
| -rw-r--r-- | ui/symbolsview.h (renamed from ui/functionsview.h) | 13 | ||||
| -rw-r--r-- | ui/viewframe.h | 2 |
10 files changed, 331 insertions, 147 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b3be594a..3fb60a84 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1572,6 +1572,8 @@ namespace BinaryNinja static NameSpace GetExternalNameSpace(); static bool ParseExpression(Ref<BinaryView> view, const std::string& expression, uint64_t &offset, uint64_t here, std::string& errorString); + bool HasSymbols() const; + bool HasDataVariables() const; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 842a2a50..9ff0e1e7 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2518,6 +2518,8 @@ extern "C" BINARYNINJACOREAPI BNFunction** BNGetAnalysisFunctionList(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeFunctionList(BNFunction** funcs, size_t count); BINARYNINJACOREAPI bool BNHasFunctions(BNBinaryView* view); + BINARYNINJACOREAPI bool BNHasSymbols(BNBinaryView* view); + BINARYNINJACOREAPI bool BNHasDataVariables(BNBinaryView* view); BINARYNINJACOREAPI BNFunction* BNGetAnalysisFunction(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI BNFunction* BNGetRecentAnalysisFunctionForAddress(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI BNFunction** BNGetAnalysisFunctionsForAddress(BNBinaryView* view, uint64_t addr, size_t* count); diff --git a/binaryview.cpp b/binaryview.cpp index 7fcf8253..85d09721 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1328,6 +1328,18 @@ bool BinaryView::HasFunctions() const } +bool BinaryView::HasSymbols() const +{ + return BNHasSymbols(m_object); +} + + +bool BinaryView::HasDataVariables() const +{ + return BNHasDataVariables(m_object); +} + + Ref<Function> BinaryView::GetAnalysisFunction(Platform* platform, uint64_t addr) { BNFunction* func = BNGetAnalysisFunction(m_object, platform->GetObject(), addr); diff --git a/python/binaryview.py b/python/binaryview.py index 4f146adc..179d0d21 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1321,6 +1321,16 @@ class BinaryView(object): return core.BNHasFunctions(self.handle) @property + def has_symbols(self): + """Boolean whether the binary has symbols (read-only)""" + return core.BNHasSymbols(self.handle) + + @property + def has_data_variables(self): + """Boolean whether the binary has functions (read-only)""" + return core.BNHasDataVariables(self.handle) + + @property def entry_function(self): """Entry function (read-only)""" func = core.BNGetAnalysisEntryPoint(self.handle) diff --git a/ui/action.h b/ui/action.h index dbeb06d1..7770a016 100644 --- a/ui/action.h +++ b/ui/action.h @@ -35,6 +35,7 @@ struct BINARYNINJAUIAPI HighlightTokenState HighlightTokenState(); }; + struct BINARYNINJAUIAPI UIActionContext { UIContext* context; diff --git a/ui/dockhandler.h b/ui/dockhandler.h index e0b62c27..ab6596c7 100644 --- a/ui/dockhandler.h +++ b/ui/dockhandler.h @@ -62,8 +62,8 @@ public: DockContextHandler(QWidget* widget, const QString& name); virtual ~DockContextHandler(); - QString getName() { return m_name; } - QWidget* getParentWindow() { return m_parentWindow; } + QString getName() const { return m_name; } + QWidget* getParentWindow() const { return m_parentWindow; } virtual void notifyFontChanged() { } virtual void notifyOffsetChanged(uint64_t /*offset*/) { } diff --git a/ui/functionlist.h b/ui/functionlist.h deleted file mode 100644 index c9119d3e..00000000 --- a/ui/functionlist.h +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -#include <QtWidgets/QListView> -#include <QtCore/QAbstractItemModel> -#include <QtCore/QTimer> -#include <QtWidgets/QLineEdit> -#include <vector> -#include <mutex> -#include "binaryninjaapi.h" -#include "viewframe.h" -#include "filter.h" -#include "uicontext.h" - -#define FUNCTION_LIST_UPDATE_INTERVAL 250 - -class FunctionsView; - -class BINARYNINJAUIAPI FunctionListModel: public QAbstractItemModel, public BinaryNinja::BinaryDataNotification -{ - Q_OBJECT - - enum FunctonListUpdateType - { - AddedToFunctionList, - RemovedFromFunctionList, - UpdatedInFunctionList - }; - - struct FunctionListUpdateEvent - { - FunctionRef func; - FunctonListUpdateType type; - }; - - struct NamedFunction - { - FunctionRef func; - std::string name; - bool named; - }; - - class FunctionListUpdate: public BinaryNinja::RefCountObject - { - std::mutex m_mutex; - bool m_valid; - FunctionListModel* m_model; - - public: - FunctionListUpdate(FunctionListModel* model); - void start(); - void abort(); - }; - - QWidget* m_funcList; - ViewFrame* m_view; - BinaryViewRef m_data; - std::vector<FunctionRef> m_funcs; - std::vector<NamedFunction> m_allFuncs; - FunctionRef m_currentFunc; - std::string m_filter; - - std::mutex m_updateMutex; - std::vector<FunctionListUpdateEvent> m_updates; - bool m_fullUpdate; - - BinaryNinja::Ref<FunctionListUpdate> m_backgroundUpdate; - volatile bool m_backgroundUpdateComplete; - std::vector<FunctionRef> m_backgroundUpdateFuncs; - - - static bool functionComparison(const FunctionRef& a, const FunctionRef& b); - static bool allFunctionComparison(const NamedFunction& a, const NamedFunction& b); - -public: - FunctionListModel(QWidget* parent, ViewFrame* view, BinaryViewRef data); - virtual ~FunctionListModel(); - - virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override; - virtual QModelIndex parent(const QModelIndex& i) const override; - virtual bool hasChildren(const QModelIndex& parent) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex& parent) const override; - virtual QVariant data(const QModelIndex& i, int role) const override; - - virtual void OnAnalysisFunctionAdded(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; - virtual void OnAnalysisFunctionRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; - virtual void OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; - - void updateFonts(); - bool setCurrentFunction(FunctionRef func); - QModelIndex findFunction(FunctionRef func); - QModelIndex findCurrentFunction(); - FunctionRef getFunctionForIndex(int i); - - void updateFunctions(); - void backgroundUpdate(); - bool hasFunctions() const; - - void setFilter(const std::string& filter); -}; - -class BINARYNINJAUIAPI FunctionList: public QListView, public FilterTarget -{ - Q_OBJECT - - ViewFrame* m_view; - BinaryViewRef m_data; - FunctionsView* m_functionsView; - FunctionListModel* m_list; - QTimer* m_updateTimer; - bool m_disableScrollToFunction; - -public: - FunctionList(FunctionsView* parent, ViewFrame* frame, BinaryViewRef data); - - void updateFonts(); - void setCurrentFunction(FunctionRef func); - - virtual void scrollToFirstItem() override; - virtual void scrollToCurrentItem() override; - virtual void selectFirstItem() override; - virtual void activateFirstItem() override; - virtual void setFilter(const std::string& filter) override; - - bool hasFunctions(); - - virtual void copy(); - virtual void paste(); - virtual bool canCopy(); - -protected: - virtual void focusOutEvent(QFocusEvent* event) override; - virtual void keyPressEvent(QKeyEvent* event) override; - -private Q_SLOTS: - void goToFunction(const QModelIndex& i); - void updateTimerEvent(); -}; diff --git a/ui/symbollist.h b/ui/symbollist.h new file mode 100644 index 00000000..e1edb6b5 --- /dev/null +++ b/ui/symbollist.h @@ -0,0 +1,294 @@ +#pragma once + +#include <QtWidgets/QListView> +#include <QtCore/QAbstractItemModel> +#include <QtCore/QTimer> +#include <QtWidgets/QLineEdit> +#include <vector> +#include <set> +#include <mutex> +#include "binaryninjaapi.h" +#include "viewframe.h" +#include "filter.h" +#include "uicontext.h" +#include "menus.h" + +#define FUNCTION_LIST_UPDATE_INTERVAL 250 + +class SymbolsView; +static std::string emptyArch; + +class BINARYNINJAUIAPI SymbolListModel: public QAbstractItemModel, public BinaryNinja::BinaryDataNotification +{ + Q_OBJECT +public: + enum SortType + { + SortAcendingAddresses, + SortDecendingAddresses, + SortAlphabeticallyAcending, + SortAlphabeticallyDecending + }; + + struct NamedObject + { + SymbolRef sym; + std::string archName; + NamedObject() : sym(nullptr), archName(emptyArch) {} + NamedObject(SymbolRef s, std::string& a=emptyArch) : sym(s), archName(a) {} + NamedObject(const NamedObject& n) + { + sym = n.sym; + archName = n.archName; + } + + // NamedObject(const NamedObject&& n) + // { + // sym = std::move(n.sym); + // archName = std::move(n.archName); + // } + + // NamedObject& operation=(const NamedObject&& n) + // { + // sym = std::move(n.sym); + // archName = std::move(n.archName); + // } + + bool operator<(const NamedObject& other) const + { + if (getStart() < other.getStart()) + return true; + if (getStart() == other.getStart() && + (sym->GetType() == FunctionSymbol && other.sym->GetType() == FunctionSymbol)) + { + return archName < other.archName; + } + return false; + } + + bool operator>(const NamedObject& other) const + { + if (getStart() > other.getStart()) + return true; + if (getStart() == other.getStart() && + (sym->GetType() == FunctionSymbol && other.sym->GetType() == FunctionSymbol)) + { + return archName > other.archName; + } + return false; + } + + bool isFunc() const { return sym->GetType() == FunctionSymbol; } + uint64_t getStart() const { return sym->GetAddress(); } + std::string getName() const { return sym->GetFullName(); } + BNSymbolType getType() const { return sym->GetType(); } + }; + +private: + enum SymbolListUpdateType + { + AddedToSymbolList, + RemovedFromSymbolList, + UpdatedInSymbolList + }; + + struct SymbolListUpdateEvent + { + NamedObject rec; + SymbolListUpdateType type; + SymbolListUpdateEvent(const NamedObject& r, SymbolListUpdateType t) : rec(r), type(t) {} + SymbolListUpdateEvent(const SymbolListUpdateEvent& s) + { + rec = s.rec; + type = s.type; + } + }; + + class SymbolListUpdate: public BinaryNinja::RefCountObject + { + std::mutex m_mutex; + bool m_valid; + SymbolListModel* m_model; + + public: + SymbolListUpdate(SymbolListModel* model); + void start(); + void abort(); + }; + + QWidget* m_funcList; + ViewFrame* m_view; + BinaryViewRef m_data; + std::set<std::string> m_archNames; + std::vector<NamedObject> m_allSyms; + std::vector<NamedObject> m_curSyms; + NamedObject m_currentSym; + std::string m_filter; + + std::mutex m_updateMutex; + std::vector<SymbolListUpdateEvent> m_updates; + bool m_fullUpdate; + + BinaryNinja::Ref<SymbolListUpdate> m_backgroundUpdate; + volatile bool m_backgroundUpdateComplete; + std::vector<NamedObject> m_backgroundUpdateFuncs; + + bool m_showImports; + bool m_showExports; + bool m_showFunctions; + bool m_showDataVars; + SortType m_sortType; + + // static bool allSymbolComparison(const NamedObject& a, const NamedObject& b); + static bool allSymbolComparisonLT(const NamedObject& a, const NamedObject& b); + static bool allSymbolComparisonGE(const NamedObject& a, const NamedObject& b); + static bool allSymbolComparisonNameLT(const NamedObject& a, const NamedObject& b); + static bool allSymbolComparisonNameGE(const NamedObject& a, const NamedObject& b); + typedef bool (*comparitor)(const NamedObject& a, const NamedObject& b); + static comparitor getComparitor(SortType type) + { + switch (type) + { + case SortAcendingAddresses: return allSymbolComparisonLT; + case SortDecendingAddresses: return allSymbolComparisonGE; + case SortAlphabeticallyAcending: return allSymbolComparisonNameLT; + case SortAlphabeticallyDecending: + default: + return allSymbolComparisonNameGE; + } + } + void getValidObject(std::vector<NamedObject>& result); + +public: + SymbolListModel(QWidget* parent, ViewFrame* view, BinaryViewRef data); + virtual ~SymbolListModel(); + + virtual QModelIndex index(int row, int col, const QModelIndex& parent) const override; + virtual QModelIndex parent(const QModelIndex& i) const override; + virtual bool hasChildren(const QModelIndex& parent) const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex& parent) const override; + virtual QVariant data(const QModelIndex& i, int role) const override; + + virtual void OnAnalysisFunctionAdded(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; + virtual void OnAnalysisFunctionRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; + virtual void OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override; + virtual void OnDataVariableAdded(BinaryNinja::BinaryView* data, const BinaryNinja::DataVariable& var) override; + virtual void OnDataVariableRemoved(BinaryNinja::BinaryView* data, const BinaryNinja::DataVariable& var) override; + virtual void OnDataVariableUpdated(BinaryNinja::BinaryView* data, const BinaryNinja::DataVariable& var) override; + + void updateFonts(); + bool isValidType(const NamedObject& rec); + bool setCurrentObject(const NamedObject& rec); + bool setCurrentFunction(FunctionRef func); + QModelIndex findSymbol(const NamedObject& rec); + QModelIndex findCurrentSymbol(); + NamedObject getNamedObjectForIndex(int i); + + void updateFunctions(); + void backgroundUpdate(); + bool hasSymbols() const; + + void setFilter(const std::string& filter); + void showExports(bool show) { m_showExports = show; } + void showImports(bool show) { m_showImports = show; } + void showFunctions(bool show) { m_showFunctions = show; } + void showDataVars(bool show) { m_showDataVars = show; } + + void toggleExports() { + m_showExports = !m_showExports; + if (m_showExports) + { + m_showImports = false; + m_showFunctions = true; + m_showDataVars = true; + } + } + void toggleImports() { + m_showImports = !m_showImports; + if (m_showImports && m_showExports) + m_showExports = false; + } + void toggleFunctions() { + m_showFunctions = !m_showFunctions; + if (m_showFunctions && m_showExports) + m_showExports = false; + } + void toggleDataVars() { + m_showDataVars = !m_showDataVars; + if (m_showDataVars && m_showExports) + m_showExports = false; + } + + bool getShowExports() const { return m_showExports; } + bool getShowImports() const { return m_showImports; } + bool getShowFunctions() const { return m_showFunctions; } + bool getShowDataVars() const { return m_showDataVars; } + + void sortSymbols(SortType type); + void setSortType(SortType type) { m_sortType = type; } + SortType getSortType() const { return m_sortType; } + NamedObject getCurrentSym() const { return m_currentSym; } + +Q_SIGNALS: + void afterListReset(); + void beforeListReset(); +}; + + +class BINARYNINJAUIAPI SymbolList: public QListView, public FilterTarget +{ + Q_OBJECT + + ViewFrame* m_view; + BinaryViewRef m_data; + SymbolsView* m_functionsView; + SymbolListModel* m_list; + QTimer* m_updateTimer; + bool m_disableScrollToFunction; + UIActionHandler m_actionHandler; + Menu m_menu; + ContextMenuManager m_contextMenuManager; + + bool m_showExports; + bool m_showImports; + bool m_showFunctions; + bool m_showDataVars; + std::string m_filter; + SymbolListModel::SortType m_sortType; + SymbolListModel::NamedObject m_index; + int m_scrollPosition; + bool m_doubleClick; + +public: + SymbolList(SymbolsView* parent, ViewFrame* frame, BinaryViewRef data); + + void updateFonts(); + void setCurrentFunction(FunctionRef func); + + virtual void scrollToFirstItem() override; + virtual void scrollToCurrentItem() override; + virtual void selectFirstItem() override; + virtual void activateFirstItem() override; + virtual void setFilter(const std::string& filter) override; + + bool hasSymbols(); + + virtual void copy(); + virtual void paste(); + virtual bool canCopy(); + void find(); + +protected: + virtual void focusOutEvent(QFocusEvent* event) override; + virtual void keyPressEvent(QKeyEvent* event) override; + virtual void contextMenuEvent(QContextMenuEvent* /*event*/) override; + +private Q_SLOTS: + void goToSymbol(const QModelIndex& i); + void updateTimerEvent(); + void savePosition(); + void restorePosition(); + void saveIndex(const QModelIndex& index); + void clearIndex(const QModelIndex& index); +}; diff --git a/ui/functionsview.h b/ui/symbolsview.h index 65b40c45..694f3ea4 100644 --- a/ui/functionsview.h +++ b/ui/symbolsview.h @@ -4,28 +4,29 @@ #include "binaryninjaapi.h" #include "dockhandler.h" #include "filter.h" +#include "symbollist.h" class ViewFrame; -class FunctionList; +class SymbolList; -class BINARYNINJAUIAPI FunctionsView: public QWidget, public DockContextHandler, public BinaryNinja::BinaryDataNotification +class BINARYNINJAUIAPI SymbolsView: public QWidget, public DockContextHandler, public BinaryNinja::BinaryDataNotification { Q_OBJECT Q_INTERFACES(DockContextHandler) BinaryViewRef m_data; - FunctionList* m_funcList; + SymbolList* m_funcList; FilteredView* m_funcFilter; bool m_updatesPending; QTimer* m_updateTimer; public: - FunctionsView(ViewFrame* frame, BinaryViewRef data); - virtual ~FunctionsView(); + SymbolsView(ViewFrame* frame, BinaryViewRef data); + virtual ~SymbolsView(); - FunctionList* getFunctionList() { return m_funcList; } + SymbolList* getSymbolList() { return m_funcList; } FilteredView* getFunctionFilter() { return m_funcFilter; } virtual void OnBinaryDataWritten(BinaryNinja::BinaryView* data, uint64_t offset, size_t len) override; diff --git a/ui/viewframe.h b/ui/viewframe.h index d08fa38e..0a73ad89 100644 --- a/ui/viewframe.h +++ b/ui/viewframe.h @@ -156,7 +156,7 @@ public: virtual View* getView() = 0; }; -class FunctionsView; +class SymbolsView; class BINARYNINJAUIAPI ViewFrame : public QWidget { |
