Warning, file /kdevelop/kdev-python/debugger/debugsession.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2012 Sven Brauch <svenbrauch@googlemail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef PDBDEBUGSESSION_H 0008 #define PDBDEBUGSESSION_H 0009 0010 #include <KProcess> 0011 #include <QMutexLocker> 0012 #include <QPointer> 0013 0014 #include <QDebug> 0015 #include "debuggerdebug.h" 0016 0017 #include <debugger/interfaces/idebugsession.h> 0018 #include <debugger/interfaces/ivariablecontroller.h> 0019 #include <debugger/interfaces/ibreakpointcontroller.h> 0020 #include "variable.h" 0021 0022 using namespace KDevelop; 0023 0024 namespace Python { 0025 0026 struct PdbCommand; 0027 0028 class DebugSession : public KDevelop::IDebugSession 0029 { 0030 Q_OBJECT 0031 public: 0032 DebugSession(QStringList program, const QUrl& workingDirectory, 0033 const QString& envProfileName); 0034 ~DebugSession() override; 0035 0036 IBreakpointController* breakpointController() const override; 0037 IFrameStackModel* frameStackModel() const override; 0038 0039 /** 0040 * @brief Start the debugger. 0041 **/ 0042 void start(); 0043 0044 /** 0045 * @brief Adds a command to the queue. 0046 * Commands are processed in the same order they're added. 0047 * If the type of the command added is UserType, automatic updates 0048 * (of local variables, location, ...) will be triggered. 0049 * 0050 * @param cmd The command to enqeue. 0051 **/ 0052 void addCommand(PdbCommand* cmd); 0053 0054 /** 0055 * @brief Convenience function, constructs a new UserPdbCommand and enqueues it. 0056 * Use this to enqueue simple commands invoked by user clicks ("next" etc.) 0057 * 0058 * @param cmd What you would type at the debugger command line. 0059 **/ 0060 void addSimpleUserCommand(const QString& cmd); 0061 0062 /** 0063 * @brief Convencience function, constructs a new InternalPdbCommand and enqueues it. 0064 * Use this to enqueue simple commands which are needed internally ("where", ...) 0065 * 0066 * @param cmd What you would type at the debugger command line. 0067 **/ 0068 void addSimpleInternalCommand(const QString& cmd); 0069 0070 /** 0071 * @brief Interrupt the running program with SIGINT and immediately run the specified command. 0072 * This will also trigger a location update. Program execution will continue immediately after 0073 * the given command has been run! 0074 * 0075 * @param cmd What you would type at the debugger command line, terminated by \n. 0076 **/ 0077 void runImmediately(const QString& cmd); 0078 0079 /** 0080 * @brief Constructs commands to add the given breakpoint to the debugger. 0081 * 0082 * @param bp The breakpoint to add 0083 **/ 0084 void addBreakpoint(Breakpoint* bp); 0085 0086 /** 0087 * @brief Constructs commands to remove the given breakpoint from the debugger. 0088 * 0089 * @param bp The breakpoint to remove 0090 **/ 0091 void removeBreakpoint(Breakpoint* bp); 0092 0093 /** 0094 * @brief Access this session's variable controller 0095 **/ 0096 IVariableController* variableController() const override; 0097 0098 /// Those functions just execute the basic debugger commands. They're used when the user 0099 /// clicks the appropriate button. 0100 void stepOut() override; 0101 void stepOverInstruction() override; 0102 void stepInto() override; 0103 void stepIntoInstruction() override; 0104 void stepOver() override; 0105 void jumpToCursor() override; 0106 void runToCursor() override; 0107 void run() override; 0108 void restartDebugger() override; 0109 0110 bool restartAvaliable() const override; 0111 0112 /** 0113 * @brief Interrupt the running program with SIGINT and set the state to PausedState 0114 **/ 0115 void interruptDebugger() override; 0116 0117 /** 0118 * @brief Kill the debugger and program being debugged. 0119 * This tries to send a "quit" command, and if the debugger doesn't react to that quickly, 0120 * it'll just kill it. 0121 **/ 0122 void stopDebugger() override; 0123 0124 /** 0125 * @brief Kill the debugger process synchronously 0126 **/ 0127 void killDebuggerNow() override; 0128 0129 /** 0130 * @brief Gives the debugger state. 0131 * The two main states are "ActiveState" and "PausedState"; the former is given 0132 * if the *user program* is being run by the debugger. 0133 * 0134 * @return :IDebugSession::DebuggerState the current state the debugger is in 0135 **/ 0136 IDebugSession::DebuggerState state() const override; 0137 0138 /** 0139 * @brief Change the debugger state, and trigger various events depending on the previous and new state. 0140 * WARNING: Do *not* switch to ActiveState for running internal commands: If 0141 * the location is being updated by "where", no state switching should occur. 0142 * Otherwise, various endless loops might occur because kdevplatform tries auto- 0143 * update various things (like the location, ...) 0144 * State changes should only occur when starting up, shutting down, or on explicit user interaction. 0145 * 0146 * @param state The state to change to. 0147 **/ 0148 void setState(IDebugSession::DebuggerState state); 0149 0150 /** 0151 * @brief Enqueue a command which updates the location. 0152 * Run this whenever you enqueue a command which might change the location in the source code 0153 * (like "next" or similar). This is queued, so you can do addSimpleUserCommand("next"); updateLocation(); 0154 * without problems. 0155 **/ 0156 void updateLocation(); 0157 0158 /** 0159 * @brief Clears the table of object IDs stored in the debugger script 0160 **/ 0161 void clearObjectTable(); 0162 0163 /** 0164 * @brief Write raw data to the debugger process' stdin. 0165 * Remember that you have to terminate your input by "\n" for the debugger to process it. 0166 * 0167 * @param cmd data to write to stdin 0168 **/ 0169 void write(const QByteArray& cmd); 0170 0171 public slots: 0172 /** 0173 * @brief Emitted when new data has been received from the debugger process (via stdout) 0174 **/ 0175 void dataAvailable(); 0176 /** 0177 * @brief Fetch the given variable's value and assign it, and when done call the given callback method. 0178 * 0179 * @param variable Variable object to fetch data for 0180 * @param callback object to call callbackMethod on 0181 * @param callbackMethod method to call when done 0182 **/ 0183 void createVariable(Python::Variable* variable, QObject* callback, const char* callbackMethod); 0184 0185 /** 0186 * @brief Check the command queue, and run the next command if it's not empty. 0187 **/ 0188 void checkCommandQueue(); 0189 0190 /** 0191 * @brief Performs a location update. 0192 * This is used by updateLocation(). 0193 **/ 0194 void locationUpdateReady(QByteArray data); 0195 void debuggerQuit(int); 0196 0197 signals: 0198 /// Emitted when the debugger becomes ready to process a new command, i.e. shows its prompt 0199 void debuggerReady(); 0200 /// Emitted when a new command is added to the queue 0201 void commandAdded(); 0202 /// Emitted when real data from the program is received (needs improvement) 0203 void realDataReceived(QStringList); 0204 void stderrReceived(QStringList); 0205 0206 private: 0207 IBreakpointController* m_breakpointController; 0208 IVariableController* m_variableController; 0209 IFrameStackModel* m_frameStackModel; 0210 KProcess* m_debuggerProcess; 0211 IDebugSession::DebuggerState m_state; 0212 QByteArray m_buffer; 0213 QStringList m_program; 0214 QList<PdbCommand*> m_commandQueue; 0215 const QUrl& m_workingDirectory; 0216 const QString m_envProfileName; 0217 private: 0218 /// objects to notify next 0219 QPointer<QObject> m_nextNotifyObject; 0220 const char* m_nextNotifyMethod; 0221 /// whether the process is busy processing an internal command 0222 bool m_processBusy; 0223 0224 /** 0225 * @brief Set the object to notify when the next command is done processing 0226 **/ 0227 void setNotifyNext(QPointer<QObject> object, const char* method); 0228 0229 /** 0230 * @brief Invoke the method given by setNotifyNext, and clear it 0231 **/ 0232 void notifyNext(); 0233 0234 /** 0235 * @brief Process the next command in the queue. 0236 * WARNING: The queue must be non-empty when this is called. 0237 * If the process is busy doing something else, returns and does nothing. 0238 **/ 0239 void processNextCommand(); 0240 0241 /** 0242 * @brief Clear the data accumulated in m_buffer. 0243 **/ 0244 void clearOutputBuffer(); 0245 0246 /** 0247 * @brief Clean up and switch to EndedState after stopping/killing the debugger 0248 **/ 0249 void finalizeState(); 0250 0251 /// stores whether the data currently received comes from the debugger 0252 /// or the debuggee. 0253 int m_inDebuggerData; 0254 }; 0255 0256 /** 0257 * @brief Base class for all Pdb command objects. Those are enqueued in the debug session. 0258 **/ 0259 struct PdbCommand { 0260 public: 0261 /// notifyMethod must have a QByteArray argument, which is the 0262 /// output produced by the command. 0263 PdbCommand(QObject* notifyObject, const char* notifyMethod) : 0264 m_notifyObject(notifyObject) 0265 , m_notifyMethod(notifyMethod) 0266 , m_output(QByteArray()) {}; 0267 0268 /** 0269 * @brief Implement this method in your sub-class to execute the command in the given session. 0270 * WARNING: The process is already locked and ready when this is called. 0271 * Don't acquire or release any locks or do fancy checking here, just do your business (write data 0272 * to the process, ...). Everything else is handled from outside. 0273 * @param session the debug session to run the command in 0274 **/ 0275 virtual void run(DebugSession* session) = 0; 0276 virtual ~PdbCommand() {}; 0277 void setOutput(QByteArray output) { 0278 m_output = output; 0279 }; 0280 QPointer<QObject> notifyObject() { 0281 return m_notifyObject; 0282 }; 0283 const char* notifyMethod() { 0284 return m_notifyMethod; 0285 }; 0286 0287 enum Type { 0288 InvalidType, 0289 InternalType, 0290 UserType 0291 }; 0292 0293 inline Type type() const { 0294 return m_type; 0295 }; 0296 0297 protected: 0298 Type m_type; 0299 QPointer<QObject> m_notifyObject; 0300 const char* m_notifyMethod; 0301 QByteArray m_output; 0302 }; 0303 0304 /** 0305 * @brief Base-class for commands which just write a simple piece of text to the debugger command line and read its output. 0306 **/ 0307 struct SimplePdbCommand : public PdbCommand { 0308 public: 0309 SimplePdbCommand(QObject* notifyObject, const char* notifyMethod, const QString& command) : 0310 PdbCommand(notifyObject, notifyMethod) 0311 , m_command(command) { 0312 m_type = InvalidType; 0313 }; 0314 void run(DebugSession* session) override { 0315 Q_ASSERT(m_command.endsWith('\n') && "command must end with a newline"); 0316 qCDebug(KDEV_PYTHON_DEBUGGER) << "running command:" << m_command<< m_notifyMethod; 0317 session->write(m_command.toUtf8()); 0318 } 0319 private: 0320 QString m_command; 0321 }; 0322 0323 /** 0324 * @brief Represents a command which is invoked by kdevelop to obtain information to display in the UI. 0325 **/ 0326 struct InternalPdbCommand : public SimplePdbCommand { 0327 public: 0328 InternalPdbCommand(QObject* notifyObject, const char* notifyMethod, const QString& command) : 0329 SimplePdbCommand(notifyObject, notifyMethod, command) { 0330 m_type = InternalType; 0331 } ; 0332 }; 0333 0334 /** 0335 * @brief Represents a command which is invoked by the user by clicking a button. 0336 **/ 0337 struct UserPdbCommand : public SimplePdbCommand { 0338 public: 0339 UserPdbCommand(QObject* notifyObject, const char* notifyMethod, const QString& command) : 0340 SimplePdbCommand(notifyObject, notifyMethod, command) { 0341 m_type = UserType; 0342 } ; 0343 }; 0344 0345 } 0346 0347 #endif // DEBUGSESSION_H