work save: #259 Remove hard-coded GDB-MI commands outside the gdbmi implementation.

This commit is contained in:
Roy Qu 2024-03-10 21:25:24 +08:00
parent b83c45782b
commit 9cb980f2f6
8 changed files with 214 additions and 145 deletions

View File

@ -71,16 +71,16 @@ void DAPDebuggerClient::run()
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 (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 (errorOccured) {
emit processFailed(mProcess->error());

View File

@ -31,13 +31,8 @@ protected:
// 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;
DebuggerType clientType() override;
protected:
void runNextCmd() override;
private:
void initializeRequest();
private:

View File

@ -73,7 +73,12 @@ Debugger::~Debugger()
// delete mMemoryModel;
}
bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStringList& binDirs, const QString& sourceFile)
bool Debugger::startClient(int compilerSetIndex,
const QString& inferior,
bool inferiorHasSymbols,
bool inferiorHasBreakpoints,
const QStringList& binDirs,
const QString& sourceFile)
{
mCurrentSourceFile = sourceFile;
Settings::PCompilerSet compilerSet = pSettings->compilerSets().getSet(compilerSetIndex);
@ -206,15 +211,33 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin
connect(mClient, &DebuggerClient::inferiorStopped,this,
&Debugger::refreshAll);
mClient->registerInferiorStoppedCommand("-stack-list-frames","");
mClient->start();
mClient->waitStart();
pMainWindow->updateAppTitle();
mClient->initialize(inferior, inferiorHasSymbols);
includeOrSkipDirsInSymbolSearch(compilerSet->libDirs(), pSettings->debugger().skipCustomLibraries());
includeOrSkipDirsInSymbolSearch(compilerSet->CIncludeDirs(), pSettings->debugger().skipCustomLibraries());
includeOrSkipDirsInSymbolSearch(compilerSet->CppIncludeDirs(), pSettings->debugger().skipCustomLibraries());
//Application.HintHidePause := 5000;
//gcc system libraries is auto loaded by gdb
if (pSettings->debugger().skipSystemLibraries()) {
includeOrSkipDirsInSymbolSearch(compilerSet->defaultCIncludeDirs(),true);
includeOrSkipDirsInSymbolSearch(compilerSet->defaultCIncludeDirs(),true);
includeOrSkipDirsInSymbolSearch(compilerSet->defaultCppIncludeDirs(),true);
}
sendAllBreakpointsToDebugger();
pMainWindow->updateAppTitle();
mInferiorHasBreakpoints = inferiorHasBreakpoints;
return true;
}
void Debugger::runInferior()
{
if (mClient)
mClient->runInferior(mInferiorHasBreakpoints);
}
void Debugger::stop() {
if (mExecuting) {
if (mTarget) {
@ -355,6 +378,17 @@ void Debugger::stepIntoInstruction()
mClient->stepIntoInstruction();
}
void Debugger::runClientCommand(const QString &command, const QString &params, DebugCommandSource source)
{
if (!mClient)
return;
if (mClient->clientType()!=DebuggerType::GDB
&& mClient->clientType()!=DebuggerType::LLDB_MI)
return;
GDBMIDebuggerClient* gdbmiClient = dynamic_cast<GDBMIDebuggerClient*>(mClient);
gdbmiClient->postCommand(command, params, source);
}
bool Debugger::isForProject() const
{
return mBreakpointModel->isForProject();
@ -930,6 +964,15 @@ void Debugger::addWatchVar(const PWatchVar &watchVar, bool forProject)
sendWatchCommand(watchVar);
}
void Debugger::includeOrSkipDirsInSymbolSearch(const QStringList &dirs, bool skip)
{
if (skip) {
mClient->skipDirectoriesInSymbolSearch(dirs);
} else {
mClient->addSymbolSearchDirectories(dirs);
}
}
void Debugger::syncFinishedParsing()
{
bool spawnedcpuform = false;
@ -955,19 +998,23 @@ void Debugger::syncFinishedParsing()
pMainWindow->addDebugOutput(line);
}
} else {
if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") {
// if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") {
} else {
for (const QString& line:mClient->consoleOutput()) {
pMainWindow->addDebugOutput(line);
}
if (
(mClient->currentCmd()
&& mClient->currentCmd()->source== DebugCommandSource::Console)
|| !mClient->consoleOutput().isEmpty() ) {
pMainWindow->addDebugOutput("(gdb)");
}
// } else {
// for (const QString& line:mClient->consoleOutput()) {
// pMainWindow->addDebugOutput(line);
// }
// if (
// (mClient->currentCmd()
// && mClient->currentCmd()->source== DebugCommandSource::Console)
// || !mClient->consoleOutput().isEmpty() ) {
// pMainWindow->addDebugOutput("(gdb)");
// }
// }
for (const QString& line:mClient->consoleOutput()) {
pMainWindow->addDebugOutput(line);
}
pMainWindow->addDebugOutput("(gdb)");
}
}
@ -1133,11 +1180,6 @@ void DebuggerClient::setDebuggerPath(const QString &debuggerPath)
mDebuggerPath = debuggerPath;
}
bool DebuggerClient::commandRunning()
{
return !mCmdQueue.isEmpty();
}
void DebuggerClient::waitStart()
{
mStartSemaphore.acquire(1);

View File

@ -302,7 +302,14 @@ public:
explicit Debugger(QObject *parent = nullptr);
~Debugger();
// Play/pause
bool start(int compilerSetIndex, const QString& inferior, const QStringList& binDirs, const QString& sourceFile=QString());
bool startClient(
int compilerSetIndex,
const QString& inferior,
bool inferiorHasSymbols,
bool inferiorHasBreakpoints,
const QStringList& binDirs,
const QString& sourceFile=QString());
void runInferior();
bool commandRunning();
bool inferiorRunning();
void interrupt();
@ -314,6 +321,8 @@ public:
void stepOverInstruction();
void stepIntoInstruction();
void runClientCommand(const QString &command, const QString &params, DebugCommandSource source);
bool isForProject() const;
void setIsForProject(bool newIsForProject);
void clearForProject();
@ -359,6 +368,8 @@ public:
void refreshRegisters();
void disassembleCurrentFrame(bool blendMode);
void setDisassemblyLanguage(bool isIntel);
void includeOrSkipDirsInSymbolSearch(const QStringList &dirs, bool skip);
// void notifyWatchVarUpdated(PWatchVar var);
std::shared_ptr<BacktraceModel> backtraceModel();
@ -433,6 +444,7 @@ private:
qint64 mLastLoadtime;
qint64 mProjectLastLoadtime;
QString mCurrentSourceFile;
bool mInferiorHasBreakpoints;
};
class DebugTarget: public QThread {
@ -473,10 +485,8 @@ class DebuggerClient : public QThread
Q_OBJECT
public:
explicit DebuggerClient(Debugger* debugger, QObject *parent = nullptr);
virtual void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) = 0;
virtual void registerInferiorStoppedCommand(const QString &Command, const QString &Params) = 0;
virtual void stopDebug() = 0;
bool commandRunning();
virtual bool commandRunning() = 0;
QString debuggerPath() const;
void setDebuggerPath(const QString &debuggerPath);
void waitStart();
@ -508,6 +518,9 @@ public:
virtual DebuggerType clientType() = 0;
//requests
virtual void initialize(const QString& inferior, bool hasSymbols) = 0;
virtual void runInferior(bool hasBreakpoints) = 0;
virtual void stepOver() = 0;
virtual void stepInto() = 0;
virtual void stepOut() = 0;
@ -542,6 +555,8 @@ public:
virtual void disassembleCurrentFrame(bool blendMode) = 0;
virtual void setDisassemblyLanguage(bool isIntel) = 0;
virtual void skipDirectoriesInSymbolSearch(const QStringList& lst) = 0;
virtual void addSymbolSearchDirectories(const QStringList& lst) = 0;
signals:
void parseStarted();
void invalidateAllVars();
@ -579,8 +594,6 @@ signals:
const QString& newType, int newNumChildren,
bool hasMore);
void varsValueUpdated();
protected:
virtual void runNextCmd() = 0;
protected:
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QRecursiveMutex mCmdQueueMutex;

