diff options
Diffstat (limited to 'src/plugins/debugger')
32 files changed, 422 insertions, 123 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 75782ae6d5..13db44f7ca 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -665,7 +665,7 @@ void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data) if (partsMask & FileAndLinePart) { data->lineNumber = m_lineEditLineNumber->text().toInt(); data->pathUsage = static_cast<BreakpointPathUsage>(m_comboBoxPathUsage->currentIndex()); - data->fileName = FilePath::fromUserInput(m_pathChooserFileName->path()); + data->fileName = m_pathChooserFileName->filePath(); } if (partsMask & FunctionPart) data->functionName = m_lineEditFunction->text(); @@ -702,7 +702,7 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data) m_lineEditMessage->setText(data.message); if (mask & FileAndLinePart) { - m_pathChooserFileName->setFileName(data.fileName); + m_pathChooserFileName->setFilePath(data.fileName); m_lineEditLineNumber->setText(QString::number(data.lineNumber)); } @@ -1174,19 +1174,19 @@ void BreakHandler::removeAlienBreakpoint(const QString &rid) void BreakHandler::requestBreakpointInsertion(const Breakpoint &bp) { bp->gotoState(BreakpointInsertionRequested, BreakpointNew); - QTimer::singleShot(0, m_engine, [this, bp] { m_engine->insertBreakpoint(bp); }); + m_engine->insertBreakpoint(bp); } void BreakHandler::requestBreakpointUpdate(const Breakpoint &bp) { bp->gotoState(BreakpointUpdateRequested, BreakpointInserted); - QTimer::singleShot(0, m_engine, [this, bp] { m_engine->updateBreakpoint(bp); }); + m_engine->updateBreakpoint(bp); } void BreakHandler::requestBreakpointRemoval(const Breakpoint &bp) { bp->gotoState(BreakpointRemoveRequested, BreakpointInserted); - QTimer::singleShot(0, m_engine, [this, bp] { m_engine->removeBreakpoint(bp); }); + m_engine->removeBreakpoint(bp); } void BreakHandler::requestBreakpointEnabling(const Breakpoint &bp, bool enabled) @@ -1330,7 +1330,12 @@ void DebuggerEngine::notifyBreakpointInsertOk(const Breakpoint &bp) void DebuggerEngine::notifyBreakpointInsertFailed(const Breakpoint &bp) { QTC_ASSERT(bp, return); + GlobalBreakpoint gbp = bp->globalBreakpoint(); bp->gotoState(BreakpointDead, BreakpointInsertionProceeding); + breakHandler()->removeDisassemblerMarker(bp); + breakHandler()->destroyItem(bp); + QTC_ASSERT(gbp, return); + gbp->updateMarker(); } void DebuggerEngine::notifyBreakpointRemoveProceeding(const Breakpoint &bp) @@ -1509,7 +1514,7 @@ bool BreakHandler::setData(const QModelIndex &idx, const QVariant &value, int ro return contextMenuEvent(ev); if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete) { + if (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) { QModelIndexList si = ev.currentOrSelectedRows(); const Breakpoints bps = findBreakpointsByIndex(si); for (Breakpoint bp : bps) { @@ -2490,7 +2495,7 @@ GlobalBreakpoint BreakpointManager::findBreakpointFromContext(const ContextData matchLevel = 2; bestMatch = gbp; } else if (matchLevel < 2) { - for (const QPointer<DebuggerEngine> engine : EngineManager::engines()) { + for (const QPointer<DebuggerEngine> &engine : EngineManager::engines()) { BreakHandler *handler = engine->breakHandler(); for (Breakpoint bp : handler->breakpoints()) { if (bp->globalBreakpoint() == gbp) { @@ -2547,7 +2552,7 @@ bool BreakpointManager::setData(const QModelIndex &idx, const QVariant &value, i return contextMenuEvent(ev); if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete) { + if (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) { QModelIndexList si = ev.currentOrSelectedRows(); const GlobalBreakpoints gbps = findBreakpointsByIndex(si); for (GlobalBreakpoint gbp : gbps) diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 55a4bfd9bd..f0ee77b872 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -93,6 +93,7 @@ private: friend class BreakHandler; friend class BreakpointManager; friend class BreakpointMarker; + friend class DebuggerEngine; void updateMarker(); void updateMarkerIcon(); diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index a98ee3e9a7..056991b06b 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -966,6 +966,13 @@ void CdbEngine::executeDebuggerCommand(const QString &command) // Post command to the cdb process void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) { + constexpr int maxCommandLength = 4096; + constexpr int maxTokenLength = 4 /*" -t "*/ + + 5 /* 99999 tokens should be enough for a single qc run time*/ + + 1 /* token part splitter '.' */ + + 3 /* 1000 parts should also be more than enough */ + + 1 /* final space */; + QString cmd = dbgCmd.function + dbgCmd.argsToString(); if (!m_accessible) { doInterruptInferior([this, dbgCmd](){ @@ -977,11 +984,26 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) return; } + if (dbgCmd.flags == ScriptCommand) { + // repack script command into an extension command + DebuggerCommand newCmd("script", ExtensionCommand, dbgCmd.callback); + if (!dbgCmd.args.isNull()) + newCmd.args = QString{dbgCmd.function + '(' + dbgCmd.argsToPython() + ')'}; + else + newCmd.args = dbgCmd.function; + runCommand(newCmd); + return; + } + QString fullCmd; if (dbgCmd.flags == NoFlags) { - fullCmd = cmd; + fullCmd = cmd + '\n'; + if (fullCmd.length() > maxCommandLength) { + showMessage("Command is longer than 4096 characters execution will likely fail.", + LogWarning); + } } else { - const int token = m_nextCommandToken++; + const int token = ++m_nextCommandToken; StringInputStream str(fullCmd); if (dbgCmd.flags == BuiltinCommand) { // Post a built-in-command producing free-format output with a callback. @@ -989,23 +1011,35 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) // printing a specially formatted token to be identifiable in the output. str << ".echo \"" << m_tokenPrefix << token << "<\"\n" << cmd << "\n" - << ".echo \"" << m_tokenPrefix << token << ">\""; + << ".echo \"" << m_tokenPrefix << token << ">\"" << '\n'; + if (fullCmd.length() > maxCommandLength) { + showMessage("Command is longer than 4096 characters execution will likely fail.", + LogWarning); + } } else if (dbgCmd.flags == ExtensionCommand) { + // Post an extension command producing one-line output with a callback, // pass along token for identification in hash. - str << m_extensionCommandPrefix << dbgCmd.function << "%1%2"; - if (dbgCmd.args.isString()) - str << ' ' << dbgCmd.argsToString(); - cmd = fullCmd.arg("", ""); - fullCmd = fullCmd.arg(" -t ").arg(token); - } else if (dbgCmd.flags == ScriptCommand) { - // Add extension prefix and quotes the script command - // pass along token for identification in hash. - str << m_extensionCommandPrefix + "script %1%2 " << dbgCmd.function; - if (!dbgCmd.args.isNull()) - str << '(' << dbgCmd.argsToPython() << ')'; - cmd = fullCmd.arg("", ""); - fullCmd = fullCmd.arg(" -t ").arg(token); + const QString prefix = m_extensionCommandPrefix + dbgCmd.function; + QList<QStringRef> splittedArguments; + if (dbgCmd.args.isString()) { + const QString &arguments = dbgCmd.argsToString(); + cmd = prefix + arguments; + int argumentSplitPos = 0; + QList<QStringRef> splittedArguments; + int maxArgumentSize = maxCommandLength - prefix.length() - maxTokenLength; + while (argumentSplitPos < arguments.size()) { + splittedArguments << arguments.midRef(argumentSplitPos, maxArgumentSize); + argumentSplitPos += splittedArguments.last().length(); + } + QTC_CHECK(argumentSplitPos == arguments.size()); + int tokenPart = splittedArguments.size(); + for (const QStringRef &part : qAsConst(splittedArguments)) + str << prefix << " -t " << token << '.' << --tokenPart << ' ' << part << '\n'; + } else { + cmd = prefix; + str << prefix << " -t " << token << '.' << 0 << '\n'; + } } m_commandForToken.insert(token, dbgCmd); } @@ -1018,7 +1052,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd) qDebug("CdbEngine::postCommand: resulting command '%s'\n", qPrintable(fullCmd)); } showMessage(cmd, LogInput); - m_process.write(fullCmd.toLocal8Bit() + '\n'); + m_process.write(fullCmd.toLocal8Bit()); } void CdbEngine::activateFrame(int index) diff --git a/src/plugins/debugger/cdb/stringinputstream.h b/src/plugins/debugger/cdb/stringinputstream.h index 61c78c7a0a..21f4ccd14e 100644 --- a/src/plugins/debugger/cdb/stringinputstream.h +++ b/src/plugins/debugger/cdb/stringinputstream.h @@ -42,6 +42,7 @@ public: StringInputStream &operator<<(char a) { m_target.append(a); return *this; } StringInputStream &operator<<(const char *a) { m_target.append(QString::fromUtf8(a)); return *this; } StringInputStream &operator<<(const QString &a) { m_target.append(a); return *this; } + StringInputStream &operator<<(const QStringRef &a) { m_target.append(a); return *this; } StringInputStream &operator<<(int i) { appendInt(i); return *this; } StringInputStream &operator<<(unsigned i) { appendInt(i); return *this; } diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index 2f21805d27..24138b192c 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -296,7 +296,7 @@ public: label->setText("<html><head/><body>\n<p>" + tr("The debugging helpers are used to produce a nice " "display of objects of certain types like QString or " - "std::map in the "Locals and Expressions" view.") + "std::map in the "Locals" and "Expressions" views.") + "</p></body></html>"); auto groupBoxCustomDumperCommands = new QGroupBox(debuggingHelperGroupBox); diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index f47dc28937..9df57cb430 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -169,7 +169,7 @@ DebuggerSettings::DebuggerSettings() item->setCheckable(true); item->setDefaultValue(true); item->setSettingsKey(debugModeGroup, "AutoDerefPointers"); - item->setToolTip(tr("<p>This switches the Locals and Expressions view to " + item->setToolTip(tr("<p>This switches the Locals and Expressions views to " "automatically dereference pointers. This saves a level in the " "tree view, but also loses data for the now-missing intermediate " "level.")); @@ -587,7 +587,7 @@ DebuggerSettings::DebuggerSettings() item = new SavedAction; item->setSettingsKey(debugModeGroup, "DisplayStringLimit"); item->setToolTip(tr("<p>The maximum length of string entries in the " - "Locals and Expressions pane. Longer than that are cut off " + "Locals and Expressions views. Longer than that are cut off " "and displayed with an ellipsis attached.")); item->setDefaultValue(100); insertItem(DisplayStringLimit, item); diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 226026f99c..afaaf6af56 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -479,14 +479,14 @@ StartApplicationParameters StartApplicationDialog::parameters() const StartApplicationParameters result; result.serverPort = d->serverPortSpinBox->value(); result.serverAddress = d->channelOverrideEdit->text(); - result.runnable.executable = d->localExecutablePathChooser->fileName(); - result.serverStartScript = d->serverStartScriptPathChooser->fileName(); + result.runnable.executable = d->localExecutablePathChooser->filePath(); + result.serverStartScript = d->serverStartScriptPathChooser->filePath(); result.serverInitCommands = d->serverInitCommandsTextEdit->toPlainText(); result.serverResetCommands = d->serverResetCommandsTextEdit->toPlainText(); result.kitId = d->kitChooser->currentKitId(); - result.debugInfoLocation = d->debuginfoPathChooser->path(); + result.debugInfoLocation = d->debuginfoPathChooser->filePath().toString(); result.runnable.commandLineArguments = d->arguments->text(); - result.runnable.workingDirectory = d->workingDirectory->path(); + result.runnable.workingDirectory = d->workingDirectory->filePath().toString(); result.breakAtMain = d->breakAtMainCheckBox->isChecked(); result.runInTerminal = d->runInTerminalCheckBox->isChecked(); return result; @@ -497,8 +497,8 @@ void StartApplicationDialog::setParameters(const StartApplicationParameters &p) d->kitChooser->setCurrentKitId(p.kitId); d->serverPortSpinBox->setValue(p.serverPort); d->channelOverrideEdit->setText(p.serverAddress); - d->localExecutablePathChooser->setFileName(p.runnable.executable); - d->serverStartScriptPathChooser->setFileName(p.serverStartScript); + d->localExecutablePathChooser->setFilePath(p.runnable.executable); + d->serverStartScriptPathChooser->setFilePath(p.serverStartScript); d->serverInitCommandsTextEdit->setPlainText(p.serverInitCommands); d->serverResetCommandsTextEdit->setPlainText(p.serverResetCommands); d->debuginfoPathChooser->setPath(p.debugInfoLocation); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index ff3bc70788..bda6442e6b 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1760,11 +1760,11 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c case AppOutput: case AppStuff: d->m_logWindow->showOutput(channel, msg); - emit appendMessageRequested(msg, StdOutFormatSameLine, false); + emit appendMessageRequested(msg, StdOutFormat, false); break; case AppError: d->m_logWindow->showOutput(channel, msg); - emit appendMessageRequested(msg, StdErrFormatSameLine, false); + emit appendMessageRequested(msg, StdErrFormat, false); break; default: d->m_logWindow->showOutput(channel, msg); diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index bb31684a54..a0775c2da6 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -107,8 +107,8 @@ DebuggerItem::DebuggerItem(const QVariant &id) DebuggerItem::DebuggerItem(const QVariantMap &data) { m_id = data.value(DEBUGGER_INFORMATION_ID).toString(); - m_command = FilePath::fromUserInput(data.value(DEBUGGER_INFORMATION_COMMAND).toString()); - m_workingDirectory = FilePath::fromUserInput(data.value(DEBUGGER_INFORMATION_WORKINGDIRECTORY).toString()); + m_command = FilePath::fromVariant(data.value(DEBUGGER_INFORMATION_COMMAND)); + m_workingDirectory = FilePath::fromVariant(data.value(DEBUGGER_INFORMATION_WORKINGDIRECTORY)); m_unexpandedDisplayName = data.value(DEBUGGER_INFORMATION_DISPLAYNAME).toString(); m_isAutoDetected = data.value(DEBUGGER_INFORMATION_AUTODETECTED, false).toBool(); m_version = data.value(DEBUGGER_INFORMATION_VERSION).toString(); @@ -309,8 +309,8 @@ QVariantMap DebuggerItem::toMap() const QVariantMap data; data.insert(DEBUGGER_INFORMATION_DISPLAYNAME, m_unexpandedDisplayName); data.insert(DEBUGGER_INFORMATION_ID, m_id); - data.insert(DEBUGGER_INFORMATION_COMMAND, m_command.toString()); - data.insert(DEBUGGER_INFORMATION_WORKINGDIRECTORY, m_workingDirectory.toString()); + data.insert(DEBUGGER_INFORMATION_COMMAND, m_command.toVariant()); + data.insert(DEBUGGER_INFORMATION_WORKINGDIRECTORY, m_workingDirectory.toVariant()); data.insert(DEBUGGER_INFORMATION_ENGINETYPE, int(m_engineType)); data.insert(DEBUGGER_INFORMATION_AUTODETECTED, m_isAutoDetected); data.insert(DEBUGGER_INFORMATION_VERSION, m_version); diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 34ea3b46cd..4be3de93a9 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -348,8 +348,8 @@ DebuggerItem DebuggerItemConfigWidget::item() const { DebuggerItem item(m_id); item.setUnexpandedDisplayName(m_displayNameLineEdit->text()); - item.setCommand(m_binaryChooser->fileName()); - item.setWorkingDirectory(m_workingDirectoryChooser->fileName()); + item.setCommand(m_binaryChooser->filePath()); + item.setWorkingDirectory(m_workingDirectoryChooser->filePath()); item.setAutoDetected(m_autodetected); Abis abiList; const QStringList abis = m_abis->text().split(QRegExp("[^A-Za-z0-9-_]+")); @@ -390,10 +390,10 @@ void DebuggerItemConfigWidget::load(const DebuggerItem *item) m_typeLineEdit->setText(item->engineTypeName()); m_binaryChooser->setReadOnly(item->isAutoDetected()); - m_binaryChooser->setFileName(item->command()); + m_binaryChooser->setFilePath(item->command()); m_workingDirectoryChooser->setReadOnly(item->isAutoDetected()); - m_workingDirectoryChooser->setFileName(item->workingDirectory()); + m_workingDirectoryChooser->setFilePath(item->workingDirectory()); QString text; QString versionCommand; @@ -427,7 +427,7 @@ void DebuggerItemConfigWidget::binaryPathHasChanged() return; DebuggerItem tmp; - QFileInfo fi = QFileInfo(m_binaryChooser->path()); + QFileInfo fi = QFileInfo(m_binaryChooser->filePath().toString()); if (fi.isExecutable()) { tmp = item(); tmp.reinitializeFromFile(); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index 1c404a22b2..53e37ecc1a 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -250,8 +250,8 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent) m_toolBarDock = dock; q->addDockWidget(Qt::BottomDockWidgetArea, m_toolBarDock); - connect(viewButton, &QAbstractButton::clicked, this, [this, viewButton] { - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + connect(viewButton, &QAbstractButton::clicked, this, [viewButton] { + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); viewsMenu->menu()->exec(viewButton->mapToGlobal(QPoint())); }); @@ -277,7 +277,7 @@ DebuggerMainWindow::DebuggerMainWindow() Context debugcontext(Debugger::Constants::C_DEBUGMODE); - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); Command *cmd = ActionManager::registerAction(showCentralWidgetAction(), "Debugger.Views.ShowCentralWidget", debugcontext); cmd->setAttribute(Command::CA_Hide); @@ -315,7 +315,7 @@ DebuggerMainWindow::~DebuggerMainWindow() void DebuggerMainWindow::contextMenuEvent(QContextMenuEvent *ev) { - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); viewsMenu->menu()->exec(ev->globalPos()); } @@ -896,7 +896,7 @@ void Perspective::addWindow(QWidget *widget, Command *cmd = ActionManager::registerAction(op.toggleViewAction, op.commandId, d->context()); cmd->setAttribute(Command::CA_Hide); - ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd); + ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS)->addAction(cmd); } d->m_dockOperations.append(op); diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp index 91c32a15c1..076fd9723d 100644 --- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp +++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp @@ -27,17 +27,18 @@ #include "debuggerconstants.h" +#include <coreplugin/helpmanager.h> #include <coreplugin/icontext.h> #include <coreplugin/icore.h> -#include <coreplugin/helpmanager.h> +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/buildstep.h> +#include <projectexplorer/buildsteplist.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/project.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/runconfiguration.h> #include <projectexplorer/target.h> -#include <projectexplorer/buildconfiguration.h> -#include <projectexplorer/buildstep.h> -#include <projectexplorer/buildsteplist.h> +#include <qtsupport/qtbuildaspects.h> #include <QCheckBox> #include <QDebug> @@ -243,12 +244,9 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const // // Try to find a build configuration to check whether qml debugging is enabled there - // (Using the Qt metatype system to avoid a hard build system dependency) - // if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) { - const QVariant linkProperty = bc->property("linkQmlDebuggingLibrary"); - if (linkProperty.isValid() && linkProperty.canConvert(QVariant::Bool)) - return linkProperty.toBool(); + const auto aspect = bc->aspect<QtSupport::QmlDebuggingAspect>(); + return aspect && aspect->setting() == TriState::Enabled; } return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 463342357b..ee7c5dab36 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -128,14 +128,14 @@ public: { const QByteArray ba = m_proc.readAllStandardOutput(); const QString msg = QString::fromLocal8Bit(ba, ba.length()); - m_runTool->appendMessage(msg, StdOutFormatSameLine); + m_runTool->appendMessage(msg, StdOutFormat); } void handleStandardError() { const QByteArray ba = m_proc.readAllStandardError(); const QString msg = QString::fromLocal8Bit(ba, ba.length()); - m_runTool->appendMessage(msg, StdErrFormatSameLine); + m_runTool->appendMessage(msg, StdErrFormat); } void handleFinished() @@ -508,6 +508,11 @@ void DebuggerRunTool::addQmlServerInferiorCommandLineArgumentIfNeeded() d->addQmlServerInferiorCommandLineArgumentIfNeeded = true; } +void DebuggerRunTool::modifyDebuggerEnvironment(const EnvironmentItems &items) +{ + m_runParameters.debugger.environment.modify(items); +} + void DebuggerRunTool::setCrashParameter(const QString &event) { m_runParameters.crashParameter = event; @@ -689,10 +694,10 @@ void DebuggerRunTool::start() if (m_runParameters.startMode == StartInternal) { QStringList unhandledIds; - for (const GlobalBreakpoint bp : BreakpointManager::globalBreakpoints()) { +// for (const GlobalBreakpoint &bp : BreakpointManager::globalBreakpoints()) { // if (bp->isEnabled() && !m_engine->acceptsBreakpoint(bp)) // unhandledIds.append(bp.id().toString()); - } +// } if (!unhandledIds.isEmpty()) { QString warningMessage = DebuggerPlugin::tr("Some breakpoints cannot be handled by the debugger " @@ -895,6 +900,11 @@ Internal::TerminalRunner *DebuggerRunTool::terminalRunner() const return d->terminalRunner; } +DebuggerEngineType DebuggerRunTool::cppEngineType() const +{ + return m_runParameters.cppEngineType; +} + DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerminal) : RunWorker(runControl), d(new DebuggerRunToolPrivate) { @@ -972,7 +982,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm const Tasks tasks = DebuggerKitAspect::validateDebugger(kit); for (const Task &t : tasks) { if (t.type != Task::Warning) - m_runParameters.validationErrors.append(t.description); + m_runParameters.validationErrors.append(t.description()); } RunConfiguration *runConfig = runControl->runConfiguration(); @@ -1030,10 +1040,10 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout) m_engine->showMessage(msg, channel, timeout); switch (channel) { case AppOutput: - appendMessage(msg, StdOutFormatSameLine); + appendMessage(msg, StdOutFormat); break; case AppError: - appendMessage(msg, StdErrFormatSameLine); + appendMessage(msg, StdErrFormat); break; case AppStuff: appendMessage(msg, DebugFormat); diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h index adc9de8fef..a971c25807 100644 --- a/src/plugins/debugger/debuggerruncontrol.h +++ b/src/plugins/debugger/debuggerruncontrol.h @@ -33,6 +33,8 @@ #include <projectexplorer/runconfiguration.h> #include <projectexplorer/devicesupport/deviceusedportsgatherer.h> +#include <utils/environmentfwd.h> + namespace Debugger { namespace Internal { @@ -78,7 +80,7 @@ public: void setRunControlName(const QString &name); void setStartMessage(const QString &msg); void addQmlServerInferiorCommandLineArgumentIfNeeded(); - + void modifyDebuggerEnvironment(const Utils::EnvironmentItems &item); void setCrashParameter(const QString &event); void addExpectedSignal(const QString &signal); @@ -127,6 +129,7 @@ public: void setAbi(const ProjectExplorer::Abi &abi); Internal::TerminalRunner *terminalRunner() const; + DebuggerEngineType cppEngineType() const; private: bool fixupParameters(); diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index 49aa316571..58ec3663ab 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -586,7 +586,8 @@ DebuggerToolTipWidget::DebuggerToolTipWidget() << item->name << '\t' << item->value << '\t' << item->type << '\n'; }); QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(text, QClipboard::Selection); + if (clipboard->supportsSelection()) + clipboard->setText(text, QClipboard::Selection); clipboard->setText(text, QClipboard::Clipboard); }); diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp index 97e08b47fe..baa5e7c84d 100644 --- a/src/plugins/debugger/disassembleragent.cpp +++ b/src/plugins/debugger/disassembleragent.cpp @@ -337,7 +337,7 @@ void DisassemblerAgent::setContentsToDocument(const DisassemblerLines &contents) .arg(d->location.functionName())); const Breakpoints bps = d->engine->breakHandler()->breakpoints(); - for (const Breakpoint bp : bps) + for (const Breakpoint &bp : bps) updateBreakpointMarker(bp); updateLocationMarker(); diff --git a/src/plugins/debugger/enginemanager.cpp b/src/plugins/debugger/enginemanager.cpp index 8c2bbca146..1770758b11 100644 --- a/src/plugins/debugger/enginemanager.cpp +++ b/src/plugins/debugger/enginemanager.cpp @@ -310,7 +310,7 @@ bool EngineItem::setData(int row, const QVariant &value, int role) } if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete && m_engine) { + if ((kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) && m_engine) { m_engine->quitDebugger(); } else if (kev->key() == Qt::Key_Return || kev->key() == Qt::Key_Enter) { d->activateEngineByIndex(row); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 0fadcc150a..c1cb8c7bad 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3637,7 +3637,6 @@ void GdbEngine::setupEngine() //runCommand("define hookpost-stop\nprint 5\nend"); //runCommand("define hook-call\nprint 6\nend"); //runCommand("define hookpost-call\nprint 7\nend"); - runCommand({"set print object on"}); //runCommand("set step-mode on"); // we can't work with that yes //runCommand("set exec-done-display on"); //runCommand("set print pretty on"); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 61d9012ccb..03c6bdf7fa 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -314,6 +314,11 @@ void LldbEngine::setupEngine() const bool success = response.data["success"].toInt(); if (success) { BreakpointManager::claimBreakpointsForEngine(this); + // Some extra roundtrip to make sure we end up behind all commands triggered + // from claimBreakpointsForEngine(). + DebuggerCommand cmd3("executeRoundtrip"); + cmd3.callback = [this](const DebuggerResponse &) { notifyEngineSetupOk(); }; + runCommand(cmd3); } else { notifyEngineSetupFailed(); } @@ -402,6 +407,8 @@ void LldbEngine::handleResponse(const QString &response) notifyInferiorPid(item.toProcessHandle()); else if (name == "breakpointmodified") handleInterpreterBreakpointModified(item); + else if (name == "bridgemessage") + showMessage(item["msg"].data(), item["channel"].toInt()); } } @@ -673,7 +680,7 @@ void LldbEngine::requestModuleSymbols(const QString &moduleName) { DebuggerCommand cmd("fetchSymbols"); cmd.arg("module", moduleName); - cmd.callback = [this, moduleName](const DebuggerResponse &response) { + cmd.callback = [moduleName](const DebuggerResponse &response) { const GdbMi &symbols = response.data["symbols"]; QString moduleName = response.data["module"].data(); Symbols syms; @@ -903,8 +910,6 @@ void LldbEngine::handleStateNotification(const GdbMi &item) notifyInferiorStopFailed(); else if (newState == "inferiorill") notifyInferiorIll(); - else if (newState == "enginesetupok") - notifyEngineSetupOk(); else if (newState == "enginesetupfailed") { Core::AsynchronousMessageBox::critical(adapterStartFailed(), item["error"].data()); diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index d4af42714d..550fdc2d20 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -370,9 +370,9 @@ void AttachCoreDialog::coreFileChanged(const QString &core) Runnable debugger = DebuggerKitAspect::runnable(k); CoreInfo cinfo = CoreInfo::readExecutableNameFromCore(debugger, core); if (!cinfo.foundExecutableName.isEmpty()) - d->symbolFileName->setFileName(FilePath::fromString(cinfo.foundExecutableName)); + d->symbolFileName->setFilePath(FilePath::fromString(cinfo.foundExecutableName)); else if (!d->symbolFileName->isValid() && !cinfo.rawStringFromCore.isEmpty()) - d->symbolFileName->setFileName(FilePath::fromString(cinfo.rawStringFromCore)); + d->symbolFileName->setFilePath(FilePath::fromString(cinfo.rawStringFromCore)); } changed(); } @@ -412,12 +412,12 @@ void AttachCoreDialog::selectRemoteCoreFile() QString AttachCoreDialog::localCoreFile() const { - return d->localCoreFileName->path(); + return d->localCoreFileName->filePath().toString(); } FilePath AttachCoreDialog::symbolFile() const { - return d->symbolFileName->fileName(); + return d->symbolFileName->filePath(); } void AttachCoreDialog::setSymbolFile(const QString &symbolFileName) @@ -462,7 +462,7 @@ Kit *AttachCoreDialog::kit() const QString AttachCoreDialog::overrideStartScript() const { - return d->overrideStartScriptFileName->path(); + return d->overrideStartScriptFileName->filePath().toString(); } void AttachCoreDialog::setOverrideStartScript(const QString &scriptName) diff --git a/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp index 0bd667f457..ae5e38366c 100644 --- a/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp +++ b/src/plugins/debugger/shared/cdbsymbolpathlisteditor.cpp @@ -75,7 +75,7 @@ void CacheDirectoryDialog::setPath(const QString &p) QString CacheDirectoryDialog::path() const { - return m_chooser->path(); + return m_chooser->filePath().toString(); } void CacheDirectoryDialog::accept() diff --git a/src/plugins/debugger/shared/symbolpathsdialog.cpp b/src/plugins/debugger/shared/symbolpathsdialog.cpp index eb396c2c9b..db0354cca4 100644 --- a/src/plugins/debugger/shared/symbolpathsdialog.cpp +++ b/src/plugins/debugger/shared/symbolpathsdialog.cpp @@ -56,7 +56,7 @@ bool SymbolPathsDialog::useSymbolServer() const QString SymbolPathsDialog::path() const { - return ui->pathChooser->path(); + return ui->pathChooser->filePath().toString(); } void SymbolPathsDialog::setUseSymbolCache(bool useSymbolCache) diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 51d27228d1..d1af61e2c7 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -479,7 +479,8 @@ void StackHandler::copyContentsToClipboard() }); QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); + if (clipboard->supportsSelection()) + clipboard->setText(str, QClipboard::Selection); clipboard->setText(str, QClipboard::Clipboard); } diff --git a/src/plugins/debugger/unstartedappwatcherdialog.cpp b/src/plugins/debugger/unstartedappwatcherdialog.cpp index c27ff5f72e..2ef8c67588 100644 --- a/src/plugins/debugger/unstartedappwatcherdialog.cpp +++ b/src/plugins/debugger/unstartedappwatcherdialog.cpp @@ -121,7 +121,7 @@ UnstartedAppWatcherDialog::UnstartedAppWatcherDialog(QWidget *parent) if (isLocal(runConfig)) { resetExecutable->setEnabled(true); connect(resetExecutable, &QPushButton::clicked, this, [this, runnable] { - m_pathChooser->setFileName(runnable.executable); + m_pathChooser->setFilePath(runnable.executable); }); } } @@ -256,7 +256,7 @@ void UnstartedAppWatcherDialog::startStopTimer(bool start) void UnstartedAppWatcherDialog::findProcess() { - const QString &appName = Utils::FileUtils::normalizePathName(m_pathChooser->path()); + const QString &appName = Utils::FileUtils::normalizePathName(m_pathChooser->filePath().toString()); DeviceProcessItem fallback; foreach (const DeviceProcessItem &p, DeviceProcessList::localProcesses()) { if (Utils::FileUtils::normalizePathName(p.exe) == appName) { @@ -291,8 +291,8 @@ void UnstartedAppWatcherDialog::kitChanged() bool UnstartedAppWatcherDialog::checkExecutableString() const { - if (!m_pathChooser->path().isEmpty()) { - QFileInfo fileInfo(m_pathChooser->path()); + if (!m_pathChooser->filePath().toString().isEmpty()) { + QFileInfo fileInfo(m_pathChooser->filePath().toString()); return (fileInfo.exists() && fileInfo.isFile()); } return false; diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp index 33889646ed..3b4aa43765 100644 --- a/src/plugins/debugger/uvsc/uvscclient.cpp +++ b/src/plugins/debugger/uvsc/uvscclient.cpp @@ -43,7 +43,7 @@ constexpr int kMaximumRegisterGroupsCount = 128; constexpr int kMaximumRegisterEnumsCount = 512; constexpr int kMaximumVarinfosCount = 256; constexpr int kMaximumValueBitsSize = 32; -constexpr int kMaximumBreakpointResponseSize = 1024; +constexpr int kMaximumBreakpointEnumsCount = 128; constexpr int kMaximumDisassembledBytesCount = 1024; const QEvent::Type kUvscMsgEventType = static_cast<QEvent::Type>(QEvent::User + 1); @@ -691,6 +691,41 @@ bool UvscClient::inspectWatcher(const QStringList &expandedWatcherINames, return true; } +bool UvscClient::fetchMemory(quint64 address, QByteArray &data) +{ + if (data.isEmpty()) + data.resize(sizeof(quint8)); + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast<AMEM *>(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_READ(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + data = QByteArray(reinterpret_cast<char *>(&amemPtr->bytes), + amemPtr->bytesCount); + return true; +} + +bool UvscClient::changeMemory(quint64 address, const QByteArray &data) +{ + if (data.isEmpty()) { + setError(RuntimeError); + return false; + } + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast<AMEM *>(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_WRITE(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + return true; +} + bool UvscClient::disassemblyAddress(quint64 address, QByteArray &result) { if (!checkConnection()) @@ -764,22 +799,32 @@ bool UvscClient::createBreakpoint(const QString &exp, quint32 &tickMark, quint64 if (!checkConnection()) return false; - QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, exp); - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CREATE_BP(m_descriptor, - reinterpret_cast<BKPARM *>(bkparm.data()), - bkparm.size(), - reinterpret_cast<BKRSP *>(bkrsp.data()), - &bkrspLength); - if (st != UVSC_STATUS_SUCCESS) { - setError(RuntimeError); + // Magic workaround to prevent the stalling. + if (!controlHiddenBreakpoint(exp)) + return false; + + // Execute command to create the BP. + const QString setCmd = QStringLiteral("BS %1").arg(exp); + QString setCmdOutput; + if (!executeCommand(setCmd, setCmdOutput)) + return false; + + std::vector<BKRSP> bpenums; + if (!enumerateBreakpoints(bpenums)) + return false; + + const auto bpenumBegin = bpenums.cbegin(); + const auto bpenumEnd = bpenums.cend(); + const auto bpenumIt = std::find_if(bpenumBegin, bpenumEnd, [exp](const BKRSP &bpenum) { + const QString bpexp = QString::fromLatin1(reinterpret_cast<const char *>(bpenum.expressionBuffer), + bpenum.expressionLength).trimmed(); + return bpexp.contains(exp); + }); + if (bpenumIt == bpenumEnd) return false; - } - const auto bkrspPtr = reinterpret_cast<const BKRSP *>(bkrsp.constData()); - tickMark = bkrspPtr->tickMark; - address = bkrspPtr->address; + tickMark = bpenumIt->tickMark; + address = bpenumIt->address; if (!addressToFileLine(address, fileName, function, line)) return false; @@ -794,11 +839,9 @@ bool UvscClient::deleteBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_KILLBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast<BKRSP *>(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -814,11 +857,9 @@ bool UvscClient::enableBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_ENABLEBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast<BKRSP *>(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -834,11 +875,9 @@ bool UvscClient::disableBreakpoint(quint32 tickMark) BKCHG bkchg = {}; bkchg.type = CHG_DISABLEBP; bkchg.tickMark = tickMark; - QByteArray bkrsp(kMaximumBreakpointResponseSize, 0); - qint32 bkrspLength = bkrsp.size(); - const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), - reinterpret_cast<BKRSP *>(bkrsp.data()), - &bkrspLength); + BKRSP bkrsp = {}; + qint32 bkrspLength = sizeof(bkrsp); + const UVSC_STATUS st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); if (st != UVSC_STATUS_SUCCESS) { setError(RuntimeError); return false; @@ -846,6 +885,69 @@ bool UvscClient::disableBreakpoint(quint32 tickMark) return true; } +bool UvscClient::controlHiddenBreakpoint(const QString &exp) +{ + if (!checkConnection()) + return false; + + // It is a magic workaround to prevent the UVSC bug when the break-point + // creation may stall. A problem is that sometime the UVSC_DBG_CREATE_BP + // function blocks and returns then with the timeout error when the original + // break-point contains the full expression including the line number. + // + // It can be avoided with helps of creation and then deletion of the + // 'fake hidden' break-point with the same expression excluding the line + // number, before creation of an original break-point. + + const int slashIndex = exp.lastIndexOf('\\'); + if (slashIndex == -1 || (slashIndex + 1) == exp.size()) + return true; + + BKRSP bkrsp = {}; + + const QString hiddenExp = exp.mid(0, slashIndex); + QByteArray bkparm = UvscUtils::encodeBreakPoint(BRKTYPE_EXEC, hiddenExp); + qint32 bkrspLength = sizeof(bkrsp); + UVSC_STATUS st = ::UVSC_DBG_CREATE_BP(m_descriptor, + reinterpret_cast<BKPARM *>(bkparm.data()), + bkparm.size(), + &bkrsp, &bkrspLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + BKCHG bkchg = {}; + bkchg.type = CHG_KILLBP; + bkchg.tickMark = bkrsp.tickMark; + bkrspLength = sizeof(bkrsp); + st = ::UVSC_DBG_CHANGE_BP(m_descriptor, &bkchg, sizeof(bkchg), &bkrsp, &bkrspLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + return true; +} + +bool UvscClient::enumerateBreakpoints(std::vector<BKRSP> &bpenums) +{ + if (!checkConnection()) + return false; + + bpenums.resize(kMaximumBreakpointEnumsCount); + qint32 bpenumsCount = kMaximumBreakpointEnumsCount; + std::vector<qint32> indexes(bpenumsCount, 0); + const UVSC_STATUS st = ::UVSC_DBG_ENUMERATE_BP(m_descriptor, bpenums.data(), + indexes.data(), &bpenumsCount); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + bpenums.resize(bpenumsCount); + return true; +} + bool UvscClient::calculateExpression(const QString &exp, QByteArray &) { if (!checkConnection()) @@ -1097,5 +1199,36 @@ bool UvscClient::addressToFileLine(quint64 address, QString &fileName, return true; } +bool UvscClient::executeCommand(const QString &cmd, QString &output) +{ + if (!checkConnection()) + return false; + + EXECCMD exeCmd = UvscUtils::encodeCommand(cmd); + UVSC_STATUS st = ::UVSC_DBG_EXEC_CMD(m_descriptor, &exeCmd, sizeof(exeCmd.command)); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + qint32 outputLength = 0; + st = ::UVSC_GetCmdOutputSize(m_descriptor, &outputLength); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + QByteArray data(outputLength, 0); + st = UVSC_GetCmdOutput(m_descriptor, reinterpret_cast<qint8 *>(data.data()), data.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + // Note: UVSC API support only ASCII! + output = QString::fromLatin1(data); + return true; +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/uvsc/uvscclient.h b/src/plugins/debugger/uvsc/uvscclient.h index a602622a2b..98b001ac4e 100644 --- a/src/plugins/debugger/uvsc/uvscclient.h +++ b/src/plugins/debugger/uvsc/uvscclient.h @@ -36,6 +36,7 @@ QT_END_NAMESPACE // From UVSC api. struct STACKENUM; +struct BKRSP; namespace Utils { class FilePath; } @@ -87,6 +88,9 @@ public: bool fetchWatchers(const QStringList &expandedWatcherINames, const std::vector<std::pair<QString, QString>> &rootWatchers, GdbMi &data); + bool fetchMemory(quint64 address, QByteArray &data); + bool changeMemory(quint64 address, const QByteArray &data); + bool disassemblyAddress(quint64 address, QByteArray &result); bool setRegisterValue(int index, const QString &value); @@ -138,6 +142,10 @@ private: void updateLocation(const QByteArray &bpreason); bool addressToFileLine(quint64 address, QString &fileName, QString &function, quint32 &line); + bool controlHiddenBreakpoint(const QString &exp); + bool enumerateBreakpoints(std::vector<BKRSP> &bpenums); + bool executeCommand(const QString &cmd, QString &output); + qint32 m_descriptor = -1; quint64 m_exitAddress = 0; UvscError m_error = NoError; diff --git a/src/plugins/debugger/uvsc/uvscdatatypes.h b/src/plugins/debugger/uvsc/uvscdatatypes.h index c2ef9d7712..4392d81644 100644 --- a/src/plugins/debugger/uvsc/uvscdatatypes.h +++ b/src/plugins/debugger/uvsc/uvscdatatypes.h @@ -610,9 +610,9 @@ struct BKRSP { quint32 tickMark; quint64 address; quint32 expressionLength; - qint8 expressionBuffer[1]; + qint8 expressionBuffer[512]; }; -static_assert(sizeof(BKRSP) == 29, "BKRSP size is not 29 bytes"); +static_assert(sizeof(BKRSP) == 540, "BKRSP size is not 540 bytes"); // Breakpoint change data. struct BKCHG { diff --git a/src/plugins/debugger/uvsc/uvscengine.cpp b/src/plugins/debugger/uvsc/uvscengine.cpp index bc796172c1..23b657ac58 100644 --- a/src/plugins/debugger/uvsc/uvscengine.cpp +++ b/src/plugins/debugger/uvsc/uvscengine.cpp @@ -32,6 +32,7 @@ #include <debugger/disassemblerlines.h> #include <debugger/memoryagent.h> #include <debugger/moduleshandler.h> +#include <debugger/peripheralregisterhandler.h> #include <debugger/registerhandler.h> #include <debugger/stackhandler.h> #include <debugger/threadshandler.h> @@ -162,6 +163,9 @@ void UvscEngine::setupEngine() if (!configureProject(rp)) return; + + // Reload peripheral register description. + peripheralRegisterHandler()->updateRegisterGroups(); } void UvscEngine::runEngine() @@ -231,6 +235,14 @@ void UvscEngine::setRegisterValue(const QString &name, const QString &value) reloadRegisters(); } +void UvscEngine::setPeripheralRegisterValue(quint64 address, quint64 value) +{ + const QByteArray data = UvscUtils::encodeU32(value); + if (!m_client->changeMemory(address, data)) + return; + reloadPeripheralRegisters(); +} + void UvscEngine::executeStepOver(bool byInstruction) { notifyInferiorRunRequested(); @@ -332,6 +344,7 @@ void UvscEngine::activateFrame(int index) gotoCurrentLocation(); updateLocals(); reloadRegisters(); + reloadPeripheralRegisters(); } bool UvscEngine::stateAcceptsBreakpointChanges() const @@ -469,6 +482,17 @@ void UvscEngine::reloadRegisters() handleReloadRegisters(); } +void UvscEngine::reloadPeripheralRegisters() +{ + if (!isPeripheralRegistersWindowVisible()) + return; + + const QList<quint64> addresses = peripheralRegisterHandler()->activeRegisters(); + if (addresses.isEmpty()) + return; // Nothing to update. + handleReloadPeripheralRegisters(addresses); +} + void UvscEngine::reloadFullStack() { resetLocation(); @@ -496,6 +520,7 @@ void UvscEngine::updateAll() handleThreadInfo(); reloadRegisters(); + reloadPeripheralRegisters(); updateLocals(); } @@ -608,6 +633,8 @@ void UvscEngine::handleUpdateLocation(quint64 address) void UvscEngine::handleStartExecution() { + if (state() != InferiorRunRequested) + notifyInferiorRunRequested(); notifyInferiorRunOk(); } @@ -653,6 +680,7 @@ void UvscEngine::handleReloadStack(bool isFull) if (!m_client->fetchStackFrames(taskId, m_address, data)) { m_address = 0; reloadRegisters(); + reloadPeripheralRegisters(); return; } @@ -678,6 +706,19 @@ void UvscEngine::handleReloadRegisters() } } +void UvscEngine::handleReloadPeripheralRegisters(const QList<quint64> &addresses) +{ + for (const quint64 address : addresses) { + QByteArray data = UvscUtils::encodeU32(0); + if (!m_client->fetchMemory(address, data)) { + showMessage(tr("UVSC: Fetching peripheral register failed"), LogMisc); + } else { + const quint32 value = UvscUtils::decodeU32(data); + peripheralRegisterHandler()->updateRegister(address, value); + } + } +} + void UvscEngine::handleUpdateLocals(bool partial) { m_inUpdateLocals = false; diff --git a/src/plugins/debugger/uvsc/uvscengine.h b/src/plugins/debugger/uvsc/uvscengine.h index 97f843f44c..ace70fd5c5 100644 --- a/src/plugins/debugger/uvsc/uvscengine.h +++ b/src/plugins/debugger/uvsc/uvscengine.h @@ -49,6 +49,7 @@ public: bool hasCapability(unsigned cap) const final; void setRegisterValue(const QString &name, const QString &value) final; + void setPeripheralRegisterValue(quint64 address, quint64 value) final; void executeStepOver(bool byInstruction) final; void executeStepIn(bool byInstruction) final; @@ -72,6 +73,8 @@ public: void fetchDisassembler(DisassemblerAgent *agent) final; void reloadRegisters() final; + void reloadPeripheralRegisters() final; + void reloadFullStack() final; private slots: @@ -84,6 +87,7 @@ private slots: void handleThreadInfo(); void handleReloadStack(bool isFull); void handleReloadRegisters(); + void handleReloadPeripheralRegisters(const QList<quint64> &addresses); void handleUpdateLocals(bool partial); void handleInsertBreakpoint(const QString &exp, const Breakpoint &bp); void handleRemoveBreakpoint(const Breakpoint &bp); diff --git a/src/plugins/debugger/uvsc/uvscutils.cpp b/src/plugins/debugger/uvsc/uvscutils.cpp index e3b7e8799a..a8e7d97e62 100644 --- a/src/plugins/debugger/uvsc/uvscutils.cpp +++ b/src/plugins/debugger/uvsc/uvscutils.cpp @@ -110,6 +110,24 @@ QByteArray encodeAmem(quint64 address, quint32 bytesCount) return buffer; } +QByteArray encodeAmem(quint64 address, const QByteArray &data) +{ + QByteArray buffer(sizeof(AMEM) - 1, 0); + buffer.append(data); + const auto amem = reinterpret_cast<AMEM *>(buffer.data()); + amem->address = address; + amem->bytesCount = data.size(); + return buffer; +} + +EXECCMD encodeCommand(const QString &cmd) +{ + EXECCMD exeCmd = {}; + exeCmd.useEcho = false; + exeCmd.command = encodeSstr(cmd); + return exeCmd; +} + TVAL encodeVoidTval() { TVAL tval = {}; @@ -238,6 +256,24 @@ QString adjustHexValue(QString hex, const QString &type) return {}; } +QByteArray encodeU32(quint32 value) +{ + QByteArray data; + QDataStream out(&data, QIODevice::WriteOnly); + out.setByteOrder(QDataStream::LittleEndian); + out << value; + return data; +} + +quint32 decodeU32(const QByteArray &data) +{ + QDataStream in(data); + in.setByteOrder(QDataStream::LittleEndian); + quint32 value = 0; + in >> value; + return value; +} + QString buildLocalId(const VARINFO &varinfo) { return QString::number(varinfo.id); diff --git a/src/plugins/debugger/uvsc/uvscutils.h b/src/plugins/debugger/uvsc/uvscutils.h index 6295912839..61778f11e5 100644 --- a/src/plugins/debugger/uvsc/uvscutils.h +++ b/src/plugins/debugger/uvsc/uvscutils.h @@ -56,6 +56,8 @@ QString decodeAscii(const qint8 *ascii); QByteArray encodeProjectData(const QStringList &someNames); QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd = QString()); QByteArray encodeAmem(quint64 address, quint32 bytesCount); +QByteArray encodeAmem(quint64 address, const QByteArray &data); +EXECCMD encodeCommand(const QString &cmd); TVAL encodeVoidTval(); TVAL encodeIntTval(int value); TVAL encodeU64Tval(quint64 value); @@ -65,6 +67,9 @@ VSET encodeU64Vset(quint64 index, const QString &value); bool isKnownRegister(int type); QString adjustHexValue(QString hex, const QString &type); +QByteArray encodeU32(quint32 value); +quint32 decodeU32(const QByteArray &data); + QString buildLocalId(const VARINFO &varinfo); QString buildLocalEditable(const VARINFO &varinfo); QString buildLocalNumchild(const VARINFO &varinfo); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 066f9be23b..bd473776ef 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1108,7 +1108,8 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role } if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (item && kev->key() == Qt::Key_Delete && item->isWatcher()) { + if (item && (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) + && item->isWatcher()) { foreach (const QModelIndex &idx, ev.selectedRows()) removeWatchItem(itemForIndex(idx)); return true; @@ -1595,7 +1596,8 @@ static QString removeWatchActionText(QString exp) static void copyToClipboard(const QString &clipboardText) { QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(clipboardText, QClipboard::Selection); + if (clipboard->supportsSelection()) + clipboard->setText(clipboardText, QClipboard::Selection); clipboard->setText(clipboardText, QClipboard::Clipboard); } @@ -1909,12 +1911,18 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item, QWidget *parent) }); } + addAction(menu, tr("Reset All Individual Formats"), true, [this]() { + theIndividualFormats.clear(); + saveFormats(); + m_engine->updateLocals(); + }); + menu->addSeparator(); addAction(menu, tr("Change Display for Type \"%1\":").arg(item->type), false); addCheckableAction(menu, spacer + tr("Automatic"), true, typeFormat == AutomaticFormat, [this, item] { - //const QModelIndexList active = activeRows(); + //const QModelIndexList active = activeRows(); //for (const QModelIndex &idx : active) // setModelData(LocalsTypeFormatRole, AutomaticFormat, idx); setTypeFormat(item->type, AutomaticFormat); @@ -1924,11 +1932,17 @@ QMenu *WatchModel::createFormatMenu(WatchItem *item, QWidget *parent) for (int format : alternativeFormats) { addCheckableAction(menu, spacer + nameForFormat(format), true, format == typeFormat, [this, format, item] { - setTypeFormat(item->type, format); - m_engine->updateLocals(); + setTypeFormat(item->type, format); + m_engine->updateLocals(); }); } + addAction(menu, tr("Reset All Formats for Types"), true, [this]() { + theTypeFormats.clear(); + saveFormats(); + m_engine->updateLocals(); + }); + return menu; } |