forked from Vector35/binaryninja-api
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflowgraphwidget.h
394 lines (318 loc) · 13.4 KB
/
flowgraphwidget.h
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
#pragma once
#include <QtWidgets/QWidget>
#include <QtWidgets/QAbstractScrollArea>
#include "binaryninjaapi.h"
#include "render.h"
#include "viewframe.h"
#include "menus.h"
#include "uicontext.h"
#include "commentdialog.h"
#include "instructionedit.h"
/*!
\defgroup flowgraphwidget FlowGraphWidget
\ingroup uiapi
*/
/*!
\ingroup flowgraphwidget
*/
class BINARYNINJAUIAPI GraphLayoutCompleteEvent : public QEvent
{
FlowGraphRef m_graph;
public:
GraphLayoutCompleteEvent(QEvent::Type type, const FlowGraphRef& graph);
FlowGraphRef GetGraph() { return m_graph; }
};
/*!
\ingroup flowgraphwidget
*/
class BINARYNINJAUIAPI FlowGraphHistoryEntry : public HistoryEntry
{
PlatformRef m_platform;
ArchitectureRef m_arch;
uint64_t m_func;
int m_scrollX, m_scrollY;
float m_scale;
uint64_t m_addr;
HighlightTokenState m_highlight;
public:
PlatformRef getPlatform() const { return m_platform; }
ArchitectureRef getArchitecture() const { return m_arch; }
uint64_t getFunction() const { return m_func; }
int getScrollX() const { return m_scrollX; }
int getScrollY() const { return m_scrollY; }
float getScale() const { return m_scale; }
uint64_t getCurrentAddress() const { return m_addr; }
const HighlightTokenState& getHighlightTokenState() const { return m_highlight; }
void setPlatform(PlatformRef platform) { m_platform = platform; }
void setArchitecture(ArchitectureRef arch) { m_arch = arch; }
void setFunction(uint64_t f) { m_func = f; }
void setScrollX(int x) { m_scrollX = x; }
void setScrollY(int y) { m_scrollY = y; }
void setScale(float s) { m_scale = s; }
void setCurrentAddress(uint64_t a) { m_addr = a; }
void setHighlightTokenState(const HighlightTokenState& state) { m_highlight = state; }
virtual Json::Value serialize() const override;
virtual bool deserialize(const Json::Value& value) override;
};
class BINARYNINJAUIAPI FlowGraphWidget :
public QAbstractScrollArea,
public View,
public PreviewScrollHandler,
public BinaryNinja::BinaryDataNotification
{
Q_OBJECT
struct CursorPosition
{
size_t lineInNode;
uint64_t address;
size_t instrIndex;
size_t lineIndexForAddress;
size_t tokenIndex;
size_t characterIndex;
// Directly from QMouseEvent, not used in comparators
int cursorX;
int cursorY;
bool operator==(const CursorPosition& other) const;
bool operator<(const CursorPosition& other) const;
bool operator<=(const CursorPosition& other) const;
};
BinaryViewRef m_data;
FlowGraphRef m_graph;
FlowGraphRef m_updateGraph;
FlowGraphLayoutRequestRef m_graphLayoutRequest;
FlowGraphLayoutRequestRef m_updateGraphLayoutRequest;
FunctionRef m_func;
BinaryNinja::AdvancedFunctionAnalysisDataRequestor m_advancedAnalysisData;
View* m_navigationTarget;
bool m_ready;
QTimer* m_loadingTimer;
QTimer* m_zoomTimer;
QTimer* m_zoomPauseTimer;
std::mutex m_updateMutex;
bool m_updated;
RenderContext m_render;
int m_width, m_height;
int m_renderXOfs, m_renderYOfs, m_renderWidth, m_renderHeight;
float m_scale;
QRect m_renderRect;
bool m_scrollMode;
int m_scrollBaseX, m_scrollBaseY;
bool m_mouseSelectMode = false;
FlowGraphNodeRef m_selectedNode, m_selectedEdgeSource;
bool m_selectedEdgeIncoming = false;
std::map<FlowGraphNodeRef, FlowGraphNodeRef> m_selectedEdgeIncomingPriority, m_selectedEdgeOutgoingPriority;
BinaryNinja::FlowGraphEdge m_selectedEdge;
CursorPosition m_cursorPos, m_selectionStartPos;
HighlightTokenState m_highlight;
bool m_tokenSelection = false;
std::set<size_t> m_relatedIndexHighlights;
std::set<uint64_t> m_relatedInstructionHighlights;
ContextMenuManager* m_contextMenuManager;
QPointer<CommentDialog> m_commentDialog;
BinaryNinja::Ref<FlowGraphHistoryEntry> m_pendingHistoryEntry, m_layoutHistoryEntry;
bool m_useAddrAfterLayout;
uint64_t m_addrAfterLayout;
bool m_pendingXrefNavigation, m_xrefNavigation;
uint64_t m_xrefTarget;
size_t m_indexAfterlayout;
InstructionEdit* m_instrEdit;
bool m_isPreview;
QPointF m_previewPos;
QTimer* m_hoverTimer;
FlowGraphRef m_recenterWithGraph;
int m_recenterXofs, m_recenterYofs;
static int m_layoutCompleteEventType;
static int m_updateCompleteEventType;
void adjustSize(int width, int height);
void defineNameAtAddr(uint64_t addr);
static std::string getValueStr(int64_t value);
static std::string getValueStr(uint64_t value);
FlowGraphNodeRef findUpdatedNode(FlowGraphRef oldGraph, FlowGraphNodeRef oldNode, CursorPosition& pos);
bool updatePositionForNode(FlowGraphNodeRef oldNode, FlowGraphNodeRef newNode, CursorPosition& pos);
void recenterUpdatedGraph(FlowGraphRef oldGraph, int oldXOfs, int oldYOfs);
BNDeadStoreElimination getCurrentVariableDeadStoreElimination();
std::optional<std::pair<BinaryNinja::Variable, BinaryNinja::Variable>> getMergeVariablesAtCurrentLocation();
protected:
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override;
virtual void customEvent(QEvent* event) override;
virtual void scrollContentsBy(int dx, int dy) override;
HighlightTokenState getTokenForMouseEvent(QMouseEvent* event);
virtual void contextMenuEvent(QContextMenuEvent*) override;
void bindActions();
virtual void bindDynamicActions();
void navigateToAddress(uint64_t addr);
void navigateToGotoLabel(uint64_t label);
void setGraphInternal(FlowGraphRef graph, BinaryNinja::Ref<FlowGraphHistoryEntry> entry, bool useAddr,
uint64_t addr, bool notify, bool recenterWithPreviousGraph, size_t index = BN_INVALID_EXPR);
void up(bool selecting, size_t count = 1);
void down(bool selecting, size_t count = 1);
void left(bool selecting);
void right(bool selecting);
void leftToSymbol(bool selecting);
void rightToSymbol(bool selecting);
void pageUp(bool selecting);
void pageDown(bool selecting);
void moveToStartOfLine(bool selecting);
void moveToEndOfLine(bool selecting);
void moveToStartOfView();
void moveToEndOfView();
void selectAll();
void selectNone();
void navigateToHighlightedToken();
std::optional<uint64_t> addressForCall();
uint64_t getTokenAddress();
bool isFunctionHeader();
bool m_enableBlockIndicators = false;
public:
FlowGraphWidget(QWidget* parent, BinaryViewRef view, FlowGraphRef graph = FlowGraphRef());
~FlowGraphWidget();
virtual void notifyRefresh() override;
virtual void OnAnalysisFunctionUpdated(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override;
virtual void OnAnalysisFunctionUpdateRequested(BinaryNinja::BinaryView* data, BinaryNinja::Function* func) override;
virtual void OnDataMetadataUpdated(BinaryNinja::BinaryView* data, uint64_t offset) override;
virtual void OnTagUpdated(BinaryNinja::BinaryView* data, const BinaryNinja::TagReference& tagRef) override;
void setInitialGraph(FlowGraphRef graph);
void setInitialGraph(FlowGraphRef graph, uint64_t addr);
void setGraph(FlowGraphRef graph);
void setGraph(FlowGraphRef graph, uint64_t addr);
void setGraphAtIndex(FlowGraphRef graph, size_t index);
void setGraph(FlowGraphRef graph, BinaryNinja::Ref<FlowGraphHistoryEntry> entry);
void setRelatedGraph(FlowGraphRef graph);
void setRelatedGraph(FlowGraphRef graph, uint64_t addr);
void updateToGraph(FlowGraphRef graph);
virtual void updateFonts() 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 pos) override;
virtual bool navigateToFunction(FunctionRef func, uint64_t pos) override;
virtual bool navigateToViewLocation(const ViewLocation& viewLocation, bool center = false) override;
bool navigateWithHistoryEntry(uint64_t addr, BinaryNinja::Ref<FlowGraphHistoryEntry> entry);
bool navigateWithHistoryEntry(FunctionRef func, uint64_t addr, BinaryNinja::Ref<FlowGraphHistoryEntry> entry);
void setNavigationTarget(View* target) { m_navigationTarget = target; }
virtual void clearRelatedHighlights() override;
virtual void setRelatedIndexHighlights(FunctionRef func, const std::set<size_t>& related) override;
virtual void setRelatedInstructionHighlights(FunctionRef func, const std::set<uint64_t>& related) override;
float getScale() const { return m_scale; }
float maxScale() const;
virtual void zoom(bool direction);
virtual void zoomToScale(float scale = 1.0f);
virtual void zoomToCursor();
virtual bool event(QEvent* event) override;
void disableZoom();
virtual void sendWheelEvent(QWheelEvent* event) override;
virtual bool canCopyWithTransform() override;
virtual bool canCut() override;
virtual bool canCopy() override;
virtual bool canCopyAddress() override;
virtual bool canPaste() override;
virtual void cut() override;
virtual void copy(TransformRef xform) override;
virtual void paste(TransformRef xform) override;
virtual bool canAssemble() override;
virtual bool canCompile() override;
virtual void closing() override;
virtual BinaryNinja::Ref<HistoryEntry> getHistoryEntry() override;
void populateDefaultHistoryEntry(FlowGraphHistoryEntry* entry);
virtual void navigateToHistoryEntry(BinaryNinja::Ref<HistoryEntry> entry) override;
virtual FunctionRef getCurrentFunction() override;
virtual BasicBlockRef getCurrentBasicBlock() override;
virtual ArchitectureRef getCurrentArchitecture() override;
virtual LowLevelILFunctionRef getCurrentLowLevelILFunction() override;
virtual MediumLevelILFunctionRef getCurrentMediumLevelILFunction() override;
virtual HighLevelILFunctionRef getCurrentHighLevelILFunction() override;
virtual size_t getCurrentILInstructionIndex() override;
virtual size_t getSelectionStartILInstructionIndex() override;
virtual BNILIndexRange getILIndexRange() override;
void scrollToCursor(bool center = false);
bool isUpdating();
QFont getFont() override { return m_render.getFont(); }
virtual HighlightTokenState getHighlightTokenState() override { return m_highlight; }
void paintMiniGraphAndViewport(QWidget* owner, QRect& miniRenderRect);
bool paintMiniGraph(QWidget* owner, QPainter& p, QRect& miniRenderRect);
void paintNode(QPainter& p, FlowGraphNodeRef& node, int minY, int maxY);
void paintHighlight(QPainter& p, const std::vector<BinaryNinja::DisassemblyTextLine>& lines, int nodeX,
int nodeWidth, int x, int y, size_t line, int tagIndent);
void paintEdge(QPainter& p, const FlowGraphNodeRef& node, const BinaryNinja::FlowGraphEdge& edge);
void showAddress(uint64_t addr, bool select = false, bool center = false);
void showIndex(size_t index, bool center = false);
void showTopNode();
void showNode(FlowGraphNodeRef node);
void showLineInNode(FlowGraphNodeRef node, size_t lineIndex);
void ensureCursorVisible();
void setInstructionHighlight(BNHighlightColor color);
void setBlockHighlight(BNHighlightColor color);
virtual bool goToReference(FunctionRef func, uint64_t source, uint64_t target) override;
void setHighlightToken(const HighlightTokenState& state, bool notify = true, bool update = false);
virtual void notifyUpdateInProgress(FunctionRef func);
virtual void onFunctionSelected(FunctionRef func);
virtual void onHighlightChanged(const HighlightTokenState& highlight);
// protected:
// These APIs are really supposed to be protected but since the bindings need to call them
// and they have out parameters (and thus need to be re-implemented) they must be public
bool getNodeForMouseEvent(QMouseEvent* event, FlowGraphNodeRef& node);
bool getLineForMouseEvent(QMouseEvent* event, CursorPosition& pos);
bool getEdgeForMouseEvent(QMouseEvent* event, FlowGraphNodeRef& source, BinaryNinja::FlowGraphEdge& edge, bool& incoming);
FlowGraphWidget* duplicate();
Q_SIGNALS:
void layoutComplete();
void updateMiniGraph();
private Q_SLOTS:
void loadingTimerEvent();
void hoverTimerEvent();
void zoomTimerEvent();
bool zoomDisabled();
void zoomPauseTimerEvent();
void goToAddress();
void goToEntryPoint();
void goToAddressAtFileOffset();
void followPointer();
void defineName();
void undefine();
void defineFuncName();
void editFunctionProperties();
void createFunc(const UIActionContext& context);
void createFuncWithPlatform(PlatformRef platform, bool autoSelect = false);
void changeType();
void inferStructureType(const UIActionContext& context);
void forwardPropagateType();
void inferFunctionType();
void propagateVariableTypeAndName();
void comment();
void addUserXref();
void functionComment();
void commentAccepted();
void functionCommentAccepted();
void bookmarkAddress();
void unbookmarkAddress();
void tagAddress();
void tagAddressAccepted(TagTypeRef tt, const QString& text);
void manageAddressTags();
void mergeVariables();
void mergeVariablesAtCurrentLocation();
void splitVariable();
void convertToNop();
void alwaysBranch();
void invertBranch();
void skipAndReturnZero();
void skipAndReturnValue();
void makePtr();
void makeString(size_t charSize = 1);
void reanalyze();
void setStackAdjustment();
void setCallTypeAdjustment();
void editInstruction();
void instrEditDoneEvent();
void setCurrentVariableDeadStoreElimination(BNDeadStoreElimination elimination);
void splitToNewTabAndNavigateFromCursorPosition();
void splitToNewWindowAndNavigateFromCursorPosition();
void splitToNewPaneAndNavigateFromCursorPosition();
};