View File

@ -35,27 +35,28 @@ GDBMIDebuggerClient::GDBMIDebuggerClient(
{
mProcess = std::make_shared<QProcess>();
mAsyncUpdated = false;
registerInferiorStoppedCommand("-stack-list-frames","");
}
void GDBMIDebuggerClient::postCommand(const QString &Command, const QString &Params,
DebugCommandSource Source)
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;
pCmd->command = command;
pCmd->params = params;
pCmd->source = source;
mCmdQueue.enqueue(pCmd);
// if (!mCmdRunning)
// runNextCmd();
}
void GDBMIDebuggerClient::registerInferiorStoppedCommand(const QString &Command, const QString &Params)
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->command = command;
pCmd->params = params;
pCmd->source = DebugCommandSource::Other;
mInferiorStoppedHookCommands.append(pCmd);
}
@ -874,6 +875,52 @@ const PDebugCommand &GDBMIDebuggerClient::currentCmd() const
return mCurrentCmd;
}
void GDBMIDebuggerClient::initialize(const QString& inferior, bool hasSymbols)
{
postCommand("-gdb-set", "mi-async on");
postCommand("-enable-pretty-printing","");
postCommand("-data-list-register-names","");
postCommand("-gdb-set", "width 0"); // don't wrap output, very annoying
postCommand("-gdb-set", "confirm off");
postCommand("-gdb-set", "print repeats 10");
postCommand("-gdb-set", "print null-stop");
postCommand("-gdb-set", QString("print elements %1").arg(pSettings->debugger().arrayElements())); // limit array elements to 30
postCommand("-gdb-set", QString("print characters %1").arg(pSettings->debugger().characters())); // limit array elements to 300
postCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(inferior))); // restore working directory
if (hasSymbols) {
postCommand("-file-exec-and-symbols", '"' + inferior + '"');
} else {
postCommand("-file-exec-file", '"' + inferior + '"');
}
}
void GDBMIDebuggerClient::runInferior(bool hasBreakpoints)
{
if (debugger()->useDebugServer()) {
postCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort()));
if (!hasBreakpoints) {
postCommand("-break-insert","-t main");
}
if (pSettings->executor().useParams()) {
postCommand("-exec-arguments", pSettings->executor().params());
}
postCommand("-exec-continue","");
} else {
#ifdef Q_OS_WIN
postCommand("-gdb-set", "new-console on");
#endif
if (pSettings->executor().useParams()) {
postCommand("-exec-arguments", pSettings->executor().params());
}
if (!hasBreakpoints) {
postCommand("-exec-run","--start");
} else {
postCommand("-exec-run","");
}
}
}
void GDBMIDebuggerClient::stepOver()
{
postCommand("-exec-next", "");
@ -1058,6 +1105,25 @@ void GDBMIDebuggerClient::setDisassemblyLanguage(bool isIntel)
}
}
void GDBMIDebuggerClient::skipDirectoriesInSymbolSearch(const QStringList &lst)
{
foreach(const QString &dirName, lst) {
postCommand(
"skip",
QString("-gfi \"%1/%2\"")
.arg(dirName,"*.*"));
}
}
void GDBMIDebuggerClient::addSymbolSearchDirectories(const QStringList &lst)
{
foreach(const QString &dirName, lst) {
postCommand(
"-environment-directory",
QString("\"%1\"").arg(dirName));
}
}
void GDBMIDebuggerClient::runInferiorStoppedHook()
{
QMutexLocker locker(&mCmdQueueMutex);
@ -1071,3 +1137,8 @@ void GDBMIDebuggerClient::clearCmdQueue()
QMutexLocker locker(&mCmdQueueMutex);
mCmdQueue.clear();
}
bool GDBMIDebuggerClient::commandRunning()
{
return !mCmdQueue.isEmpty();
}

