diff options
| author | Xusheng <xusheng@vector35.com> | 2021-10-21 18:27:06 +0800 |
|---|---|---|
| committer | Xusheng <xusheng@vector35.com> | 2021-10-28 15:08:53 +0800 |
| commit | 927390bc14ccd6739a62c2a291e50a4a3ce4d0b0 (patch) | |
| tree | a628e18289034040005afd0a5c450fd8bea99e0f | |
| parent | c6f170d1541c53a5b2a9821b31f77612d0b8559f (diff) | |
Smartly update the TypeView
| -rw-r--r-- | binaryninjaapi.h | 3 | ||||
| -rw-r--r-- | binaryninjacore.h | 1 | ||||
| -rw-r--r-- | binaryview.cpp | 10 | ||||
| -rw-r--r-- | python/binaryview.py | 10 | ||||
| -rw-r--r-- | python/examples/notification_callbacks.py | 3 | ||||
| -rw-r--r-- | suite/testcommon.py | 3 | ||||
| -rw-r--r-- | ui/typeview.h | 58 |
7 files changed, 71 insertions, 17 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index d08fea8a..a2f5b122 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1090,6 +1090,7 @@ __attribute__ ((format (printf, 1, 2))) static void TypeDefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type); static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type); static void TypeReferenceChangedCallback(void* ctx, BNBinaryView* data, BNQualifiedName* name, BNType* type); + static void TypeFieldReferenceChangedCallback(void* ctx, BNBinaryView* data, BNQualifiedName* name, uint64_t offset); public: BinaryDataNotification(); @@ -1121,6 +1122,8 @@ __attribute__ ((format (printf, 1, 2))) virtual void OnTypeUndefined(BinaryView* data, const QualifiedName& name, Type* type) { (void)data; (void)name; (void)type; } virtual void OnTypeReferenceChanged(BinaryView* data, const QualifiedName&name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeFieldReferenceChanged(BinaryView* data, const QualifiedName& name, uint64_t offset) + { (void)data; (void)name; (void)offset; } }; class FileAccessor diff --git a/binaryninjacore.h b/binaryninjacore.h index 8bbb4e0a..ec9951c9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1338,6 +1338,7 @@ extern "C" void (*typeDefined)(void* ctxt, BNBinaryView* view, BNQualifiedName* name, BNType* type); void (*typeUndefined)(void* ctxt, BNBinaryView* view, BNQualifiedName* name, BNType* type); void (*typeReferenceChanged)(void* ctxt, BNBinaryView* view, BNQualifiedName* name, BNType* type); + void (*typeFieldReferenceChanged)(void* ctxt, BNBinaryView* view, BNQualifiedName* name, uint64_t offset); }; struct BNFileAccessor diff --git a/binaryview.cpp b/binaryview.cpp index d7040cea..749368dc 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -225,6 +225,15 @@ void BinaryDataNotification::TypeReferenceChangedCallback(void* ctxt, BNBinaryVi } +void BinaryDataNotification::TypeFieldReferenceChangedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, uint64_t offset) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(data)); + notify->OnTypeFieldReferenceChanged(view, QualifiedName::FromAPIObject(name), offset); +} + + + BinaryDataNotification::BinaryDataNotification() { m_callbacks.context = this; @@ -251,6 +260,7 @@ BinaryDataNotification::BinaryDataNotification() m_callbacks.typeDefined = TypeDefinedCallback; m_callbacks.typeUndefined = TypeUndefinedCallback; m_callbacks.typeReferenceChanged = TypeReferenceChangedCallback; + m_callbacks.typeFieldReferenceChanged = TypeFieldReferenceChangedCallback; } diff --git a/python/binaryview.py b/python/binaryview.py index 65a005b7..3ef879ef 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -181,6 +181,8 @@ class BinaryDataNotification: def type_ref_changed(self, view:'BinaryView', name:'_types.QualifiedName', type:'_types.Type') -> None: pass + def type_field_ref_changed(self, view:'BinaryView', name:'_types.QualifiedName', offset: int) -> None: + pass class StringReference: _decodings = { @@ -417,6 +419,7 @@ class BinaryDataNotificationCallbacks: self._cb.typeDefined = self._cb.typeDefined.__class__(self._type_defined) self._cb.typeUndefined = self._cb.typeUndefined.__class__(self._type_undefined) self._cb.typeReferenceChanged = self._cb.typeReferenceChanged.__class__(self._type_ref_changed) + self._cb.typeFieldReferenceChanged = self._cb.typeFieldReferenceChanged.__class__(self._type_field_ref_changed) def _register(self) -> None: core.BNRegisterDataNotification(self._view.handle, self._cb) @@ -618,6 +621,13 @@ class BinaryDataNotificationCallbacks: except: log_error(traceback.format_exc()) + def _type_field_ref_changed(self, ctxt, view:core.BNBinaryView, name:str, offset:int) -> None: + try: + qualified_name = _types.QualifiedName._from_core_struct(name[0]) + self._notify.type_field_ref_changed(self._view, qualified_name, offset) + except: + log_error(traceback.format_exc()) + @property def view(self) -> 'BinaryView': return self._view diff --git a/python/examples/notification_callbacks.py b/python/examples/notification_callbacks.py index e299aa06..f51df6e3 100644 --- a/python/examples/notification_callbacks.py +++ b/python/examples/notification_callbacks.py @@ -97,4 +97,7 @@ class DemoNotification(BinaryDataNotification): def type_ref_changed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) + def type_field_ref_changed(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) + PluginCommand.register("Register Notification", "", reg_notif) diff --git a/suite/testcommon.py b/suite/testcommon.py index 52cdc242..a13a72e6 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -982,6 +982,9 @@ class TestBuilder(Builder): def type_ref_changed(self, view, name, type): results.append("type reference changed: {0}".format(name)) + def type_field_ref_changed(self, view, name, offset): + results.append("type field reference changed: {0}, offset {1}".format(name, hex(offset))) + test = NotifyTest() bv.register_notification(test) sacrificial_addr = 0x84fc diff --git a/ui/typeview.h b/ui/typeview.h index ff34c8b8..527e35cf 100644 --- a/ui/typeview.h +++ b/ui/typeview.h @@ -34,6 +34,17 @@ enum BINARYNINJAUIAPI TypeDefinitionLineType UndefinedXrefLineType }; + +enum TypeLinesFilteredReason +{ + TypeLinesFilterNotApplied, + TypeLinesFilterAccepted, + TypeLinesFilteredByTextFilter, + TypeLinesFilteredBySystemTypesFilter, + TypeLinesFilteredByBothFilters +}; + + struct BINARYNINJAUIAPI TypeDefinitionLine { TypeDefinitionLineType lineType; @@ -44,6 +55,14 @@ struct BINARYNINJAUIAPI TypeDefinitionLine size_t fieldIndex; }; + +struct BINARYNINJAUIAPI TypeDefinitionLinesAndFilterStatus +{ + std::vector<TypeDefinitionLine> lines; + TypeLinesFilteredReason reason; +}; + + class BINARYNINJAUIAPI TypeViewHistoryEntry: public HistoryEntry { BinaryNinja::QualifiedName m_cursorType; @@ -103,9 +122,7 @@ class BINARYNINJAUIAPI TypeView: public QAbstractScrollArea, public View, public QWidget* m_lineNumberArea; int m_lineNumberAreaWidth = 0; int m_lineCount = 0; - size_t m_systemTypesHidden = 0; std::optional<int> m_showSystemTypesLine; - size_t m_typesFiltered = 0; std::optional<int> m_clearFilterLine; int m_cols, m_rows, m_paddingCols, m_offsetPaddingWidth; uint64_t m_maxOffset; @@ -122,12 +139,22 @@ class BINARYNINJAUIAPI TypeView: public QAbstractScrollArea, public View, public size_t m_selectionStartLine; size_t m_selectionStartOffset; + // m_typeLines are the types being displayed in the typeview (with filter applied) + // m_allTypeLines are the lines and filter status of all types in the data std::map<BinaryNinja::QualifiedName, std::vector<TypeDefinitionLine>> m_typeLines; + std::map<BinaryNinja::QualifiedName, TypeDefinitionLinesAndFilterStatus> m_allTypeLines; std::vector<TypeLineIndex> m_types; - BinaryNinja::Ref<BinaryNinja::AnalysisCompletionEvent> m_completionEvent = nullptr; - std::atomic_bool m_updatesRequired; QTimer* m_updateTimer; + std::recursive_mutex m_updateMutex; + std::atomic_bool m_updatesRequired = true; + std::atomic_bool m_initialUpdate = true; + std::atomic_bool m_filterChanged = false; + std::set<BinaryNinja::QualifiedName> m_typesChanged; + + std::set<std::string> m_textFilteredTypeNames; + size_t m_systemTypesHidden = 0; + size_t m_typesFiltered = 0; Qt::KeyboardModifiers m_ctrl, m_command; @@ -199,12 +226,11 @@ public: BinaryNinja::Type* type) override; virtual void OnTypeReferenceChanged(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override; - virtual void OnDataVariableAdded(BinaryNinja::BinaryView*, const BinaryNinja::DataVariable&) override; - virtual void OnDataVariableRemoved(BinaryNinja::BinaryView*, const BinaryNinja::DataVariable&) override; - virtual void OnDataVariableUpdated(BinaryNinja::BinaryView*, const BinaryNinja::DataVariable&) override; - virtual void OnDataMetadataUpdated(BinaryNinja::BinaryView*, uint64_t offset) override; + virtual void OnTypeFieldReferenceChanged(BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, + uint64_t offset) override; - void MarkUpdatesRequired() { m_updatesRequired = true; } + void MarkFilterChanged() { m_updatesRequired = true; m_filterChanged = true; } + void MarkTypeChanged(const BinaryNinja::QualifiedName& typeName); virtual void updateFonts() override; virtual StatusBarWidget* getStatusBarWidget() override; @@ -243,6 +269,8 @@ public: virtual bool canDisplayAs(const UIActionContext& context, const BNIntegerDisplayType) override { return false; } + bool isTypeTextFiltered(const std::string& name) const; + protected: virtual void resizeEvent(QResizeEvent* event) override; virtual void paintEvent(QPaintEvent* event) override; @@ -328,8 +356,6 @@ class BINARYNINJAUIAPI TypeFilter: public QWidget ClickableIcon* m_showSystemTypes; TypeFilterEdit* m_textFilter; - std::set<std::string> m_textFilteredTypeNames; - bool MatchesAutoFilter(BinaryViewRef data, const BinaryNinja::QualifiedName& name); bool MatchesTextFilter(const std::vector<TypeDefinitionLine>& lines); @@ -343,14 +369,12 @@ public: TypeFilter(TypesContainer* container = nullptr); void setContainer(TypesContainer* container) { m_container = container; } - std::map<BinaryNinja::QualifiedName, std::vector<TypeDefinitionLine>> GetFilteredTypeLines( - BinaryViewRef data, int padding, size_t& systemTypesHidden, size_t& typesFiltered); + TypeLinesFilteredReason checkTypeLinesForFilter(BinaryViewRef data, const BinaryNinja::QualifiedName& name, + const std::vector<TypeDefinitionLine>& lines); void showAndFocus(); - bool areAutoTypesVisible(); - void setShowAutoTypes(bool showAutoTypes); + bool areAutoTypesVisible(); + void setShowAutoTypes(bool showAutoTypes); void clearTextFilter(); - - bool isTypeTextFiltered(const std::string& name) const; }; |
