summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXusheng <xusheng@vector35.com>2021-10-21 18:27:06 +0800
committerXusheng <xusheng@vector35.com>2021-10-28 15:08:53 +0800
commit927390bc14ccd6739a62c2a291e50a4a3ce4d0b0 (patch)
treea628e18289034040005afd0a5c450fd8bea99e0f
parentc6f170d1541c53a5b2a9821b31f77612d0b8559f (diff)
Smartly update the TypeView
-rw-r--r--binaryninjaapi.h3
-rw-r--r--binaryninjacore.h1
-rw-r--r--binaryview.cpp10
-rw-r--r--python/binaryview.py10
-rw-r--r--python/examples/notification_callbacks.py3
-rw-r--r--suite/testcommon.py3
-rw-r--r--ui/typeview.h58
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;
};