View File

@ -42,11 +42,15 @@ public:
// DebuggerClient interface
public:
void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source = DebugCommandSource::Other) override;
void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override;
void postCommand(const QString &command, const QString &params, DebugCommandSource source = DebugCommandSource::Other);
void stopDebug() override;
DebuggerType clientType() override;
const PDebugCommand &currentCmd() const;
bool commandRunning() override;
void initialize(const QString& inferior, bool hasSymbols) override;
void runInferior(bool hasBreakpoints) override;
void stepOver() override;
void stepInto() override;
@ -76,14 +80,19 @@ public:
void evalExpression(const QString& expression) override;
void selectFrame(PTrace trace) override;
void refreshFrame() override;
void refreshRegisters() override;
void disassembleCurrentFrame(bool blendMode) override;
void setDisassemblyLanguage(bool isIntel) override;
void skipDirectoriesInSymbolSearch(const QStringList& lst) override;
void addSymbolSearchDirectories(const QStringList& lst) override;
// QThread interface
protected:
void run() override;
void runNextCmd() override;
void runNextCmd();
private:
QStringList tokenize(const QString& s) const;
bool outputTerminated(const QByteArray& text) const;
@ -108,6 +117,7 @@ private:
QByteArray removeToken(const QByteArray& line) const;
void runInferiorStoppedHook();
void clearCmdQueue();
void registerInferiorStoppedCommand(const QString &command, const QString &params);
private slots:
void asyncUpdate();
private:

