RedPanda-CPP/RedPandaIDE/debugger.h

396 lines
12 KiB
C
Raw Normal View History

2021-07-03 21:57:50 +08:00
#ifndef DEBUGGER_H
#define DEBUGGER_H
2021-07-17 19:32:23 +08:00
#include <QAbstractTableModel>
2021-07-03 21:57:50 +08:00
#include <QList>
#include <QList>
2021-07-17 19:32:23 +08:00
#include <QMap>
2021-07-03 21:57:50 +08:00
#include <QMutex>
#include <QObject>
2021-07-19 23:02:32 +08:00
#include <QProcess>
2021-07-03 21:57:50 +08:00
#include <QQueue>
#include <QQueue>
2021-07-27 00:14:24 +08:00
#include <QSemaphore>
2021-07-19 23:02:32 +08:00
#include <QThread>
2021-07-03 21:57:50 +08:00
#include <memory>
2021-11-20 07:53:39 +08:00
#include "gdbmiresultparser.h"
2021-07-03 21:57:50 +08:00
enum class DebugCommandSource {
Console,
Other
};
struct DebugCommand{
QString command;
QString params;
DebugCommandSource source;
};
using PDebugCommand = std::shared_ptr<DebugCommand>;
2021-07-31 14:04:43 +08:00
struct WatchVar;
using PWatchVar = std::shared_ptr<WatchVar>;
2021-07-17 19:32:23 +08:00
struct WatchVar {
QString name;
2021-09-19 09:45:03 +08:00
QString value;
QString fullName;
2021-07-17 19:32:23 +08:00
int gdbIndex;
2021-07-31 14:04:43 +08:00
QList<PWatchVar> children;
WatchVar * parent; //use raw point to prevent circular-reference
2021-07-17 19:32:23 +08:00
};
2021-07-03 21:57:50 +08:00
struct Breakpoint {
2021-11-12 10:51:00 +08:00
int number; // breakpoint number
QString type; // type of the breakpoint
QString catch_type;
2021-07-03 21:57:50 +08:00
int line;
2021-07-24 11:18:25 +08:00
QString filename;
2021-07-03 21:57:50 +08:00
QString condition;
bool enabled;
2021-07-03 21:57:50 +08:00
};
using PBreakpoint = std::shared_ptr<Breakpoint>;
struct Trace {
QString funcname;
QString filename;
2021-11-23 21:08:33 +08:00
QString address;
2021-07-03 21:57:50 +08:00
int line;
2021-11-23 21:08:33 +08:00
int level;
2021-07-03 21:57:50 +08:00
};
using PTrace = std::shared_ptr<Trace>;
2021-08-01 23:24:37 +08:00
class RegisterModel: public QAbstractTableModel {
Q_OBJECT
public:
explicit RegisterModel(QObject* parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
2021-11-25 09:05:45 +08:00
void updateNames(const QStringList& regNames);
void updateValues(const QHash<int,QString> registerValues);
2021-08-01 23:24:37 +08:00
void clear();
private:
2021-11-25 09:05:45 +08:00
QStringList mRegisterNames;
QHash<int,QString> mRegisterValues;
2021-08-01 23:24:37 +08:00
};
2021-07-17 19:32:23 +08:00
class BreakpointModel: public QAbstractTableModel {
2021-07-24 11:18:25 +08:00
Q_OBJECT
2021-07-17 19:32:23 +08:00
// QAbstractItemModel interface
public:
2021-07-24 11:18:25 +08:00
explicit BreakpointModel(QObject *parent = nullptr);
2021-07-17 19:32:23 +08:00
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void addBreakpoint(PBreakpoint p);
void clear();
2021-07-24 11:18:25 +08:00
void removeBreakpoint(int index);
PBreakpoint setBreakPointCondition(int index, const QString& condition);
const QList<PBreakpoint>& breakpoints() const;
PBreakpoint breakpoint(int index) const;
void save(const QString& filename);
void load(const QString& filename);
public slots:
2021-11-21 08:38:03 +08:00
void updateBreakpointNumber(const QString& filename, int line, int number);
void invalidateAllBreakpointNumbers(); // call this when gdb is stopped
void onFileDeleteLines(const QString& filename, int startLine, int count);
void onFileInsertLines(const QString& filename, int startLine, int count);
2021-07-17 19:32:23 +08:00
private:
QList<PBreakpoint> mList;
};
class BacktraceModel : public QAbstractTableModel {
2021-07-31 14:04:43 +08:00
Q_OBJECT
2021-07-17 19:32:23 +08:00
// QAbstractItemModel interface
public:
2021-07-24 11:18:25 +08:00
explicit BacktraceModel(QObject *parent = nullptr);
2021-07-17 19:32:23 +08:00
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void addTrace(PTrace p);
void clear();
2021-07-24 11:18:25 +08:00
void removeTrace(int index);
const QList<PTrace>& backtraces() const;
PTrace backtrace(int index) const;
2021-07-17 19:32:23 +08:00
private:
QList<PTrace> mList;
};
2021-07-31 14:04:43 +08:00
class WatchModel: public QAbstractItemModel {
Q_OBJECT
public:
2021-07-31 20:19:45 +08:00
explicit WatchModel(QObject *parent = nullptr);
2021-07-31 14:04:43 +08:00
QVariant data(const QModelIndex &index, int role) const override;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
void addWatchVar(PWatchVar watchVar);
void removeWatchVar(const QString& name);
void removeWatchVar(int gdbIndex);
void removeWatchVar(const QModelIndex& index);
2021-07-31 14:04:43 +08:00
void clear();
const QList<PWatchVar>& watchVars();
PWatchVar findWatchVar(const QString& name);
PWatchVar findWatchVar(int gdbIndex);
void beginUpdate();
void endUpdate();
2021-07-31 20:19:45 +08:00
void notifyUpdated(PWatchVar var);
void save(const QString& filename);
void load(const QString& filename);
2021-07-31 14:04:43 +08:00
private:
QList<PWatchVar> mWatchVars;
int mUpdateCount;
// QAbstractItemModel interface
public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
2021-07-31 14:04:43 +08:00
};
2021-07-17 19:32:23 +08:00
2021-07-03 21:57:50 +08:00
class DebugReader;
2021-07-24 11:18:25 +08:00
class Editor;
using PDebugReader = std::shared_ptr<DebugReader>;
2021-07-03 21:57:50 +08:00
class Debugger : public QObject
{
Q_OBJECT
public:
explicit Debugger(QObject *parent = nullptr);
2021-07-24 11:18:25 +08:00
// Play/pause
2021-08-20 12:43:01 +08:00
bool start();
2021-07-24 11:18:25 +08:00
void sendCommand(const QString& command, const QString& params,
DebugCommandSource source = DebugCommandSource::Other);
2021-08-29 22:08:43 +08:00
bool commandRunning();
2021-11-24 21:22:01 +08:00
bool inferiorRunning();
2021-07-24 11:18:25 +08:00
2021-07-26 18:22:09 +08:00
//breakpoints
2021-07-24 11:18:25 +08:00
void addBreakpoint(int line, const Editor* editor);
void addBreakpoint(int line, const QString& filename);
void deleteBreakpoints(const QString& filename);
void deleteBreakpoints(const Editor* editor);
void deleteBreakpoints();
2021-07-24 11:18:25 +08:00
void removeBreakpoint(int line, const Editor* editor);
void removeBreakpoint(int line, const QString& filename);
void removeBreakpoint(int index);
PBreakpoint breakpointAt(int line, const QString& filename, int &index);
PBreakpoint breakpointAt(int line, const Editor* editor, int &index);
2021-07-24 11:18:25 +08:00
void setBreakPointCondition(int index, const QString& condition);
2021-07-25 13:03:46 +08:00
void sendAllBreakpointsToDebugger();
2021-11-20 07:53:39 +08:00
void validateBreakpoint(int line, const QString& filename, int number);
void invalidateAllBreakpoints();
2021-07-31 20:19:45 +08:00
2021-07-26 18:22:09 +08:00
//watch vars
void addWatchVar(const QString& namein);
// void removeWatchVar(nodein: TTreeNode); overload;
void renameWatchVar(const QString& oldname, const QString& newname);
void refreshWatchVars();
void removeWatchVars(bool deleteparent);
void removeWatchVar(const QModelIndex& index);
2021-07-26 18:22:09 +08:00
void invalidateAllVars();
void sendAllWatchvarsToDebugger();
2021-08-01 01:06:43 +08:00
void invalidateWatchVar(const QString& name);
2021-07-26 18:22:09 +08:00
void invalidateWatchVar(PWatchVar var);
2021-08-01 01:06:43 +08:00
PWatchVar findWatchVar(const QString& name);
2021-09-19 02:00:25 +08:00
// void notifyWatchVarUpdated(PWatchVar var);
void notifyBeforeProcessWatchVar();
void notifyAfterProcessWatchVar();
2021-07-26 18:22:09 +08:00
2021-07-24 08:12:51 +08:00
bool useUTF8() const;
void setUseUTF8(bool useUTF8);
2021-07-25 00:26:13 +08:00
BacktraceModel* backtraceModel();
BreakpointModel* breakpointModel();
2021-07-26 11:47:54 +08:00
bool executing() const;
2021-07-26 18:22:09 +08:00
int leftPageIndexBackup() const;
void setLeftPageIndexBackup(int leftPageIndexBackup);
2021-08-01 01:06:43 +08:00
WatchModel *watchModel() const;
2021-08-01 23:24:37 +08:00
RegisterModel *registerModel() const;
2021-08-29 22:08:43 +08:00
signals:
void evalValueReady(const QString& s);
void memoryExamineReady(const QStringList& s);
void localsReady(const QStringList& s);
2021-07-26 00:22:08 +08:00
public slots:
void stop();
2021-07-24 11:18:25 +08:00
private:
2021-07-31 20:19:45 +08:00
void sendWatchCommand(PWatchVar var);
void sendRemoveWatchCommand(PWatchVar var);
2021-07-25 13:03:46 +08:00
void sendBreakpointCommand(PBreakpoint breakpoint);
2021-07-24 11:18:25 +08:00
void sendClearBreakpointCommand(int index);
2021-07-25 13:03:46 +08:00
void sendClearBreakpointCommand(PBreakpoint breakpoint);
2021-08-01 01:06:43 +08:00
2021-07-26 11:47:54 +08:00
private slots:
void syncFinishedParsing();
2021-11-25 07:42:56 +08:00
void updateMemory(const QStringList& value);
void updateEval(const QString& value);
void updateDisassembly(const QString& file, const QString& func,const QStringList& value);
2021-07-30 23:28:58 +08:00
void onChangeDebugConsoleLastline(const QString& text);
2021-07-31 14:04:43 +08:00
void clearUpReader();
2021-11-25 09:05:45 +08:00
void updateRegisterNames(const QStringList& registerNames);
void updateRegisterValues(const QHash<int,QString>& values);
2021-07-03 21:57:50 +08:00
private:
bool mExecuting;
bool mCommandChanged;
2021-08-01 23:24:37 +08:00
BreakpointModel *mBreakpointModel;
2021-07-03 21:57:50 +08:00
bool mUseUTF8;
2021-08-01 23:24:37 +08:00
BacktraceModel *mBacktraceModel;
WatchModel *mWatchModel;
RegisterModel *mRegisterModel;
DebugReader *mReader;
2021-07-26 18:22:09 +08:00
int mLeftPageIndexBackup;
2021-07-03 21:57:50 +08:00
};
2021-07-19 23:02:32 +08:00
class DebugReader : public QThread
2021-07-03 21:57:50 +08:00
{
Q_OBJECT
public:
2021-07-25 00:26:13 +08:00
explicit DebugReader(Debugger* debugger, QObject *parent = nullptr);
2021-11-24 17:53:25 +08:00
void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source);
void registerInferiorStoppedCommand(const QString &Command, const QString &Params);
2021-07-25 00:26:13 +08:00
QString debuggerPath() const;
void setDebuggerPath(const QString &debuggerPath);
void stopDebug();
2021-08-29 22:08:43 +08:00
bool commandRunning();
2021-11-24 17:53:25 +08:00
void waitStart();
2021-08-29 22:08:43 +08:00
2021-08-01 01:06:43 +08:00
bool invalidateAllVars() const;
void setInvalidateAllVars(bool invalidateAllVars);
2021-11-10 17:05:37 +08:00
bool inferiorPaused() const;
bool processExited() const;
2021-11-23 21:08:33 +08:00
bool signalReceived() const;
const QStringList &consoleOutput() const;
int breakPointLine() const;
const QString &breakPointFile() const;
const PDebugCommand &currentCmd() const;
bool updateCPUInfo() const;
bool updateLocals() const;
const QStringList &localsValue() const;
bool evalReady() const;
const QString &evalValue() const;
bool updateMemory() const;
const QStringList &memoryValue() const;
2021-11-10 17:05:37 +08:00
2021-11-24 10:07:35 +08:00
bool receivedSFWarning() const;
2021-11-24 17:53:25 +08:00
const QStringList &fullOutput() const;
2021-11-24 21:22:01 +08:00
bool inferiorRunning() const;
2021-11-25 09:05:45 +08:00
const QString &signalName() const;
const QString &signalMeaning() const;
2021-07-18 08:52:53 +08:00
signals:
void parseStarted();
void invalidateAllVars();
void parseFinished();
2021-07-19 23:02:32 +08:00
void writeToDebugFailed();
void processError(QProcess::ProcessError error);
2021-08-01 10:00:27 +08:00
void changeDebugConsoleLastLine(const QString& text);
void cmdStarted();
void cmdFinished();
2021-11-21 08:38:03 +08:00
void breakpointInfoGetted(const QString& filename, int line, int number);
2021-11-24 10:07:35 +08:00
void inferiorContinued();
2021-11-24 17:53:25 +08:00
void inferiorStopped(const QString& filename, int line, bool setFocus);
2021-11-24 10:07:35 +08:00
void localsUpdated(const QStringList& localsValue);
void evalUpdated(const QString& value);
void memoryUpdated(const QStringList& memoryValues);
2021-11-25 07:42:56 +08:00
void disassemblyUpdate(const QString& filename, const QString& funcName, const QStringList& result);
2021-11-25 09:05:45 +08:00
void registerNamesUpdated(const QStringList& registerNames);
void registerValuesUpdated(const QHash<int,QString>& values);
2021-07-03 21:57:50 +08:00
private:
void clearCmdQueue();
2021-11-12 10:51:00 +08:00
2021-07-18 08:52:53 +08:00
QString processEvalOutput();
void processWatchOutput(PWatchVar WatchVar);
2021-07-19 23:02:32 +08:00
void runNextCmd();
2021-09-19 09:45:03 +08:00
QStringList tokenize(const QString& s);
2021-11-12 10:51:00 +08:00
2021-11-24 17:53:25 +08:00
bool outputTerminated(const QByteArray& text);
2021-11-20 07:53:39 +08:00
void handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint);
2021-11-23 21:08:33 +08:00
void handleStack(const QList<GDBMIResultParser::ParseValue> & stack);
void handleLocalVariables(const QList<GDBMIResultParser::ParseValue> & variables);
void handleEvaluation(const QString& value);
void handleMemory(const QList<GDBMIResultParser::ParseValue> & rows);
2021-11-25 09:05:45 +08:00
void handleRegisterNames(const QList<GDBMIResultParser::ParseValue> & names);
void handleRegisterValue(const QList<GDBMIResultParser::ParseValue> & values);
2021-11-12 10:51:00 +08:00
void processConsoleOutput(const QByteArray& line);
void processResult(const QByteArray& result);
void processExecAsyncRecord(const QByteArray& line);
void processError(const QByteArray& errorLine);
void processResultRecord(const QByteArray& line);
void processDebugOutput(const QByteArray& debugOutput);
2021-11-24 17:53:25 +08:00
void runInferiorStoppedHook();
2021-11-12 10:51:00 +08:00
QByteArray removeToken(const QByteArray& line);
2021-07-03 21:57:50 +08:00
private:
2021-08-01 23:24:37 +08:00
Debugger *mDebugger;
2021-07-25 00:26:13 +08:00
QString mDebuggerPath;
2021-07-27 00:14:24 +08:00
QRecursiveMutex mCmdQueueMutex;
QSemaphore mStartSemaphore;
2021-07-03 21:57:50 +08:00
QQueue<PDebugCommand> mCmdQueue;
bool mInvalidateAllVars;
//fOnInvalidateAllVars: TInvalidateAllVarsEvent;
bool mCmdRunning;
PDebugCommand mCurrentCmd;
2021-07-27 00:14:24 +08:00
QProcess* mProcess;
2021-07-19 23:02:32 +08:00
2021-07-03 21:57:50 +08:00
//fWatchView: TTreeView;
2021-11-23 21:08:33 +08:00
2021-11-25 09:05:45 +08:00
QString mSignalName;
QString mSignalMeaning;
2021-07-03 21:57:50 +08:00
2021-11-20 07:53:39 +08:00
//
2021-11-24 17:53:25 +08:00
QList<PDebugCommand> mInferiorStoppedHookCommands;
2021-11-24 10:07:35 +08:00
bool mInferiorRunning;
2021-11-10 17:05:37 +08:00
bool mProcessExited;
2021-11-23 21:08:33 +08:00
bool mSignalReceived;
bool mUpdateCPUInfo;
2021-11-24 10:07:35 +08:00
bool mReceivedSFWarning;
2021-11-23 21:08:33 +08:00
2021-11-24 17:53:25 +08:00
int mCurrentLine;
int mCurrentAddress;
2021-11-25 07:42:56 +08:00
QString mCurrentFunc;
2021-11-24 17:53:25 +08:00
QString mCurrentFile;
2021-11-10 17:05:37 +08:00
QStringList mConsoleOutput;
2021-11-24 17:53:25 +08:00
QStringList mFullOutput;
2021-11-10 17:05:37 +08:00
bool mStop;
2021-07-19 23:02:32 +08:00
// QThread interface
protected:
void run() override;
2021-07-03 21:57:50 +08:00
};
#endif // DEBUGGER_H