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
277 lines (203 loc) · 7.66 KB
/
stackview.h
File metadata and controls
277 lines (203 loc) · 7.66 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
#pragma once
#include <QtWidgets/QAbstractScrollArea>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
#include <QtWidgets/QLineEdit>
#include "dockhandler.h"
#include "render.h"
#include "sidebar.h"
#include "uitypes.h"
#define STACK_VIEW_UPDATE_CHECK_INTERVAL 200
//! Dialog to enable arbitrary stack variable creation.
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.
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 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;
bool m_isReferenced;
bool m_isUnused;
BinaryNinja::DisassemblyTextLine m_content;
};
//! Simple direction enum; used for cursor movement functions.
enum class Direction
{
Up,
Down,
Left,
Right
};
//! The stack view!
class BINARYNINJAUIAPI StackView : public QAbstractScrollArea, public View
{
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;
//! 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;
protected:
void paintEvent(QPaintEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
public:
StackView(ViewFrame* view, BinaryViewRef data);
//! 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();
//! Override the default event handler so we can have nice tooltips.
bool event(QEvent* event) override;
BinaryViewRef getData() override;
uint64_t getCurrentOffset() override;
bool canCopyAddress() override { return false; };
bool canPaste() override { return false; };
void setSelectionOffsets(BNAddressRange range) override;
bool navigate(uint64_t offset) override;
QFont getFont() override;
void updateFonts() override;
};
//! Stack view sidebar widget wrapper.
class BINARYNINJAUIAPI StackViewSidebarWidget : public SidebarWidget
{
Q_OBJECT
StackView* m_stackView;
QWidget* m_header;
public:
StackViewSidebarWidget(ViewFrame* view, BinaryViewRef data);
void refresh();
void focus() override { refresh(); }
void notifyFontChanged() override { m_stackView->updateFonts(); }
QWidget* headerWidget() override { return m_header; }
};
class BINARYNINJAUIAPI StackViewSidebarWidgetType : public SidebarWidgetType
{
public:
StackViewSidebarWidgetType();
SidebarWidget* createWidget(ViewFrame* frame, BinaryViewRef data) override;
};