View File

@ -2283,7 +2283,7 @@ void MainWindow::debug()
QStringList binDirs;
QSet<QString> unitFiles;
switch(getCompileTarget()) {
case CompileTarget::Project:
case CompileTarget::Project: {
compilerSet=pSettings->compilerSets().getSet(mProject->options().compilerSet);
if (!compilerSet)
compilerSet = pSettings->compilerSets().defaultSet();
@ -2384,21 +2384,29 @@ void MainWindow::debug()
unitFiles.insert(unit->fileName());
}
mDebugger->deleteInvalidProjectBreakpoints(unitFiles);
if (!mDebugger->start(mProject->options().compilerSet, filePath, binDirs))
return;
filePath.replace('\\','/');
mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"');
bool inferiorHasSymbols { true };
QString inferior { filePath };
if (mProject->options().type == ProjectType::DynamicLib) {
QString host =mProject->options().hostApplication;
host.replace('\\','/');
mDebugger->sendCommand("-file-exec-file", '"' + host + '"');
inferior=mProject->options().hostApplication;
inferiorHasSymbols = false;
}
inferior.replace('\\','/');
if (!mDebugger->startClient(
mProject->options().compilerSet,
inferior,
inferiorHasSymbols,
debugInferiorhasBreakpoint(),
binDirs
))
return;
includeOrSkipDirs(mProject->options().includeDirs,
pSettings->debugger().skipProjectLibraries());
includeOrSkipDirs(mProject->options().libDirs,
pSettings->debugger().skipProjectLibraries());
mDebugger->includeOrSkipDirsInSymbolSearch(
mProject->options().includeDirs,
pSettings->debugger().skipProjectLibraries());
mDebugger->includeOrSkipDirsInSymbolSearch(
mProject->options().libDirs,
pSettings->debugger().skipProjectLibraries());
}
break;
case CompileTarget::File: {
binDirs = compilerSet->binDirs();
@ -2480,9 +2488,14 @@ void MainWindow::debug()
prepareDebugger();
QString filePath = debugFile.filePath().replace('\\','/');
if (!mDebugger->start(pSettings->compilerSets().defaultIndex(),filePath, binDirs,e->filename()))
if (!mDebugger->startClient(
pSettings->compilerSets().defaultIndex(),
filePath,
true,
debugInferiorhasBreakpoint(),
binDirs,
e->filename()))
return;
mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(filePath));
}
}
break;
@ -2494,53 +2507,7 @@ void MainWindow::debug()
updateEditorActions();
// Add library folders
includeOrSkipDirs(compilerSet->libDirs(), pSettings->debugger().skipCustomLibraries());
includeOrSkipDirs(compilerSet->CIncludeDirs(), pSettings->debugger().skipCustomLibraries());
includeOrSkipDirs(compilerSet->CppIncludeDirs(), pSettings->debugger().skipCustomLibraries());
//gcc system libraries is auto loaded by gdb
if (pSettings->debugger().skipSystemLibraries()) {
includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true);
includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true);
includeOrSkipDirs(compilerSet->defaultCppIncludeDirs(),true);
}
mDebugger->sendAllBreakpointsToDebugger();
// Run the debugger
mDebugger->sendCommand("-gdb-set", "mi-async on");
mDebugger->sendCommand("-enable-pretty-printing","");
mDebugger->sendCommand("-data-list-register-names","");
mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying
mDebugger->sendCommand("-gdb-set", "confirm off");
mDebugger->sendCommand("-gdb-set", "print repeats 10");
mDebugger->sendCommand("-gdb-set", "print null-stop");
mDebugger->sendCommand("-gdb-set", QString("print elements %1").arg(pSettings->debugger().arrayElements())); // limit array elements to 30
mDebugger->sendCommand("-gdb-set", QString("print characters %1").arg(pSettings->debugger().characters())); // limit array elements to 300
mDebugger->sendCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(filePath))); // restore working directory
if (mDebugger->useDebugServer()) {
mDebugger->sendCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort()));
if (!debugInferiorhasBreakpoint() || !debugEnabled) {
mDebugger->sendCommand("-break-insert","-t main");
}
if (pSettings->executor().useParams()) {
mDebugger->sendCommand("-exec-arguments", pSettings->executor().params());
}
mDebugger->sendCommand("-exec-continue","");
} else {
#ifdef Q_OS_WIN
mDebugger->sendCommand("-gdb-set", "new-console on");
#endif
if (pSettings->executor().useParams()) {
mDebugger->sendCommand("-exec-arguments", pSettings->executor().params());
}
if (!debugInferiorhasBreakpoint()) {
mDebugger->sendCommand("-exec-run","--start");
} else {
mDebugger->sendCommand("-exec-run","");
}
}
mDebugger->runInferior();
}
void MainWindow::showSearchPanel(bool showReplace)
@ -3184,24 +3151,6 @@ void MainWindow::scanActiveProject(bool parse)
};
}
void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip)
{
Q_ASSERT(mDebugger);
foreach (QString dir,dirs) {
QString dirName = dir.replace('\\','/');
if (skip) {
mDebugger->sendCommand(
"skip",
QString("-gfi \"%1/%2\"")
.arg(dirName,"*.*"));
} else {
mDebugger->sendCommand(
"-environment-directory",
QString("\"%1\"").arg(dirName));
}
}
}
void MainWindow::onBookmarkContextMenu(const QPoint &pos)
{
QMenu menu(this);
@ -6150,7 +6099,7 @@ void MainWindow::cleanUpCPUDialog()
void MainWindow::onDebugCommandInput(const QString& command)
{
if (mDebugger->executing()) {
mDebugger->sendCommand(command,"", DebugCommandSource::Console);
mDebugger->runClientCommand(command,"", DebugCommandSource::Console);
}
}
@ -6399,16 +6348,6 @@ bool MainWindow::debugInferiorhasBreakpoint()
return true;
}
}
// if (!e->inProject()) {
// } else {
// for (const PBreakpoint& breakpoint:mDebugger->breakpointModel()->breakpoints(e->inProject())) {
// Editor* e1 = mEditorList->getOpenedEditorByFilename(breakpoint->filename);
// if (e1 && e1->inProject()) {
// return true;
// }
// }
// }
return false;
}
@ -8770,7 +8709,7 @@ void MainWindow::switchCurrentStackTrace(int idx)
if (e) {
e->setCaretPositionAndActivate(trace->line,1);
}
mDebugger->sendCommand("-stack-select-frame", QString("%1").arg(trace->level));
mDebugger->selectFrame(trace);
mDebugger->refreshStackVariables();
mDebugger->refreshWatchVars();
if (this->mCPUDialog) {

View File

@ -310,7 +310,6 @@ private:
const QString& objectName,
QKeySequence shortcut=QKeySequence());
void scanActiveProject(bool parse=false);
void includeOrSkipDirs(const QStringList& dirs, bool skip);
void showSearchReplacePanel(bool show);
void clearIssues();
void doCompileRun(RunType runType);