1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
|
#pragma once
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QComboBox>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QtWidgets/QAction>
#else
#include <QtGui/QAction>
#endif
#include <QtCore/QTimer>
#include <string>
#include <utility>
#include <vector>
#include <unordered_set>
#include "binaryninjaapi.h"
#include "viewframe.h"
#include "render.h"
#include "menus.h"
#include "xreflist.h"
#include "clickablelabel.h"
#define TYPE_VIEW_UPDATE_CHECK_INTERVAL 200
enum TypeLinesFilteredReason
{
TypeLinesFilterNotApplied,
TypeLinesFilterAccepted,
TypeLinesFilteredByTextFilter,
TypeLinesFilteredBySystemTypesFilter,
TypeLinesFilteredByBothFilters
};
struct BINARYNINJAUIAPI TypeDefinitionLinesAndFilterStatus
{
std::vector<BinaryNinja::TypeDefinitionLine> lines;
TypeLinesFilteredReason reason;
};
class BINARYNINJAUIAPI TypeViewHistoryEntry : public HistoryEntry
{
BinaryNinja::QualifiedName m_cursorType;
size_t m_cursorLine;
size_t m_cursorOffset;
bool m_selectionValid;
std::string m_selectionStartType;
size_t m_selectionStartLine;
size_t m_selectionStartOffset;
HighlightTokenState m_highlight;
public:
const BinaryNinja::QualifiedName& getCursorType() const { return m_cursorType; }
size_t getCursorLine() const { return m_cursorLine; }
size_t getCursorOffset() const { return m_cursorOffset; }
bool isSelectionValid() const { return m_selectionValid; }
const std::string& getSelectionStartType() const { return m_selectionStartType; }
size_t getSelectionStartLine() const { return m_selectionStartLine; }
size_t getSelectionStartOffset() const { return m_selectionStartOffset; }
const HighlightTokenState& getHighlightTokenState() const { return m_highlight; }
void setCursorType(const BinaryNinja::QualifiedName& type) { m_cursorType = type; }
void setCursorLine(size_t line) { m_cursorLine = line; }
void setCursorOffset(size_t offset) { m_cursorOffset = offset; }
void setSelectionValid(bool valid) { m_selectionValid = valid; }
void setSelectionStartType(const std::string& type) { m_selectionStartType = type; }
void setSelectionStartLine(size_t line) { m_selectionStartLine = line; }
void setSelectionStartOffset(size_t offset) { m_selectionStartOffset = offset; }
void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; }
virtual Json::Value serialize() const override;
virtual bool deserialize(const Json::Value& value) override;
};
class TypesContainer;
enum ModifyExistingMember
{
DontModify,
ToggleSize,
ToggleSign
};
class BINARYNINJAUIAPI TypeView : public QAbstractScrollArea, public View, public BinaryNinja::BinaryDataNotification
{
Q_OBJECT
struct TypeLineIndex
{
BinaryNinja::QualifiedName name;
int line, end;
};
BinaryViewRef m_data;
ViewFrame* m_view;
TypesContainer* m_container;
std::unordered_set<std::string> m_collapsedTypes;
RenderContext m_render;
QWidget* m_lineNumberArea;
int m_lineNumberAreaWidth = 0;
int m_lineCount = 0;
std::optional<int> m_showSystemTypesLine;
std::optional<int> m_clearFilterLine;
int m_cols, m_rows, m_paddingCols, m_offsetPaddingWidth;
uint64_t m_maxOffset;
size_t m_offsetWidth;
HighlightTokenState m_highlight;
BinaryNinja::QualifiedName m_cursorType;
size_t m_cursorTypeIndex;
size_t m_cursorLine;
size_t m_cursorOffset;
std::string m_navigationMode = "TypeNavigation";
bool m_selectionValid;
size_t m_selectionStartTypeIndex;
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<BinaryNinja::TypeDefinitionLine>> m_typeLines;
std::map<BinaryNinja::QualifiedName, TypeDefinitionLinesAndFilterStatus> m_allTypeLines;
std::vector<TypeLineIndex> m_types;
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;
ContextMenuManager* m_contextMenuManager;
QAction* m_actionCopy;
QAction* m_actionSelectAll;
bool m_compact;
void adjustSize(int width, int height);
void refreshAllTypes();
void ensureCursorVisible();
void focusOnCursor();
void changeToSpecificType(TypeRef type, ModifyExistingMember modifyExisting = DontModify);
bool canCreateMembersInSelectedRegion();
void createMembersInSelectedRegion(TypeRef type, ModifyExistingMember modifyExisting = DontModify);
void deleteMembersInSelectedRegion();
void moveUp(bool selecting);
void moveDown(bool selecting);
void moveLeft(size_t count, bool selecting);
void moveRight(size_t count, bool selecting);
void pageUp(bool selecting);
void pageDown(bool selecting);
void setCursorAbsoluteLine(size_t line);
void moveToStartOfLine(bool selecting);
void moveToEndOfLine(bool selecting);
void moveToStartOfView(bool selecting);
void moveToEndOfView(bool selecting);
void goToAddress(bool selecting);
void moveCursorToMouse(QMouseEvent* event, bool selecting);
void createNewTypes(
const QString& definition = "", const std::set<BinaryNinja::QualifiedName>& typesAllowRedefinition = {});
void bindActions();
void checkForValidSelection();
public:
explicit TypeView(BinaryViewRef data, ViewFrame* view, TypesContainer* container, bool compact = false);
virtual ~TypeView();
virtual bool findNextData(uint64_t start, uint64_t end, const BinaryNinja::DataBuffer& data, uint64_t& addr,
BNFindFlag flags, const std::function<bool(size_t current, size_t total)>& cb) override;
virtual bool findNextText(uint64_t start, uint64_t end, const std::string& text, uint64_t& addr,
DisassemblySettingsRef settings, BNFindFlag flags, BNFunctionGraphType graph,
const std::function<bool(size_t current, size_t total)>& cb) override;
virtual BinaryViewRef getData() override { return m_data; }
virtual uint64_t getCurrentOffset() override;
virtual BNAddressRange getSelectionOffsets() override;
virtual SelectionInfoForXref getSelectionForXref() override;
virtual void setSelectionOffsets(BNAddressRange range) override;
virtual bool navigate(uint64_t) override;
virtual std::string getNavigationMode() override;
virtual void setNavigationMode(std::string mode) override;
virtual std::vector<std::string> getNavigationModes() override;
uint64_t findMatchingLine(const BinaryNinja::QualifiedName& name, uint64_t offset, size_t& cursorOffset);
bool navigateToType(const std::string& name, uint64_t offset = 0);
virtual void OnTypeDefined(
BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
virtual void OnTypeUndefined(
BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
virtual void OnTypeReferenceChanged(
BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, BinaryNinja::Type* type) override;
virtual void OnTypeFieldReferenceChanged(
BinaryNinja::BinaryView* view, const BinaryNinja::QualifiedName& name, uint64_t offset) override;
void MarkFilterChanged()
{
m_updatesRequired = true;
m_filterChanged = true;
}
void MarkTypeChanged(const BinaryNinja::QualifiedName& typeName);
virtual void updateFonts() override;
virtual StatusBarWidget* getStatusBarWidget() override;
virtual BinaryNinja::Ref<HistoryEntry> getHistoryEntry() override;
virtual void navigateToHistoryEntry(BinaryNinja::Ref<HistoryEntry> entry) override;
void lineNumberAreaPaintEvent(QPaintEvent* event);
int lineNumberAreaWidth();
virtual bool canCut() override { return false; }
virtual bool canCopy() override;
virtual bool canCopyWithTransform() override { return false; }
virtual bool canPaste() override { return false; }
virtual bool canPasteWithTransform() override { return false; }
virtual bool canTransform() override { return false; }
virtual bool canCopyAddress() override { return false; }
virtual void copy(TransformRef xform = nullptr) override;
virtual QFont getFont() override { return m_render.getFont(); }
virtual HighlightTokenState getHighlightTokenState() override { return m_highlight; }
static void registerActions();
virtual ArchitectureRef getOrAskForArchitecture();
bool isTypeCollapsed(const std::string& name) const
{
return m_collapsedTypes.find(name) != m_collapsedTypes.end();
}
void showContextMenu(Menu* source = nullptr);
void focusAtTopOfView();
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;
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
virtual void scrollContentsBy(int dx, int dy) override;
private Q_SLOTS:
void copySelection();
void selectAll();
void updateTimerEvent();
void defineName();
void undefine();
void changeType();
void toggleIntSize();
void toggleFloatSize();
void toggleIntSign();
void makeInt8();
void makeInt16();
void makeInt32();
void makeInt64();
void makeFloat32();
void makeFloat64();
void makePtr();
void makeString(size_t charSize = 1);
void makeArray();
void newTypes();
void createStructure();
void createUnion();
void setStructureSize();
void addUserXref();
void updateLineNumberAreaWidth(size_t lineCount);
void focusFilter();
void toggleCollapseType();
void collapseAll();
void expandAll();
};
class BINARYNINJAUIAPI LineNumberArea : public QWidget
{
public:
LineNumberArea(TypeView* editor) : QWidget(editor), m_typeEditor(editor) {}
QSize sizeHint() const override { return QSize(m_typeEditor->lineNumberAreaWidth(), 0); }
protected:
void paintEvent(QPaintEvent* event) override { m_typeEditor->lineNumberAreaPaintEvent(event); }
private:
TypeView* m_typeEditor;
};
class TypeViewType : public ViewType
{
static TypeViewType* m_instance;
public:
TypeViewType();
virtual int getPriority(BinaryViewRef data, const QString& filename) override;
virtual QWidget* create(BinaryViewRef data, ViewFrame* viewFrame) override;
static void init();
};
class BINARYNINJAUIAPI TypeFilterEdit : public QLineEdit
{
Q_OBJECT
public:
TypeFilterEdit(QWidget* parent);
protected:
virtual void keyPressEvent(QKeyEvent* event) override;
Q_SIGNALS:
void focusView();
};
class BINARYNINJAUIAPI TypeFilter : public QWidget
{
Q_OBJECT
TypesContainer* m_container;
ClickableIcon* m_showSystemTypes;
TypeFilterEdit* m_textFilter;
bool MatchesAutoFilter(BinaryViewRef data, const BinaryNinja::QualifiedName& name);
bool MatchesTextFilter(const std::vector<BinaryNinja::TypeDefinitionLine>& lines);
Q_SIGNALS:
void filterChanged();
private Q_SLOTS:
void focusView();
public:
TypeFilter(TypesContainer* container = nullptr);
void setContainer(TypesContainer* container) { m_container = container; }
TypeLinesFilteredReason checkTypeLinesForFilter(
BinaryViewRef data, const BinaryNinja::QualifiedName& name, const std::vector<BinaryNinja::TypeDefinitionLine>& lines);
void showAndFocus();
bool areAutoTypesVisible();
void setShowAutoTypes(bool showAutoTypes);
void clearTextFilter();
};
class BINARYNINJAUIAPI TypesContainer : public QWidget, public ViewContainer
{
Q_OBJECT
TypeView* m_typeView;
TypeFilter* m_typeFilter;
UIActionHandler m_actionHandler;
public:
TypesContainer(BinaryViewRef data, ViewFrame* view, TypeFilter* filter = nullptr, bool compact = false);
virtual View* getView() override { return m_typeView; }
TypeView* getTypesView() { return m_typeView; }
TypeFilter* getTypeFilter() { return m_typeFilter; }
bool navigateToType(const std::string& name, uint64_t offset = 0);
protected:
virtual void focusInEvent(QFocusEvent* event) override;
};
class BINARYNINJAUIAPI TypeViewSidebarWidget : public SidebarWidget
{
Q_OBJECT
TypesContainer* m_container;
QWidget* m_header;
Menu m_addMenu;
public:
TypeViewSidebarWidget(BinaryViewRef data, ViewFrame* frame);
TypesContainer* container() const { return m_container; }
virtual void focus() override;
virtual QWidget* headerWidget() override { return m_header; }
private Q_SLOTS:
void showAddMenu();
};
class BINARYNINJAUIAPI TypeViewSidebarWidgetType : public SidebarWidgetType
{
public:
TypeViewSidebarWidgetType();
virtual SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override;
};
|