From cc6c3eab1a3b14e3156b22e9bb30cc33d8a032a6 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Tue, 5 Jun 2012 10:25:48 +0200 Subject: [PATCH] debugger: add Load Remote Core Change-Id: I3ea5ddd608ff9e6764a995dc042466d436ca8474 Reviewed-by: hjk <qthjk@ovi.com> --- src/plugins/debugger/debugger.pro | 2 + src/plugins/debugger/debugger.qbs | 2 + src/plugins/debugger/debuggerconstants.h | 1 + src/plugins/debugger/debuggerplugin.cpp | 46 ++- src/plugins/debugger/debuggerrunner.cpp | 1 + src/plugins/debugger/gdb/gdbengine.cpp | 4 +- src/plugins/debugger/loadremotecoredialog.cpp | 269 ++++++++++++++++++ src/plugins/debugger/loadremotecoredialog.h | 73 +++++ 8 files changed, 391 insertions(+), 7 deletions(-) create mode 100644 src/plugins/debugger/loadremotecoredialog.cpp create mode 100644 src/plugins/debugger/loadremotecoredialog.h diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index beff0420f23..afe40429e6f 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -40,6 +40,7 @@ HEADERS += \ debuggerstringutils.h \ disassembleragent.h \ disassemblerlines.h \ + loadremotecoredialog.h \ logwindow.h \ memoryagent.h \ moduleshandler.h \ @@ -93,6 +94,7 @@ SOURCES += \ debuggerstreamops.cpp \ disassembleragent.cpp \ disassemblerlines.cpp \ + loadremotecoredialog.cpp \ logwindow.cpp \ memoryagent.cpp \ moduleshandler.cpp \ diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs index 9cf8b36f308..55c7b7a6e16 100644 --- a/src/plugins/debugger/debugger.qbs +++ b/src/plugins/debugger/debugger.qbs @@ -76,6 +76,8 @@ QtcPlugin { "disassembleragent.h", "disassemblerlines.cpp", "disassemblerlines.h", + "loadremotecoredialog.cpp", + "loadremotecoredialog.h", "localsandexpressionsoptionspage.ui", "localsandexpressionswindow.cpp", "localsandexpressionswindow.h", diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 62b30ecaf6b..18da8fa782a 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -130,6 +130,7 @@ enum DebuggerStartMode AttachCore, // Attach to a core file AttachToRemoteServer, // Attach to a running gdbserver AttachToRemoteProcess, // Attach to a running remote process + LoadRemoteCore, // Load a remote core file StartRemoteProcess, // Start and attach to a remote process StartRemoteGdb, // Start gdb itself remotely StartRemoteEngine // Start ipc guest engine on other machine diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index b4c7b57f537..86c9b0dfc65 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -63,6 +63,7 @@ #include "watchutils.h" #include "debuggertooltipmanager.h" #include "localsandexpressionswindow.h" +#include "loadremotecoredialog.h" #include "snapshothandler.h" #include "threadshandler.h" @@ -115,19 +116,20 @@ #include <utils/statuslabel.h> #include <utils/fileutils.h> -#include <QTimer> -#include <QtPlugin> #include <QComboBox> #include <QDockWidget> #include <QFileDialog> +#include <QInputDialog> #include <QMenu> #include <QMessageBox> #include <QPushButton> +#include <QTemporaryFile> #include <QTextBlock> #include <QTextCursor> +#include <QTimer> #include <QToolButton> +#include <QtPlugin> #include <QTreeWidget> -#include <QInputDialog> #ifdef WITH_TESTS #include <QTest> @@ -762,6 +764,7 @@ public slots: void startRemoteCdbSession(); void startRemoteProcess(); void startRemoteServer(); + void loadRemoteCoreFile(); bool queryRemoteParameters(DebuggerStartParameters &sp, bool useScript); void attachToRemoteServer(); void attachToRemoteProcess(); @@ -1114,6 +1117,7 @@ public: QAction *m_attachToRemoteServerAction; QAction *m_startRemoteCdbAction; QAction *m_startRemoteLldbAction; + QAction *m_loadRemoteCoreAction; QAction *m_attachToLocalProcessAction; QAction *m_attachToCoreAction; QAction *m_detachAction; @@ -1285,7 +1289,8 @@ void DebuggerPluginPrivate::maybeEnrichParameters(DebuggerStartParameters *sp) if (sp->sysroot.isEmpty() && (sp->startMode == AttachToRemoteServer || sp->startMode == StartRemoteProcess - || sp->startMode == AttachToRemoteProcess)) { + || sp->startMode == AttachToRemoteProcess + || sp->startMode == LoadRemoteCore)) { // FIXME: Get from BaseQtVersion. sp->sysroot = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_SYSROOT")); showMessage(QString::fromLatin1("USING QTC_DEBUGGER_SYSROOT %1") @@ -1682,6 +1687,28 @@ void DebuggerPluginPrivate::gdbServerStarted(const QString &channel, showStatusMessage(tr("gdbserver is now listening at %1").arg(channel)); } +void DebuggerPluginPrivate::loadRemoteCoreFile() +{ + DebuggerStartParameters sp; + { + QTemporaryFile localCoreFile(QDir::tempPath() + "/remotecore-XXXXXX"); + localCoreFile.open(); + sp.coreFile = localCoreFile.fileName(); + } + LoadRemoteCoreFileDialog dlg(mainWindow()); + dlg.setLocalCoreFileName(sp.coreFile); + if (!dlg.exec()) + return; + sp.displayName = tr("Core file \"%1\"").arg(sp.coreFile); + sp.startMode = AttachCore; + //sp.debuggerCommand = dlg.debuggerCommand(); + //sp.toolChainAbi = dlg.abi(); + sp.sysroot = dlg.sysroot(); + //sp.overrideStartScript = dlg.overrideStartScript(); + if (DebuggerRunControl *rc = createDebugger(sp)) + startDebugger(rc); +} + void DebuggerPluginPrivate::attachToRemoteProcess() { PluginManager *pm = PluginManager::instance(); @@ -1689,7 +1716,7 @@ void DebuggerPluginPrivate::attachToRemoteProcess() QObject *rl = pm->getObjectByName(_("RemoteLinuxPlugin")); QTC_ASSERT(rl, return); QMetaObject::invokeMethod(rl, "attachToRemoteProcess", Qt::QueuedConnection); - // This will call back attachedtToProcess() below. + // This will call back attachedToProcess() below. } void DebuggerPluginPrivate::attachedToProcess(const QString &channel, @@ -3102,6 +3129,10 @@ void DebuggerPluginPrivate::extensionsInitialized() act->setText(tr("Attach to Running Remote Process...")); connect(act, SIGNAL(triggered()), SLOT(attachToRemoteProcess())); + act = m_loadRemoteCoreAction = new QAction(this); + act->setText(tr("Load Remote Core File...")); + connect(act, SIGNAL(triggered()), SLOT(loadRemoteCoreFile())); + act = m_attachToQmlPortAction = new QAction(this); act->setText(tr("Attach to QML Port...")); connect(act, SIGNAL(triggered()), SLOT(attachToQmlPort())); @@ -3186,6 +3217,11 @@ void DebuggerPluginPrivate::extensionsInitialized() cmd->setDescription(tr("Attach to Remote Process")); mstart->addAction(cmd, Debugger::Constants::G_AUTOMATIC_REMOTE); + cmd = Core::ActionManager::registerAction(m_loadRemoteCoreAction, + "Debugger.LoadRemoteCore", globalcontext); + cmd->setDescription(tr("Load Remote Core File")); + mstart->addAction(cmd, Debugger::Constants::G_AUTOMATIC_REMOTE); + #ifdef WITH_LLDB cmd = Core::ActionManager::registerAction(m_startRemoteLldbAction, "Debugger.RemoteLldb", globalcontext); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 64fb0f9a80e..3232b43cf2f 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -674,6 +674,7 @@ static QList<DebuggerEngineType> engineTypes(const DebuggerStartParameters &sp) if (sp.startMode != AttachToRemoteServer && sp.startMode != AttachToRemoteProcess + && sp.startMode != LoadRemoteCore && !sp.executable.isEmpty()) result = enginesForExecutable(sp.executable); if (!result.isEmpty()) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a2b33bb3a6d..d127e1f78ae 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -5321,8 +5321,8 @@ bool GdbEngine::usesExecInterrupt() const // debuggerCore()->boolSetting(TargetAsync) DebuggerStartMode mode = startParameters().startMode; - return (mode == AttachToRemoteServer - || mode == AttachToRemoteProcess) && debuggerCore()->boolSetting(TargetAsync); + return (mode == AttachToRemoteServer || mode == AttachToRemoteProcess) + && debuggerCore()->boolSetting(TargetAsync); } void GdbEngine::scheduleTestResponse(int testCase, const QByteArray &response) diff --git a/src/plugins/debugger/loadremotecoredialog.cpp b/src/plugins/debugger/loadremotecoredialog.cpp new file mode 100644 index 00000000000..ab6ef56680e --- /dev/null +++ b/src/plugins/debugger/loadremotecoredialog.cpp @@ -0,0 +1,269 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "loadremotecoredialog.h" +#include "debuggerstartparameters.h" +#include "debuggerconstants.h" +#include "debuggercore.h" + +#include <coreplugin/icore.h> +#include <projectexplorer/abi.h> +#include <projectexplorer/devicesupport/devicemanager.h> +#include <projectexplorer/devicesupport/devicemanagermodel.h> +#include <ssh/sshconnection.h> +#include <ssh/sshremoteprocessrunner.h> +#include <ssh/sftpfilesystemmodel.h> +#include <utils/historycompleter.h> +#include <utils/pathchooser.h> +#include <utils/portlist.h> +#include <utils/qtcassert.h> + +#include <QCoreApplication> +#include <QDebug> +#include <QDir> +#include <QRegExp> + +#include <QButtonGroup> +#include <QComboBox> +#include <QFileDialog> +#include <QFormLayout> +#include <QGridLayout> +#include <QGroupBox> +#include <QHeaderView> +#include <QLineEdit> +#include <QMessageBox> +#include <QPushButton> +#include <QRadioButton> +#include <QScrollArea> +#include <QStandardItemModel> +#include <QTableView> +#include <QTextBrowser> +#include <QTreeView> + +using namespace Core; +using namespace ProjectExplorer; +using namespace QSsh; +using namespace Utils; + +namespace Debugger { +namespace Internal { + +/////////////////////////////////////////////////////////////////////// +// +// LoadRemoteCoreFileDialog +// +/////////////////////////////////////////////////////////////////////// + +class LoadRemoteCoreFileDialogPrivate +{ +public: + DeviceManagerModel *deviceManagerModel; + + QComboBox *deviceComboBox; + QTreeView *fileSystemView; + QPushButton *loadCoreFileButton; + QTextBrowser *textBrowser; + QPushButton *closeButton; + PathChooser *sysrootPathChooser; + + QSettings *settings; + QString remoteCommandLine; + QString remoteExecutable; + QString localCoreFile; + + SftpFileSystemModel *fileSystemModel; + SftpJobId sftpJobId; +}; + +LoadRemoteCoreFileDialog::LoadRemoteCoreFileDialog(QWidget *parent) + : QDialog(parent), d(new LoadRemoteCoreFileDialogPrivate) +{ + setWindowTitle(tr("Select Remote Core File")); + + d->settings = ICore::settings(); + + d->deviceComboBox = new QComboBox(this); + + d->sysrootPathChooser = new PathChooser(this); + d->sysrootPathChooser->setExpectedKind(PathChooser::Directory); + d->sysrootPathChooser->setPromptDialogTitle(tr("Select Sysroot")); + d->sysrootPathChooser->setPath(d->settings->value(QLatin1String("LastSysroot")).toString()); + + d->fileSystemModel = new SftpFileSystemModel(this); + + //executablePathChooser = new PathChooser(q); + //executablePathChooser->setExpectedKind(PathChooser::File); + //executablePathChooser->setPromptDialogTitle(tr("Select Executable")); + //executablePathChooser->setPath(settings->value(LastLocalExecutable).toString()); + + d->fileSystemView = new QTreeView(this); + d->fileSystemView->setSortingEnabled(true); + d->fileSystemView->header()->setDefaultSectionSize(100); + d->fileSystemView->header()->setStretchLastSection(true); + d->fileSystemView->setSelectionMode(QAbstractItemView::SingleSelection); + d->fileSystemView->setModel(d->fileSystemModel); + + d->loadCoreFileButton = new QPushButton(this); + d->loadCoreFileButton->setText(tr("&Load Selected Core File")); + + d->closeButton = new QPushButton(this); + d->closeButton->setText(tr("Close")); + + d->textBrowser = new QTextBrowser(this); + d->textBrowser->setEnabled(false); + + QFormLayout *formLayout = new QFormLayout(); + formLayout->addRow(tr("Device:"), d->deviceComboBox); + formLayout->addRow(tr("Sysroot:"), d->sysrootPathChooser); + + QHBoxLayout *horizontalLayout2 = new QHBoxLayout(); + horizontalLayout2->addStretch(1); + horizontalLayout2->addWidget(d->loadCoreFileButton); + horizontalLayout2->addWidget(d->closeButton); + + formLayout->addRow(d->fileSystemView); + formLayout->addRow(d->textBrowser); + formLayout->addRow(horizontalLayout2); + setLayout(formLayout); + + d->deviceManagerModel = new DeviceManagerModel(DeviceManager::instance(), this); + + QObject::connect(d->closeButton, SIGNAL(clicked()), this, SLOT(reject())); + + d->deviceComboBox->setModel(d->deviceManagerModel); + d->deviceComboBox->setCurrentIndex(d->settings->value(QLatin1String("LastDevice")).toInt()); + + if (d->deviceManagerModel->rowCount() == 0) { + d->fileSystemView->setEnabled(false); + } else { + d->fileSystemView->setSelectionBehavior(QAbstractItemView::SelectRows); + connect(d->fileSystemView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + SLOT(updateButtons())); + connect(d->sysrootPathChooser, SIGNAL(changed(QString)), + SLOT(updateButtons())); + connect(d->loadCoreFileButton, SIGNAL(clicked()), SLOT(selectCoreFile())); + connect(d->deviceComboBox, SIGNAL(currentIndexChanged(int)), + SLOT(attachToDevice(int))); + updateButtons(); + attachToDevice(d->deviceComboBox->currentIndex()); + } +} + +LoadRemoteCoreFileDialog::~LoadRemoteCoreFileDialog() +{ + delete d; +} + +void LoadRemoteCoreFileDialog::setLocalCoreFileName(const QString &fileName) +{ + d->localCoreFile = fileName; +} + +QString LoadRemoteCoreFileDialog::localCoreFileName() const +{ + return d->localCoreFile; +} + +QString LoadRemoteCoreFileDialog::sysroot() const +{ + return d->sysrootPathChooser->path(); +} + +void LoadRemoteCoreFileDialog::attachToDevice(int modelIndex) +{ + IDevice::ConstPtr device = d->deviceManagerModel->device(modelIndex); + if (!device) + return; + connect(d->fileSystemModel, SIGNAL(sftpOperationFailed(QString)), + SLOT(handleSftpOperationFailed(QString))); + connect(d->fileSystemModel, SIGNAL(connectionError(QString)), + SLOT(handleConnectionError(QString))); + d->fileSystemModel->setSshConnection(device->sshParameters()); + //d->fileSystemModel->setRootDirectory(d->settings->value(QLatin1String("LastSftpRoot")).toString()); +} + +void LoadRemoteCoreFileDialog::handleSftpOperationFailed(const QString &errorMessage) +{ + d->textBrowser->append(errorMessage); + //reject(); +} + +void LoadRemoteCoreFileDialog::handleConnectionError(const QString &errorMessage) +{ + d->textBrowser->append(errorMessage); + //reject(); +} + +void LoadRemoteCoreFileDialog::handleSftpOperationFinished(QSsh::SftpJobId, const QString &error) +{ + if (error.isEmpty()) { + d->textBrowser->append(tr("Download of Core File succeeded.")); + accept(); + } else { + d->textBrowser->append(error); + //reject(); + } +} + +void LoadRemoteCoreFileDialog::handleRemoteError(const QString &errorMessage) +{ + d->textBrowser->append(errorMessage); + updateButtons(); +} + +void LoadRemoteCoreFileDialog::selectCoreFile() +{ + const QModelIndexList &indexes = + d->fileSystemView->selectionModel()->selectedIndexes(); + if (indexes.empty()) + return; + + d->loadCoreFileButton->setEnabled(false); + d->fileSystemView->setEnabled(false); + + d->settings->setValue(QLatin1String("LastSysroot"), d->sysrootPathChooser->path()); + d->settings->setValue(QLatin1String("LastDevice"), d->deviceComboBox->currentIndex()); + d->settings->setValue(QLatin1String("LastSftpRoot"), d->fileSystemModel->rootDirectory()); + + connect(d->fileSystemModel, SIGNAL(sftpOperationFinished(QSsh::SftpJobId,QString)), + SLOT(handleSftpOperationFinished(QSsh::SftpJobId,QString))); + d->sftpJobId = d->fileSystemModel->downloadFile(indexes.at(0), d->localCoreFile); +} + +void LoadRemoteCoreFileDialog::updateButtons() +{ + d->loadCoreFileButton->setEnabled(d->fileSystemView->selectionModel()->hasSelection()); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/loadremotecoredialog.h b/src/plugins/debugger/loadremotecoredialog.h new file mode 100644 index 00000000000..272b1a3e223 --- /dev/null +++ b/src/plugins/debugger/loadremotecoredialog.h @@ -0,0 +1,73 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef DEBUGGER_LOADREMOTECOREDIALOG_H +#define DEBUGGER_LOADREMOTECOREDIALOG_H + +#include <ssh/sftpdefs.h> + +#include <QDialog> + +namespace Debugger { +namespace Internal { + +class LoadRemoteCoreFileDialogPrivate; + +class LoadRemoteCoreFileDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LoadRemoteCoreFileDialog(QWidget *parent); + ~LoadRemoteCoreFileDialog(); + + void setLocalCoreFileName(const QString &fileName); + QString localCoreFileName() const; + QString sysroot() const; + +private slots: + void handleSftpOperationFinished(QSsh::SftpJobId, const QString &error); + void handleSftpOperationFailed(const QString &errorMessage); + void handleConnectionError(const QString &errorMessage); + void updateButtons(); + void attachToDevice(int modelIndex); + void handleRemoteError(const QString &errorMessage); + void selectCoreFile(); + +private: + LoadRemoteCoreFileDialogPrivate *d; +}; + +} // namespace Debugger +} // namespace Internal + +#endif // DEBUGGER_LOADREMOTECOREDIALOG_H -- GitLab