#pragma once #include #include #include #include #include #include #include #include #include #include "binaryninjaapi.h" #include "viewframe.h" #include "filter.h" #include "uicontext.h" #include "menus.h" #define FUNCTION_LIST_UPDATE_INTERVAL 500 class SymbolsView; static std::string emptyArch; /*! \defgroup symbollist SymbolList \ingroup uiapi */ /*! \ingroup symbollist */ class BINARYNINJAUIAPI SymbolListDelegate : public QStyledItemDelegate { Q_OBJECT QFont m_font; int m_height, m_charWidth; public: SymbolListDelegate(QWidget* parent); void updateFonts(); virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; }; /*! \ingroup symbollist */ class BINARYNINJAUIAPI SymbolListModel : public QAbstractItemModel, public BinaryNinja::BinaryDataNotification { Q_OBJECT public: enum SortType { SortAscendingAddresses, SortDescendingAddresses, SortAlphabeticallyAscending, SortAlphabeticallyDescending }; struct NamedObject { std::string name; std::string rawName; uint64_t address; BNSymbolType type; BNSymbolBinding binding; NamedObject() { address = 0; type = FunctionSymbol; binding = NoBinding; } NamedObject(SymbolRef s) { address = s->GetAddress(); name = s->GetFullName(); rawName = s->GetRawName(); type = s->GetType(); binding = s->GetBinding(); } NamedObject(const NamedObject& n) { address = n.address; name = n.name; rawName = n.rawName; type = n.type; binding = n.binding; } NamedObject& operator=(const NamedObject& n) { address = n.address; name = n.name; rawName = n.rawName; type = n.type; binding = n.binding; return *this; } NamedObject(NamedObject&& n) { name = std::move(n.name); rawName = std::move(n.rawName); address = n.address; type = n.type; binding = n.binding; } NamedObject& operator=(NamedObject&& n) { address = n.address; name = std::move(n.name); rawName = std::move(n.rawName); type = n.type; binding = n.binding; return *this; } bool operator==(const NamedObject& other) const { return (getStart() == other.getStart()) && (getType() == other.getType()); } bool operator!=(const NamedObject& other) const { return !((*this) == other); } bool operator<(const NamedObject& other) const { if (getStart() < other.getStart()) return true; if ((*this) == other) return getType() < other.getType(); return false; } bool operator>(const NamedObject& other) const { if (getStart() > other.getStart()) return true; if ((*this) == other) return getType() > other.getType(); return false; } bool isFunc() const { return (getType() == FunctionSymbol) || (getType() == ImportedFunctionSymbol) || (getType() == LibraryFunctionSymbol); } uint64_t getStart() const { return address; } std::string getName() const { return name; } std::string getRawName() const { return rawName; } BNSymbolType getType() const { return type; } BNSymbolBinding getBinding() const { return binding; } bool lessThanAlpha(const NamedObject& other) const { if (name < other.name) return true; else if (name == other.name) { if (rawName < other.rawName) return true; if (rawName == other.rawName) return getStart() < other.getStart(); } return false; } bool lessThanAlphaRaw(const NamedObject& other) const { if (rawName < other.rawName) return true; else if (rawName == other.rawName) { if (name < other.name) return true; if (name == other.name) return getStart() < other.getStart(); } return false; } }; private: enum SymbolListUpdateType { UnnamedFunctionAddedToSymbolList, UnnamedDataAddedToSymbolList, SymbolAddedToSymbolList, SymbolUpdatedInSymbolList, SymbolRemovedFromSymbolList }; 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(); void startDestroy(); }; QWidget* m_funcList; ViewFrame* m_view; BinaryViewRef m_data; std::set m_archNames; std::unique_ptr> m_allSyms; std::unique_ptr> m_curSyms; std::unique_ptr> m_oldAllSyms; std::unique_ptr> m_oldCurSyms; NamedObject m_currentSym; std::string m_filter; FilterOptions m_filterOptions; int m_maxWidth = 32; std::mutex m_updateMutex; std::vector m_updates; bool m_fullUpdate; BinaryNinja::Ref m_backgroundUpdate; BinaryNinja::Ref m_backgroundDestroy; volatile bool m_backgroundUpdateComplete; std::unique_ptr> m_backgroundUpdateFuncs; std::unique_ptr> m_backgroundCurSyms; bool m_showImports; bool m_showExportedDataVars; bool m_showExportedFunctions; bool m_showLocalFunctions; bool m_showLocalDataVars; SortType m_sortType; bool m_displayMangled; static bool symbolLessThan(const NamedObject& a, const NamedObject& b); static bool symbolNameLessThan(const NamedObject& a, const NamedObject& b); static bool symbolRawNameLessThan(const NamedObject& a, const NamedObject& b); void getValidObject(std::unique_ptr>& 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 OnDataVariableAdded(BinaryNinja::BinaryView* data, const BinaryNinja::DataVariable& var) override; virtual void OnDataVariableRemoved(BinaryNinja::BinaryView* data, const BinaryNinja::DataVariable& var) override; virtual void OnSymbolAdded(BinaryNinja::BinaryView* data, BinaryNinja::Symbol* sym) override; virtual void OnSymbolUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Symbol* sym) override; virtual void OnSymbolRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Symbol* sym) override; void updateFonts(); bool isValidType(const NamedObject& rec); bool setCurrentObject(const NamedObject& rec); bool setCurrentFunction(FunctionRef func); QModelIndex findSymbol(const NamedObject& rec) const; QModelIndex getSymbolIndex(const std::deque::const_iterator rec) const; QModelIndex findCurrentSymbol() const; NamedObject getNamedObjectForIndex(int i) const; void updateFunctions(); void backgroundUpdate(); void backgroundDestroy(); bool hasSymbols() const; int getMaximumWidth() const { return m_maxWidth; } void setFilter(const std::string& filter, FilterOptions options); void showExportedDataVars(bool show) { m_showExportedDataVars = show; } void showExportedFunctions(bool show) { m_showExportedFunctions = show; } void showLocalFunctions(bool show) { m_showLocalFunctions = show; } void showLocalDataVars(bool show) { m_showLocalDataVars = show; } void showImports(bool show) { m_showImports = show; } void toggleExportedDataVars() { m_showExportedDataVars = !m_showExportedDataVars; } void toggleExportedFunctions() { m_showExportedFunctions = !m_showExportedFunctions; } void toggleLocalFunctions() { m_showLocalFunctions = !m_showLocalFunctions; } void toggleLocalDataVars() { m_showLocalDataVars = !m_showLocalDataVars; } void toggleImports() { m_showImports = !m_showImports; } bool getShowExportedFunctions() const { return m_showExportedFunctions; } bool getShowExportedDataVars() const { return m_showExportedDataVars; } bool getShowLocalFunctions() const { return m_showLocalFunctions; } bool getShowLocalDataVars() const { return m_showLocalDataVars; } bool getShowImports() const { return m_showImports; } bool getShowMangled() const { return m_displayMangled; } void setShowMangled(bool show) { m_displayMangled = show; } void sortSymbols(SortType type); void setSortType(SortType type) { m_sortType = type; } SortType getSortType() const { return m_sortType; } NamedObject getCurrentSym() const { return m_currentSym; } bool checkTriggerFullUpdate(); Q_SIGNALS: void afterListReset(); void beforeListReset(); }; /*! \ingroup symbollist */ class BINARYNINJAUIAPI SymbolList : public QListView, public FilterTarget { Q_OBJECT ViewFrame* m_view; BinaryViewRef m_data; SymbolsView* m_functionsView; SymbolListModel* m_list; SymbolListDelegate* m_delegate; QTimer* m_updateTimer; bool m_doubleClickLatch = false; QTimer* m_resumeUpdateTimer; bool m_disableScrollToFunction; bool m_showExportedFunctions; bool m_showExportedDataVars; bool m_showLocalFunctions; bool m_showLocalDataVars; bool m_showImports; std::string m_filter; FilterOptions m_filterOptions; SymbolListModel::NamedObject m_index; SymbolListModel::NamedObject m_topIndex; public: SymbolList(SymbolsView* parent, ViewFrame* frame, BinaryViewRef data); void updateFonts(); void setCurrentFunction(FunctionRef func); virtual void scrollToFirstItem() override; virtual void scrollToCurrentItem() override; virtual void ensureSelection() override; virtual void activateSelection() override; virtual void setFilter(const std::string& filter, FilterOptions options) override; bool hasSymbols(); virtual void copy(); virtual void paste(); virtual bool canCopy(); void find(); bool getShowExportedFunctions() const { return m_list->getShowExportedFunctions(); } bool getShowExportedDataVars() const { return m_list->getShowExportedDataVars(); } bool getShowLocalFunctions() const { return m_list->getShowLocalFunctions(); } bool getShowLocalDataVars() const { return m_list->getShowLocalDataVars(); } bool getShowImports() const { return m_list->getShowImports(); } bool getShowMangled() const { return m_list->getShowMangled(); } void toggleExportedFunctions() { m_list->toggleExportedFunctions(); } void toggleExportedDataVars() { m_list->toggleExportedDataVars(); } void toggleLocalFunctions() { m_list->toggleLocalFunctions(); } void toggleLocalDataVars() { m_list->toggleLocalDataVars(); } void toggleImports() { m_list->toggleImports(); } protected: virtual void focusOutEvent(QFocusEvent* event) override; virtual void keyPressEvent(QKeyEvent* event) override; virtual bool event(QEvent* event) override; virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override; private Q_SLOTS: void goToSymbol(const QModelIndex& i); void updateTimerEvent(); void resumeUpdateTimerEvent(); void savePosition(); void restorePosition(); void saveIndex(const QModelIndex& index); void clearIndex(const QModelIndex& index); };