From b2598d0030acb930bc8f50ea1e5f6a29ec791feb Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 4 May 2009 14:47:45 +0200 Subject: [PATCH] debugger: initial work on remote debugging --- src/plugins/debugger/attachremotedialog.ui | 53 ++++------- src/plugins/debugger/debuggerdialogs.cpp | 100 +++++++++------------ src/plugins/debugger/debuggerdialogs.h | 18 ++-- src/plugins/debugger/debuggermanager.cpp | 61 +++++++++---- src/plugins/debugger/debuggermanager.h | 7 +- src/plugins/debugger/debuggerplugin.cpp | 10 +++ src/plugins/debugger/gdbengine.cpp | 31 +++++-- tests/manual/gdbdebugger/simple/app.cpp | 3 + 8 files changed, 147 insertions(+), 136 deletions(-) diff --git a/src/plugins/debugger/attachremotedialog.ui b/src/plugins/debugger/attachremotedialog.ui index 04a1073492c..0326926a31f 100644 --- a/src/plugins/debugger/attachremotedialog.ui +++ b/src/plugins/debugger/attachremotedialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>561</width> - <height>866</height> + <width>310</width> + <height>224</height> </rect> </property> <property name="windowTitle"> @@ -22,58 +22,35 @@ </property> <item> <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> <item row="0" column="0"> - <widget class="QLabel" name="pidLabel"> + <widget class="QLabel" name="channelLabel"> <property name="text"> - <string>Attach to Process ID:</string> + <string>Host and Port:</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QLineEdit" name="pidLineEdit"/> + <widget class="QLineEdit" name="channelLineEdit"> + <property name="text"> + <string>localhost:5115</string> + </property> + </widget> </item> <item row="1" column="0"> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="architectureLabel"> <property name="text"> - <string>Filter:</string> + <string>Architecture:</string> </property> </widget> </item> <item row="1" column="1"> - <widget class="QWidget" name="filterWidget" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QLineEdit" name="filterLineEdit"/> - </item> - <item> - <widget class="QToolButton" name="filterClearToolButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - </layout> - </widget> + <widget class="QComboBox" name="architectureComboBox"/> </item> </layout> </item> - <item> - <widget class="QTreeView" name="procView"> - <property name="editTriggers"> - <set>QAbstractItemView::NoEditTriggers</set> - </property> - </widget> - </item> - <item> - <widget class="Line" name="line"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 483ad82a1e6..e404ea88e02 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -51,7 +51,7 @@ namespace Debugger { - namespace Internal { +namespace Internal { bool operator<(const ProcData &p1, const ProcData &p2) { @@ -59,7 +59,8 @@ bool operator<(const ProcData &p1, const ProcData &p2) } // A filterable process list model -class ProcessListFilterModel : public QSortFilterProxyModel { +class ProcessListFilterModel : public QSortFilterProxyModel +{ public: explicit ProcessListFilterModel(QObject *parent); QString processIdAt(const QModelIndex &index) const; @@ -69,9 +70,9 @@ private: QStandardItemModel *m_model; }; -ProcessListFilterModel::ProcessListFilterModel(QObject *parent) : - QSortFilterProxyModel(parent), - m_model(new QStandardItemModel(this)) +ProcessListFilterModel::ProcessListFilterModel(QObject *parent) + : QSortFilterProxyModel(parent), + m_model(new QStandardItemModel(this)) { QStringList columns; columns << AttachExternalDialog::tr("Process ID") @@ -116,6 +117,7 @@ void ProcessListFilterModel::populate(QList<ProcData> processes, const QString & } } + /////////////////////////////////////////////////////////////////////// // // AttachCoreDialog @@ -164,9 +166,10 @@ void AttachCoreDialog::setCoreFile(const QString &fileName) m_ui->coreFileName->setPath(fileName); } + /////////////////////////////////////////////////////////////////////// // -// process model helpers +// Process model helpers // /////////////////////////////////////////////////////////////////////// @@ -224,11 +227,11 @@ static QList<ProcData> processList() // /////////////////////////////////////////////////////////////////////// -AttachExternalDialog::AttachExternalDialog(QWidget *parent) : - QDialog(parent), - m_selfPid(QString::number(QCoreApplication::applicationPid())), - m_ui(new Ui::AttachExternalDialog), - m_model(new ProcessListFilterModel(this)) +AttachExternalDialog::AttachExternalDialog(QWidget *parent) + : QDialog(parent), + m_selfPid(QString::number(QCoreApplication::applicationPid())), + m_ui(new Ui::AttachExternalDialog), + m_model(new ProcessListFilterModel(this)) { m_ui->setupUi(this); okButton()->setDefault(true); @@ -292,48 +295,26 @@ int AttachExternalDialog::attachPID() const void AttachExternalDialog::pidChanged(const QString &pid) { - okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid); + bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid;; + okButton()->setEnabled(enabled); } + /////////////////////////////////////////////////////////////////////// // // AttachRemoteDialog // /////////////////////////////////////////////////////////////////////// -AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) : - QDialog(parent), - m_ui(new Ui::AttachRemoteDialog), - m_model(new ProcessListFilterModel(this)) +AttachRemoteDialog::AttachRemoteDialog(QWidget *parent) + : QDialog(parent), + m_ui(new Ui::AttachRemoteDialog) { m_ui->setupUi(this); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - m_defaultPID = pid; - - m_ui->procView->setModel(m_model); - m_ui->procView->setSortingEnabled(true); - + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - // Do not use activated, will be single click in Oxygen - connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(procSelected(QModelIndex))); - - QPushButton *refreshButton = new QPushButton(tr("Refresh")); - connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList())); - m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole); - - connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(pidChanged(QString))); - - connect(m_ui->filterClearToolButton, SIGNAL(clicked()), - m_ui->filterLineEdit, SLOT(clear())); - connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)), - m_model, SLOT(setFilterFixedString(QString))); - - m_ui->pidLineEdit->setText(m_defaultPID); - rebuildProcessList(); } AttachRemoteDialog::~AttachRemoteDialog() @@ -341,37 +322,36 @@ AttachRemoteDialog::~AttachRemoteDialog() delete m_ui; } -QPushButton *AttachRemoteDialog::okButton() const +void AttachRemoteDialog::setRemoteChannel(const QString &channel) { - return m_ui->buttonBox->button(QDialogButtonBox::Ok); + m_ui->channelLineEdit->setText(channel); } -void AttachRemoteDialog::rebuildProcessList() +QString AttachRemoteDialog::remoteChannel() const { - m_model->populate(processList()); - m_ui->procView->expandAll(); - m_ui->procView->resizeColumnToContents(0); - m_ui->procView->resizeColumnToContents(1); + return m_ui->channelLineEdit->text(); } -void AttachRemoteDialog::procSelected(const QModelIndex &index0) -{ - const QString proccessId = m_model->processIdAt(index0); - if (!proccessId.isEmpty()) { - m_ui->pidLineEdit->setText(proccessId); - if (okButton()->isEnabled()) - okButton()->animateClick(); +void AttachRemoteDialog::setRemoteArchitectures(const QStringList &list) +{ + m_ui->architectureComboBox->clear(); + if (!list.isEmpty()) { + m_ui->architectureComboBox->insertItems(0, list); + m_ui->architectureComboBox->setCurrentIndex(0); } } -int AttachRemoteDialog::attachPID() const +void AttachRemoteDialog::setRemoteArchitecture(const QString &arch) { - return m_ui->pidLineEdit->text().toInt(); + int index = m_ui->architectureComboBox->findText(arch); + if (index != -1) + m_ui->architectureComboBox->setCurrentIndex(index); } -void AttachRemoteDialog::pidChanged(const QString &pid) +QString AttachRemoteDialog::remoteArchitecture() const { - okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0")); + int index = m_ui->architectureComboBox->currentIndex(); + return m_ui->architectureComboBox->itemText(index); } @@ -426,5 +406,5 @@ QString StartExternalDialog::executableArguments() const return m_ui->argsEdit->text(); } -} -} +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index f263e710c66..c51fc3abe77 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -101,30 +101,24 @@ private: ProcessListFilterModel *m_model; }; - class AttachRemoteDialog : public QDialog { Q_OBJECT public: - explicit AttachRemoteDialog(QWidget *parent, const QString &pid); + explicit AttachRemoteDialog(QWidget *parent); ~AttachRemoteDialog(); - int attachPID() const; - -private slots: - void rebuildProcessList(); - void procSelected(const QModelIndex &); - void pidChanged(const QString &); + void setRemoteChannel(const QString &host); + void setRemoteArchitecture(const QString &arch); + void setRemoteArchitectures(const QStringList &arches); + QString remoteChannel() const; + QString remoteArchitecture() const; private: - inline QPushButton *okButton() const; Ui::AttachRemoteDialog *m_ui; - QString m_defaultPID; - ProcessListFilterModel *m_model; }; - class StartExternalDialog : public QDialog { Q_OBJECT diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index d77c7b10829..0120ae02d25 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -89,6 +89,7 @@ using namespace Debugger::Constants; static const QString tooltipIName = "tooltip"; +#define _(s) QString::fromLatin1(s) static const char *stateName(int s) { @@ -304,6 +305,11 @@ void DebuggerManager::init() m_attachCoreAction->setText(tr("Attach to Core...")); connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore())); + m_attachRemoteAction = new QAction(this); + m_attachRemoteAction->setText(tr("Attach to Running Remote Application...")); + connect(m_attachRemoteAction, SIGNAL(triggered()), + this, SLOT(attachRemoteApplication())); + m_continueAction = new QAction(this); m_continueAction->setText(tr("Continue")); m_continueAction->setIcon(QIcon(":/gdbdebugger/images/debugger_continue_small.png")); @@ -437,7 +443,7 @@ QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(const QStringList { QList<Core::IOptionsPage*> rc; gdbEngine = createGdbEngine(this, &rc); - const bool cdbDisabled = arguments.contains(QLatin1String("-disable-cdb")); + const bool cdbDisabled = arguments.contains(_("-disable-cdb")); winEngine = createWinEngine(this, cdbDisabled, &rc); scriptEngine = createScriptEngine(this, &rc); setDebuggerType(GdbDebugger); @@ -810,12 +816,18 @@ void DebuggerManager::attachCore() emit debuggingFinished(); } +void DebuggerManager::attachRemoteApplication() +{ + if (!startNewDebugger(AttachRemote)) + emit debuggingFinished(); +} + // Figure out the debugger type of an executable static bool determineDebuggerType(const QString &executable, DebuggerManager::DebuggerType *dt, QString *errorMessage) { - if (executable.endsWith(QLatin1String(".js"))) { + if (executable.endsWith(_(".js"))) { *dt = DebuggerManager::ScriptDebugger; return true; } @@ -869,21 +881,21 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode) case StartExternal: { StartExternalDialog dlg(mainWindow()); dlg.setExecutableFile( - configValue(QLatin1String("LastExternalExecutableFile")).toString()); + configValue(_("LastExternalExecutableFile")).toString()); dlg.setExecutableArguments( - configValue(QLatin1String("LastExternalExecutableArguments")).toString()); + configValue(_("LastExternalExecutableArguments")).toString()); if (dlg.exec() != QDialog::Accepted) return false; - setConfigValue(QLatin1String("LastExternalExecutableFile"), + setConfigValue(_("LastExternalExecutableFile"), dlg.executableFile()); - setConfigValue(QLatin1String("LastExternalExecutableArguments"), + setConfigValue(_("LastExternalExecutableArguments"), dlg.executableArguments()); m_executable = dlg.executableFile(); m_processArgs = dlg.executableArguments().split(' '); m_workingDir = QString(); m_attachedPID = -1; - } break; + } case AttachExternal: { AttachExternalDialog dlg(mainWindow()); if (dlg.exec() != QDialog::Accepted) @@ -897,9 +909,9 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode) tr("Cannot attach to PID 0")); return false; } - } break; - case StartInternal: + } + case StartInternal: { if (m_executable.isEmpty()) { QString startDirectory = m_executable; if (m_executable.isEmpty()) { @@ -920,30 +932,46 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode) m_attachedPID = 0; } else { //m_executable = QDir::convertSeparators(m_executable); - //m_processArgs = sd.processArgs.join(QLatin1String(" ")); + //m_processArgs = sd.processArgs.join(_(" ")); m_attachedPID = 0; } break; + } case AttachCore: { AttachCoreDialog dlg(mainWindow()); dlg.setExecutableFile( - configValue(QLatin1String("LastExternalExecutableFile")).toString()); + configValue(_("LastExternalExecutableFile")).toString()); dlg.setCoreFile( - configValue(QLatin1String("LastExternalCoreFile")).toString()); + configValue(_("LastExternalCoreFile")).toString()); if (dlg.exec() != QDialog::Accepted) return false; - setConfigValue(QLatin1String("LastExternalExecutableFile"), + setConfigValue(_("LastExternalExecutableFile"), dlg.executableFile()); - setConfigValue(QLatin1String("LastExternalCoreFile"), + setConfigValue(_("LastExternalCoreFile"), dlg.coreFile()); m_executable = dlg.executableFile(); m_coreFile = dlg.coreFile(); m_processArgs.clear(); m_workingDir = QString(); m_attachedPID = -1; + break; } + case AttachRemote: { + AttachRemoteDialog dlg(mainWindow()); + QStringList arches; + arches.append(_("i386:x86-64:intel")); + dlg.setRemoteArchitectures(arches); + dlg.setRemoteChannel(configValue(_("LastRemoteChannel")).toString()); + dlg.setRemoteArchitecture(configValue(_("LastRemoteArchtecture")).toString()); + if (dlg.exec() != QDialog::Accepted) + return false; + setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel()); + setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture()); + m_remoteChannel = dlg.remoteChannel(); + m_remoteArchitecture = dlg.remoteArchitecture(); break; } + } emit debugModeRequested(); @@ -1218,7 +1246,7 @@ void DebuggerManager::setStatus(int status) if (0 && !isAllowedTransition(m_status, status)) { const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3"). - arg(QLatin1String(Q_FUNC_INFO), QLatin1String(stateName(m_status)), QLatin1String(stateName(status))); + arg(_(Q_FUNC_INFO), _(stateName(m_status)), _(stateName(status))); qWarning("%s", qPrintable(msg)); } @@ -1242,6 +1270,7 @@ void DebuggerManager::setStatus(int status) #else m_attachCoreAction->setEnabled(!started && !starting); #endif + m_attachRemoteAction->setEnabled(!started && !starting); m_watchAction->setEnabled(ready); m_breakAction->setEnabled(true); @@ -1535,7 +1564,7 @@ void DebuggerManager::showQtDumperLibraryWarning(const QString &details) dialog.setDetailedText(details); dialog.exec(); if (dialog.clickedButton() == qtPref) { - Core::ICore::instance()->showOptionsDialog(QLatin1String("Qt4"), QLatin1String("Qt Versions")); + Core::ICore::instance()->showOptionsDialog(_("Qt4"), _("Qt Versions")); } else if (dialog.clickedButton() == helperOff) { theDebuggerAction(UseDebuggingHelpers)->setValue(qVariantFromValue(false), false); } diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 67b3e988372..f238b148ab7 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -111,7 +111,8 @@ enum DebuggerStartMode StartInternal, // Start current start project's binary StartExternal, // Start binary found in file system AttachExternal, // Attach to running process - AttachCore // Attach to a core file + AttachCore, // Attach to a core file + AttachRemote // Attach to a remote process }; class IDebuggerEngine; @@ -225,6 +226,7 @@ public slots: void startExternalApplication(); void attachExternalApplication(); void attachCore(); + void attachRemoteApplication(); void jumpToLineExec(); void runToLineExec(); @@ -358,6 +360,8 @@ public: QString m_dumperLib; int m_attachedPID; bool m_useTerminal; + QString m_remoteChannel; + QString m_remoteArchitecture; private: void init(); @@ -404,6 +408,7 @@ private: QAction *m_startExternalAction; QAction *m_attachExternalAction; QAction *m_attachCoreAction; + QAction *m_attachRemoteAction; QAction *m_continueAction; QAction *m_stopAction; QAction *m_resetAction; // FIXME: Should not be needed in a stable release diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 58df17849f7..70ccb01e598 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -99,6 +99,7 @@ namespace Constants { const char * const STARTEXTERNAL = "Debugger.StartExternal"; const char * const ATTACHEXTERNAL = "Debugger.AttachExternal"; const char * const ATTACHCORE = "Debugger.AttachCore"; +const char * const ATTACHREMOTE = "Debugger.AttachRemote"; const char * const RUN_TO_LINE = "Debugger.RunToLine"; const char * const RUN_TO_FUNCTION = "Debugger.RunToFunction"; @@ -478,6 +479,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE); } + #if 0 + // FIXME: not yet functional + if (m_manager->m_attachRemoteAction) { + cmd = am->registerAction(m_manager->m_attachRemoteAction, + Constants::ATTACHREMOTE, globalcontext); + mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE); + } + #endif + cmd = am->registerAction(m_manager->m_continueAction, ProjectExplorer::Constants::DEBUG, QList<int>() << m_gdbRunningContext); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 54c598169ff..6085b8c0dd3 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -92,7 +92,14 @@ Q_DECLARE_METATYPE(Debugger::Internal::GdbMi); #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) -#define _c(s) QLatin1Char(s) +struct _c +{ + inline _c(char c) : m_c(c) {} + inline operator QChar() const { return QLatin1Char(m_c); } + char m_c; +}; + +#define _c(c) QLatin1Char(c) #define __(s) QLatin1String(s) #define _(s) QString::fromLatin1(s) @@ -1601,6 +1608,8 @@ bool GdbEngine::startDebugger() if (q->startMode() == AttachCore || q->startMode() == AttachExternal) { // nothing to do + } else if (q->startMode() == AttachRemote) { + // nothing to do } else if (q->m_useTerminal) { m_stubProc.stop(); // We leave the console open, so recycle it now. @@ -1726,6 +1735,7 @@ bool GdbEngine::startDebugger() if (q->startMode() == AttachExternal) { sendCommand(_("attach ") + QString::number(q->m_attachedPID), GdbAttached); + qq->breakHandler()->removeAllBreakpoints(); } else if (q->startMode() == AttachCore) { QFileInfo fi(q->m_executable); QString fileName = _c('"') + fi.absoluteFilePath() + _c('"'); @@ -1733,9 +1743,17 @@ bool GdbEngine::startDebugger() // quoting core name below fails in gdb 6.8-debian QString coreName = fi2.absoluteFilePath(); sendCommand(_("-file-exec-and-symbols ") + fileName); - sendCommand(_("target core ") + coreName, GdbTargetCore); + sendCommand(_("target core %1").arg(coreName), GdbTargetCore); + qq->breakHandler()->removeAllBreakpoints(); + } else if (q->startMode() == AttachRemote) { + sendCommand(_("set architecture %1").arg(q->m_remoteArchitecture)); + sendCommand(_("target remote %1").arg(q->m_remoteChannel)); + qq->breakHandler()->setAllPending(); + //sendCommand(_("info target"), GdbStart); + qq->notifyInferiorRunningRequested(); + sendCommand(_("-exec-continue"), GdbExecContinue); } else if (q->m_useTerminal) { - // nothing needed, stub takes care + qq->breakHandler()->setAllPending(); } else if (q->startMode() == StartInternal || q->startMode() == StartExternal) { QFileInfo fi(q->m_executable); QString fileName = _c('"') + fi.absoluteFilePath() + _c('"'); @@ -1756,13 +1774,8 @@ bool GdbEngine::startDebugger() qq->notifyInferiorRunningRequested(); sendCommand(_("-exec-run")); #endif - } - - // set all to "pending" - if (q->startMode() == AttachExternal || q->startMode() == AttachCore) - qq->breakHandler()->removeAllBreakpoints(); - else if (q->startMode() == StartInternal || q->startMode() == StartExternal) qq->breakHandler()->setAllPending(); + } return true; } diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index a5b0d0c2a6a..35376bac992 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -615,6 +615,9 @@ void testStdList() flist.push_back(3); flist.push_back(4); + foreach (Foo f, flist) + {} + std::list<bool> vec; vec.push_back(true); vec.push_back(false); -- GitLab