Commit c4a0abcd authored by Friedemann Kleint's avatar Friedemann Kleint

Enabled passing on PIDs from the command line to the debugger.

Introduced struct DebuggerStartParameters to pass around
start parameters, removing the need for the engines to
access private members of DebuggerManager. Pass it
to DebuggerManager::startNewDebugger() and move
the GUI parts of that function into DebuggerPlugin,
making it possible to create the struct from command line
parameters. Introduce command line parsing with a few more
-enable-xx options. Introduce warning() to debugger panel
in the CDB engine.

On this occasion, clean out a few trailing whitespaces.
parent 2eb2a382
......@@ -25,6 +25,11 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
<dependency name="Find" version="1.1.80"/>
</dependencyList>
<argumentList>
<argument name="-disable-cdb">Disable CDB debugger engine</argument>
<argument name="-disable-cdb">Disable Cdb debugger engine</argument>
<argument name="-disable-gdb">Disable Gdb debugger engine</argument>
<argument name="-disable-sdb">Disable Qt Script debugger engine</argument>
<argument name="-disable-tcf">Disable Tcf debugger engine</argument>
<argument name="-debug" parameter="process-id">Attach to Process-Id</argument>
<argument name="-winexception" parameter="exception-code">Exception code</argument>
</argumentList>
</plugin>
This diff is collapsed.
......@@ -107,6 +107,7 @@ private slots:
void slotConsoleStubStarted();
void slotConsoleStubError(const QString &msg);
void slotConsoleStubTerminated();
void warning(const QString &w);
private:
bool startAttachDebugger(qint64 pid, QString *errorMessage);
......
......@@ -289,9 +289,9 @@ void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
}
}
int AttachExternalDialog::attachPID() const
qint64 AttachExternalDialog::attachPID() const
{
return m_ui->pidLineEdit->text().toInt();
return m_ui->pidLineEdit->text().toLongLong();
}
void AttachExternalDialog::pidChanged(const QString &pid)
......
......@@ -87,7 +87,7 @@ public:
explicit AttachExternalDialog(QWidget *parent);
~AttachExternalDialog();
int attachPID() const;
qint64 attachPID() const;
private slots:
void rebuildProcessList();
......
This diff is collapsed.
......@@ -34,6 +34,7 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
class QAction;
......@@ -44,6 +45,7 @@ class QMainWindow;
class QPoint;
class QTimer;
class QWidget;
class QDebug;
QT_END_NAMESPACE
namespace Core {
......@@ -87,9 +89,9 @@ class Symbol;
// DebuggerProcessStartingUp
// | <-------------------------------------.
// DebuggerInferiorRunningRequested |
// | |
// DebuggerInferiorRunning |
// | |
// | |
// DebuggerInferiorRunning |
// | |
// DebuggerInferiorStopRequested |
// | |
// DebuggerInferiorStopped |
......@@ -124,12 +126,41 @@ enum DebuggerStartMode
StartRemote // Start and attach to a remote process
};
struct DebuggerStartParameters {
DebuggerStartParameters();
void clear();
QString executable;
QString coreFile;
QStringList processArgs;
QStringList environment;
QString workingDir;
QString buildDir;
qint64 attachPID;
bool useTerminal;
// for remote debugging
QString remoteChannel;
QString remoteArchitecture;
QString serverStartScript;
};
QDebug operator<<(QDebug str, const DebuggerStartParameters &);
class IDebuggerEngine;
class GdbEngine;
class ScriptEngine;
class CdbDebugEngine;
struct CdbDebugEnginePrivate;
// Flags for initialization
enum DebuggerEngineTypeFlags {
GdbEngineType = 0x1,
ScriptEngineType = 0x2,
CdbEngineType = 0x4,
TcfEngineType = 0x8,
AllEngineTypes = (GdbEngineType|ScriptEngineType|CdbEngineType|TcfEngineType)
};
// The construct below is not nice but enforces a bit of order. The
// DebuggerManager interfaces a lots of thing: The DebuggerPlugin,
// the DebuggerEngines, the RunMode, the handlers and views.
......@@ -150,6 +181,7 @@ public:
private:
// This is the part of the interface that's exclusively seen by the
// debugger engines
friend class CdbDebugEngine;
friend class CdbDebugEventCallback;
friend class CdbDumperHelper;
......@@ -161,11 +193,11 @@ private:
// called from the engines after successful startup
virtual void notifyInferiorStopRequested() = 0;
virtual void notifyInferiorStopped() = 0;
virtual void notifyInferiorStopped() = 0;
virtual void notifyInferiorRunningRequested() = 0;
virtual void notifyInferiorRunning() = 0;
virtual void notifyInferiorExited() = 0;
virtual void notifyInferiorPidChanged(int) = 0;
virtual void notifyInferiorPidChanged(qint64) = 0;
virtual DisassemblerHandler *disassemblerHandler() = 0;
virtual ModulesHandler *modulesHandler() = 0;
......@@ -179,7 +211,7 @@ private:
virtual void showApplicationOutput(const QString &data) = 0;
virtual void showDebuggerOutput(const QString &prefix, const QString &msg) = 0;
virtual void showDebuggerInput(const QString &prefix, const QString &msg) = 0;
virtual void reloadDisassembler() = 0;
virtual void reloadModules() = 0;
virtual void reloadSourceFiles() = 0;
......@@ -189,6 +221,9 @@ private:
virtual QString qtDumperLibraryName() const = 0;
virtual void showQtDumperLibraryWarning(const QString &details = QString()) = 0;
virtual qint64 inferiorPid() const = 0;
virtual QSharedPointer<DebuggerStartParameters> startParameters() const = 0;
};
......@@ -203,7 +238,7 @@ class DebuggerManager : public QObject,
public:
DebuggerManager();
QList<Core::IOptionsPage*> initializeEngines(const QStringList &arguments);
QList<Core::IOptionsPage*> initializeEngines(unsigned enabledTypeFlags);
~DebuggerManager();
......@@ -212,8 +247,13 @@ public:
QLabel *statusLabel() const { return m_statusLabel; }
public slots:
void startNewDebugger(DebuggerRunControl *runControl);
void exitDebugger();
void startNewDebugger(DebuggerRunControl *runControl, const QSharedPointer<DebuggerStartParameters> &startParameters);
void exitDebugger();
virtual QSharedPointer<DebuggerStartParameters> startParameters() const;
virtual qint64 inferiorPid() const;
void setQtDumperLibraryName(const QString &dl); // Run Control
void setSimpleDockWidgetArrangement();
void setLocked(bool locked);
......@@ -222,9 +262,6 @@ public slots:
void setBusyCursor(bool on);
void queryCurrentTextEditor(QString *fileName, int *lineNumber, QObject **ed);
QVariant configValue(const QString &name);
void queryConfigValue(const QString &name, QVariant *value);
void setConfigValue(const QString &name, const QVariant &value);
QVariant sessionValue(const QString &name);
void gotoLocation(const QString &file, int line, bool setLocationMarker);
......@@ -254,7 +291,7 @@ public slots:
void addToWatchWindow();
void updateWatchModel();
void sessionLoaded();
void sessionUnloaded();
void aboutToSaveSession();
......@@ -293,7 +330,7 @@ private slots:
private:
//
// Implementation of IDebuggerManagerAccessForEngines
//
//
DisassemblerHandler *disassemblerHandler() { return m_disassemblerHandler; }
ModulesHandler *modulesHandler() { return m_modulesHandler; }
BreakHandler *breakHandler() { return m_breakHandler; }
......@@ -308,9 +345,9 @@ private:
void notifyInferiorStopRequested();
void notifyInferiorRunning();
void notifyInferiorExited();
void notifyInferiorPidChanged(int);
void notifyInferiorPidChanged(qint64);
void cleanupViews();
void cleanupViews();
//
// Implementation of IDebuggerManagerAccessForDebugMode
......@@ -322,15 +359,15 @@ private:
virtual QString qtDumperLibraryName() const;
virtual void showQtDumperLibraryWarning(const QString &details = QString());
//
//
// internal implementation
//
//
Q_SLOT void loadSessionData();
Q_SLOT void saveSessionData();
Q_SLOT void dumpLog();
public:
// stuff in this block should be made private by moving it to
// stuff in this block should be made private by moving it to
// one of the interfaces
QAbstractItemModel *threadsModel();
int status() const { return m_status; }
......@@ -357,20 +394,6 @@ signals:
void applicationOutputAvailable(const QString &output);
public:
// FIXME: make private
QString m_executable;
QString m_coreFile;
QStringList m_environment;
QString m_workingDir;
QString m_buildDir;
QStringList m_processArgs;
QString m_dumperLib;
int m_attachedPID;
bool m_useTerminal;
// for remote debugging
QString m_remoteChannel;
QString m_remoteArchitecture;
QString m_serverStartScript;
private:
void init();
......@@ -388,7 +411,11 @@ private:
BreakpointData *findBreakpoint(const QString &fileName, int lineNumber);
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
QSharedPointer<DebuggerStartParameters> m_startParameters;
DebuggerRunControl *m_runControl;
QString m_dumperLib;
qint64 m_inferiorPid;
/// Views
QMainWindow *m_mainWindow;
......
This diff is collapsed.
......@@ -33,6 +33,7 @@
#include <extensionsystem/iplugin.h>
#include <QtCore/QObject>
#include <QtCore/QStringList>
QT_BEGIN_NAMESPACE
class QAbstractItemView;
......@@ -69,9 +70,11 @@ public:
~DebuggerPlugin();
private:
bool initialize(const QStringList &arguments, QString *error_message);
void shutdown();
void extensionsInitialized();
virtual bool initialize(const QStringList &arguments, QString *error_message);
virtual void shutdown();
virtual void extensionsInitialized();
QVariant configValue(const QString &name) const;
private slots:
void activatePreviousMode();
......@@ -90,7 +93,6 @@ private slots:
int lineNumber, QMenu *menu);
void updateActions(int status);
void resetLocation();
void gotoLocation(const QString &fileName, int line, bool setMarker);
......@@ -104,10 +106,16 @@ private slots:
void attachExternalApplication();
void attachCore();
void attachRemoteTcf();
void attachCmdLinePid();
private:
void readSettings();
void writeSettings() const;
bool parseArguments(const QStringList &args, QString *errorMessage);
inline bool parseArgument(QStringList::const_iterator &it,
const QStringList::const_iterator& end,
QString *errorMessage);
void attachExternalApplication(qint64 pid);
friend class DebuggerManager;
friend class GdbOptionPage;
......@@ -121,7 +129,10 @@ private:
QString m_previousMode;
LocationMark *m_locationMark;
int m_gdbRunningContext;
unsigned m_cmdLineEnabledEngines;
quint64 m_cmdLineAttachPid;
// Exception that crashed an app passed on by Windows
unsigned long m_cmdLineWinException;
QAction *m_toggleLockedAction;
QAction *m_startExternalAction;
......
......@@ -58,13 +58,13 @@ using ProjectExplorer::ApplicationRunConfiguration;
////////////////////////////////////////////////////////////////////////
// A factory to create DebuggerRunControls
DebuggerRunner::DebuggerRunner(DebuggerManager *manager)
: m_manager(manager)
DebuggerRunner::DebuggerRunner(DebuggerManager *manager) :
m_manager(manager)
{}
bool DebuggerRunner::canRun(RunConfigurationPtr runConfiguration, const QString &mode)
{
return mode == ProjectExplorer::Constants::DEBUGMODE
return mode == ProjectExplorer::Constants::DEBUGMODE
&& !qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration).isNull();
}
......@@ -74,22 +74,24 @@ QString DebuggerRunner::displayName() const
}
RunControl* DebuggerRunner::run(RunConfigurationPtr runConfiguration,
const QString &mode, DebuggerStartMode startMode)
const QString &mode,
const QSharedPointer<DebuggerStartParameters> &sp,
DebuggerStartMode startMode)
{
QTC_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE, return 0);
ApplicationRunConfigurationPtr rc =
qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration);
//QTC_ASSERT(rc, return 0);
//qDebug() << "***** Debugging" << rc->name() << rc->executable();
DebuggerRunControl *runControl = new DebuggerRunControl(m_manager, rc);
runControl->setStartMode(startMode);
DebuggerRunControl *runControl = new DebuggerRunControl(m_manager, startMode, sp, rc);
return runControl;
}
RunControl* DebuggerRunner::run(RunConfigurationPtr runConfiguration,
const QString &mode)
{
return run(runConfiguration, mode, StartInternal);
const QSharedPointer<DebuggerStartParameters> sp(new DebuggerStartParameters);
return run(runConfiguration, mode, sp, StartInternal);
}
QWidget *DebuggerRunner::configurationWidget(RunConfigurationPtr runConfiguration)
......@@ -109,8 +111,14 @@ QWidget *DebuggerRunner::configurationWidget(RunConfigurationPtr runConfiguratio
DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager,
QSharedPointer<ApplicationRunConfiguration> runConfiguration)
: RunControl(runConfiguration), m_manager(manager), m_running(false)
DebuggerStartMode mode,
const QSharedPointer<DebuggerStartParameters> &startParameters,
QSharedPointer<ApplicationRunConfiguration> runConfiguration) :
RunControl(runConfiguration),
m_mode(mode),
m_startParameters(startParameters),
m_manager(manager),
m_running(false)
{
connect(m_manager, SIGNAL(debuggingFinished()),
this, SLOT(debuggingFinished()),
......@@ -131,28 +139,31 @@ void DebuggerRunControl::start()
ApplicationRunConfigurationPtr rc =
qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration());
if (rc) {
m_manager->m_executable = rc->executable();
m_manager->m_environment = rc->environment().toStringList();
m_manager->m_workingDir = rc->workingDirectory();
m_manager->m_processArgs = rc->commandLineArguments();
m_manager->m_dumperLib = rc->dumperLibrary();
ProjectExplorer::Project *project = rc->project();
QTC_ASSERT(project, /**/);
if (project) {
m_manager->m_buildDir =
project->buildDirectory(project->activeBuildConfiguration());
// Enhance parameters by info from the project, but do not clobber
// arguments given in the dialogs
if (m_startParameters->executable.isEmpty())
m_startParameters->executable = rc->executable();
if (m_startParameters->environment.empty())
m_startParameters->environment = rc->environment().toStringList();
if (m_startParameters->workingDir.isEmpty())
m_startParameters->workingDir = rc->workingDirectory();
if (m_mode != StartExternal)
m_startParameters->processArgs = rc->commandLineArguments();
m_manager->setQtDumperLibraryName(rc->dumperLibrary());
if (const ProjectExplorer::Project *project = rc->project()) {
m_startParameters->buildDir = project->buildDirectory(project->activeBuildConfiguration());
}
m_manager->m_useTerminal = rc->runMode() == ApplicationRunConfiguration::Console;
m_startParameters->useTerminal = rc->runMode() == ApplicationRunConfiguration::Console;
}
//emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable));
m_manager->startNewDebugger(this);
m_manager->startNewDebugger(this, m_startParameters);
emit started();
//debuggingFinished();
}
void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data)
{
{
emit addToOutputWindowInline(this, data);
}
......
......@@ -59,14 +59,19 @@ public:
// ProjectExplorer::IRunConfigurationRunner
virtual bool canRun(RunConfigurationPtr runConfiguration, const QString &mode);
virtual ProjectExplorer::RunControl *run(RunConfigurationPtr runConfiguration, const QString &mode);
virtual QString displayName() const;
virtual ProjectExplorer::RunControl *run(RunConfigurationPtr runConfiguration,
const QString &mode);
virtual QWidget *configurationWidget(RunConfigurationPtr runConfiguration);
virtual ProjectExplorer::RunControl *run(RunConfigurationPtr runConfiguration,
const QString &mode, DebuggerStartMode startMode);
virtual ProjectExplorer::RunControl
*run(RunConfigurationPtr runConfiguration,
const QString &mode,
const QSharedPointer<DebuggerStartParameters> &sp,
DebuggerStartMode startMode);
private:
QSharedPointer<DebuggerStartParameters> m_startParameters;
DebuggerManager *m_manager;
};
......@@ -76,18 +81,20 @@ class DebuggerRunControl : public ProjectExplorer::RunControl
Q_OBJECT
public:
DebuggerRunControl(DebuggerManager *manager,
ApplicationRunConfigurationPtr runConfiguration);
explicit DebuggerRunControl(DebuggerManager *manager,
DebuggerStartMode mode,
const QSharedPointer<DebuggerStartParameters> &sp,
ApplicationRunConfigurationPtr runConfiguration);
DebuggerStartMode startMode() const { return m_mode; }
// ProjectExplorer::RunControl
virtual void start();
virtual void stop();
virtual bool isRunning() const;
void setStartMode(DebuggerStartMode mode) { m_mode = mode; }
DebuggerStartMode startMode() const { return m_mode; }
Q_SLOT void debuggingFinished();
signals:
void stopRequested();
......@@ -95,9 +102,10 @@ private slots:
void slotAddToOutputWindowInline(const QString &output);
private:
const DebuggerStartMode m_mode;
const QSharedPointer<DebuggerStartParameters> m_startParameters;
DebuggerManager *m_manager;
bool m_running;
DebuggerStartMode m_mode;
};
} // namespace Internal
......
......@@ -542,9 +542,9 @@ void GdbEngine::handleStubAttached(const GdbResultRecord &, const QVariant &)
void GdbEngine::stubStarted()
{
q->m_attachedPID = m_stubProc.applicationPID();
qq->notifyInferiorPidChanged(q->m_attachedPID);
postCommand(_("attach %1").arg(q->m_attachedPID), CB(handleStubAttached));
const qint64 attachedPID = m_stubProc.applicationPID();
qq->notifyInferiorPidChanged(attachedPID);
postCommand(_("attach %1").arg(attachedPID), CB(handleStubAttached));
}
void GdbEngine::stubError(const QString &msg)
......@@ -602,26 +602,27 @@ void GdbEngine::interruptInferior()
return;
}
if (q->m_attachedPID <= 0) {
const qint64 attachedPID = q->inferiorPid();
if (attachedPID <= 0) {
debugMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
return;
}
if (!interruptProcess(q->m_attachedPID))
debugMessage(_("CANNOT INTERRUPT %1").arg(q->m_attachedPID));
if (!interruptProcess(attachedPID))
debugMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
}
void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
{
int pid = pid0.toInt();
const qint64 pid = pid0.toLongLong();
if (pid == 0) {
debugMessage(_("Cannot parse PID from %1").arg(pid0));
return;
}
if (pid == q->m_attachedPID)
if (pid == q->inferiorPid())
return;
debugMessage(_("FOUND PID %1").arg(pid));
q->m_attachedPID = pid;
debugMessage(_("FOUND PID %1").arg(pid));
qq->notifyInferiorPidChanged(pid);
if (m_dumperInjectionLoad)
tryLoadDebuggingHelpers();
......@@ -1364,27 +1365,29 @@ bool GdbEngine::startDebugger()
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
const QSharedPointer<DebuggerStartParameters> sp = q->startParameters();
if (q->startMode() == AttachCore || q->startMode() == AttachExternal) {
// nothing to do
} else if (q->startMode() == StartRemote) {
// Start the remote server
if (q->m_serverStartScript.isEmpty()) {
if (sp->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);
if (!sp->workingDir.isEmpty())
m_uploadProc.setWorkingDirectory(sp->workingDir);
if (!sp->environment.isEmpty())
m_uploadProc.setEnvironment(sp->environment);
m_uploadProc.start(_("/bin/sh ") + sp->serverStartScript);
m_uploadProc.waitForStarted();
}
} else if (q->m_useTerminal) {
} else if (sp->useTerminal) {
m_stubProc.stop(); // We leave the console open, so recycle it now.
m_stubProc.setWorkingDirectory(q->m_workingDir);
m_stubProc.setEnvironment(q->m_environment);
if (!m_stubProc.start(q->m_executable, q->m_processArgs))
m_stubProc.setWorkingDirectory(sp->workingDir);
m_stubProc.setEnvironment(sp->environment);
if (!m_stubProc.start(sp->executable, sp->processArgs))
return false; // Error message for user is delivered via a signal.
} else {
if (!m_outputCollector.listen()) {
......@@ -1395,10 +1398,10 @@ bool GdbEngine::startDebugger()
}
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
if (!q->m_workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(q->m_workingDir);
if (!q->m_environment.isEmpty())
m_gdbProc.setEnvironment(q->m_environment);
if (!sp->workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(sp->workingDir);
if (!sp->environment.isEmpty())
m_gdbProc.setEnvironment(sp->environment);
}
#if 0
......@@ -1407,8 +1410,8 @@ bool GdbEngine::startDebugger()
qDebug() << "ScriptFile:" << q->settings()->m_scriptFile;
qDebug() << "Environment:" << m_gdbProc.environment();
qDebug() << "Arguments:" << gdbArgs;
qDebug() << "BuildDir:" << q->m_buildDir;
qDebug() << "ExeFile:" << q->m_executable;
qDebug() << "BuildDir:" << sp->buildDir;
qDebug() << "ExeFile:" << sp->executable;
#endif
QString loc = theDebuggerStringSetting(GdbLocation);
......@@ -1504,38 +1507,38 @@ bool GdbEngine::startDebugger()
}
if (q->startMode() == AttachExternal) {
postCommand(_("attach %1").arg(q->m_attachedPID), CB(handleAttach));
postCommand(_("attach %1").arg(sp->attachPID), CB(handleAttach));
qq->breakHandler()->removeAllBreakpoints();
} else if (q->startMode() == AttachCore) {
QFileInfo fi(q->m_executable);
QFileInfo fi(sp->executable);
QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
QFileInfo fi2(q->m_coreFile);
QFileInfo fi2(sp->coreFile);
// quoting core name below fails in gdb 6.8-debian
QString coreName = fi2.absoluteFilePath();
postCommand(_("-file-exec-and-symbols ") + fileName);
postCommand(_("target core ") + coreName, CB(handleTargetCore));
qq->breakHandler()->removeAllBreakpoints();
} else if (q->startMode() == StartRemote) {
postCommand(_("set architecture %1").arg(q->m_remoteArchitecture));
postCommand(_("set architecture %1").arg(sp->remoteArchitecture));
qq->breakHandler()->setAllPending