forked from Vector35/binaryninja-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstackview.h
More file actions
354 lines (258 loc) · 9.79 KB
/
stackview.h
File metadata and controls
354 lines (258 loc) · 9.79 KB
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
#pragma once
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
#include <QtWidgets/QLineEdit>
#include <optional>
#include "render.h"
#include "sidebar.h"
#include "uitypes.h"
#define STACK_VIEW_UPDATE_CHECK_INTERVAL 200
/*!
\defgroup stackview StackView
\ingroup uiapi
*/
/*! Dialog to enable arbitrary stack variable creation.
\ingroup stackview
*/
class BINARYNINJAUIAPI CreateStackVariableDialog : public QDialog
{
Q_OBJECT
BinaryViewRef m_data;
FunctionRef m_func;
QLineEdit* m_offsetField;
QLineEdit* m_nameField;
QComboBox* m_typeDropdown;
//! Automatically update/sanitize the offset and name fields after input.
void autoFillFields();
protected:
void accept() override;
public:
CreateStackVariableDialog(QWidget* parent, BinaryViewRef data, FunctionRef func, int64_t initialOffset = 0);
};
/*! A single line in the stack view.
\ingroup stackview
*/
class StackViewLine
{
public:
enum class Type
{
Variable,
Member,
OffsetRef,
Annotation,
Fill
};
//! Create a new line for a variable.
static StackViewLine variable(int64_t offset, const BinaryNinja::VariableNameAndType& vnat, PlatformRef plat);
//! Create a new line for a struct or array member.
static StackViewLine member(int64_t offset, const BinaryNinja::VariableNameAndType& vnat, PlatformRef plat);
//! Create a new line for a struct offset reference.
static StackViewLine offsetRef(int64_t base, uint64_t offset, size_t size);
//! Create a new annotation line.
static StackViewLine annotation(int64_t offset, const std::string& text);
//! Create a new fill line.
static StackViewLine fill(int64_t offset, size_t length);
//! Get this line's type.
StackViewLine::Type type() const;
//! Get the stack frame offset for this line.
int64_t offset() const;
//! Get the value of the base offset
int64_t baseOffset() const;
//! Get the name of the base offset
std::string baseName() const;
//! Set the base offset to a given name and value. Does not affect offset()
void setBase(const std::string& baseName, int64_t baseOffset);
//! Get the number of bytes this line represents on the stack.
size_t width() const;
//! Get the hierarchical level of this line.
size_t level() const;
//! Set the hierarchical level for this line.
void setLevel(size_t level);
//! Get the type of the data this line represents.
TypeRef dataType() const;
//! Set the type of the data this line represents. Does not affect the underlying variable.
void setDataType(TypeRef vnat);
//! Get the variable represented by this line.
BinaryNinja::Variable variable() const;
//! Set the variable represented by this line.
void setVariable(const BinaryNinja::Variable& var);
//! Set a width override for this line.
void setWidthOverride(size_t width);
//! Is this line backed by data or is it ephermeral?
bool isDataBacked() const;
//! Is the data represented by this line referenced in the current function?
bool isReferenced() const;
//! Set whether the data represented by this line is referenced in the current function.
void setIsReferenced(bool isReferenced);
//! Is the data represented by this line unused in the current function?
bool isUnused() const;
//! Set whether the data represented by this line unused in the current function.
void setIsUnused(bool isUnused);
//! Get the content (with no offset) for this line.
BinaryNinja::DisassemblyTextLine content() const;
//! Get the content with the leading offset (or padding) for this line.
BinaryNinja::DisassemblyTextLine contentWithOffset(bool hide = false) const;
//! Get the width of the total line content in characters.
size_t contentWidth(bool withOffset = true) const;
//! Append a single token to this line's content.
void appendToken(const BinaryNinja::InstructionTextToken& token);
//! Append multiple tokens to this line's content.
void appendTokens(const std::vector<BinaryNinja::InstructionTextToken>& tokens);
//! Indent this line's content.
void indent(size_t levels = 1);
private:
StackViewLine(StackViewLine::Type type, int64_t offset);
StackViewLine::Type m_type;
int64_t m_offset;
size_t m_level;
TypeRef m_dataType;
BinaryNinja::Variable m_var;
size_t m_widthOverride;
std::string m_baseName;
int64_t m_baseOffset;
bool m_isReferenced;
bool m_isUnused;
BinaryNinja::DisassemblyTextLine m_content;
};
/*! Simple direction enum; used for cursor movement functions.
\ingroup stackview
*/
enum class Direction
{
Up,
Down,
Left,
Right
};
/*! The Stack View
\ingroup stackview
*/
class BINARYNINJAUIAPI StackView : public QAbstractScrollArea, public View, public UIContextNotification
{
Q_OBJECT
ViewFrame* m_view;
BinaryViewRef m_data;
FunctionRef m_func;
BinaryNinja::AdvancedFunctionAnalysisDataRequestor m_analysisRequestor;
RenderContext m_renderer;
std::vector<StackViewLine> m_lines;
HighlightTokenState m_highlight;
size_t m_lineIndex;
size_t m_tokenIndex;
bool m_needFirstFocus;
bool m_positionAware;
// Selection state
size_t m_selectionStartLine;
size_t m_selectionStartToken;
bool m_hasSelection;
bool m_isDragging;
//! Bind and register all stack view actions.
void setupActions();
//! Internal refresh method, rebuilds all lines.
void rebuildLines();
//! Refresh the internal highlight token state.
//!
//! \param shouldUpdateStatus Should UIContext::updateStatus() be called?
void refreshHighlight(bool shouldUpdateStatus = true);
//! Find the end of a stack void given a start offset.
int64_t findVoidEnd(int64_t start) const;
//! Get the beginning of the current selection (min position)
void getSelectionRange(size_t& startLine, size_t& startToken, size_t& endLine, size_t& endToken) const;
protected:
void paintEvent(QPaintEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
public:
StackView(ViewFrame* view, BinaryViewRef data);
~StackView();
//! Refresh the stack view's content.
void refresh();
//! Move the cursor to approximate clicked position.
void moveCursorToMouse(QMouseEvent* event, bool isSelecting);
//! Ensure the cursor is visible by adjusting the scroll position.
void ensureCursorIsVisible();
//! Move the cursor via the keyboard.
void moveCursor(Direction dir);
//! Ensure the cursor is not selecting any prohibited tokens.
void sanitizeCursor(Direction preference);
//! Get the selected StackViewLine.
const StackViewLine* selectedLine() const;
//! Rename the variable belonging to the selected line.
void renameVariable();
//! Change the type of the variable belonging to the selected line.
void retypeVariable();
//! Undefine the variable belonging to the selected line.
void undefineVariable();
//! Show the "Create Variable" dialog.
void showCreateVariableDialog();
//! Create an integer of the given size at the cursor position. Pass `0`
//! for `size` to cycle through integer sizes automatically.
void quickCreateIntegerAtCursor(size_t size);
//! Toggle the sign of the integer at the cursor position.
void quickInvertIntegerSignAtCursor();
//! Create an float of the given size at the cursor position. Pass `0`
//! for `size` to cycle through float sizes automatically.
void quickCreateFloatAtCursor(size_t size);
//! Create a pointer the cursor.
void quickCreatePointerAtCursor();
//! Create an array at the cursor, spanning until the next stack variable.
void quickCreateArrayAtCursor();
//! Create a new struct at the cursor, spanning until the next stack variable.
void quickCreateStructAtCursor();
//! Show the dialog to switch which base register is used for offsets
void chooseBaseRegister();
//! Show the dialog to pick a constant base offset
void chooseBaseOffset();
//! Set the base offset to a register (or clear on nullopt)
void setBaseRegister(ArchitectureRef arch, std::optional<std::string> regName);
//! Get the base offset
int64_t getBaseOffset(FunctionRef func);
//! Set the base offset to a constant (or clear on nullopt)
void setBaseOffset(FunctionRef func, std::optional<int64_t> offset);
//! Set whether we show only the vars relevant for the current address
void setPositionAware(bool positionAware);
//! Override the default event handler so we can have nice tooltips.
bool event(QEvent* event) override;
//! Get the current base name/offset using the currently selected base register
std::pair<std::string, int64_t> calculateBaseOffset() const;
BinaryViewRef getData() override;
uint64_t getCurrentOffset() override;
bool canCopy() override { return selectedLine() != nullptr; }
bool canCopyAddress() override { return false; };
bool canPaste() override { return false; };
void copy(TransformRef xform = nullptr) override;
void setSelectionOffsets(BNAddressRange range) override;
bool navigate(uint64_t offset) override;
QFont getFont() override;
void updateFonts() override;
virtual void OnNewSelectionForXref(UIContext* context, ViewFrame* frame, View* view, const SelectionInfoForXref& selection) override;
};
/*! Stack view sidebar widget wrapper.
\ingroup stackview
*/
class BINARYNINJAUIAPI StackViewSidebarWidget : public SidebarWidget
{
Q_OBJECT
QWidget* m_header;
StackView* m_stackView;
public:
StackViewSidebarWidget(ViewFrame* view, BinaryViewRef data);
QWidget* headerWidget() override { return m_header; }
void refresh();
void focus() override { refresh(); }
void notifyFontChanged() override { m_stackView->updateFonts(); }
};
/*!
\ingroup stackview
*/
class BINARYNINJAUIAPI StackViewSidebarWidgetType : public SidebarWidgetType
{
public:
StackViewSidebarWidgetType();
SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override;
virtual SidebarWidgetLocation defaultLocation() const override { return SidebarWidgetLocation::RightContent; }
};