File indexing completed on 2024-04-28 05:48:33
0001 // 0002 // gdbbackend.h 0003 // 0004 // Description: Manages the interaction with GDB 0005 // 0006 // 0007 // SPDX-FileCopyrightText: 2008-2010 Ian Wakeling <ian.wakeling@ntlworld.com> 0008 // SPDX-FileCopyrightText: 2010 Kåre Särs <kare.sars@iki.fi> 0009 // 0010 // SPDX-License-Identifier: LGPL-2.0-only 0011 0012 #pragma once 0013 0014 #include <QObject> 0015 0016 #include <QList> 0017 #include <QProcess> 0018 #include <QUrl> 0019 #include <optional> 0020 #include <sys/types.h> 0021 0022 #include "backendinterface.h" 0023 #include "configview.h" 0024 #include "dap/entities.h" 0025 #include "gdbmi/parser.h" 0026 #include "gdbmi/records.h" 0027 #include "gdbvariableparser.h" 0028 0029 struct GdbCommand { 0030 QStringList arguments; 0031 enum RequestType { 0032 None, 0033 BreakpointList, 0034 Continue, 0035 Step, 0036 ThreadInfo, 0037 StackListFrames, 0038 StackListVariables, 0039 BreakInsert, 0040 BreakDelete, 0041 ListFeatures, 0042 DataEvaluateExpression, 0043 InfoGdbMiCommand, 0044 Exit, 0045 Kill, 0046 LldbVersion, 0047 RegisterNames, 0048 RegisterValues, 0049 ChangedRegisters, 0050 }; 0051 RequestType type = None; 0052 std::optional<QJsonValue> data = std::nullopt; 0053 0054 bool isMachineInterface() const; 0055 bool check(const QString &command) const; 0056 bool check(const QString &part1, const QString &part2) const; 0057 static GdbCommand parse(const QString &request); 0058 }; 0059 0060 struct BreakPoint { 0061 int number; 0062 QUrl file; 0063 int line; 0064 0065 static BreakPoint parse(const QJsonObject &); 0066 }; 0067 0068 class GdbBackend : public BackendInterface 0069 { 0070 Q_OBJECT 0071 public: 0072 GdbBackend(QObject *parent); 0073 ~GdbBackend() override; 0074 0075 void runDebugger(const GDBTargetConf &conf, const QStringList &ioFifos); 0076 bool debuggerRunning() const override; 0077 bool debuggerBusy() const override; 0078 bool hasBreakpoint(QUrl const &url, int line) const override; 0079 0080 bool supportsMovePC() const override; 0081 bool supportsRunToCursor() const override; 0082 bool canSetBreakpoints() const override; 0083 bool canMove() const override; 0084 bool canContinue() const override; 0085 0086 void toggleBreakpoint(QUrl const &url, int line) override; 0087 void movePC(QUrl const &url, int line) override; 0088 void runToCursor(QUrl const &url, int line) override; 0089 0090 void issueCommand(QString const &cmd) override; 0091 0092 QString targetName() const override; 0093 void setFileSearchPaths(const QStringList &paths) override; 0094 0095 public Q_SLOTS: 0096 void slotInterrupt() override; 0097 void slotStepInto() override; 0098 void slotStepOver() override; 0099 void slotStepOut() override; 0100 void slotContinue() override; 0101 void slotKill() override; 0102 void slotReRun() override; 0103 QString slotPrintVariable(const QString &variable) override; 0104 0105 void slotQueryLocals(bool display) override; 0106 void changeStackFrame(int index) override; 0107 void changeThread(int index) override; 0108 void changeScope(int scopeId) override; 0109 0110 private Q_SLOTS: 0111 void slotError(); 0112 void slotReadDebugStdOut(); 0113 void slotReadDebugStdErr(); 0114 void slotDebugFinished(int exitCode, QProcess::ExitStatus status); 0115 void issueNextCommand(); 0116 0117 private: 0118 enum State { none, ready, executingCmd }; 0119 0120 enum GdbState { Disconnected, Connected, Running, Stopped }; 0121 0122 private: 0123 QUrl resolveFileName(const QString &fileName, bool silent = false); 0124 0125 void setState(State newState, std::optional<GdbState> newGdbState = std::nullopt); 0126 void setGdbState(GdbState newState); 0127 void resetSession(); 0128 void clearFrames(); 0129 void clearVariables(); 0130 void updateInspectable(bool inspectable); 0131 0132 BreakPoint parseBreakpoint(const QJsonObject &item); 0133 int findFirstBreakpoint(const QUrl &url, int line) const; 0134 QStringList findAllBreakpoints(const QUrl &url, int line) const; 0135 void deleteBreakpoint(const int bpNumber); 0136 void insertBreakpoint(const QJsonObject &item); 0137 QString makeCmdBreakInsert(const QUrl &url, int line, bool pending = false, bool temporal = false) const; 0138 QString makeFrameFlags() const; 0139 0140 bool inferiorRunning() const; 0141 void onMIParserError(const QString &error); 0142 void processMIStreamOutput(const gdbmi::StreamOutput &record); 0143 void processMIRecord(const gdbmi::Record &record); 0144 void processMIExec(const gdbmi::Record &record); 0145 void processMINotify(const gdbmi::Record &record); 0146 void processMIResult(const gdbmi::Record &record); 0147 void processMIPrompt(); 0148 bool responseMIBreakpointList(const gdbmi::Record &record); 0149 bool responseMIThreadInfo(const gdbmi::Record &record); 0150 bool responseMIStackListFrames(const gdbmi::Record &record); 0151 bool responseMIStackListVariables(const gdbmi::Record &record); 0152 bool responseMIBreakInsert(const gdbmi::Record &record); 0153 bool responseMIBreakDelete(const gdbmi::Record &record, const QStringList &args); 0154 void notifyMIBreakpointDeleted(const gdbmi::Record &record); 0155 void notifyMIBreakpointModified(const gdbmi::Record &record); 0156 bool responseMIListFeatures(const gdbmi::Record &record); 0157 bool responseMIDataEvaluateExpression(const gdbmi::Record &record, const std::optional<QJsonValue> &data); 0158 bool responseMIRegisterNames(const gdbmi::Record &record); 0159 bool responseMIRegisterValues(const gdbmi::Record &record); 0160 bool responseMIChangedRegisters(const gdbmi::Record &record); 0161 bool responseMIExit(const gdbmi::Record &record); 0162 bool responseMIKill(const gdbmi::Record &record); 0163 bool responseMIInfoGdbCommand(const gdbmi::Record &record, const QStringList &args); 0164 bool responseMILldbVersion(const gdbmi::Record &record); 0165 void responseMIScopes(const gdbmi::Record &record); 0166 void responseMIThisScope(const gdbmi::Record &record); 0167 void informStackFrame(); 0168 dap::StackFrame parseFrame(const QJsonObject &object); 0169 0170 void enqueueScopeVariables(); 0171 void enqueueScopes(); 0172 void enqueueProtocolHandshake(); 0173 QStringList makeInitSequence(); 0174 void enqueueThreadInfo(); 0175 QStringList makeRunSequence(bool stop); 0176 void enqueue(const QString &command); 0177 void enqueue(const QString &command, const QJsonValue &data, uint8_t captureMode = CaptureMode::Default); 0178 void enqueue(const QStringList &commands, bool prepend = false); 0179 void prepend(const QString &command); 0180 void issueCommand(const QString &cmd, const std::optional<QJsonValue> &data, uint8_t captureMode = CaptureMode::Default); 0181 void issueNextCommandLater(const std::optional<State> &state); 0182 void updateInputReady(bool newState, bool force = false); 0183 void clearDebugLocation(); 0184 0185 void cmdKateInit(); 0186 void cmdKateTryRun(const GdbCommand &cmd, const QJsonValue &data); 0187 0188 private: 0189 QProcess m_debugProcess; 0190 GDBTargetConf m_targetConf; 0191 QString m_ioPipeString; 0192 0193 State m_state; 0194 0195 struct PendingCommand { 0196 QString command; 0197 std::optional<QJsonValue> data; 0198 uint8_t captureMode; 0199 }; 0200 QList<PendingCommand> m_nextCommands; 0201 QString m_lastCommand; 0202 bool m_debugLocationChanged; 0203 QHash<int, BreakPoint> m_breakpointTable; 0204 QByteArray m_outBuffer; 0205 QString m_errBuffer; 0206 bool m_queryLocals; 0207 0208 GDBVariableParser m_variableParser; 0209 0210 gdbmi::GdbmiParser *m_parser; 0211 QHash<int, GdbCommand> m_requests; 0212 int m_seq = 0; 0213 GdbState m_gdbState = Disconnected; 0214 QList<dap::StackFrame> m_stackFrames; 0215 QList<QString> m_registerNames; 0216 QSet<int> m_changedRegisters; 0217 bool m_lastInputReady = false; 0218 bool m_pointerThis = false; 0219 0220 enum CaptureMode { Default = 0x0, CaptureConsole = 0x1, MuteLog = 0x2 }; 0221 uint8_t m_captureOutput = Default; 0222 QStringList m_capturedOutput; 0223 bool m_inspectable = false; 0224 std::optional<int> m_currentThread; 0225 std::optional<int> m_currentFrame; 0226 std::optional<int> m_currentScope; 0227 std::optional<int> m_watchedScope; 0228 int m_errorCounter = 0; 0229 0230 enum DebuggerFamily { Unknown, GDB, LLDB }; 0231 struct { 0232 DebuggerFamily family; 0233 std::optional<bool> async; 0234 std::optional<bool> execRunStart; 0235 std::optional<bool> threadInfo; 0236 std::optional<bool> breakList; 0237 std::optional<bool> pendingBreakpoints; 0238 std::optional<bool> execJump; 0239 std::optional<bool> changedRegisters; 0240 } m_capabilities; 0241 };