File indexing completed on 2024-04-28 04:38:35
0001 /* 0002 SPDX-FileCopyrightText: 1999-2001 John Birch <jbb@kdevelop.org> 0003 SPDX-FileCopyrightText: 2001 Bernd Gehrmann <bernd@kdevelop.org> 0004 SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org> 0005 SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com> 0006 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 0007 0008 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0009 */ 0010 0011 #ifndef MIDEBUGSESSION_H 0012 #define MIDEBUGSESSION_H 0013 0014 #include <debugger/interfaces/idebugsession.h> 0015 0016 #include "dbgglobal.h" 0017 #include "mibreakpointcontroller.h" 0018 #include "mi/mi.h" 0019 #include "mi/micommand.h" 0020 0021 #include <QMap> 0022 #include <QPointer> 0023 0024 #include <memory> 0025 0026 class IExecutePlugin; 0027 namespace KDevelop { 0028 class ILaunchConfiguration; 0029 class ProcessLineMaker; 0030 } 0031 0032 namespace KDevMI { 0033 0034 namespace MI { 0035 class CommandQueue; 0036 } 0037 0038 class MIDebugger; 0039 class MIDebuggerPlugin; 0040 class MIVariable; 0041 class STTY; 0042 class MIDebugSession : public KDevelop::IDebugSession 0043 { 0044 Q_OBJECT 0045 public: 0046 explicit MIDebugSession(MIDebuggerPlugin *plugin = nullptr); 0047 ~MIDebugSession() override; 0048 0049 Q_SIGNALS: 0050 /** 0051 * Emits when received standard output lines from inferior 0052 */ 0053 void inferiorStdoutLines(const QStringList& lines); 0054 0055 /** 0056 * Emits when received standard error lines from inferior 0057 */ 0058 void inferiorStderrLines(const QStringList& lines); 0059 0060 void inferiorStopped(const MI::AsyncRecord& r); 0061 0062 void inferiorRunning(); 0063 0064 /** 0065 * Emits when received standard output from debugger for user commands 0066 */ 0067 void debuggerUserCommandOutput(const QString &output); 0068 0069 /** 0070 * Emits when received standard output from debugger for internal commands 0071 */ 0072 void debuggerInternalCommandOutput(const QString& output); 0073 0074 /** 0075 * Emits when received internal output from debugger 0076 */ 0077 void debuggerInternalOutput(const QString& output) const; 0078 0079 /** 0080 * Emits when received standard output from inferior's tty 0081 */ 0082 void inferiorTtyStdout(const QByteArray& output); 0083 0084 /** 0085 * Emits when received standard output from inferior's tty 0086 */ 0087 void inferiorTtyStderr(const QByteArray& output); 0088 0089 /** 0090 * Emits when the debugger instance state changes 0091 */ 0092 void debuggerStateChanged(DBGStateFlags oldState, DBGStateFlags newState); 0093 0094 /** 0095 * Emits when there's message needed to be show to user. 0096 */ 0097 void showMessage(const QString& message, int timeout); 0098 0099 /** 0100 * Emits when the debugger console view need to be raised. 0101 */ 0102 void raiseDebuggerConsoleViews(); 0103 0104 /** 0105 * Emits when need to reset 0106 */ 0107 void reset(); 0108 0109 public: 0110 bool debuggerStateIsOn(DBGStateFlags state) const; 0111 DBGStateFlags debuggerState() const; 0112 0113 bool hasCrashed() const; 0114 0115 // BEGIN IDebugSession overrides 0116 public: 0117 DebuggerState state() const override; 0118 bool restartAvaliable() const override; 0119 0120 MIBreakpointController * breakpointController() const override = 0; 0121 0122 public Q_SLOTS: 0123 void restartDebugger() override; 0124 void stopDebugger() override; 0125 void killDebuggerNow() override; 0126 void interruptDebugger() override; 0127 void run() override; 0128 void runToCursor() override; 0129 void jumpToCursor() override; 0130 void stepOver() override; 0131 void stepIntoInstruction() override; 0132 void stepInto() override; 0133 void stepOverInstruction() override; 0134 void stepOut() override; 0135 // END IDebugSession overrides 0136 0137 public Q_SLOTS: 0138 /** 0139 * Run currently executing program to the given \a url and \a line. 0140 */ 0141 void runUntil(const QUrl& url, int line); 0142 0143 /** 0144 * Run currently executing program to the given \a address 0145 */ 0146 void runUntil(const QString& address); 0147 0148 /** 0149 * Move the execution point of the currently executing program to the given \a url and \a line. 0150 */ 0151 void jumpTo(const QUrl& url, int line); 0152 0153 /** 0154 * Move the execution point of the currently executing program to the given \a address. 0155 *Note: It can be really very dangerous, so use jumpTo instead. 0156 */ 0157 void jumpToMemoryAddress(const QString& address); 0158 0159 /** 0160 * Start the debugger, and execute the inferior program specified by \a cfg. 0161 */ 0162 bool startDebugging(KDevelop::ILaunchConfiguration *cfg, IExecutePlugin *iexec); 0163 0164 /** 0165 * Start the debugger, and examine the core file given by \a coreFile. 0166 */ 0167 bool examineCoreFile(const QUrl &debugee, const QUrl &coreFile); 0168 0169 /** 0170 * Start the debugger, and attach to a currently running process with the given \a pid. 0171 */ 0172 bool attachToProcess(int pid); 0173 0174 public: 0175 virtual std::unique_ptr<MI::MICommand> createCommand(MI::CommandType type, const QString& arguments, 0176 MI::CommandFlags flags = {}) const; 0177 virtual std::unique_ptr<MI::MICommand> createUserCommand(const QString& cmd) const; 0178 /** Adds a command to the end of queue of commands to be executed 0179 by debugger. The command will be actually sent to debugger only when 0180 replies from all previous commands are received and full processed. 0181 0182 The literal command sent to debugger is obtained by calling 0183 cmd->cmdToSend. The call is made immediately before sending the 0184 command, so it's possible to use results of prior commands when 0185 computing the exact command to send. 0186 */ 0187 void addUserCommand(const QString &cmd); 0188 0189 void addCommand(std::unique_ptr<MI::MICommand> cmd); 0190 0191 /** Same as above, but internally constructs MICommand using createCommand() */ 0192 void addCommand(MI::CommandType type, const QString& arguments = QString(), 0193 MI::CommandFlags flags = {}); 0194 0195 void addCommand(MI::CommandType type, const QString& arguments, 0196 MI::MICommandHandler* handler, 0197 MI::CommandFlags flags = {}); 0198 0199 void addCommand(MI::CommandType type, const QString& arguments, 0200 const MI::FunctionCommandHandler::Function& callback, 0201 MI::CommandFlags flags = {}); 0202 0203 template<class Handler> 0204 void addCommand(MI::CommandType type, const QString& arguments, 0205 Handler* handler_this, 0206 void (Handler::* handler_method)(const MI::ResultRecord&), 0207 MI::CommandFlags flags = {}); 0208 0209 QMap<QString, MIVariable*> & variableMapping(); 0210 MIVariable* findVariableByVarobjName(const QString &varobjName) const; 0211 void markAllVariableDead(); 0212 0213 protected Q_SLOTS: 0214 virtual void slotDebuggerReady(); 0215 virtual void slotDebuggerExited(bool abnormal, const QString &msg); 0216 virtual void slotInferiorStopped(const MI::AsyncRecord &r); 0217 /** 0218 * Triggered every time program begins/continues it's execution. 0219 */ 0220 virtual void slotInferiorRunning(); 0221 0222 /** 0223 * Handle MI async notifications. 0224 */ 0225 virtual void processNotification(const MI::AsyncRecord &n); 0226 0227 /** Default handler for errors. 0228 Tries to guess is the error message is telling that target is 0229 gone, if so, informs the user. 0230 Otherwise, shows a dialog box and reloads view state. */ 0231 virtual void defaultErrorHandler(const MI::ResultRecord &result); 0232 0233 /** 0234 * Update session state when debugger state changes, and show messages 0235 */ 0236 virtual void handleDebuggerStateChange(DBGStateFlags oldState, DBGStateFlags newState); 0237 0238 void handleNoInferior(const QString &msg); 0239 void handleInferiorFinished(const QString &msg); 0240 0241 protected: 0242 void queueCmd(std::unique_ptr<MI::MICommand> cmd); 0243 0244 /** Try to execute next command in the queue. If GDB is not 0245 busy with previous command, and there's a command in the 0246 queue, sends it. */ 0247 void executeCmd(); 0248 void destroyCmds(); 0249 0250 virtual void ensureDebuggerListening(); 0251 0252 /** 0253 * Start the debugger instance 0254 */ 0255 bool startDebugger(KDevelop::ILaunchConfiguration *cfg); 0256 0257 /** 0258 * MIDebugSession takes the ownership of the created instance. 0259 */ 0260 virtual MIDebugger *createDebugger() const = 0; 0261 0262 /** 0263 * Initialize debugger and set default configurations. 0264 */ 0265 virtual void initializeDebugger() = 0; 0266 0267 /** 0268 * Do per launch configuration. 0269 */ 0270 virtual void configInferior(KDevelop::ILaunchConfiguration *cfg, IExecutePlugin *iexec, 0271 const QString &executable) = 0; 0272 0273 /** 0274 * Start the inferior program (either local or remote). 0275 */ 0276 virtual bool execInferior(KDevelop::ILaunchConfiguration *cfg, IExecutePlugin *iexec, 0277 const QString &executable) = 0; 0278 0279 /** 0280 * Further config the debugger and load the core dump 0281 */ 0282 virtual bool loadCoreFile(KDevelop::ILaunchConfiguration *cfg, 0283 const QString &debugee, const QString &corefile) = 0; 0284 0285 /** 0286 * Manipulate debugger instance state 0287 */ 0288 void setDebuggerStateOn(DBGStateFlags stateOn); 0289 void setDebuggerStateOff(DBGStateFlags stateOff); 0290 void setDebuggerState(DBGStateFlags newState); 0291 0292 /** 0293 * Manipulate the session state 0294 */ 0295 void setSessionState(DebuggerState state); 0296 0297 void raiseEvent(event_t e) override; 0298 0299 /** Called when there are no pending commands and 'm_stateReloadNeeded' 0300 is true. Also can be used to immediately reload program state. 0301 Issues commands to completely reload all program state shown 0302 to the user. 0303 */ 0304 void reloadProgramState(); 0305 0306 void programNoApp(const QString &msg); 0307 void programFinished(const QString &msg); 0308 0309 // FIXME: Whether let the debugger source init files when starting, 0310 // only used in unit test currently, potentially could be made a user 0311 // configurable option 0312 void setSourceInitFile(bool enable); 0313 0314 private Q_SLOTS: 0315 void handleTargetAttach(const MI::ResultRecord& r); 0316 // Pops up a dialog box with some hopefully 0317 // detailed information about which state debugger 0318 // is in, which commands were sent and so on. 0319 void explainDebuggerStatus(); 0320 0321 protected: 0322 KDevelop::ProcessLineMaker *m_procLineMaker; 0323 0324 std::unique_ptr<MI::CommandQueue> m_commandQueue; 0325 0326 // Though the misleading class name, this is the session level state. 0327 // see m_debuggerState for debugger instance state 0328 DebuggerState m_sessionState = NotStartedState; 0329 0330 MIDebugger *m_debugger = nullptr; 0331 DBGStateFlags m_debuggerState; 0332 0333 bool m_stateReloadInProgress = false; 0334 bool m_stateReloadNeeded = false; 0335 0336 std::unique_ptr<STTY> m_tty; 0337 0338 bool m_hasCrashed = false; 0339 bool m_sourceInitFile = true; 0340 0341 // Map from GDB varobj name to MIVariable. 0342 QMap<QString, MIVariable*> m_allVariables; 0343 0344 QPointer<MIDebuggerPlugin> m_plugin; 0345 0346 private: 0347 void addGdbExitCommand(); 0348 void killDebuggerImpl(); 0349 }; 0350 0351 template<class Handler> 0352 void MIDebugSession::addCommand(MI::CommandType type, const QString& arguments, 0353 Handler* handler_this, 0354 void (Handler::* handler_method)(const MI::ResultRecord&), 0355 MI::CommandFlags flags) 0356 { 0357 auto cmd = createCommand(type, arguments, flags); 0358 cmd->setHandler(handler_this, handler_method); 0359 queueCmd(std::move(cmd)); 0360 } 0361 0362 } // end of namespace KDevMI 0363 0364 #endif // MIDEBUGSESSION_H