RedPanda-CPP/RedPandaIDE/debugger.h

352 lines
10 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>
enum class DebugCommandSource {
Console,
Other
};
enum class AnnotationType {
TPrePrompt, TPrompt, TPostPrompt,
TSource,
TDisplayBegin, TDisplayEnd,
TDisplayExpression,
TFrameSourceFile, TFrameSourceBegin, TFrameSourceLine, TFrameFunctionName, TFrameWhere,
TFrameArgs,
TFrameBegin, TFrameEnd,
TErrorBegin, TErrorEnd,
TArrayBegin, TArrayEnd,
TElt, TEltRep, TEltRepEnd,
TExit,
TSignal, TSignalName, TSignalNameEnd, TSignalString, TSignalStringEnd,
TValueHistoryValue, TValueHistoryBegin, TValueHistoryEnd,
TArgBegin, TArgEnd, TArgValue, TArgNameEnd,
TFieldBegin, TFieldEnd, TFieldValue, TFieldNameEnd,
TInfoReg, TInfoAsm,
TUnknown, TEOF,
TLocal, TParam
};
struct DebugCommand{
QString command;
QString params;
bool updateWatch;
bool showInConsole;
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-07-31 14:04:43 +08:00
QString text;
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 {
int line;
2021-07-24 11:18:25 +08:00
QString filename;
2021-07-03 21:57:50 +08:00
QString condition;
};
using PBreakpoint = std::shared_ptr<Breakpoint>;
struct Trace {
QString funcname;
QString filename;
int line;
};
using PTrace = std::shared_ptr<Trace>;
struct Register {
QString name;
2021-07-17 19:32:23 +08:00
QString hexValue;
QString decValue;
2021-07-03 21:57:50 +08:00
};
using PRegister = std::shared_ptr<Register>;
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;
void update(const QList<PRegister>& regs);
void clear();
private:
QList<PRegister> mRegisters;
};
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;
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;
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 clear();
const QList<PWatchVar>& watchVars();
PWatchVar findWatchVar(const QString& name);
PWatchVar findWatchVar(int gdbIndex);
2021-07-31 20:19:45 +08:00
void notifyUpdated(PWatchVar var);
2021-07-31 14:04:43 +08:00
private:
QList<PWatchVar> mWatchVars;
};
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,
bool updateWatch = true,
bool showInConsole = false,
DebugCommandSource source = DebugCommandSource::Other);
2021-08-29 22:08:43 +08:00
bool commandRunning();
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 removeBreakpoint(int line, const Editor* editor);
void removeBreakpoint(int line, const QString& filename);
void removeBreakpoint(int index);
void setBreakPointCondition(int index, const QString& condition);
2021-07-25 13:03:46 +08:00
void sendAllBreakpointsToDebugger();
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 deleteWatchVars(bool deleteparent);
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);
void notifyWatchVarUpdated(PWatchVar var);
2021-07-26 18:22:09 +08:00
void updateDebugInfo();
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);
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-07-30 23:28:58 +08:00
void onChangeDebugConsoleLastline(const QString& text);
2021-07-31 14:04:43 +08:00
void clearUpReader();
2021-08-01 10:00:27 +08:00
void onAddLocalWithoutLinebreak(const QString& text);
void onAddLocalWithLinebreak(const QString& text);
void onClearLocals();
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-07-19 23:02:32 +08:00
void postCommand(const QString &Command, const QString &Params,
bool UpdateWatch, bool ShowInConsole, DebugCommandSource Source);
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-08-01 01:06:43 +08:00
bool invalidateAllVars() const;
void setInvalidateAllVars(bool invalidateAllVars);
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 pauseWatchUpdate();
void updateWatch();
void processError(QProcess::ProcessError error);
2021-08-01 10:00:27 +08:00
void changeDebugConsoleLastLine(const QString& text);
void addLocalWithoutLinebreak(const QString& text);
void addLocalWithLinebreak(const QString& text);
void clearLocals();
2021-07-03 21:57:50 +08:00
private:
void clearCmdQueue();
bool findAnnotation(AnnotationType annotation);
AnnotationType getAnnotation(const QString& s);
2021-07-19 23:02:32 +08:00
AnnotationType getLastAnnotation(const QByteArray& text);
2021-07-03 21:57:50 +08:00
AnnotationType getNextAnnotation();
2021-07-17 19:32:23 +08:00
QString getNextFilledLine();
QString getNextLine();
QString getNextWord();
QString getRemainingLine();
void handleDisassembly();
void handleDisplay();
void handleError();
void handleExit();
void handleFrames();
void handleLocalOutput();
void handleLocals();
void handleParams();
void handleRegisters();
2021-07-18 00:18:07 +08:00
void handleSignal();
void handleSource();
void handleValueHistoryValue();
AnnotationType peekNextAnnotation();
void processDebugOutput();
2021-07-18 08:52:53 +08:00
QString processEvalOutput();
void processWatchOutput(PWatchVar WatchVar);
2021-07-19 23:02:32 +08:00
void runNextCmd();
void skipSpaces();
void skipToAnnotation();
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;
int mUpdateCount;
bool mInvalidateAllVars;
//fOnInvalidateAllVars: TInvalidateAllVarsEvent;
bool mCmdRunning;
PDebugCommand mCurrentCmd;
QList<PRegister> mRegisters;
QStringList mDisassembly;
2021-07-24 08:12:51 +08:00
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;
int mIndex;
int mBreakPointLine;
QString mBreakPointFile;
QString mOutput;
QString mEvalValue;
QString mSignal;
bool mUseUTF8;
// attempt to cut down on Synchronize calls
bool dobacktraceready;
bool dodisassemblerready;
bool doregistersready;
bool doevalready;
bool doprocessexited;
bool doupdatecpuwindow;
bool doupdateexecution;
bool doreceivedsignal;
bool doreceivedsfwarning;
2021-07-19 23:02:32 +08:00
bool mStop;
2021-07-26 11:47:54 +08:00
friend class Debugger;
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