-
-
Notifications
You must be signed in to change notification settings - Fork 342
Expand file tree
/
Copy pathDebugger.h
More file actions
372 lines (327 loc) · 10.9 KB
/
Copy pathDebugger.h
File metadata and controls
372 lines (327 loc) · 10.9 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
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*
* Copyright (C) 2006 - 2025 Evan Teran <evan.teran@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef DEBUGGER_H_20090811_
#define DEBUGGER_H_20090811_
#include "DataViewInfo.h"
#include "IDebugEventHandler.h"
#include "OSTypes.h"
#include "QDisassemblyView.h"
#include "QHexView"
#include "TabWidget.h"
#include <QDockWidget>
#include <QMainWindow>
#include <QProcess>
#include <QSet>
#include <QVector>
#include <memory>
#include "ui_Debugger.h"
template <class T, class E>
class Result;
class CommentServer;
class DialogArguments;
class IBinary;
class IBreakpoint;
class IDebugEvent;
class IPlugin;
class IProcess;
class RecentFileManager;
class TabWidget;
struct Module;
class QDisassemblyView;
class QDockWidget;
class QDragEnterEvent;
class QDropEvent;
class QLabel;
class QListView;
class QMainWindow;
class QPlainTextEdit;
class QSplitter;
class QStringListModel;
class QTimer;
class QToolButton;
class Debugger : public QMainWindow, public IDebugEventHandler {
Q_OBJECT
public:
explicit Debugger(QWidget *parent = nullptr);
Debugger(const Debugger &) = delete;
Debugger &operator=(const Debugger &) = delete;
~Debugger() override;
private:
enum class ResumeFlag {
None = 0,
Forced = 1,
};
enum DebugMode {
Step,
Trace,
Run
};
enum ExceptionResume {
IgnoreException,
PassException
};
enum DetachAction {
NoKillOnDetach,
KillOnDetach
};
enum GuiState {
Paused,
Running,
Terminated
};
public:
[[nodiscard]] int currentTab() const;
[[nodiscard]] QLabel *statusLabel() const;
[[nodiscard]] Register activeRegister() const;
[[nodiscard]] std::shared_ptr<DataViewInfo> currentDataViewInfo() const;
bool dumpData(edb::address_t address, bool new_tab);
bool dumpDataRange(edb::address_t address, edb::address_t end_address, bool new_tab);
bool dumpStack(edb::address_t address, bool scroll_to);
bool jumpToAddress(edb::address_t address);
void attach(edb::pid_t pid);
void clearData(const std::shared_ptr<DataViewInfo> &v);
void execute(const QString &program, const QList<QByteArray> &args, const QString &input, const QString &output);
void refreshUi();
void updateData(const std::shared_ptr<DataViewInfo> &v);
void updateUi();
Q_SIGNALS:
void uiUpdated();
// TODO(eteran): maybe this is better off as a single event
// with a type passed?
void debugEvent();
void detachEvent();
void attachEvent();
public Q_SLOTS:
// the auto-connected slots
void on_actionAbout_QT_triggered();
void on_actionApplication_Arguments_triggered();
void on_actionApplication_Working_Directory_triggered();
void on_actionRun_Until_Return_triggered();
void on_actionStep_Out_triggered();
void on_action_About_triggered();
void on_action_Attach_triggered();
void on_action_Configure_Debugger_triggered();
void on_action_Detach_triggered();
void on_action_Help_triggered();
void on_action_Kill_triggered();
void on_action_Memory_Regions_triggered();
void on_action_Open_triggered();
void on_action_Pause_triggered();
void on_action_Plugins_triggered();
void on_action_Restart_triggered();
void on_action_Run_Pass_Signal_To_Application_triggered();
void on_action_Run_triggered();
void on_action_Step_Into_Pass_Signal_To_Application_triggered();
void on_action_Step_Into_triggered();
void on_action_Step_Over_Pass_Signal_To_Application_triggered();
void on_action_Step_Over_triggered();
void on_action_Threads_triggered();
void on_action_Breakpoints_triggered();
void on_action_Reset_UI_triggered();
private:
void toggleFlag(int);
void runToThisLine(ExceptionResume pass_signal);
private Q_SLOTS:
// the manually connected general slots
void mnuModifyBytes();
private Q_SLOTS:
// the manually connected CPU slots
void mnuCPUEditComment();
void mnuCPURemoveComment();
void mnuCPURunToThisLine();
void mnuCPURunToThisLinePassSignal();
void mnuCPUToggleBreakpoint() const;
void mnuCPUAddConditionalBreakpoint();
void mnuCPUFillNop();
void mnuCPUFillZero();
void mnuCPUFollow();
void mnuCPUFollowInDump();
void mnuCPUFollowInStack();
void mnuCPUJumpToAddress();
void mnuCPUJumpToEIP();
void mnuCPUModify() const;
void mnuCPURemoveBreakpoint() const;
void mnuCPUSetEIP();
void mnuCPULabelAddress();
void breakPointToggled_triggered(edb::address_t);
void customContextMenuRequested_triggered(const QPoint &);
private Q_SLOTS:
// the manually connected Register slots
QList<QAction *> currentRegisterContextMenuItems() const;
void mnuRegisterFollowInDump() { followRegisterInDump(false); }
void mnuRegisterFollowInDumpNewTab() { followRegisterInDump(true); }
void mnuRegisterFollowInStack();
private Q_SLOTS:
// the manually connected Dump slots
void mnuDumpContextMenu(const QPoint &pos);
void mnuDumpCreateTab();
void mnuDumpDeleteTab();
void mnuDumpFollowInCPU();
void mnuDumpFollowInDump();
void mnuDumpFollowInStack();
void mnuDumpGotoAddress();
void mnuDumpModify();
void mnuDumpSaveToFile();
private Q_SLOTS:
// the manually connected Stack slots
void mnuStackContextMenu(const QPoint &);
void mnuStackFollowInCPU();
void mnuStackFollowInDump();
void mnuStackFollowInStack();
void mnuStackGotoAddress();
void mnuStackGotoEBP();
void mnuStackGotoESP();
void mnuStackModify();
void mnuStackPop();
void mnuStackPush();
void mnuStackToggleLock(bool locked);
private Q_SLOTS:
void gotoTriggered();
void nextDebugEvent();
void openFile(const QString &filename, const QList<QByteArray> &args);
void tabContextMenu(int index, const QPoint &pos);
void ttyProcFinished(int exit_code, QProcess::ExitStatus exit_status);
private:
void closeEvent(QCloseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
void showEvent(QShowEvent *event) override;
public:
edb::EventStatus handleEvent(const std::shared_ptr<IDebugEvent> &event) override;
private:
QString createTty();
[[nodiscard]] QString sessionFilename() const;
Result<edb::address_t, QString> getGotoExpression();
[[nodiscard]] Result<edb::reg_t, QString> getFollowRegister() const;
bool commonOpen(const QString &s, const QList<QByteArray> &args, const QString &input, const QString &output);
bool isBreakpointConditionTrue(const QString &condition);
edb::EventStatus handleEventExited(const std::shared_ptr<IDebugEvent> &event);
edb::EventStatus handleEventStopped(const std::shared_ptr<IDebugEvent> &event);
edb::EventStatus handleEventTerminated(const std::shared_ptr<IDebugEvent> &event);
edb::EventStatus handleTrap(const std::shared_ptr<IDebugEvent> &event);
edb::EventStatus resumeStatus(bool pass_exception);
std::shared_ptr<IRegion> updateCpuView(const State &state);
void applyDefaultFonts();
void applyDefaultShowSeparator();
void attachComplete();
void cleanupDebugger();
void cpuFill(uint8_t byte);
void createDataTab();
void deleteDataTab();
void detachFromProcess(DetachAction kill);
void doJumpToAddress(edb::address_t address, const std::shared_ptr<IRegion> &r, bool scroll_to) const;
void finishPluginSetup();
void followRegisterInDump(bool tabbed);
void resumeExecution(ExceptionResume pass_exception, DebugMode mode, ResumeFlag flags);
void setDebuggerCaption(const QString &appname);
void setInitialBreakpoint(const QString &s);
void setInitialDebuggerState();
void setupDataViews();
void setupStackView();
void setupTabButtons();
void setupUi();
void testNativeBinary();
void updateDataViews();
void updateDisassembly(edb::address_t address, const std::shared_ptr<IRegion> &r);
void updateMenuState(GuiState state);
void updateStackView(const State &state);
void updateTabCaption(const std::shared_ptr<QHexView> &view, edb::address_t start, edb::address_t end) const;
void setLibraryLoadHook();
private:
template <class F>
QAction *createAction(const QString &text, const QKeySequence &keySequence, F func);
template <class F>
void followMemory(edb::address_t address, F follow_func);
template <class Ptr>
Result<edb::address_t, QString> getFollowAddress(const Ptr &hexview);
template <class F>
QList<QAction *> getPluginContextMenuItems(const F &f) const;
template <class F, class T>
void addPluginContextMenu(const T &menu, const F &f);
template <class Ptr>
void followInCpu(const Ptr &hexview);
template <class Ptr>
void followInDump(const Ptr &hexview);
template <class Ptr>
void followInStack(const Ptr &hexview);
template <class Ptr>
void modifyBytes(const Ptr &hexview);
template <class F1, class F2>
void stepOver(F1 run_func, F2 step_func);
template <class Addr>
void handle_library_event(IProcess *process, [[maybe_unused]] edb::address_t debug_pointer);
public:
Ui::Debugger ui;
QDisassemblyView *cpuView_ = nullptr;
QListView *listView_ = nullptr;
QDockWidget *dataDock_ = nullptr;
QDockWidget *stackDock_ = nullptr;
TabWidget *tabWidget_ = nullptr;
QMainWindow *mainWindow_ = nullptr;
QPlainTextEdit *logger_ = nullptr;
QSplitter *splitter_ = nullptr;
private:
GuiState guiState_ = Terminated;
QProcess *ttyProc_ = nullptr;
DialogArguments *argumentsDialog_ = nullptr;
QLabel *status_ = nullptr;
QStringListModel *listModel_ = nullptr;
QTimer *timer_ = nullptr;
QToolButton *tabCreate_ = nullptr;
QToolButton *tabDelete_ = nullptr;
RecentFileManager *recentFileManager_ = nullptr;
bool stackViewLocked_ = false;
bool ui_reset_ = false;
#if defined(Q_OS_LINUX)
edb::address_t debugPointer_ = 0;
QSet<Module> loadedModules_;
#endif
private:
DataViewInfo stackViewInfo_;
QString lastOpenDirectory_;
QString programExecutable_;
QString ttyFile_;
QString workingDirectory_;
QVector<std::shared_ptr<DataViewInfo>> dataRegions_;
std::shared_ptr<IBreakpoint> reenableBreakpointRun_;
std::shared_ptr<IBreakpoint> reenableBreakpointStep_;
std::shared_ptr<CommentServer> commentServer_;
std::shared_ptr<QHexView> stackView_;
std::shared_ptr<const IDebugEvent> lastEvent_;
std::unique_ptr<IBinary> binaryInfo_;
QPointer<QDialog> breakpointDialog_;
private:
QAction *gotoAddressAction_;
QAction *editCommentAction_;
QAction *editBytesAction_;
QAction *toggleBreakpointAction_;
QAction *conditionalBreakpointAction_;
QAction *runToThisLineAction_;
QAction *runToLinePassAction_;
QAction *fillWithZerosAction_;
QAction *fillWithNOPsAction_;
QAction *setAddressLabelAction_;
QAction *followConstantInDumpAction_;
QAction *followConstantInStackAction_;
QAction *followAction_;
QAction *setRIPAction_;
QAction *gotoRIPAction_;
QAction *dumpFollowInCPUAction_;
QAction *dumpFollowInDumpAction_;
QAction *dumpFollowInStackAction_;
QAction *dumpSaveToFileAction_;
QAction *registerFollowInDumpAction_;
QAction *registerFollowInDumpTabAction_;
QAction *registerFollowInStackAction_;
QAction *stackFollowInCPUAction_;
QAction *stackFollowInDumpAction_;
QAction *stackFollowInStackAction_;
QAction *stackGotoRSPAction_;
QAction *stackGotoRBPAction_;
QAction *stackPushAction_;
QAction *stackPopAction_;
};
#endif