diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 79bb783f2967b7e92eb3cc3c1fc3ca245251a5aa..f30ee2c417297fb9740cac61d004f94043fbe1ae 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -312,6 +312,8 @@ StartRemoteDialog::StartRemoteDialog(QWidget *parent) { m_ui->setupUi(this); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + m_ui->serverStartScript->setExpectedKind(Core::Utils::PathChooser::File); + m_ui->serverStartScript->setPromptDialogTitle(tr("Select Executable")); connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); @@ -354,6 +356,15 @@ QString StartRemoteDialog::remoteArchitecture() const return m_ui->architectureComboBox->itemText(index); } +void StartRemoteDialog::setServerStartScript(const QString &scriptName) +{ + m_ui->serverStartScript->setPath(scriptName); +} + +QString StartRemoteDialog::serverStartScript() const +{ + return m_ui->serverStartScript->path(); +} /////////////////////////////////////////////////////////////////////// // diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index 04f1e65ceda3bbed7314a3ee08444a34ca186418..403e094d4cc6c80236fca844cc772a3145ce0aa0 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -114,6 +114,8 @@ public: void setRemoteArchitectures(const QStringList &arches); QString remoteChannel() const; QString remoteArchitecture() const; + void setServerStartScript(const QString &scriptName); + QString serverStartScript() const; private: Ui::StartRemoteDialog *m_ui; diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 9942b00288656cfdc1184b5ff67b68180f8ef8ba..cbcd0f76f3e954eb318d82a0eb5b47c59cbf6dfe 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -936,14 +936,17 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl) dlg.setRemoteArchitectures(arches); dlg.setRemoteChannel(configValue(_("LastRemoteChannel")).toString()); dlg.setRemoteArchitecture(configValue(_("LastRemoteArchtecture")).toString()); + dlg.setServerStartScript(configValue(_("LastServerStartScript")).toString()); if (dlg.exec() != QDialog::Accepted) { runControl->debuggingFinished(); return; } setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel()); setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture()); + setConfigValue(_("LastServerStartScript"), dlg.serverStartScript()); m_remoteChannel = dlg.remoteChannel(); m_remoteArchitecture = dlg.remoteArchitecture(); + m_serverStartScript = dlg.serverStartScript(); break; } } diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 66336caace89ada0e5a05259f1861ae71abac154..78d73c2db2b998102ed5ba354995fb360233dc75 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -359,8 +359,10 @@ public: QString m_dumperLib; int m_attachedPID; bool m_useTerminal; + // for remote debugging QString m_remoteChannel; QString m_remoteArchitecture; + QString m_serverStartScript; private: void init(); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index f80b76b5f19f71ea478fc1fea7dc361967bcbe9f..94809204e91342d02f5f2341695e4b35020c2f16 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -131,22 +131,28 @@ GdbEngine::~GdbEngine() void GdbEngine::initializeConnections() { // Gdb Process interaction - connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), this, - SLOT(gdbProcError(QProcess::ProcessError))); - connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), this, - SLOT(readGdbStandardOutput())); - connect(&m_gdbProc, SIGNAL(readyReadStandardError()), this, - SLOT(readGdbStandardError())); - connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), q, - SLOT(exitDebugger())); - - connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString))); - connect(&m_stubProc, SIGNAL(processStarted()), SLOT(stubStarted())); - connect(&m_stubProc, SIGNAL(wrapperStopped()), q, SLOT(exitDebugger())); + connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(gdbProcError(QProcess::ProcessError))); + connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), + this, SLOT(readGdbStandardOutput())); + connect(&m_gdbProc, SIGNAL(readyReadStandardError()), + this, SLOT(readGdbStandardError())); + connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), + q, SLOT(exitDebugger())); + + connect(&m_stubProc, SIGNAL(processError(QString)), + this, SLOT(stubError(QString))); + connect(&m_stubProc, SIGNAL(processStarted()), + this, SLOT(stubStarted())); + connect(&m_stubProc, SIGNAL(wrapperStopped()), + q, SLOT(exitDebugger())); + + connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(uploadProcError(QProcess::ProcessError))); // Output connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)), - SLOT(readDebugeeOutput(QByteArray))); + this, SLOT(readDebugeeOutput(QByteArray))); connect(this, SIGNAL(gdbOutputAvailable(QString,QString)), q, SLOT(showDebuggerOutput(QString,QString)), @@ -225,6 +231,43 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error) q->exitDebugger(); } +void GdbEngine::uploadProcError(QProcess::ProcessError error) +{ + QString msg; + switch (error) { + case QProcess::FailedToStart: + msg = tr("The upload process failed to start. Either the " + "invoked script '%1' is missing, or you may have insufficient " + "permissions to invoke the program.") + .arg(theDebuggerStringSetting(GdbLocation)); + break; + case QProcess::Crashed: + msg = tr("The upload process crashed some time after starting " + "successfully."); + break; + case QProcess::Timedout: + msg = tr("The last waitFor...() function timed out. " + "The state of QProcess is unchanged, and you can try calling " + "waitFor...() again."); + break; + case QProcess::WriteError: + msg = tr("An error occurred when attempting to write " + "to the upload process. For example, the process may not be running, " + "or it may have closed its input channel."); + break; + case QProcess::ReadError: + msg = tr("An error occurred when attempting to read from " + "the upload process. For example, the process may not be running."); + break; + default: + msg = tr("An unknown error in the upload process occurred. " + "This is the default return value of error()."); + } + + q->showStatusMessage(msg); + QMessageBox::critical(q->mainWindow(), tr("Error"), msg); +} + #if 0 static void dump(const char *first, const char *middle, const QString & to) { @@ -907,6 +950,7 @@ void GdbEngine::handleAqcuiredInferior() #endif if (theDebuggerBoolSetting(ListSourceFiles)) reloadSourceFiles(); + tryLoadDebuggingHelpers(); #ifndef Q_OS_MAC @@ -1358,7 +1402,18 @@ bool GdbEngine::startDebugger() if (q->startMode() == AttachCore || q->startMode() == AttachExternal) { // nothing to do } else if (q->startMode() == StartRemote) { - // nothing to do + // Start the remote server + if (q->m_serverStartScript.isEmpty()) { + q->showStatusMessage(_("No server start script given. " + "Assuming server runs already.")); + } else { + if (!q->m_workingDir.isEmpty()) + m_uploadProc.setWorkingDirectory(q->m_workingDir); + if (!q->m_environment.isEmpty()) + m_uploadProc.setEnvironment(q->m_environment); + m_uploadProc.start(_("/bin/sh ") + q->m_serverStartScript); + m_uploadProc.waitForStarted(); + } } else if (q->m_useTerminal) { m_stubProc.stop(); // We leave the console open, so recycle it now. @@ -2795,7 +2850,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QString &type) const if (!theDebuggerBoolSetting(UseDebuggingHelpers)) return false; - if (q->startMode() == AttachCore) { + if (!startModeAllowsDumpers()) { // "call" is not possible in gdb when looking at core files return type == __("QString") || type.endsWith(__("::QString")) || type == __("QStringList") || type.endsWith(__("::QStringList")); @@ -2834,7 +2889,7 @@ void GdbEngine::runDirectDebuggingHelper(const WatchData &data, bool dumpChildre void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) { - if (q->startMode() == AttachCore) { + if (!startModeAllowsDumpers()) { runDirectDebuggingHelper(data0, dumpChildren); return; } @@ -3832,6 +3887,9 @@ void GdbEngine::tryLoadDebuggingHelpers() if (m_debuggingHelperState != DebuggingHelperUninitialized) return; + if (!startModeAllowsDumpers()) + return; + PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS"); m_debuggingHelperState = DebuggingHelperUnavailable; if (!qq->qtDumperLibraryEnabled()) @@ -3881,9 +3939,18 @@ void GdbEngine::tryLoadDebuggingHelpers() void GdbEngine::recheckDebuggingHelperAvailability() { - // retreive list of dumpable classes - execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)")); - execCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper)); + if (startModeAllowsDumpers()) { + // retreive list of dumpable classes + execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)")); + execCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper)); + } +} + +bool GdbEngine::startModeAllowsDumpers() const +{ + return q->startMode() == StartInternal + || q->startMode() == StartExternal + || q->startMode() == AttachExternal; } IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts) diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 87523ae703be962b98e735ab83085a2a818653f4..a3767ce45c4e223b7e65398083a43a53059bbe26 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -191,6 +191,7 @@ private slots: void readDebugeeOutput(const QByteArray &data); void stubStarted(); void stubError(const QString &msg); + void uploadProcError(QProcess::ProcessError error); private: int terminationIndex(const QByteArray &buffer, int &length); @@ -226,6 +227,7 @@ private: QByteArray m_inbuffer; QProcess m_gdbProc; + QProcess m_uploadProc; Core::Utils::ConsoleProcess m_stubProc; @@ -354,6 +356,8 @@ private: const WatchData &parent); void setWatchDataType(WatchData &data, const GdbMi &mi); void setLocals(const QList<GdbMi> &locals); + + bool startModeAllowsDumpers() const; QString m_editedData; int m_pendingRequests; diff --git a/src/plugins/debugger/startremotedialog.ui b/src/plugins/debugger/startremotedialog.ui index 5f616cf90b2063170abaebaf0c8c852f7f12ae79..af0bc703237904f7cc6f1ba2793e766cc2572dea 100644 --- a/src/plugins/debugger/startremotedialog.ui +++ b/src/plugins/debugger/startremotedialog.ui @@ -49,6 +49,16 @@ <item row="1" column="1"> <widget class="QComboBox" name="architectureComboBox"/> </item> + <item row="2" column="0"> + <widget class="QLabel" name="serverStartScriptLabel"> + <property name="text"> + <string>Server start script</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="Core::Utils::PathChooser" name="serverStartScript" native="true"/> + </item> </layout> </item> <item> diff --git a/tests/manual/fakevim/runremotely.sh b/tests/manual/fakevim/runremotely.sh new file mode 100755 index 0000000000000000000000000000000000000000..927c8aec9d91c779d627f4eb0dd3ff0c18303b42 --- /dev/null +++ b/tests/manual/fakevim/runremotely.sh @@ -0,0 +1,15 @@ +#!/bin/sh +account=berlin@hd +sourcedir=/data5/dev/creator/tests/manual/fakevim/ +exename=fakevim +targetdir=/tmp/run-${exename} + +executable=${sourcedir}/${exename} +qtlibs=`ldd ${executable} | grep libQt | sed -e 's/^.*=> \(.*\) (.*)$/\1/'` + +ssh ${account} "mkdir -p ${targetdir}" +scp ${executable} ${qtlibs} ${account}:${targetdir} +ssh ${account} "chrpath -r ${targetdir} ${targetdir}/*" +ssh ${account} "gdbserver localhost:5555 ${targetdir}/${exename}" +ssh ${account} "rm ${targetdir}/* ; rmdir ${targetdir}" +