summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2019-07-05 11:29:28 -0400
committerPeter LaFosse <peter@vector35.com>2019-07-14 14:42:52 -0400
commita096663fc17d08af0bf2581150b618a1a8f09767 (patch)
treea865bc30f99da2612ed4aa61d46e0c483fb35b19
parentc061061966ee12a7d6ace672b7798257eeb22cfd (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.h2
-rw-r--r--binaryninjacore.h2
-rw-r--r--binaryview.cpp12
-rw-r--r--python/binaryview.py10
-rw-r--r--ui/action.h1
-rw-r--r--ui/dockhandler.h4
-rw-r--r--ui/functionlist.h138
-rw-r--r--ui/symbollist.h294
-rw-r--r--ui/symbolsview.h (renamed from ui/functionsview.h)13
-rw-r--r--ui/viewframe.h2
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
{