Changeset View
Changeset View
Standalone View
Standalone View
debuggers/common/midebugsession.h
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Common code for debugger support | ||||
3 | * | ||||
4 | * Copyright 1999-2001 John Birch <jbb@kdevelop.org> | ||||
5 | * Copyright 2001 by Bernd Gehrmann <bernd@kdevelop.org> | ||||
6 | * Copyright 2007 Hamish Rodda <rodda@kde.org> | ||||
7 | * Copyright 2009 Niko Sams <niko.sams@gmail.com> | ||||
8 | * Copyright 2016 Aetf <aetf@unlimitedcodeworks.xyz> | ||||
9 | * | ||||
10 | * This program is free software; you can redistribute it and/or | ||||
11 | * modify it under the terms of the GNU General Public License as | ||||
12 | * published by the Free Software Foundation; either version 2 of | ||||
13 | * the License or (at your option) version 3 or any later version | ||||
14 | * accepted by the membership of KDE e.V. (or its successor approved | ||||
15 | * by the membership of KDE e.V.), which shall act as a proxy | ||||
16 | * defined in Section 14 of version 3 of the license. | ||||
17 | * | ||||
18 | * This program is distributed in the hope that it will be useful, | ||||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
21 | * GNU General Public License for more details. | ||||
22 | * | ||||
23 | * You should have received a copy of the GNU General Public License | ||||
24 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
25 | * | ||||
26 | */ | ||||
27 | | ||||
28 | #ifndef MIDEBUGSESSION_H | ||||
29 | #define MIDEBUGSESSION_H | ||||
30 | | ||||
31 | #include <debugger/interfaces/idebugsession.h> | ||||
32 | | ||||
33 | #include "dbgglobal.h" | ||||
34 | #include "mibreakpointcontroller.h" | ||||
35 | #include "mi/mi.h" | ||||
36 | | ||||
37 | #include <memory> | ||||
38 | | ||||
39 | class IExecutePlugin; | ||||
40 | namespace KDevelop { | ||||
41 | class ILaunchConfiguration; | ||||
42 | class ProcessLineMaker; | ||||
43 | } | ||||
44 | | ||||
45 | namespace KDevMI { | ||||
46 | | ||||
47 | namespace MI { | ||||
48 | class CommandQueue; | ||||
49 | class MICommand; | ||||
50 | } | ||||
51 | | ||||
52 | class MIDebugger; | ||||
53 | class STTY; | ||||
54 | class MIDebugSession : public KDevelop::IDebugSession | ||||
55 | { | ||||
56 | Q_OBJECT | ||||
57 | public: | ||||
58 | MIDebugSession(); | ||||
59 | ~MIDebugSession() override; | ||||
60 | | ||||
61 | Q_SIGNALS: | ||||
62 | /** | ||||
63 | * Emits when received standard output lines from inferior | ||||
64 | */ | ||||
65 | void inferiorStdoutLines(const QStringList &lines); | ||||
66 | | ||||
67 | /** | ||||
68 | * Emits when received standard error lines from inferior | ||||
69 | */ | ||||
70 | void inferiorStderrLines(const QStringList &lines); | ||||
71 | | ||||
72 | void inferiorStopped(const MI::AsyncRecord &r); | ||||
73 | | ||||
74 | void inferiorRunning(); | ||||
75 | | ||||
76 | /** | ||||
77 | * Emits when received standard output from debugger for user commands | ||||
78 | */ | ||||
79 | void debuggerUserCommandOutput(const QString &output); | ||||
80 | | ||||
81 | /** | ||||
82 | * Emits when received standard output from debugger for internal commands | ||||
83 | */ | ||||
84 | void debuggerInternalCommandOutput(const QString &output); | ||||
85 | | ||||
86 | /** | ||||
87 | * Emits when received standard output from inferior's tty | ||||
88 | */ | ||||
89 | void inferiorTtyStdout(const QByteArray &output); | ||||
90 | | ||||
91 | /** | ||||
92 | * Emits when received standard output from inferior's tty | ||||
93 | */ | ||||
94 | void inferiorTtyStderr(const QByteArray &output); | ||||
95 | | ||||
96 | /** | ||||
97 | * Emits when the debugger instance state changes | ||||
98 | */ | ||||
99 | void debuggerStateChanged(DBGStateFlags oldState, DBGStateFlags newState); | ||||
100 | | ||||
101 | /** | ||||
102 | * Emits when there's message needed to be show to user. | ||||
103 | */ | ||||
104 | void showMessage(const QString& message, int timeout); | ||||
105 | | ||||
106 | /** | ||||
107 | * Emits when the debugger console view need to be raised. | ||||
108 | */ | ||||
109 | void raiseDebuggerConsoleViews(); | ||||
110 | | ||||
111 | /** | ||||
112 | * Emits when need to reset | ||||
113 | */ | ||||
114 | void reset(); | ||||
115 | | ||||
116 | public: | ||||
117 | bool debuggerStateIsOn(DBGStateFlags state) const; | ||||
118 | DBGStateFlags debuggerState() const; | ||||
119 | | ||||
120 | bool hasCrashed() const; | ||||
121 | | ||||
122 | // BEGIN IDebugSession overrides | ||||
123 | public: | ||||
124 | DebuggerState state() const override; | ||||
125 | bool restartAvaliable() const override; | ||||
126 | | ||||
127 | MIBreakpointController * breakpointController() const override = 0; | ||||
128 | | ||||
129 | public Q_SLOTS: | ||||
130 | void restartDebugger() override; | ||||
131 | void stopDebugger() override; | ||||
132 | void interruptDebugger() override; | ||||
133 | void run() override; | ||||
134 | void runToCursor() override; | ||||
135 | void jumpToCursor() override; | ||||
136 | void stepOver() override; | ||||
137 | void stepIntoInstruction() override; | ||||
138 | void stepInto() override; | ||||
139 | void stepOverInstruction() override; | ||||
140 | void stepOut() override; | ||||
141 | // END IDebugSession overrides | ||||
142 | | ||||
143 | public Q_SLOTS: | ||||
144 | /** | ||||
145 | * Run currently executing program to the given \a url and \a line. | ||||
146 | */ | ||||
147 | void runUntil(const QUrl& url, int line); | ||||
148 | | ||||
149 | /** | ||||
150 | * Run currently executing program to the given \a address | ||||
151 | */ | ||||
152 | void runUntil(const QString& address); | ||||
153 | | ||||
154 | /** | ||||
155 | * Move the execution point of the currently executing program to the given \a url and \a line. | ||||
156 | */ | ||||
157 | void jumpTo(const QUrl& url, int line); | ||||
158 | | ||||
159 | /** | ||||
160 | * Move the execution point of the currently executing program to the given \a address. | ||||
161 | *Note: It can be really very dangerous, so use jumpTo instead. | ||||
162 | */ | ||||
163 | void jumpToMemoryAddress(const QString& address); | ||||
164 | | ||||
165 | /** | ||||
166 | * Start the debugger, and execute the inferior program specified by \a cfg. | ||||
167 | */ | ||||
168 | bool startDebugging(KDevelop::ILaunchConfiguration *cfg, IExecutePlugin *iexec); | ||||
169 | | ||||
170 | /** | ||||
171 | * Start the debugger, and examine the core file given by \a coreFile. | ||||
172 | */ | ||||
173 | bool examineCoreFile(const QUrl &debugee, const QUrl &coreFile); | ||||
174 | | ||||
175 | /** | ||||
176 | * Start the debugger, and attach to a currently running process with the given \a pid. | ||||
177 | */ | ||||
178 | bool attachToProcess(int pid); | ||||
179 | | ||||
180 | /** Adds a command to the end of queue of commands to be executed | ||||
181 | by gdb. The command will be actually sent to gdb only when | ||||
182 | replies from all previous commands are received and full processed. | ||||
183 | | ||||
184 | The literal command sent to gdb is obtained by calling | ||||
185 | cmd->cmdToSend. The call is made immediately before sending the | ||||
186 | command, so it's possible to use results of prior commands when | ||||
187 | computing the exact command to send. | ||||
188 | */ | ||||
189 | void addCommand(MI::MICommand* cmd); | ||||
190 | | ||||
191 | /** Same as above, but internally constructs new MI::MICommand | ||||
192 | instance from the string. */ | ||||
193 | void addCommand(MI::CommandType type, const QString& cmd = QString()); | ||||
194 | | ||||
195 | void addUserCommand(const QString &cmd); | ||||
196 | | ||||
197 | protected Q_SLOTS: | ||||
198 | virtual void slotDebuggerReady(); | ||||
199 | virtual void slotDebuggerExited(bool abnormal, const QString &msg); | ||||
200 | virtual void slotInferiorStopped(const MI::AsyncRecord &r); | ||||
201 | /** | ||||
202 | * Triggered every time program begins/continues it's execution. | ||||
203 | */ | ||||
204 | virtual void slotInferiorRunning(); | ||||
205 | | ||||
206 | /** | ||||
207 | * Handle MI async notifications. | ||||
208 | */ | ||||
209 | virtual void processNotification(const MI::AsyncRecord &n); | ||||
210 | | ||||
211 | /** Default handler for errors. | ||||
212 | Tries to guess is the error message is telling that target is | ||||
213 | gone, if so, informs the user. | ||||
214 | Otherwise, shows a dialog box and reloads view state. */ | ||||
215 | virtual void defaultErrorHandler(const MI::ResultRecord &result); | ||||
216 | | ||||
217 | /** | ||||
218 | * Update session state when debugger state changes, and show messages | ||||
219 | */ | ||||
220 | virtual void handleDebuggerStateChange(DBGStateFlags oldState, DBGStateFlags newState); | ||||
221 | | ||||
222 | void handleNoInferior(const QString &msg); | ||||
223 | void handleInferiorFinished(const QString &msg); | ||||
224 | | ||||
225 | protected: | ||||
226 | void queueCmd(MI::MICommand *cmd); | ||||
227 | | ||||
228 | /** Try to execute next command in the queue. If GDB is not | ||||
229 | busy with previous command, and there's a command in the | ||||
230 | queue, sends it. */ | ||||
231 | void executeCmd(); | ||||
232 | void ensureDebuggerListening(); | ||||
233 | void destroyCmds(); | ||||
234 | | ||||
235 | /** | ||||
236 | * Start the debugger instance | ||||
237 | */ | ||||
238 | bool startDebugger(KDevelop::ILaunchConfiguration *cfg); | ||||
239 | | ||||
240 | /** | ||||
241 | * MIDebugSession takes the ownership of the created instance. | ||||
242 | */ | ||||
243 | virtual MIDebugger *createDebugger() const = 0; | ||||
244 | | ||||
245 | /** | ||||
246 | * Initialize debugger and set default configurations. | ||||
247 | */ | ||||
248 | virtual void initializeDebugger() = 0; | ||||
249 | | ||||
250 | /** | ||||
251 | * Further config the debugger and start the inferior program (either local or remote). | ||||
252 | */ | ||||
253 | virtual bool execInferior(KDevelop::ILaunchConfiguration *cfg, const QString &executable) = 0; | ||||
254 | | ||||
255 | /** | ||||
256 | * Manipulate debugger instance state | ||||
257 | */ | ||||
258 | void setDebuggerStateOn(DBGStateFlags stateOn); | ||||
259 | void setDebuggerStateOff(DBGStateFlags stateOff); | ||||
260 | void setDebuggerState(DBGStateFlags newState); | ||||
261 | | ||||
262 | void debuggerStateChange(DBGStateFlags oldState, DBGStateFlags newState); | ||||
263 | | ||||
264 | /** | ||||
265 | * Manipulate the session state | ||||
266 | */ | ||||
267 | void setSessionState(DebuggerState state); | ||||
268 | | ||||
269 | void raiseEvent(event_t e) override; | ||||
270 | | ||||
271 | /** Called when there are no pending commands and 'm_stateReloadNeeded' | ||||
272 | is true. Also can be used to immediately reload program state. | ||||
273 | Issues commands to completely reload all program state shown | ||||
274 | to the user. | ||||
275 | */ | ||||
276 | void reloadProgramState(); | ||||
277 | | ||||
278 | void programNoApp(const QString &msg); | ||||
279 | void programFinished(const QString &msg); | ||||
280 | | ||||
281 | // FIXME: Whether let the debugger source init files when starting, | ||||
282 | // only used in unit test currently, potentially could be made a user | ||||
283 | // configurable option | ||||
284 | void setSourceInitFile(bool enable); | ||||
285 | | ||||
286 | private Q_SLOTS: | ||||
287 | void handleTargetAttach(const MI::ResultRecord& r); | ||||
288 | void handleCoreFile(const MI::ResultRecord& r); | ||||
289 | // Pops up a dialog box with some hopefully | ||||
290 | // detailed information about which state debugger | ||||
291 | // is in, which commands were sent and so on. | ||||
292 | void explainDebuggerStatus(); | ||||
293 | | ||||
294 | protected: | ||||
295 | KDevelop::ProcessLineMaker *m_procLineMaker; | ||||
296 | | ||||
297 | std::unique_ptr<MI::CommandQueue> m_commandQueue; | ||||
298 | | ||||
299 | // Though the misleading class name, this is the session level state. | ||||
300 | // see m_debuggerState for debugger instance state | ||||
301 | DebuggerState m_sessionState; | ||||
302 | | ||||
303 | MIDebugger *m_debugger; | ||||
304 | DBGStateFlags m_debuggerState; | ||||
305 | | ||||
306 | bool m_stateReloadInProgress; | ||||
307 | bool m_stateReloadNeeded; | ||||
308 | | ||||
309 | std::unique_ptr<STTY> m_tty; | ||||
310 | | ||||
311 | bool m_hasCrashed; | ||||
312 | bool m_sourceInitFile; | ||||
313 | }; | ||||
314 | | ||||
315 | } // end of namespace KDevMI | ||||
316 | | ||||
317 | #endif // MIDEBUGSESSION_H |