summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh F <josh@vector35.com>2022-07-06 13:40:52 -0400
committerJosh F <josh@vector35.com>2022-07-18 16:13:50 -0400
commit11458f3160e9c82d3e0f48b7013d952b729ec38b (patch)
tree4c2165c208fa9542a2c744b7a3f94be52877315e
parentc3362d1ffb2c581c0647a1e9f480b98e7976fe25 (diff)
Memory map sidebar widget + segment/section notifications
-rw-r--r--binaryninjaapi.h39
-rw-r--r--binaryninjacore.h6
-rw-r--r--binaryview.cpp66
-rw-r--r--python/binaryview.py78
-rw-r--r--python/examples/notification_callbacks.py18
-rw-r--r--ui/memorymap.h182
6 files changed, 389 insertions, 0 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index eb605e8a..1c33f70b 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1100,6 +1100,8 @@ namespace BinaryNinja {
class Tag;
class TagType;
struct TagReference;
+ class Section;
+ class Segment;
class BinaryDataNotification
{
@@ -1132,6 +1134,13 @@ namespace BinaryNinja {
static void TypeReferenceChangedCallback(void* ctx, BNBinaryView* data, BNQualifiedName* name, BNType* type);
static void TypeFieldReferenceChangedCallback(
void* ctx, BNBinaryView* data, BNQualifiedName* name, uint64_t offset);
+ static void SegmentAddedCallback(void* ctx, BNBinaryView* data, BNSegment* segment);
+ static void SegmentUpdatedCallback(void* ctx, BNBinaryView* data, BNSegment* segment);
+ static void SegmentRemovedCallback(void* ctx, BNBinaryView* data, BNSegment* segment);
+ static void SectionAddedCallback(void* ctx, BNBinaryView* data, BNSection* section);
+ static void SectionUpdatedCallback(void* ctx, BNBinaryView* data, BNSection* section);
+ static void SectionRemovedCallback(void* ctx, BNBinaryView* data, BNSection* section);
+
public:
BinaryDataNotification();
@@ -1270,6 +1279,36 @@ namespace BinaryNinja {
(void)name;
(void)offset;
}
+ virtual void OnSegmentAdded(BinaryView* data, Segment* segment)
+ {
+ (void)data;
+ (void)segment;
+ }
+ virtual void OnSegmentUpdated(BinaryView* data, Segment* segment)
+ {
+ (void)data;
+ (void)segment;
+ }
+ virtual void OnSegmentRemoved(BinaryView* data, Segment* segment)
+ {
+ (void)data;
+ (void)segment;
+ }
+ virtual void OnSectionAdded(BinaryView* data, Section* section)
+ {
+ (void)data;
+ (void)section;
+ }
+ virtual void OnSectionUpdated(BinaryView* data, Section* section)
+ {
+ (void)data;
+ (void)section;
+ }
+ virtual void OnSectionRemoved(BinaryView* data, Section* section)
+ {
+ (void)data;
+ (void)section;
+ }
};
class FileAccessor
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 707c32df..be051b50 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -1373,6 +1373,12 @@ extern "C"
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);
+ void (*segmentAdded)(void* ctxt, BNBinaryView* view, BNSegment* segment);
+ void (*segmentUpdated)(void* ctxt, BNBinaryView* view, BNSegment* segment);
+ void (*segmentRemoved)(void* ctxt, BNBinaryView* view, BNSegment* segment);
+ void (*sectionAdded)(void* ctxt, BNBinaryView* view, BNSection* section);
+ void (*sectionUpdated)(void* ctxt, BNBinaryView* view, BNSection* section);
+ void (*sectionRemoved)(void* ctxt, BNBinaryView* view, BNSection* section);
};
struct BNFileAccessor
diff --git a/binaryview.cpp b/binaryview.cpp
index 330a1412..db45cc88 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -240,6 +240,66 @@ void BinaryDataNotification::TypeFieldReferenceChangedCallback(
}
+void BinaryDataNotification::SegmentAddedCallback(void* ctxt, BNBinaryView* data, BNSegment* segment)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Segment> segmentObj = new Segment(BNNewSegmentReference(segment));
+
+ notify->OnSegmentAdded(view, segmentObj);
+}
+
+
+void BinaryDataNotification::SegmentUpdatedCallback(void* ctxt, BNBinaryView* data, BNSegment* segment)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Segment> segmentObj = new Segment(BNNewSegmentReference(segment));
+
+ notify->OnSegmentUpdated(view, segmentObj);
+}
+
+
+void BinaryDataNotification::SegmentRemovedCallback(void* ctxt, BNBinaryView* data, BNSegment* segment)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Segment> segmentObj = new Segment(BNNewSegmentReference(segment));
+
+ notify->OnSegmentRemoved(view, segmentObj);
+}
+
+
+void BinaryDataNotification::SectionAddedCallback(void* ctxt, BNBinaryView* data, BNSection* section)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Section> sectionObj = new Section(BNNewSectionReference(section));
+
+ notify->OnSectionAdded(view, sectionObj);
+}
+
+
+void BinaryDataNotification::SectionUpdatedCallback(void* ctxt, BNBinaryView* data, BNSection* section)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Section> sectionObj = new Section(BNNewSectionReference(section));
+
+ notify->OnSectionUpdated(view, sectionObj);
+}
+
+
+void BinaryDataNotification::SectionRemovedCallback(void* ctxt, BNBinaryView* data, BNSection* section)
+{
+ BinaryDataNotification* notify = (BinaryDataNotification*)ctxt;
+ Ref<BinaryView> view = new BinaryView(BNNewViewReference(data));
+ Ref<Section> sectionObj = new Section(BNNewSectionReference(section));
+
+ notify->OnSectionRemoved(view, sectionObj);
+}
+
+
BinaryDataNotification::BinaryDataNotification()
{
m_callbacks.context = this;
@@ -267,6 +327,12 @@ BinaryDataNotification::BinaryDataNotification()
m_callbacks.typeUndefined = TypeUndefinedCallback;
m_callbacks.typeReferenceChanged = TypeReferenceChangedCallback;
m_callbacks.typeFieldReferenceChanged = TypeFieldReferenceChangedCallback;
+ m_callbacks.segmentAdded = SegmentAddedCallback;
+ m_callbacks.segmentUpdated = SegmentUpdatedCallback;
+ m_callbacks.segmentRemoved = SegmentRemovedCallback;
+ m_callbacks.sectionAdded = SectionAddedCallback;
+ m_callbacks.sectionUpdated = SectionUpdatedCallback;
+ m_callbacks.sectionRemoved = SectionRemovedCallback;
}
diff --git a/python/binaryview.py b/python/binaryview.py
index fbbba6f9..61123621 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -210,6 +210,23 @@ class BinaryDataNotification:
def type_field_ref_changed(self, view: 'BinaryView', name: '_types.QualifiedName', offset: int) -> None:
pass
+ def segment_added(self, view: 'BinaryView', segment: 'Segment') -> None:
+ pass
+
+ def segment_updated(self, view: 'BinaryView', segment: 'Segment') -> None:
+ pass
+
+ def segment_removed(self, view: 'BinaryView', segment: 'Segment') -> None:
+ pass
+
+ def section_added(self, view: 'BinaryView', section: 'Section') -> None:
+ pass
+
+ def section_updated(self, view: 'BinaryView', section: 'Section') -> None:
+ pass
+
+ def section_removed(self, view: 'BinaryView', section: 'Section') -> None:
+ pass
class StringReference:
_decodings = {
@@ -439,6 +456,13 @@ class BinaryDataNotificationCallbacks:
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)
+ self._cb.segmentAdded = self._cb.segmentAdded.__class__(self._segment_added)
+ self._cb.segmentUpdated = self._cb.segmentUpdated.__class__(self._segment_updated)
+ self._cb.segmentRemoved = self._cb.segmentRemoved.__class__(self._segment_removed)
+ self._cb.sectionAdded = self._cb.sectionAdded.__class__(self._section_added)
+ self._cb.sectionUpdated = self._cb.sectionUpdated.__class__(self._section_updated)
+ self._cb.sectionRemoved = self._cb.sectionRemoved.__class__(self._section_removed)
+
def _register(self) -> None:
core.BNRegisterDataNotification(self._view.handle, self._cb)
@@ -658,6 +682,60 @@ class BinaryDataNotificationCallbacks:
except:
log_error(traceback.format_exc())
+ def _segment_added(self, ctxt, view: core.BNBinaryView, segment_obj: core.BNSegment) -> None:
+ try:
+ segment_handle = core.BNNewSegmentReference(segment_obj)
+ assert segment_handle is not None, "core.BNNewSegmentReference returned None"
+ result = Segment(segment_handle)
+ self._notify.segment_added(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _segment_updated(self, ctxt, view: core.BNBinaryView, segment_obj: core.BNSegment) -> None:
+ try:
+ segment_handle = core.BNNewSegmentReference(segment_obj)
+ assert segment_handle is not None, "core.BNNewSegmentReference returned None"
+ result = Segment(segment_handle)
+ self._notify.segment_updated(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _segment_removed(self, ctxt, view: core.BNBinaryView, segment_obj: core.BNSegment) -> None:
+ try:
+ segment_handle = core.BNNewSegmentReference(segment_obj)
+ assert segment_handle is not None, "core.BNNewSegmentReference returned None"
+ result = Segment(segment_handle)
+ self._notify.segment_removed(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _section_added(self, ctxt, view: core.BNBinaryView, section_obj: core.BNSection) -> None:
+ try:
+ section_handle = core.BNNewSectionReference(section_obj)
+ assert section_handle is not None, "core.BNNewSectionReference returned None"
+ result = Section(section_handle)
+ self._notify.section_added(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _section_updated(self, ctxt, view: core.BNBinaryView, section_obj: core.BNSection) -> None:
+ try:
+ section_handle = core.BNNewSectionReference(section_obj)
+ assert section_handle is not None, "core.BNNewSectionReference returned None"
+ result = Section(section_handle)
+ self._notify.section_updated(self._view, result)
+ except:
+ log_error(traceback.format_exc())
+
+ def _section_removed(self, ctxt, view: core.BNBinaryView, section_obj: core.BNSection) -> None:
+ try:
+ section_handle = core.BNNewSectionReference(section_obj)
+ assert section_handle is not None, "core.BNNewSectionReference returned None"
+ result = Section(section_handle)
+ self._notify.section_removed(self._view, result)
+ 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 24d798de..47282884 100644
--- a/python/examples/notification_callbacks.py
+++ b/python/examples/notification_callbacks.py
@@ -107,5 +107,23 @@ class DemoNotification(BinaryDataNotification):
def type_field_ref_changed(self, *args):
log.log_info(inspect.stack()[0][3] + str(args))
+ def segment_added(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
+ def segment_updated(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
+ def segment_removed(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
+ def section_added(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
+ def section_updated(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
+ def section_removed(self, *args):
+ log.log_info(inspect.stack()[0][3] + str(args))
+
PluginCommand.register("Register Notification", "", reg_notif)
diff --git a/ui/memorymap.h b/ui/memorymap.h
new file mode 100644
index 00000000..fe85035c
--- /dev/null
+++ b/ui/memorymap.h
@@ -0,0 +1,182 @@
+#pragma once
+
+#include <QtWidgets/QAbstractScrollArea>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QTableWidget>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QStyledItemDelegate>
+
+#include "dockhandler.h"
+#include "render.h"
+#include "sidebar.h"
+#include "uitypes.h"
+#include "fontsettings.h"
+
+
+class BINARYNINJAUIAPI DataComparedTableItem : public QTableWidgetItem
+{
+public:
+ DataComparedTableItem(const QString& text, int type=QTableWidgetItem::ItemType::Type): QTableWidgetItem(text, type) {};
+ bool operator<(const QTableWidgetItem& other) const;
+};
+
+
+class BINARYNINJAUIAPI MemoryMapItemDelegate : public QStyledItemDelegate
+{
+public:
+ MemoryMapItemDelegate(QObject* parent = nullptr): QStyledItemDelegate(parent) {};
+ virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+};
+
+
+class BINARYNINJAUIAPI SegmentDialog : public QDialog
+{
+
+ QPushButton* m_acceptButton;
+ QPushButton* m_cancelButton;
+ QLineEdit* m_startField;
+ QLineEdit* m_lengthField;
+ QLineEdit* m_dataOffsetField;
+ QLineEdit* m_dataLengthField;
+ QCheckBox* m_flagRead;
+ QCheckBox* m_flagWrite;
+ QCheckBox* m_flagExec;
+
+ BinaryViewRef m_data;
+ SegmentRef m_segment;
+
+ void Submit();
+public:
+ SegmentDialog(QWidget* parent, BinaryViewRef data, SegmentRef segment = nullptr);
+};
+
+
+class BINARYNINJAUIAPI SectionDialog : public QDialog
+{
+
+ QPushButton* m_acceptButton;
+ QPushButton* m_cancelButton;
+ QLineEdit* m_nameField;
+ QLineEdit* m_startField;
+ QLineEdit* m_lengthField;
+ QComboBox* m_semanticsField;
+
+ BinaryViewRef m_data;
+ SectionRef m_section;
+
+ void Submit();
+public:
+ SectionDialog(QWidget* parent, BinaryViewRef data, SectionRef section = nullptr);
+};
+
+
+class BINARYNINJAUIAPI SegmentWidget : public QWidget, public BinaryNinja::BinaryDataNotification
+{
+ Q_OBJECT
+
+ enum SEGMENT_COLUMN {
+ START = 0,
+ END,
+ DATA_OFFSET,
+ DATA_LENGTH,
+ FLAGS,
+ COLUMN_COUNT,
+ };
+
+ BinaryViewRef m_data;
+ QTableWidget* m_table;
+ std::mutex m_updateMutex;
+
+ void updateInfo();
+ void showContextMenu(const QPoint& point);
+
+ void addSegment();
+ void editSegment(SegmentRef segment);
+ void removeSegment(SegmentRef segment);
+
+public:
+ SegmentWidget(BinaryViewRef data);
+
+ void updateFont();
+ void highlightRelatedSegments(SectionRef section);
+ void itemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
+
+ virtual void OnSegmentAdded(BinaryNinja::BinaryView* data, BinaryNinja::Segment* segment) override { updateInfo(); };
+ virtual void OnSegmentUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Segment* segment) override { updateInfo(); };
+ virtual void OnSegmentRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Segment* segment) override { updateInfo(); };
+
+Q_SIGNALS:
+ void currentSegmentChanged(SegmentRef current);
+ void addressDoubleClicked(uint64_t address);
+};
+
+
+class BINARYNINJAUIAPI SectionWidget : public QWidget, public BinaryNinja::BinaryDataNotification
+{
+ Q_OBJECT
+
+ enum SECTION_COLUMN {
+ NAME = 0,
+ START,
+ END,
+ SEMANTICS,
+ COLUMN_COUNT,
+ };
+
+ BinaryViewRef m_data;
+ QTableWidget* m_table;
+ std::mutex m_updateMutex;
+
+ void updateInfo();
+ void showContextMenu(const QPoint& point);
+
+ void addSection();
+ void editSection(SectionRef section);
+ void removeSection(SectionRef section);
+
+public:
+ SectionWidget(BinaryViewRef data);
+
+ void updateFont();
+ void highlightRelatedSections(SegmentRef segment);
+ void itemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
+
+ virtual void OnSectionAdded(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override { updateInfo(); };
+ virtual void OnSectionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override { updateInfo(); };
+ virtual void OnSectionRemoved(BinaryNinja::BinaryView* data, BinaryNinja::Section* section) override { updateInfo(); };
+
+Q_SIGNALS:
+ void currentSectionChanged(SectionRef current);
+ void addressDoubleClicked(uint64_t address);
+};
+
+
+class BINARYNINJAUIAPI MemoryMapSidebarWidget : public SidebarWidget, public BinaryNinja::BinaryDataNotification
+{
+ Q_OBJECT
+
+ SectionWidget* m_sectionWidget;
+ SegmentWidget* m_segmentWidget;
+ QWidget* m_header;
+ BinaryViewRef m_data;
+ ViewFrame* m_frame;
+
+ void navigateToAddress(uint64_t address);
+
+ public:
+ MemoryMapSidebarWidget(ViewFrame* view, BinaryViewRef data);
+
+ void notifyFontChanged() override;
+ QWidget* headerWidget() override { return m_header; }
+};
+
+
+class BINARYNINJAUIAPI MemoryMapSidebarWidgetType : public SidebarWidgetType
+{
+ public:
+ MemoryMapSidebarWidgetType();
+ SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override;
+};