work save: refactor: DebuggerClient interface
This commit is contained in:
parent
4567e11f43
commit
581b7c7cf1
|
@ -121,12 +121,14 @@ SOURCES += \
|
||||||
compiler/projectcompiler.cpp \
|
compiler/projectcompiler.cpp \
|
||||||
compiler/runner.cpp \
|
compiler/runner.cpp \
|
||||||
customfileiconprovider.cpp \
|
customfileiconprovider.cpp \
|
||||||
gdbmiresultparser.cpp \
|
|
||||||
compiler/compiler.cpp \
|
compiler/compiler.cpp \
|
||||||
compiler/compilermanager.cpp \
|
compiler/compilermanager.cpp \
|
||||||
compiler/executablerunner.cpp \
|
compiler/executablerunner.cpp \
|
||||||
compiler/filecompiler.cpp \
|
compiler/filecompiler.cpp \
|
||||||
compiler/stdincompiler.cpp \
|
compiler/stdincompiler.cpp \
|
||||||
|
debugger/debugger.cpp \
|
||||||
|
debugger/gdbmidebugger.cpp \
|
||||||
|
debugger/gdbmiresultparser.cpp \
|
||||||
cpprefacter.cpp \
|
cpprefacter.cpp \
|
||||||
parser/cppparser.cpp \
|
parser/cppparser.cpp \
|
||||||
parser/cpppreprocessor.cpp \
|
parser/cpppreprocessor.cpp \
|
||||||
|
@ -179,7 +181,6 @@ SOURCES += \
|
||||||
widgets/codecompletionlistview.cpp \
|
widgets/codecompletionlistview.cpp \
|
||||||
widgets/codecompletionpopup.cpp \
|
widgets/codecompletionpopup.cpp \
|
||||||
widgets/cpudialog.cpp \
|
widgets/cpudialog.cpp \
|
||||||
debugger/debugger.cpp \
|
|
||||||
editor.cpp \
|
editor.cpp \
|
||||||
editorlist.cpp \
|
editorlist.cpp \
|
||||||
iconsmanager.cpp \
|
iconsmanager.cpp \
|
||||||
|
@ -255,9 +256,11 @@ HEADERS += \
|
||||||
compiler/projectcompiler.h \
|
compiler/projectcompiler.h \
|
||||||
compiler/runner.h \
|
compiler/runner.h \
|
||||||
compiler/stdincompiler.h \
|
compiler/stdincompiler.h \
|
||||||
|
debugger/debugger.h \
|
||||||
|
debugger/gdbmidebugger.h \
|
||||||
|
debugger/gdbmiresultparser.h \
|
||||||
cpprefacter.h \
|
cpprefacter.h \
|
||||||
customfileiconprovider.h \
|
customfileiconprovider.h \
|
||||||
gdbmiresultparser.h \
|
|
||||||
parser/cppparser.h \
|
parser/cppparser.h \
|
||||||
parser/cpppreprocessor.h \
|
parser/cpppreprocessor.h \
|
||||||
parser/cpptokenizer.h \
|
parser/cpptokenizer.h \
|
||||||
|
@ -309,7 +312,6 @@ HEADERS += \
|
||||||
widgets/codecompletionlistview.h \
|
widgets/codecompletionlistview.h \
|
||||||
widgets/codecompletionpopup.h \
|
widgets/codecompletionpopup.h \
|
||||||
widgets/cpudialog.h \
|
widgets/cpudialog.h \
|
||||||
debugger/debugger.h \
|
|
||||||
editor.h \
|
editor.h \
|
||||||
editorlist.h \
|
editorlist.h \
|
||||||
iconsmanager.h \
|
iconsmanager.h \
|
||||||
|
|
|
@ -52,7 +52,7 @@ Debugger::Debugger(QObject *parent) : QObject(parent),
|
||||||
connect(mWatchModel.get(), &WatchModel::setWatchVarValue,
|
connect(mWatchModel.get(), &WatchModel::setWatchVarValue,
|
||||||
this, &Debugger::setWatchVarValue);
|
this, &Debugger::setWatchVarValue);
|
||||||
mExecuting = false;
|
mExecuting = false;
|
||||||
mReader = nullptr;
|
mClient = nullptr;
|
||||||
mTarget = nullptr;
|
mTarget = nullptr;
|
||||||
mCommandChanged = false;
|
mCommandChanged = false;
|
||||||
mLeftPageIndexBackup = -1;
|
mLeftPageIndexBackup = -1;
|
||||||
|
@ -158,56 +158,56 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin
|
||||||
mTarget->waitStart();
|
mTarget->waitStart();
|
||||||
}
|
}
|
||||||
//delete when thread finished
|
//delete when thread finished
|
||||||
mReader = new DebugReader(this);
|
mClient = new DebuggerClient(this);
|
||||||
mReader->addBinDirs(binDirs);
|
mClient->addBinDirs(binDirs);
|
||||||
mReader->addBinDir(pSettings->dirs().appDir());
|
mClient->addBinDir(pSettings->dirs().appDir());
|
||||||
mReader->setDebuggerPath(debuggerPath);
|
mClient->setDebuggerPath(debuggerPath);
|
||||||
connect(mReader, &QThread::finished,this,&Debugger::cleanUpReader);
|
connect(mClient, &QThread::finished,this,&Debugger::cleanUpReader);
|
||||||
connect(mReader, &QThread::finished,mMemoryModel.get(),&MemoryModel::reset);
|
connect(mClient, &QThread::finished,mMemoryModel.get(),&MemoryModel::reset);
|
||||||
connect(mReader, &DebugReader::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection);
|
connect(mClient, &DebuggerClient::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection);
|
||||||
connect(mReader, &DebugReader::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline);
|
connect(mClient, &DebuggerClient::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline);
|
||||||
connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions);
|
connect(mClient, &DebuggerClient::cmdStarted,pMainWindow, &MainWindow::disableDebugActions);
|
||||||
connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions);
|
connect(mClient, &DebuggerClient::cmdFinished,pMainWindow, &MainWindow::enableDebugActions);
|
||||||
connect(mReader, &DebugReader::inferiorStopped, pMainWindow, &MainWindow::enableDebugActions);
|
connect(mClient, &DebuggerClient::inferiorStopped, pMainWindow, &MainWindow::enableDebugActions);
|
||||||
|
|
||||||
connect(mReader, &DebugReader::breakpointInfoGetted, mBreakpointModel.get(),
|
connect(mClient, &DebuggerClient::breakpointInfoGetted, mBreakpointModel.get(),
|
||||||
&BreakpointModel::updateBreakpointNumber);
|
&BreakpointModel::updateBreakpointNumber);
|
||||||
connect(mReader, &DebugReader::localsUpdated, pMainWindow,
|
connect(mClient, &DebuggerClient::localsUpdated, pMainWindow,
|
||||||
&MainWindow::onLocalsReady);
|
&MainWindow::onLocalsReady);
|
||||||
connect(mReader, &DebugReader::memoryUpdated,this,
|
connect(mClient, &DebuggerClient::memoryUpdated,this,
|
||||||
&Debugger::updateMemory);
|
&Debugger::updateMemory);
|
||||||
connect(mReader, &DebugReader::evalUpdated,this,
|
connect(mClient, &DebuggerClient::evalUpdated,this,
|
||||||
&Debugger::updateEval);
|
&Debugger::updateEval);
|
||||||
connect(mReader, &DebugReader::disassemblyUpdate,this,
|
connect(mClient, &DebuggerClient::disassemblyUpdate,this,
|
||||||
&Debugger::updateDisassembly);
|
&Debugger::updateDisassembly);
|
||||||
connect(mReader, &DebugReader::registerNamesUpdated, this,
|
connect(mClient, &DebuggerClient::registerNamesUpdated, this,
|
||||||
&Debugger::updateRegisterNames);
|
&Debugger::updateRegisterNames);
|
||||||
connect(mReader, &DebugReader::registerValuesUpdated, this,
|
connect(mClient, &DebuggerClient::registerValuesUpdated, this,
|
||||||
&Debugger::updateRegisterValues);
|
&Debugger::updateRegisterValues);
|
||||||
connect(mReader, &DebugReader::varCreated,mWatchModel.get(),
|
connect(mClient, &DebuggerClient::varCreated,mWatchModel.get(),
|
||||||
&WatchModel::updateVarInfo);
|
&WatchModel::updateVarInfo);
|
||||||
connect(mReader, &DebugReader::prepareVarChildren,mWatchModel.get(),
|
connect(mClient, &DebuggerClient::prepareVarChildren,mWatchModel.get(),
|
||||||
&WatchModel::prepareVarChildren);
|
&WatchModel::prepareVarChildren);
|
||||||
connect(mReader, &DebugReader::addVarChild,mWatchModel.get(),
|
connect(mClient, &DebuggerClient::addVarChild,mWatchModel.get(),
|
||||||
&WatchModel::addVarChild);
|
&WatchModel::addVarChild);
|
||||||
connect(mReader, &DebugReader::varValueUpdated,mWatchModel.get(),
|
connect(mClient, &DebuggerClient::varValueUpdated,mWatchModel.get(),
|
||||||
&WatchModel::updateVarValue);
|
&WatchModel::updateVarValue);
|
||||||
connect(mReader, &DebugReader::varsValueUpdated,mWatchModel.get(),
|
connect(mClient, &DebuggerClient::varsValueUpdated,mWatchModel.get(),
|
||||||
&WatchModel::updateAllHasMoreVars);
|
&WatchModel::updateAllHasMoreVars);
|
||||||
connect(mReader, &DebugReader::inferiorContinued,pMainWindow,
|
connect(mClient, &DebuggerClient::inferiorContinued,pMainWindow,
|
||||||
&MainWindow::removeActiveBreakpoints);
|
&MainWindow::removeActiveBreakpoints);
|
||||||
connect(mReader, &DebugReader::inferiorStopped,pMainWindow,
|
connect(mClient, &DebuggerClient::inferiorStopped,pMainWindow,
|
||||||
&MainWindow::setActiveBreakpoint);
|
&MainWindow::setActiveBreakpoint);
|
||||||
connect(mReader, &DebugReader::watchpointHitted,pMainWindow,
|
connect(mClient, &DebuggerClient::watchpointHitted,pMainWindow,
|
||||||
&MainWindow::onWatchpointHitted);
|
&MainWindow::onWatchpointHitted);
|
||||||
connect(mReader, &DebugReader::errorNoSymbolTable,pMainWindow,
|
connect(mClient, &DebuggerClient::errorNoSymbolTable,pMainWindow,
|
||||||
&MainWindow::stopDebugForNoSymbolTable);
|
&MainWindow::stopDebugForNoSymbolTable);
|
||||||
connect(mReader, &DebugReader::inferiorStopped,this,
|
connect(mClient, &DebuggerClient::inferiorStopped,this,
|
||||||
&Debugger::refreshAll);
|
&Debugger::refreshAll);
|
||||||
|
|
||||||
mReader->registerInferiorStoppedCommand("-stack-list-frames","");
|
mClient->registerInferiorStoppedCommand("-stack-list-frames","");
|
||||||
mReader->start();
|
mClient->start();
|
||||||
mReader->waitStart();
|
mClient->waitStart();
|
||||||
|
|
||||||
pMainWindow->updateAppTitle();
|
pMainWindow->updateAppTitle();
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ void Debugger::stop() {
|
||||||
mTarget->stopDebug();
|
mTarget->stopDebug();
|
||||||
mTarget = nullptr;
|
mTarget = nullptr;
|
||||||
}
|
}
|
||||||
mReader->stopDebug();
|
mClient->stopDebug();
|
||||||
}
|
}
|
||||||
mCurrentSourceFile="";
|
mCurrentSourceFile="";
|
||||||
}
|
}
|
||||||
|
@ -230,8 +230,8 @@ void Debugger::cleanUpReader()
|
||||||
mExecuting = false;
|
mExecuting = false;
|
||||||
|
|
||||||
//stop debugger
|
//stop debugger
|
||||||
mReader->deleteLater();
|
mClient->deleteLater();
|
||||||
mReader=nullptr;
|
mClient=nullptr;
|
||||||
|
|
||||||
if (pMainWindow->cpuDialog()!=nullptr) {
|
if (pMainWindow->cpuDialog()!=nullptr) {
|
||||||
pMainWindow->cpuDialog()->close();
|
pMainWindow->cpuDialog()->close();
|
||||||
|
@ -290,23 +290,23 @@ std::shared_ptr<WatchModel> Debugger::watchModel() const
|
||||||
|
|
||||||
void Debugger::sendCommand(const QString &command, const QString ¶ms, DebugCommandSource source)
|
void Debugger::sendCommand(const QString &command, const QString ¶ms, DebugCommandSource source)
|
||||||
{
|
{
|
||||||
if (mExecuting && mReader) {
|
if (mExecuting && mClient) {
|
||||||
mReader->postCommand(command,params,source);
|
mClient->postCommand(command,params,source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::commandRunning()
|
bool Debugger::commandRunning()
|
||||||
{
|
{
|
||||||
if (mExecuting && mReader) {
|
if (mExecuting && mClient) {
|
||||||
return mReader->commandRunning();
|
return mClient->commandRunning();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Debugger::inferiorRunning()
|
bool Debugger::inferiorRunning()
|
||||||
{
|
{
|
||||||
if (mExecuting && mReader) {
|
if (mExecuting && mClient) {
|
||||||
return mReader->inferiorRunning();
|
return mClient->inferiorRunning();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -876,7 +876,7 @@ void Debugger::syncFinishedParsing()
|
||||||
bool spawnedcpuform = false;
|
bool spawnedcpuform = false;
|
||||||
|
|
||||||
// GDB determined that the source code is more recent than the executable. Ask the user if he wants to rebuild.
|
// GDB determined that the source code is more recent than the executable. Ask the user if he wants to rebuild.
|
||||||
if (mReader->receivedSFWarning()) {
|
if (mClient->receivedSFWarning()) {
|
||||||
if (QMessageBox::question(pMainWindow,
|
if (QMessageBox::question(pMainWindow,
|
||||||
tr("Compile"),
|
tr("Compile"),
|
||||||
tr("Source file is more recent than executable.")+"<BR /><BR />" + tr("Recompile?"),
|
tr("Source file is more recent than executable.")+"<BR /><BR />" + tr("Recompile?"),
|
||||||
|
@ -892,20 +892,20 @@ void Debugger::syncFinishedParsing()
|
||||||
// show command output
|
// show command output
|
||||||
if (pSettings->debugger().enableDebugConsole() ) {
|
if (pSettings->debugger().enableDebugConsole() ) {
|
||||||
if (pSettings->debugger().showDetailLog()) {
|
if (pSettings->debugger().showDetailLog()) {
|
||||||
for (const QString& line:mReader->fullOutput()) {
|
for (const QString& line:mClient->fullOutput()) {
|
||||||
pMainWindow->addDebugOutput(line);
|
pMainWindow->addDebugOutput(line);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mReader->currentCmd() && mReader->currentCmd()->command == "disas") {
|
if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (const QString& line:mReader->consoleOutput()) {
|
for (const QString& line:mClient->consoleOutput()) {
|
||||||
pMainWindow->addDebugOutput(line);
|
pMainWindow->addDebugOutput(line);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(mReader->currentCmd()
|
(mClient->currentCmd()
|
||||||
&& mReader->currentCmd()->source== DebugCommandSource::Console)
|
&& mClient->currentCmd()->source== DebugCommandSource::Console)
|
||||||
|| !mReader->consoleOutput().isEmpty() ) {
|
|| !mClient->consoleOutput().isEmpty() ) {
|
||||||
pMainWindow->addDebugOutput("(gdb)");
|
pMainWindow->addDebugOutput("(gdb)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -913,20 +913,20 @@ void Debugger::syncFinishedParsing()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The program to debug has stopped. Stop the debugger
|
// The program to debug has stopped. Stop the debugger
|
||||||
if (mReader->processExited()) {
|
if (mClient->processExited()) {
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mReader->signalReceived()
|
if (mClient->signalReceived()
|
||||||
&& mReader->signalName()!="SIGINT"
|
&& mClient->signalName()!="SIGINT"
|
||||||
&& mReader->signalName()!="SIGTRAP") {
|
&& mClient->signalName()!="SIGTRAP") {
|
||||||
SignalMessageDialog dialog(pMainWindow);
|
SignalMessageDialog dialog(pMainWindow);
|
||||||
dialog.setOpenCPUInfo(pSettings->debugger().openCPUInfoWhenSignaled());
|
dialog.setOpenCPUInfo(pSettings->debugger().openCPUInfoWhenSignaled());
|
||||||
dialog.setMessage(
|
dialog.setMessage(
|
||||||
tr("Signal \"%1\" Received: ").arg(mReader->signalName())
|
tr("Signal \"%1\" Received: ").arg(mClient->signalName())
|
||||||
+ "<br />"
|
+ "<br />"
|
||||||
+ mReader->signalMeaning());
|
+ mClient->signalMeaning());
|
||||||
int result = dialog.exec();
|
int result = dialog.exec();
|
||||||
if (result == QDialog::Accepted && dialog.openCPUInfo()) {
|
if (result == QDialog::Accepted && dialog.openCPUInfo()) {
|
||||||
pMainWindow->showCPUInfoDialog();
|
pMainWindow->showCPUInfoDialog();
|
||||||
|
@ -934,7 +934,7 @@ void Debugger::syncFinishedParsing()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPU form updates itself when spawned, don't update twice!
|
// CPU form updates itself when spawned, don't update twice!
|
||||||
if ((mReader->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) {
|
if ((mClient->updateCPUInfo() && !spawnedcpuform) && (pMainWindow->cpuDialog()!=nullptr)) {
|
||||||
pMainWindow->cpuDialog()->updateInfo();
|
pMainWindow->cpuDialog()->updateInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -990,7 +990,7 @@ bool Debugger::executing() const
|
||||||
return mExecuting;
|
return mExecuting;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent),
|
DebuggerClient::DebuggerClient(Debugger* debugger, QObject *parent) : QThread(parent),
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||||
mCmdQueueMutex(),
|
mCmdQueueMutex(),
|
||||||
#else
|
#else
|
||||||
|
@ -1004,36 +1004,13 @@ DebugReader::DebugReader(Debugger* debugger, QObject *parent) : QThread(parent),
|
||||||
mAsyncUpdated = false;
|
mAsyncUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::postCommand(const QString &Command, const QString &Params,
|
void DebuggerClient::clearCmdQueue()
|
||||||
DebugCommandSource Source)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
|
||||||
PDebugCommand pCmd = std::make_shared<DebugCommand>();
|
|
||||||
pCmd->command = Command;
|
|
||||||
pCmd->params = Params;
|
|
||||||
pCmd->source = Source;
|
|
||||||
mCmdQueue.enqueue(pCmd);
|
|
||||||
// if (!mCmdRunning)
|
|
||||||
// runNextCmd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugReader::registerInferiorStoppedCommand(const QString &Command, const QString &Params)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
|
||||||
PDebugCommand pCmd = std::make_shared<DebugCommand>();
|
|
||||||
pCmd->command = Command;
|
|
||||||
pCmd->params = Params;
|
|
||||||
pCmd->source = DebugCommandSource::Other;
|
|
||||||
mInferiorStoppedHookCommands.append(pCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugReader::clearCmdQueue()
|
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
mCmdQueue.clear();
|
mCmdQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processConsoleOutput(const QByteArray& line)
|
void DebuggerClient::processConsoleOutput(const QByteArray& line)
|
||||||
{
|
{
|
||||||
if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) {
|
if (line.length()>3 && line.startsWith("~\"") && line.endsWith("\"")) {
|
||||||
QByteArray s=line.mid(2,line.length()-3);
|
QByteArray s=line.mid(2,line.length()-3);
|
||||||
|
@ -1119,7 +1096,7 @@ void DebugReader::processConsoleOutput(const QByteArray& line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processLogOutput(const QByteArray &line)
|
void DebuggerClient::processLogOutput(const QByteArray &line)
|
||||||
{
|
{
|
||||||
if (mDebugger->debugInfosUsingUTF8() && line.endsWith(": No such file or directory.\n\"")) {
|
if (mDebugger->debugInfosUsingUTF8() && line.endsWith(": No such file or directory.\n\"")) {
|
||||||
QByteArray newLine = line;
|
QByteArray newLine = line;
|
||||||
|
@ -1133,7 +1110,7 @@ void DebugReader::processLogOutput(const QByteArray &line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processResult(const QByteArray &result)
|
void DebuggerClient::processResult(const QByteArray &result)
|
||||||
{
|
{
|
||||||
GDBMIResultParser parser;
|
GDBMIResultParser parser;
|
||||||
GDBMIResultType resultType;
|
GDBMIResultType resultType;
|
||||||
|
@ -1186,7 +1163,7 @@ void DebugReader::processResult(const QByteArray &result)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processExecAsyncRecord(const QByteArray &line)
|
void DebuggerClient::processExecAsyncRecord(const QByteArray &line)
|
||||||
{
|
{
|
||||||
QByteArray result;
|
QByteArray result;
|
||||||
GDBMIResultParser::ParseObject multiValues;
|
GDBMIResultParser::ParseObject multiValues;
|
||||||
|
@ -1260,7 +1237,7 @@ void DebugReader::processExecAsyncRecord(const QByteArray &line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processError(const QByteArray &errorLine)
|
void DebuggerClient::processError(const QByteArray &errorLine)
|
||||||
{
|
{
|
||||||
QString s = QString::fromLocal8Bit(errorLine);
|
QString s = QString::fromLocal8Bit(errorLine);
|
||||||
mConsoleOutput.append(s);
|
mConsoleOutput.append(s);
|
||||||
|
@ -1272,7 +1249,7 @@ void DebugReader::processError(const QByteArray &errorLine)
|
||||||
}
|
}
|
||||||
static QRegularExpression reGdbSourceLine("^(\\d)+\\s+in\\s+(.+)$");
|
static QRegularExpression reGdbSourceLine("^(\\d)+\\s+in\\s+(.+)$");
|
||||||
|
|
||||||
void DebugReader::processResultRecord(const QByteArray &line)
|
void DebuggerClient::processResultRecord(const QByteArray &line)
|
||||||
{
|
{
|
||||||
if (line.startsWith("^exit")) {
|
if (line.startsWith("^exit")) {
|
||||||
mProcessExited = true;
|
mProcessExited = true;
|
||||||
|
@ -1337,7 +1314,7 @@ void DebugReader::processResultRecord(const QByteArray &line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::processDebugOutput(const QByteArray& debugOutput)
|
void DebuggerClient::processDebugOutput(const QByteArray& debugOutput)
|
||||||
{
|
{
|
||||||
// Only update once per update at most
|
// Only update once per update at most
|
||||||
//WatchView.Items.BeginUpdate;
|
//WatchView.Items.BeginUpdate;
|
||||||
|
@ -1385,7 +1362,7 @@ void DebugReader::processDebugOutput(const QByteArray& debugOutput)
|
||||||
mFullOutput.clear();
|
mFullOutput.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::runInferiorStoppedHook()
|
void DebuggerClient::runInferiorStoppedHook()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
foreach (const PDebugCommand& cmd, mInferiorStoppedHookCommands) {
|
foreach (const PDebugCommand& cmd, mInferiorStoppedHookCommands) {
|
||||||
|
@ -1393,7 +1370,7 @@ void DebugReader::runInferiorStoppedHook()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::runNextCmd()
|
void DebuggerClient::runNextCmd()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
|
|
||||||
|
@ -1406,7 +1383,7 @@ void DebugReader::runNextCmd()
|
||||||
if (mCmdQueue.isEmpty()) {
|
if (mCmdQueue.isEmpty()) {
|
||||||
if (mDebugger->useDebugServer() && mInferiorRunning && !mAsyncUpdated) {
|
if (mDebugger->useDebugServer() && mInferiorRunning && !mAsyncUpdated) {
|
||||||
mAsyncUpdated = true;
|
mAsyncUpdated = true;
|
||||||
QTimer::singleShot(50,this,&DebugReader::asyncUpdate);
|
QTimer::singleShot(50,this,&DebuggerClient::asyncUpdate);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1451,7 +1428,6 @@ void DebugReader::runNextCmd()
|
||||||
emit writeToDebugFailed();
|
emit writeToDebugFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if devDebugger.ShowCommandLog or pCmd^.ShowInConsole then begin
|
|
||||||
if (pSettings->debugger().enableDebugConsole() ) {
|
if (pSettings->debugger().enableDebugConsole() ) {
|
||||||
//update debug console
|
//update debug console
|
||||||
if (pSettings->debugger().showDetailLog()
|
if (pSettings->debugger().showDetailLog()
|
||||||
|
@ -1461,7 +1437,7 @@ void DebugReader::runNextCmd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList DebugReader::tokenize(const QString &s)
|
QStringList DebuggerClient::tokenize(const QString &s)
|
||||||
{
|
{
|
||||||
QStringList result;
|
QStringList result;
|
||||||
int tStart,tEnd;
|
int tStart,tEnd;
|
||||||
|
@ -1557,7 +1533,7 @@ QStringList DebugReader::tokenize(const QString &s)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::outputTerminated(const QByteArray &text)
|
bool DebuggerClient::outputTerminated(const QByteArray &text)
|
||||||
{
|
{
|
||||||
QStringList lines = textToLines(QString::fromUtf8(text));
|
QStringList lines = textToLines(QString::fromUtf8(text));
|
||||||
foreach (const QString& line,lines) {
|
foreach (const QString& line,lines) {
|
||||||
|
@ -1567,7 +1543,7 @@ bool DebugReader::outputTerminated(const QByteArray &text)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint)
|
void DebuggerClient::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpoint)
|
||||||
{
|
{
|
||||||
QString filename;
|
QString filename;
|
||||||
// gdb use system encoding for file path
|
// gdb use system encoding for file path
|
||||||
|
@ -1580,7 +1556,7 @@ void DebugReader::handleBreakpoint(const GDBMIResultParser::ParseObject& breakpo
|
||||||
emit breakpointInfoGetted(filename, line , number);
|
emit breakpointInfoGetted(filename, line , number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleFrame(const GDBMIResultParser::ParseValue &frame)
|
void DebuggerClient::handleFrame(const GDBMIResultParser::ParseValue &frame)
|
||||||
{
|
{
|
||||||
if (frame.isValid()) {
|
if (frame.isValid()) {
|
||||||
GDBMIResultParser::ParseObject frameObj = frame.object();
|
GDBMIResultParser::ParseObject frameObj = frame.object();
|
||||||
|
@ -1598,7 +1574,7 @@ void DebugReader::handleFrame(const GDBMIResultParser::ParseValue &frame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleStack(const QList<GDBMIResultParser::ParseValue> & stack)
|
void DebuggerClient::handleStack(const QList<GDBMIResultParser::ParseValue> & stack)
|
||||||
{
|
{
|
||||||
mDebugger->backtraceModel()->clear();
|
mDebugger->backtraceModel()->clear();
|
||||||
foreach (const GDBMIResultParser::ParseValue& frameValue, stack) {
|
foreach (const GDBMIResultParser::ParseValue& frameValue, stack) {
|
||||||
|
@ -1616,7 +1592,7 @@ void DebugReader::handleStack(const QList<GDBMIResultParser::ParseValue> & stack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleLocalVariables(const QList<GDBMIResultParser::ParseValue> &variables)
|
void DebuggerClient::handleLocalVariables(const QList<GDBMIResultParser::ParseValue> &variables)
|
||||||
{
|
{
|
||||||
QStringList locals;
|
QStringList locals;
|
||||||
foreach (const GDBMIResultParser::ParseValue& varValue, variables) {
|
foreach (const GDBMIResultParser::ParseValue& varValue, variables) {
|
||||||
|
@ -1633,12 +1609,12 @@ void DebugReader::handleLocalVariables(const QList<GDBMIResultParser::ParseValue
|
||||||
emit localsUpdated(locals);
|
emit localsUpdated(locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleEvaluation(const QString &value)
|
void DebuggerClient::handleEvaluation(const QString &value)
|
||||||
{
|
{
|
||||||
emit evalUpdated(value);
|
emit evalUpdated(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleMemory(const QList<GDBMIResultParser::ParseValue> &rows)
|
void DebuggerClient::handleMemory(const QList<GDBMIResultParser::ParseValue> &rows)
|
||||||
{
|
{
|
||||||
QStringList memory;
|
QStringList memory;
|
||||||
foreach (const GDBMIResultParser::ParseValue& row, rows) {
|
foreach (const GDBMIResultParser::ParseValue& row, rows) {
|
||||||
|
@ -1654,7 +1630,7 @@ void DebugReader::handleMemory(const QList<GDBMIResultParser::ParseValue> &rows)
|
||||||
emit memoryUpdated(memory);
|
emit memoryUpdated(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleRegisterNames(const QList<GDBMIResultParser::ParseValue> &names)
|
void DebuggerClient::handleRegisterNames(const QList<GDBMIResultParser::ParseValue> &names)
|
||||||
{
|
{
|
||||||
QStringList nameList;
|
QStringList nameList;
|
||||||
foreach (const GDBMIResultParser::ParseValue& nameValue, names) {
|
foreach (const GDBMIResultParser::ParseValue& nameValue, names) {
|
||||||
|
@ -1665,7 +1641,7 @@ void DebugReader::handleRegisterNames(const QList<GDBMIResultParser::ParseValue>
|
||||||
emit registerNamesUpdated(nameList);
|
emit registerNamesUpdated(nameList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleRegisterValue(const QList<GDBMIResultParser::ParseValue> &values)
|
void DebuggerClient::handleRegisterValue(const QList<GDBMIResultParser::ParseValue> &values)
|
||||||
{
|
{
|
||||||
QHash<int,QString> result;
|
QHash<int,QString> result;
|
||||||
foreach (const GDBMIResultParser::ParseValue& val, values) {
|
foreach (const GDBMIResultParser::ParseValue& val, values) {
|
||||||
|
@ -1683,7 +1659,7 @@ void DebugReader::handleRegisterValue(const QList<GDBMIResultParser::ParseValue>
|
||||||
emit registerValuesUpdated(result);
|
emit registerValuesUpdated(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleCreateVar(const GDBMIResultParser::ParseObject &multiVars)
|
void DebuggerClient::handleCreateVar(const GDBMIResultParser::ParseObject &multiVars)
|
||||||
{
|
{
|
||||||
if (!mCurrentCmd)
|
if (!mCurrentCmd)
|
||||||
return;
|
return;
|
||||||
|
@ -1696,7 +1672,7 @@ void DebugReader::handleCreateVar(const GDBMIResultParser::ParseObject &multiVar
|
||||||
emit varCreated(expression,name,numChild,value,type,hasMore);
|
emit varCreated(expression,name,numChild,value,type,hasMore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleListVarChildren(const GDBMIResultParser::ParseObject &multiVars)
|
void DebuggerClient::handleListVarChildren(const GDBMIResultParser::ParseObject &multiVars)
|
||||||
{
|
{
|
||||||
if (!mCurrentCmd)
|
if (!mCurrentCmd)
|
||||||
return;
|
return;
|
||||||
|
@ -1723,7 +1699,7 @@ void DebugReader::handleListVarChildren(const GDBMIResultParser::ParseObject &mu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::handleUpdateVarValue(const QList<GDBMIResultParser::ParseValue> &changes)
|
void DebuggerClient::handleUpdateVarValue(const QList<GDBMIResultParser::ParseValue> &changes)
|
||||||
{
|
{
|
||||||
foreach (const GDBMIResultParser::ParseValue& value, changes) {
|
foreach (const GDBMIResultParser::ParseValue& value, changes) {
|
||||||
GDBMIResultParser::ParseObject obj = value.object();
|
GDBMIResultParser::ParseObject obj = value.object();
|
||||||
|
@ -1741,7 +1717,7 @@ void DebugReader::handleUpdateVarValue(const QList<GDBMIResultParser::ParseValue
|
||||||
//emit varsValueUpdated();
|
//emit varsValueUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray DebugReader::removeToken(const QByteArray &line)
|
QByteArray DebuggerClient::removeToken(const QByteArray &line)
|
||||||
{
|
{
|
||||||
int p=0;
|
int p=0;
|
||||||
while (p<line.length()) {
|
while (p<line.length()) {
|
||||||
|
@ -1756,7 +1732,7 @@ QByteArray DebugReader::removeToken(const QByteArray &line)
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::asyncUpdate()
|
void DebuggerClient::asyncUpdate()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mCmdQueueMutex);
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
if (mCmdQueue.isEmpty()) {
|
if (mCmdQueue.isEmpty()) {
|
||||||
|
@ -1765,172 +1741,91 @@ void DebugReader::asyncUpdate()
|
||||||
mAsyncUpdated = false;
|
mAsyncUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList &DebugReader::binDirs() const
|
const QStringList &DebuggerClient::binDirs() const
|
||||||
{
|
{
|
||||||
return mBinDirs;
|
return mBinDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::addBinDirs(const QStringList &binDirs)
|
void DebuggerClient::addBinDirs(const QStringList &binDirs)
|
||||||
{
|
{
|
||||||
mBinDirs.append(binDirs);
|
mBinDirs.append(binDirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::addBinDir(const QString &binDir)
|
void DebuggerClient::addBinDir(const QString &binDir)
|
||||||
{
|
{
|
||||||
mBinDirs.append(binDir);
|
mBinDirs.append(binDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &DebugReader::signalMeaning() const
|
const QString &DebuggerClient::signalMeaning() const
|
||||||
{
|
{
|
||||||
return mSignalMeaning;
|
return mSignalMeaning;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &DebugReader::signalName() const
|
const QString &DebuggerClient::signalName() const
|
||||||
{
|
{
|
||||||
return mSignalName;
|
return mSignalName;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::inferiorRunning() const
|
bool DebuggerClient::inferiorRunning() const
|
||||||
{
|
{
|
||||||
return mInferiorRunning;
|
return mInferiorRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList &DebugReader::fullOutput() const
|
const QStringList &DebuggerClient::fullOutput() const
|
||||||
{
|
{
|
||||||
return mFullOutput;
|
return mFullOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::receivedSFWarning() const
|
bool DebuggerClient::receivedSFWarning() const
|
||||||
{
|
{
|
||||||
return mReceivedSFWarning;
|
return mReceivedSFWarning;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::updateCPUInfo() const
|
bool DebuggerClient::updateCPUInfo() const
|
||||||
{
|
{
|
||||||
return mUpdateCPUInfo;
|
return mUpdateCPUInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDebugCommand &DebugReader::currentCmd() const
|
const PDebugCommand &DebuggerClient::currentCmd() const
|
||||||
{
|
{
|
||||||
return mCurrentCmd;
|
return mCurrentCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList &DebugReader::consoleOutput() const
|
const QStringList &DebuggerClient::consoleOutput() const
|
||||||
{
|
{
|
||||||
return mConsoleOutput;
|
return mConsoleOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::signalReceived() const
|
bool DebuggerClient::signalReceived() const
|
||||||
{
|
{
|
||||||
return mSignalReceived;
|
return mSignalReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugReader::processExited() const
|
bool DebuggerClient::processExited() const
|
||||||
{
|
{
|
||||||
return mProcessExited;
|
return mProcessExited;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DebugReader::debuggerPath() const
|
QString DebuggerClient::debuggerPath() const
|
||||||
{
|
{
|
||||||
return mDebuggerPath;
|
return mDebuggerPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::setDebuggerPath(const QString &debuggerPath)
|
void DebuggerClient::setDebuggerPath(const QString &debuggerPath)
|
||||||
{
|
{
|
||||||
mDebuggerPath = debuggerPath;
|
mDebuggerPath = debuggerPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::stopDebug()
|
bool DebuggerClient::commandRunning()
|
||||||
{
|
|
||||||
mStop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DebugReader::commandRunning()
|
|
||||||
{
|
{
|
||||||
return !mCmdQueue.isEmpty();
|
return !mCmdQueue.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::waitStart()
|
void DebuggerClient::waitStart()
|
||||||
{
|
{
|
||||||
mStartSemaphore.acquire(1);
|
mStartSemaphore.acquire(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReader::run()
|
|
||||||
{
|
|
||||||
mStop = false;
|
|
||||||
mInferiorRunning = false;
|
|
||||||
mProcessExited = false;
|
|
||||||
mErrorOccured = false;
|
|
||||||
QString cmd = mDebuggerPath;
|
|
||||||
// QString arguments = "--annotate=2";
|
|
||||||
QStringList arguments{"--interpret=mi", "--silent"};
|
|
||||||
QString workingDir = QFileInfo(mDebuggerPath).path();
|
|
||||||
|
|
||||||
mProcess = std::make_shared<QProcess>();
|
|
||||||
auto action = finally([&]{
|
|
||||||
mProcess.reset();
|
|
||||||
});
|
|
||||||
mProcess->setProgram(cmd);
|
|
||||||
mProcess->setArguments(arguments);
|
|
||||||
mProcess->setProcessChannelMode(QProcess::MergedChannels);
|
|
||||||
|
|
||||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
|
||||||
QString path = env.value("PATH");
|
|
||||||
QStringList pathAdded = mBinDirs;
|
|
||||||
if (!path.isEmpty()) {
|
|
||||||
path = pathAdded.join(PATH_SEPARATOR) + PATH_SEPARATOR + path;
|
|
||||||
} else {
|
|
||||||
path = pathAdded.join(PATH_SEPARATOR);
|
|
||||||
}
|
|
||||||
QString cmdDir = extractFileDir(cmd);
|
|
||||||
if (!cmdDir.isEmpty()) {
|
|
||||||
path = cmdDir + PATH_SEPARATOR + path;
|
|
||||||
}
|
|
||||||
env.insert("PATH",path);
|
|
||||||
mProcess->setProcessEnvironment(env);
|
|
||||||
|
|
||||||
mProcess->setWorkingDirectory(workingDir);
|
|
||||||
|
|
||||||
connect(mProcess.get(), &QProcess::errorOccurred,
|
|
||||||
[&](){
|
|
||||||
mErrorOccured= true;
|
|
||||||
});
|
|
||||||
QByteArray buffer;
|
|
||||||
QByteArray readed;
|
|
||||||
|
|
||||||
mProcess->start();
|
|
||||||
mProcess->waitForStarted(5000);
|
|
||||||
mStartSemaphore.release(1);
|
|
||||||
while (true) {
|
|
||||||
mProcess->waitForFinished(1);
|
|
||||||
if (mProcess->state()!=QProcess::Running) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mStop) {
|
|
||||||
mProcess->terminate();
|
|
||||||
mProcess->kill();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mErrorOccured)
|
|
||||||
break;
|
|
||||||
readed = mProcess->readAll();
|
|
||||||
buffer += readed;
|
|
||||||
|
|
||||||
if (readed.endsWith("\n")&& outputTerminated(buffer)) {
|
|
||||||
processDebugOutput(buffer);
|
|
||||||
buffer.clear();
|
|
||||||
mCmdRunning = false;
|
|
||||||
runNextCmd();
|
|
||||||
} else if (!mCmdRunning && readed.isEmpty()){
|
|
||||||
runNextCmd();
|
|
||||||
} else if (readed.isEmpty()){
|
|
||||||
msleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mErrorOccured) {
|
|
||||||
emit processError(mProcess->error());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakpointModel::BreakpointModel(QObject *parent):QAbstractTableModel(parent),
|
BreakpointModel::BreakpointModel(QObject *parent):QAbstractTableModel(parent),
|
||||||
mIsForProject(false)
|
mIsForProject(false)
|
||||||
|
|
|
@ -295,11 +295,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DebugReader;
|
class DebuggerClient;
|
||||||
class DebugTarget;
|
class DebugTarget;
|
||||||
class Editor;
|
class Editor;
|
||||||
|
|
||||||
using PDebugReader = std::shared_ptr<DebugReader>;
|
using PDebugReader = std::shared_ptr<DebuggerClient>;
|
||||||
|
|
||||||
class Debugger : public QObject
|
class Debugger : public QObject
|
||||||
{
|
{
|
||||||
|
@ -417,7 +417,7 @@ private:
|
||||||
std::shared_ptr<WatchModel> mWatchModel;
|
std::shared_ptr<WatchModel> mWatchModel;
|
||||||
std::shared_ptr<RegisterModel> mRegisterModel;
|
std::shared_ptr<RegisterModel> mRegisterModel;
|
||||||
std::shared_ptr<MemoryModel> mMemoryModel;
|
std::shared_ptr<MemoryModel> mMemoryModel;
|
||||||
DebugReader *mReader;
|
DebuggerClient *mClient;
|
||||||
DebugTarget *mTarget;
|
DebugTarget *mTarget;
|
||||||
bool mForceUTF8;
|
bool mForceUTF8;
|
||||||
bool mDebugInfosUsingUTF8;
|
bool mDebugInfosUsingUTF8;
|
||||||
|
@ -462,48 +462,29 @@ protected:
|
||||||
void run() override;
|
void run() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DebugReader : public QThread
|
class DebuggerClient : public QThread
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DebugReader(Debugger* debugger, QObject *parent = nullptr);
|
explicit DebuggerClient(Debugger* debugger, QObject *parent = nullptr);
|
||||||
void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source);
|
virtual void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) = 0;
|
||||||
void registerInferiorStoppedCommand(const QString &Command, const QString &Params);
|
virtual void registerInferiorStoppedCommand(const QString &Command, const QString &Params) = 0;
|
||||||
|
virtual void stopDebug() = 0;
|
||||||
|
bool commandRunning();
|
||||||
QString debuggerPath() const;
|
QString debuggerPath() const;
|
||||||
void setDebuggerPath(const QString &debuggerPath);
|
void setDebuggerPath(const QString &debuggerPath);
|
||||||
void stopDebug();
|
|
||||||
|
|
||||||
bool commandRunning();
|
|
||||||
void waitStart();
|
void waitStart();
|
||||||
|
|
||||||
bool inferiorPaused() const;
|
|
||||||
|
|
||||||
bool processExited() const;
|
bool processExited() const;
|
||||||
|
|
||||||
bool signalReceived() const;
|
bool signalReceived() const;
|
||||||
|
|
||||||
const QStringList &consoleOutput() const;
|
const QStringList &consoleOutput() const;
|
||||||
|
|
||||||
int breakPointLine() const;
|
|
||||||
|
|
||||||
const QString &breakPointFile() const;
|
|
||||||
|
|
||||||
const PDebugCommand ¤tCmd() const;
|
const PDebugCommand ¤tCmd() const;
|
||||||
|
|
||||||
bool updateCPUInfo() 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;
|
|
||||||
|
|
||||||
bool receivedSFWarning() const;
|
bool receivedSFWarning() const;
|
||||||
|
|
||||||
const QStringList &fullOutput() const;
|
const QStringList &fullOutput() const;
|
||||||
|
@ -585,22 +566,24 @@ private:
|
||||||
QByteArray removeToken(const QByteArray& line);
|
QByteArray removeToken(const QByteArray& line);
|
||||||
private slots:
|
private slots:
|
||||||
void asyncUpdate();
|
void asyncUpdate();
|
||||||
private:
|
protected:
|
||||||
Debugger *mDebugger;
|
|
||||||
QString mDebuggerPath;
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||||
QRecursiveMutex mCmdQueueMutex;
|
QRecursiveMutex mCmdQueueMutex;
|
||||||
#else
|
#else
|
||||||
QMutex mCmdQueueMutex;
|
QMutex mCmdQueueMutex;
|
||||||
#endif
|
#endif
|
||||||
QSemaphore mStartSemaphore;
|
|
||||||
QQueue<PDebugCommand> mCmdQueue;
|
QQueue<PDebugCommand> mCmdQueue;
|
||||||
|
QList<PDebugCommand> mInferiorStoppedHookCommands;
|
||||||
|
private:
|
||||||
|
Debugger *mDebugger;
|
||||||
|
QString mDebuggerPath;
|
||||||
|
|
||||||
|
QSemaphore mStartSemaphore;
|
||||||
bool mErrorOccured;
|
bool mErrorOccured;
|
||||||
bool mAsyncUpdated;
|
bool mAsyncUpdated;
|
||||||
//fOnInvalidateAllVars: TInvalidateAllVarsEvent;
|
//fOnInvalidateAllVars: TInvalidateAllVarsEvent;
|
||||||
bool mCmdRunning;
|
bool mCmdRunning;
|
||||||
PDebugCommand mCurrentCmd;
|
PDebugCommand mCurrentCmd;
|
||||||
std::shared_ptr<QProcess> mProcess;
|
|
||||||
QStringList mBinDirs;
|
QStringList mBinDirs;
|
||||||
QMap<QString,QStringList> mFileCache;
|
QMap<QString,QStringList> mFileCache;
|
||||||
|
|
||||||
|
@ -610,7 +593,6 @@ private:
|
||||||
QString mSignalMeaning;
|
QString mSignalMeaning;
|
||||||
|
|
||||||
//
|
//
|
||||||
QList<PDebugCommand> mInferiorStoppedHookCommands;
|
|
||||||
bool mInferiorRunning;
|
bool mInferiorRunning;
|
||||||
bool mProcessExited;
|
bool mProcessExited;
|
||||||
|
|
||||||
|
@ -624,10 +606,6 @@ private:
|
||||||
QString mCurrentFile;
|
QString mCurrentFile;
|
||||||
QStringList mConsoleOutput;
|
QStringList mConsoleOutput;
|
||||||
QStringList mFullOutput;
|
QStringList mFullOutput;
|
||||||
bool mStop;
|
|
||||||
// QThread interface
|
|
||||||
protected:
|
|
||||||
void run() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DEBUGGER_H
|
#endif // DEBUGGER_H
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "gdbmidebugger.h"
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
GDBMIDebuggerClient::GDBMIDebuggerClient(Debugger *debugger, QObject *parent):
|
||||||
|
DebuggerClient(debugger, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDBMIDebuggerClient::postCommand(const QString &Command, const QString &Params,
|
||||||
|
DebugCommandSource Source)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
|
PDebugCommand pCmd = std::make_shared<DebugCommand>();
|
||||||
|
pCmd->command = Command;
|
||||||
|
pCmd->params = Params;
|
||||||
|
pCmd->source = Source;
|
||||||
|
mCmdQueue.enqueue(pCmd);
|
||||||
|
// if (!mCmdRunning)
|
||||||
|
// runNextCmd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDBMIDebuggerClient::registerInferiorStoppedCommand(const QString &Command, const QString &Params)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mCmdQueueMutex);
|
||||||
|
PDebugCommand pCmd = std::make_shared<DebugCommand>();
|
||||||
|
pCmd->command = Command;
|
||||||
|
pCmd->params = Params;
|
||||||
|
pCmd->source = DebugCommandSource::Other;
|
||||||
|
mInferiorStoppedHookCommands.append(pCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDBMIDebuggerClient::stopDebug()
|
||||||
|
{
|
||||||
|
mStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDBMIDebuggerClient::run()
|
||||||
|
{
|
||||||
|
mStop = false;
|
||||||
|
mInferiorRunning = false;
|
||||||
|
mProcessExited = false;
|
||||||
|
mErrorOccured = false;
|
||||||
|
QString cmd = debuggerPath();
|
||||||
|
// QString arguments = "--annotate=2";
|
||||||
|
QStringList arguments{"--interpret=mi", "--silent"};
|
||||||
|
QString workingDir = QFileInfo(debuggerPath()).path();
|
||||||
|
|
||||||
|
mProcess = std::make_shared<QProcess>();
|
||||||
|
auto action = finally([&]{
|
||||||
|
mProcess.reset();
|
||||||
|
});
|
||||||
|
mProcess->setProgram(cmd);
|
||||||
|
mProcess->setArguments(arguments);
|
||||||
|
mProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
QString path = env.value("PATH");
|
||||||
|
QStringList pathAdded = binDirs();
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
path = pathAdded.join(PATH_SEPARATOR) + PATH_SEPARATOR + path;
|
||||||
|
} else {
|
||||||
|
path = pathAdded.join(PATH_SEPARATOR);
|
||||||
|
}
|
||||||
|
QString cmdDir = extractFileDir(cmd);
|
||||||
|
if (!cmdDir.isEmpty()) {
|
||||||
|
path = cmdDir + PATH_SEPARATOR + path;
|
||||||
|
}
|
||||||
|
env.insert("PATH",path);
|
||||||
|
mProcess->setProcessEnvironment(env);
|
||||||
|
|
||||||
|
mProcess->setWorkingDirectory(workingDir);
|
||||||
|
|
||||||
|
connect(mProcess.get(), &QProcess::errorOccurred,
|
||||||
|
[&](){
|
||||||
|
mErrorOccured= true;
|
||||||
|
});
|
||||||
|
QByteArray buffer;
|
||||||
|
QByteArray readed;
|
||||||
|
|
||||||
|
mProcess->start();
|
||||||
|
mProcess->waitForStarted(5000);
|
||||||
|
mStartSemaphore.release(1);
|
||||||
|
while (true) {
|
||||||
|
mProcess->waitForFinished(1);
|
||||||
|
if (mProcess->state()!=QProcess::Running) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mStop) {
|
||||||
|
mProcess->terminate();
|
||||||
|
mProcess->kill();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mErrorOccured)
|
||||||
|
break;
|
||||||
|
readed = mProcess->readAll();
|
||||||
|
buffer += readed;
|
||||||
|
|
||||||
|
if (readed.endsWith("\n")&& outputTerminated(buffer)) {
|
||||||
|
processDebugOutput(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
mCmdRunning = false;
|
||||||
|
runNextCmd();
|
||||||
|
} else if (!mCmdRunning && readed.isEmpty()){
|
||||||
|
runNextCmd();
|
||||||
|
} else if (readed.isEmpty()){
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mErrorOccured) {
|
||||||
|
emit processError(mProcess->error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef GDBMI_DEBUGGER_H
|
||||||
|
#define GDBMI_DEBUGGER_H
|
||||||
|
|
||||||
|
#include "debugger.h"
|
||||||
|
#include <QProcess>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class GDBMIDebuggerClient: public DebuggerClient {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GDBMIDebuggerClient(Debugger* debugger, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
// DebuggerClient interface
|
||||||
|
public:
|
||||||
|
void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) override;
|
||||||
|
void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override;
|
||||||
|
void stopDebug() override;
|
||||||
|
// QThread interface
|
||||||
|
protected:
|
||||||
|
void run() override;
|
||||||
|
private:
|
||||||
|
bool mStop;
|
||||||
|
std::shared_ptr<QProcess> mProcess;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GDBMI_DEBUGGER_H
|
|
@ -125,4 +125,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SYNEDITASMHIGHLIGHTER_H
|
#endif // QSYNEDIT_ASM_SYNTAXER_H
|
||||||
|
|
|
@ -221,4 +221,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SYNEDITCPPHIGHLIGHTER_H
|
#endif // QSYNEDIT_CPP_SYNTAXER_H
|
||||||
|
|
|
@ -186,4 +186,4 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // SYNEDITGLSLHIGHLIGHTER_H
|
#endif // QSYNEDIT_GLSL_SYNTAXER_H
|
||||||
|
|
|
@ -175,4 +175,4 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SYNEDITCPPHIGHLIGHTER_H
|
#endif // QSYNEDIT_LUA_SYNTAXER_H
|
||||||
|
|
|
@ -155,4 +155,4 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // MAKEFILE_H
|
#endif // QSYNEDIT_MAKEFILE_SYNTAXER_H
|
||||||
|
|
|
@ -195,4 +195,4 @@ private:
|
||||||
using PSyntaxer = std::shared_ptr<Syntaxer>;
|
using PSyntaxer = std::shared_ptr<Syntaxer>;
|
||||||
using SyntaxerList = QVector<PSyntaxer>;
|
using SyntaxerList = QVector<PSyntaxer>;
|
||||||
}
|
}
|
||||||
#endif // SYNHIGHLIGTERBASE_H
|
#endif // QSYNEDIT_SYNTAXER_H
|
||||||
|
|
|
@ -84,4 +84,4 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // MAKEFILE_H
|
#endif // QSYNEDIT_TEXTFILE_SYNTAXER_H
|
||||||
|
|
Loading…
Reference in New Issue