diff options
| author | Josh F <josh@vector35.com> | 2022-07-06 13:40:52 -0400 |
|---|---|---|
| committer | Josh F <josh@vector35.com> | 2022-07-18 16:13:50 -0400 |
| commit | 11458f3160e9c82d3e0f48b7013d952b729ec38b (patch) | |
| tree | 4c2165c208fa9542a2c744b7a3f94be52877315e | |
| parent | c3362d1ffb2c581c0647a1e9f480b98e7976fe25 (diff) | |
Memory map sidebar widget + segment/section notifications
| -rw-r--r-- | binaryninjaapi.h | 39 | ||||
| -rw-r--r-- | binaryninjacore.h | 6 | ||||
| -rw-r--r-- | binaryview.cpp | 66 | ||||
| -rw-r--r-- | python/binaryview.py | 78 | ||||
| -rw-r--r-- | python/examples/notification_callbacks.py | 18 | ||||
| -rw-r--r-- | ui/memorymap.h | 182 |
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; +}; |
