2009-02-25 09:15:00 +01:00
|
|
|
/**************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
**
|
2010-03-05 11:25:49 +01:00
|
|
|
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-06-17 00:01:27 +10:00
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** No Commercial Usage
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** This file contains pre-release code and may not be distributed.
|
|
|
|
** You may use this file in accordance with the terms and conditions
|
|
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
|
|
** this package.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** Alternatively, 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.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2010-12-17 16:01:08 +01:00
|
|
|
** 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.
|
|
|
|
**
|
|
|
|
** If you have questions regarding the use of this file, please contact
|
|
|
|
** Nokia at qt-info@nokia.com.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
**************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "debuggerrunner.h"
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "debuggeractions.h"
|
2010-11-10 11:39:01 +01:00
|
|
|
#include "debuggercore.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "debuggerengine.h"
|
2010-12-02 17:43:14 +01:00
|
|
|
#include "debuggermainwindow.h"
|
2010-06-16 11:08:54 +02:00
|
|
|
#include "debuggerplugin.h"
|
|
|
|
#include "debuggerstringutils.h"
|
2011-01-10 10:14:23 +01:00
|
|
|
#include "debuggerstartparameters.h"
|
2010-11-10 16:33:11 +01:00
|
|
|
#include "gdb/gdboptionspage.h"
|
2010-10-08 12:14:51 +02:00
|
|
|
#include "lldb/lldbenginehost.h"
|
2010-06-15 09:13:22 +02:00
|
|
|
|
2010-06-22 12:28:05 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
# include "peutils.h"
|
|
|
|
#endif
|
|
|
|
|
2009-11-09 16:25:24 +01:00
|
|
|
#include <projectexplorer/debugginghelper.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <projectexplorer/project.h>
|
2010-11-01 14:14:17 +01:00
|
|
|
#include <projectexplorer/toolchain.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2010-02-08 15:50:06 +01:00
|
|
|
#include <projectexplorer/target.h>
|
2009-11-25 18:50:20 +01:00
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
2011-01-07 14:52:18 +01:00
|
|
|
#include <projectexplorer/outputformat.h>
|
2010-06-11 16:31:54 +02:00
|
|
|
#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-09-29 10:32:41 +02:00
|
|
|
#include <utils/synchronousprocess.h>
|
2008-12-09 15:25:01 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2010-08-20 14:19:25 +02:00
|
|
|
#include <utils/fancymainwindow.h>
|
2010-12-15 13:06:39 +01:00
|
|
|
#include <utils/qtcprocess.h>
|
2009-10-08 17:23:27 +02:00
|
|
|
#include <coreplugin/icore.h>
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <QtCore/QDir>
|
2010-08-20 14:19:25 +02:00
|
|
|
#include <QtGui/QMessageBox>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-06-11 16:16:14 +02:00
|
|
|
using namespace ProjectExplorer;
|
2010-06-14 17:23:25 +02:00
|
|
|
using namespace Debugger::Internal;
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
namespace Debugger {
|
2010-12-10 09:37:31 +01:00
|
|
|
|
|
|
|
namespace Cdb {
|
|
|
|
bool isCdbEngineEnabled(); // Check the configuration page
|
2011-01-07 19:50:41 +01:00
|
|
|
ConfigurationCheck checkCdbConfiguration(ToolChainType toolChain);
|
|
|
|
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *error);
|
2010-12-10 09:37:31 +01:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &);
|
|
|
|
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &);
|
|
|
|
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &);
|
|
|
|
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &);
|
|
|
|
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
|
2010-08-18 13:54:12 +02:00
|
|
|
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &);
|
2010-11-26 10:10:00 +01:00
|
|
|
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
extern QString msgNoBinaryForToolChain(int tc);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
static QString msgEngineNotAvailable(const char *engine)
|
|
|
|
{
|
|
|
|
return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
|
|
|
|
"which is disabled.").arg(QLatin1String(engine));
|
|
|
|
}
|
|
|
|
|
2010-06-15 08:22:02 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2010-11-26 10:10:00 +01:00
|
|
|
// DebuggerRunControlPrivate
|
2010-06-15 08:22:02 +02:00
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2010-11-26 10:10:00 +01:00
|
|
|
class DebuggerRunControlPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DebuggerRunControlPrivate(DebuggerRunControl *parent,
|
2011-01-07 20:10:54 +01:00
|
|
|
RunConfiguration *runConfiguration);
|
2010-09-14 08:34:07 +02:00
|
|
|
|
2010-11-26 10:10:00 +01:00
|
|
|
DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes,
|
|
|
|
const QString &executable);
|
|
|
|
DebuggerEngineType engineForMode(unsigned enabledEngineTypes,
|
|
|
|
DebuggerStartMode mode);
|
|
|
|
|
|
|
|
public:
|
|
|
|
DebuggerRunControl *q;
|
2010-09-14 08:34:07 +02:00
|
|
|
DebuggerEngine *m_engine;
|
|
|
|
const QWeakPointer<RunConfiguration> m_myRunConfiguration;
|
|
|
|
bool m_running;
|
|
|
|
QString m_errorMessage;
|
|
|
|
QString m_settingsIdHint;
|
|
|
|
};
|
|
|
|
|
2010-11-26 10:10:00 +01:00
|
|
|
DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent,
|
2011-01-07 20:10:54 +01:00
|
|
|
RunConfiguration *runConfiguration)
|
2010-11-26 10:10:00 +01:00
|
|
|
: q(parent)
|
|
|
|
, m_engine(0)
|
2010-10-22 11:27:45 +02:00
|
|
|
, m_myRunConfiguration(runConfiguration)
|
2010-08-18 13:54:12 +02:00
|
|
|
, m_running(false)
|
2010-09-14 08:34:07 +02:00
|
|
|
{
|
|
|
|
}
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
// Figure out the debugger type of an executable. Analyze executable
|
|
|
|
// unless the toolchain provides a hint.
|
2010-11-26 10:10:00 +01:00
|
|
|
DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable
|
|
|
|
(unsigned enabledEngineTypes, const QString &executable)
|
2010-06-15 09:13:22 +02:00
|
|
|
{
|
2010-06-16 11:08:54 +02:00
|
|
|
if (executable.endsWith(_(".js"))) {
|
2010-10-05 14:30:26 +02:00
|
|
|
if (enabledEngineTypes & ScriptEngineType)
|
2010-06-16 11:08:54 +02:00
|
|
|
return ScriptEngineType;
|
2010-11-26 10:10:00 +01:00
|
|
|
m_errorMessage = msgEngineNotAvailable("Script Engine");
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
if (executable.endsWith(_(".py"))) {
|
2010-10-05 14:30:26 +02:00
|
|
|
if (enabledEngineTypes & PdbEngineType)
|
2010-06-16 11:08:54 +02:00
|
|
|
return PdbEngineType;
|
2010-11-26 10:10:00 +01:00
|
|
|
m_errorMessage = msgEngineNotAvailable("Pdb Engine");
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// A remote executable?
|
|
|
|
if (!executable.endsWith(_(".exe")))
|
2010-06-22 12:28:05 +02:00
|
|
|
return GdbEngineType;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
// If a file has PDB files, it has been compiled by VS.
|
|
|
|
QStringList pdbFiles;
|
2010-11-26 10:10:00 +01:00
|
|
|
if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) {
|
2010-06-16 11:08:54 +02:00
|
|
|
qWarning("Cannot determine type of executable %s: %s",
|
2010-11-26 10:10:00 +01:00
|
|
|
qPrintable(executable), qPrintable(m_errorMessage));
|
2010-06-22 12:28:05 +02:00
|
|
|
return NoEngineType;
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
if (pdbFiles.empty())
|
|
|
|
return GdbEngineType;
|
2010-06-14 17:23:25 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
// We need the CDB debugger in order to be able to debug VS
|
2010-11-26 11:51:12 +01:00
|
|
|
// executables.
|
2011-01-07 19:50:41 +01:00
|
|
|
ConfigurationCheck check = checkDebugConfiguration(ToolChain_MSVC);
|
|
|
|
if (!check) {
|
|
|
|
m_errorMessage = check.errorMessage;
|
|
|
|
m_settingsIdHint = check.settingsPage;
|
2010-10-05 14:30:26 +02:00
|
|
|
if (enabledEngineTypes & CdbEngineType)
|
|
|
|
return CdbEngineType;
|
2010-11-26 10:10:00 +01:00
|
|
|
m_errorMessage = msgEngineNotAvailable("Cdb Engine");
|
2010-10-05 14:30:26 +02:00
|
|
|
return NoEngineType;
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
#else
|
2010-10-05 14:30:26 +02:00
|
|
|
if (enabledEngineTypes & GdbEngineType)
|
2010-06-16 11:08:54 +02:00
|
|
|
return GdbEngineType;
|
2010-11-26 10:10:00 +01:00
|
|
|
m_errorMessage = msgEngineNotAvailable("Gdb Engine");
|
2010-06-16 11:08:54 +02:00
|
|
|
#endif
|
2009-10-08 17:36:07 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
return NoEngineType;
|
2010-06-15 08:22:02 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
// Debugger type for mode.
|
2010-11-26 10:10:00 +01:00
|
|
|
DebuggerEngineType DebuggerRunControlPrivate::engineForMode
|
|
|
|
(unsigned enabledEngineTypes, DebuggerStartMode startMode)
|
2010-06-07 16:40:33 +02:00
|
|
|
{
|
2010-06-16 11:08:54 +02:00
|
|
|
if (startMode == AttachTcf)
|
|
|
|
return TcfEngineType;
|
2010-06-07 16:40:33 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// Preferably Windows debugger for attaching locally.
|
2010-10-05 14:30:26 +02:00
|
|
|
if (startMode != AttachToRemote && (enabledEngineTypes & CdbEngineType))
|
2010-06-16 11:08:54 +02:00
|
|
|
return CdbEngineType;
|
2010-10-22 11:31:33 +02:00
|
|
|
if (startMode == AttachCrashedExternal) {
|
2010-11-26 13:06:03 +01:00
|
|
|
m_errorMessage = DebuggerRunControl::tr("There is no debugging engine available for post-mortem debugging.");
|
2010-10-22 11:31:33 +02:00
|
|
|
return NoEngineType;
|
|
|
|
}
|
2010-06-22 12:28:05 +02:00
|
|
|
return GdbEngineType;
|
2010-06-16 11:08:54 +02:00
|
|
|
#else
|
|
|
|
Q_UNUSED(startMode)
|
2010-10-05 14:30:26 +02:00
|
|
|
Q_UNUSED(enabledEngineTypes)
|
2010-11-26 10:10:00 +01:00
|
|
|
// >m_errorMessage = msgEngineNotAvailable("Gdb Engine");
|
2010-06-16 11:08:54 +02:00
|
|
|
return GdbEngineType;
|
|
|
|
#endif
|
2010-04-15 11:59:22 +02:00
|
|
|
}
|
|
|
|
|
2010-12-10 09:37:31 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
|
|
|
|
2010-11-26 10:10:00 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// DebuggerRunControl
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
static DebuggerEngineType engineForToolChain(ToolChainType toolChainType)
|
2010-11-26 10:10:00 +01:00
|
|
|
{
|
|
|
|
switch (toolChainType) {
|
2011-01-07 19:50:41 +01:00
|
|
|
case ToolChain_LINUX_ICC:
|
|
|
|
case ToolChain_MinGW:
|
|
|
|
case ToolChain_GCC:
|
|
|
|
case ToolChain_WINSCW: // S60
|
|
|
|
case ToolChain_GCCE:
|
|
|
|
case ToolChain_RVCT2_ARMV5:
|
|
|
|
case ToolChain_RVCT2_ARMV6:
|
|
|
|
case ToolChain_RVCT_ARMV5_GNUPOC:
|
|
|
|
case ToolChain_GCCE_GNUPOC:
|
|
|
|
case ToolChain_GCC_MAEMO:
|
2010-11-26 15:10:10 +01:00
|
|
|
#ifdef WITH_LLDB
|
|
|
|
// lldb override
|
|
|
|
if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool())
|
|
|
|
return LldbEngineType;
|
|
|
|
#endif
|
2010-11-26 10:10:00 +01:00
|
|
|
return GdbEngineType;
|
|
|
|
|
2010-11-26 15:10:10 +01:00
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
case ToolChain_MSVC:
|
|
|
|
case ToolChain_WINCE:
|
2010-11-26 10:10:00 +01:00
|
|
|
return CdbEngineType;
|
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
case ToolChain_OTHER:
|
|
|
|
case ToolChain_UNKNOWN:
|
|
|
|
case ToolChain_INVALID:
|
2010-11-26 10:10:00 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return NoEngineType;
|
|
|
|
}
|
|
|
|
|
2011-01-07 20:10:54 +01:00
|
|
|
|
|
|
|
unsigned filterEngines(unsigned enabledEngineTypes)
|
|
|
|
{
|
|
|
|
#ifdef CDB_ENABLED
|
|
|
|
if (!isCdbEngineEnabled() && !Cdb::isCdbEngineEnabled())
|
|
|
|
enabledEngineTypes &= ~CdbEngineType;
|
|
|
|
#endif
|
|
|
|
return enabledEngineTypes;
|
|
|
|
}
|
|
|
|
|
2010-12-03 16:18:50 +01:00
|
|
|
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
|
2011-01-07 20:10:54 +01:00
|
|
|
const DebuggerStartParameters &startParams)
|
2010-12-03 16:18:50 +01:00
|
|
|
: RunControl(runConfiguration, Constants::DEBUGMODE),
|
2011-01-07 20:10:54 +01:00
|
|
|
d(new DebuggerRunControlPrivate(this, runConfiguration))
|
2009-09-09 18:35:25 +02:00
|
|
|
{
|
2010-12-03 16:18:50 +01:00
|
|
|
connect(this, SIGNAL(finished()), SLOT(handleFinished()));
|
2010-08-18 13:54:12 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
// Figure out engine according to toolchain, executable, attach or default.
|
|
|
|
DebuggerEngineType engineType = NoEngineType;
|
2010-11-10 11:39:01 +01:00
|
|
|
DebuggerLanguages activeLangs = debuggerCore()->activeLanguages();
|
2010-12-03 16:18:50 +01:00
|
|
|
DebuggerStartParameters sp = startParams;
|
2011-01-07 20:10:54 +01:00
|
|
|
unsigned enabledEngineTypes = filterEngines(sp.enabledEngines);
|
|
|
|
|
2010-09-27 17:22:57 +02:00
|
|
|
if (sp.executable.endsWith(_(".js")))
|
2010-06-16 11:08:54 +02:00
|
|
|
engineType = ScriptEngineType;
|
|
|
|
else if (sp.executable.endsWith(_(".py")))
|
|
|
|
engineType = PdbEngineType;
|
2010-10-05 14:30:26 +02:00
|
|
|
else {
|
2010-06-16 11:08:54 +02:00
|
|
|
engineType = engineForToolChain(sp.toolChainType);
|
2010-10-05 14:30:26 +02:00
|
|
|
if (engineType == CdbEngineType && !(enabledEngineTypes & CdbEngineType)) {
|
|
|
|
d->m_errorMessage = msgEngineNotAvailable("Cdb Engine");
|
|
|
|
engineType = NoEngineType;
|
|
|
|
}
|
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-12-15 09:35:31 +01:00
|
|
|
// FIXME: Unclean ipc override. Someone please have a better idea.
|
2010-12-01 15:41:08 +01:00
|
|
|
if (sp.startMode == StartRemoteEngine)
|
2010-12-15 09:35:31 +01:00
|
|
|
// For now thats the only supported IPC engine.
|
2010-11-30 08:59:22 +01:00
|
|
|
engineType = LldbEngineType;
|
|
|
|
|
2010-12-15 09:35:31 +01:00
|
|
|
// FIXME: 1 of 3 testing hacks.
|
2010-10-19 11:14:03 +02:00
|
|
|
if (sp.processArgs.startsWith(__("@tcf@ ")))
|
2010-06-25 15:06:30 +02:00
|
|
|
engineType = GdbEngineType;
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
if (engineType == NoEngineType
|
|
|
|
&& sp.startMode != AttachToRemote
|
|
|
|
&& !sp.executable.isEmpty())
|
2010-11-26 10:10:00 +01:00
|
|
|
engineType = d->engineForExecutable(enabledEngineTypes, sp.executable);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-10-22 11:27:45 +02:00
|
|
|
if (engineType == NoEngineType)
|
2010-11-26 10:10:00 +01:00
|
|
|
engineType = d->engineForMode(enabledEngineTypes, sp.startMode);
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-10-22 11:27:45 +02:00
|
|
|
if ((engineType != QmlEngineType && engineType != NoEngineType)
|
|
|
|
&& (activeLangs & QmlLanguage)) {
|
2010-08-24 17:17:54 +02:00
|
|
|
if (activeLangs & CppLanguage) {
|
2010-08-18 13:54:12 +02:00
|
|
|
sp.cppEngineType = engineType;
|
|
|
|
engineType = QmlCppEngineType;
|
|
|
|
} else {
|
|
|
|
engineType = QmlEngineType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-22 12:28:05 +02:00
|
|
|
// qDebug() << "USING ENGINE : " << engineType;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
|
|
|
switch (engineType) {
|
|
|
|
case GdbEngineType:
|
2010-09-14 08:34:07 +02:00
|
|
|
d->m_engine = createGdbEngine(sp);
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-06-16 11:08:54 +02:00
|
|
|
case ScriptEngineType:
|
2010-11-26 10:10:00 +01:00
|
|
|
d->m_engine = createScriptEngine(sp);
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-06-16 11:08:54 +02:00
|
|
|
case CdbEngineType:
|
2011-01-07 15:04:11 +01:00
|
|
|
d->m_engine = Cdb::createCdbEngine(sp, &d->m_errorMessage);
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-06-16 11:08:54 +02:00
|
|
|
case PdbEngineType:
|
2010-11-26 10:10:00 +01:00
|
|
|
d->m_engine = createPdbEngine(sp);
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-06-16 11:08:54 +02:00
|
|
|
case TcfEngineType:
|
2010-11-26 10:10:00 +01:00
|
|
|
d->m_engine = createTcfEngine(sp);
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-06-16 11:08:54 +02:00
|
|
|
case QmlEngineType:
|
2010-11-26 10:10:00 +01:00
|
|
|
d->m_engine = createQmlEngine(sp);
|
2010-06-16 11:08:54 +02:00
|
|
|
break;
|
2010-08-18 13:54:12 +02:00
|
|
|
case QmlCppEngineType:
|
2010-11-26 10:10:00 +01:00
|
|
|
d->m_engine = createQmlCppEngine(sp);
|
2010-08-18 13:54:12 +02:00
|
|
|
break;
|
2010-11-26 10:10:00 +01:00
|
|
|
case LldbEngineType:
|
|
|
|
d->m_engine = createLldbEngine(sp);
|
2010-11-30 08:59:22 +01:00
|
|
|
case NoEngineType:
|
|
|
|
case AllEngineTypes:
|
2010-06-14 18:19:02 +02:00
|
|
|
break;
|
2010-10-05 14:30:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!d->m_engine) {
|
|
|
|
// Could not find anything suitable.
|
|
|
|
debuggingFinished();
|
2010-11-26 11:10:03 +01:00
|
|
|
// Create Message box with possibility to go to settings.
|
2011-01-07 19:50:41 +01:00
|
|
|
QString toolChainName = ToolChain::toolChainName(sp.toolChainType);
|
2010-10-05 14:30:26 +02:00
|
|
|
const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
|
2011-01-07 10:13:41 +01:00
|
|
|
.arg(sp.executable, toolChainName, d->m_errorMessage);
|
2010-10-05 14:30:26 +02:00
|
|
|
Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
|
2010-11-26 11:10:03 +01:00
|
|
|
msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
|
|
|
|
d->m_settingsIdHint);
|
2010-06-14 18:19:02 +02:00
|
|
|
}
|
2010-04-19 14:21:33 +02:00
|
|
|
}
|
|
|
|
|
2010-12-03 16:18:50 +01:00
|
|
|
DebuggerRunControl::~DebuggerRunControl()
|
|
|
|
{
|
|
|
|
disconnect();
|
|
|
|
if (DebuggerEngine *engine = d->m_engine) {
|
|
|
|
d->m_engine = 0;
|
|
|
|
engine->disconnect();
|
|
|
|
delete engine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const DebuggerStartParameters &DebuggerRunControl::startParameters() const
|
|
|
|
{
|
|
|
|
QTC_ASSERT(d->m_engine, return *(new DebuggerStartParameters()));
|
|
|
|
return d->m_engine->startParameters();
|
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
QString DebuggerRunControl::displayName() const
|
2010-06-15 08:22:02 +02:00
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
QTC_ASSERT(d->m_engine, return QString());
|
|
|
|
return d->m_engine->startParameters().displayName;
|
2010-06-15 08:22:02 +02:00
|
|
|
}
|
|
|
|
|
2010-09-23 10:35:23 +02:00
|
|
|
void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
|
2010-06-15 08:22:02 +02:00
|
|
|
{
|
2010-12-15 09:17:31 +01:00
|
|
|
QTC_ASSERT(d->m_engine, return);
|
2010-10-19 11:14:03 +02:00
|
|
|
d->m_engine->startParameters().environment = env;
|
2010-06-15 08:22:02 +02:00
|
|
|
}
|
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
ConfigurationCheck checkDebugConfiguration(ToolChainType toolChain)
|
2010-06-16 11:08:54 +02:00
|
|
|
{
|
2011-01-07 19:50:41 +01:00
|
|
|
ConfigurationCheck result;
|
2010-06-16 11:08:54 +02:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
if (!(debuggerCore()->activeLanguages() & CppLanguage))
|
2011-01-07 19:50:41 +01:00
|
|
|
return result;
|
2010-10-15 13:28:46 +02:00
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
switch(toolChain) {
|
2011-01-07 19:50:41 +01:00
|
|
|
case ToolChain_GCC:
|
|
|
|
case ToolChain_LINUX_ICC:
|
|
|
|
case ToolChain_MinGW:
|
|
|
|
case ToolChain_WINCE: // S60
|
|
|
|
case ToolChain_WINSCW:
|
|
|
|
case ToolChain_GCCE:
|
|
|
|
case ToolChain_RVCT2_ARMV5:
|
|
|
|
case ToolChain_RVCT2_ARMV6:
|
2010-11-10 16:33:11 +01:00
|
|
|
if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) {
|
2011-01-07 19:50:41 +01:00
|
|
|
result.errorMessage = msgNoBinaryForToolChain(toolChain);
|
|
|
|
result.errorMessage += msgEngineNotAvailable("Gdb");
|
|
|
|
result.settingsPage = GdbOptionsPage::settingsId();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
2010-06-16 11:08:54 +02:00
|
|
|
break;
|
2011-01-07 19:50:41 +01:00
|
|
|
case ToolChain_MSVC:
|
|
|
|
result = Cdb::checkCdbConfiguration(toolChain);
|
|
|
|
if (!result) {
|
|
|
|
result.errorMessage += msgEngineNotAvailable("Cdb");
|
|
|
|
result.settingsPage = QLatin1String("Cdb");
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-09-11 08:55:16 +02:00
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
if (!result && !result.settingsPage.isEmpty())
|
|
|
|
result.settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
|
|
|
|
|
|
|
|
return result;
|
2010-06-15 09:13:22 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void DebuggerRunControl::start()
|
2010-06-15 09:13:22 +02:00
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
QTC_ASSERT(d->m_engine, return);
|
2010-12-15 09:17:31 +01:00
|
|
|
debuggerCore()->runControlStarted(d->m_engine);
|
2010-08-27 16:22:51 +02:00
|
|
|
|
2010-09-29 10:32:41 +02:00
|
|
|
// We might get a synchronous startFailed() notification on Windows,
|
|
|
|
// when launching the process fails. Emit a proper finished() sequence.
|
2010-06-16 11:08:54 +02:00
|
|
|
emit started();
|
2010-09-29 10:32:41 +02:00
|
|
|
d->m_running = true;
|
|
|
|
|
2010-12-15 09:17:31 +01:00
|
|
|
d->m_engine->startDebugger(this);
|
2010-09-29 10:32:41 +02:00
|
|
|
|
2011-01-07 11:34:25 +01:00
|
|
|
if (d->m_running)
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(tr("Debugging starts"), NormalMessageFormat);
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void DebuggerRunControl::startFailed()
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(tr("Debugging has failed"), NormalMessageFormat);
|
2010-09-14 08:34:07 +02:00
|
|
|
d->m_running = false;
|
2010-06-16 11:08:54 +02:00
|
|
|
emit finished();
|
2010-12-15 09:17:31 +01:00
|
|
|
d->m_engine->handleStartFailed();
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void DebuggerRunControl::handleFinished()
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(tr("Debugging has finished"), NormalMessageFormat);
|
2010-12-15 09:17:31 +01:00
|
|
|
if (d->m_engine)
|
|
|
|
d->m_engine->handleFinished();
|
|
|
|
debuggerCore()->runControlFinished(d->m_engine);
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void DebuggerRunControl::showMessage(const QString &msg, int channel)
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2010-06-16 11:08:54 +02:00
|
|
|
switch (channel) {
|
|
|
|
case AppOutput:
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(msg, StdOutFormatSameLine);
|
2010-06-16 11:08:54 +02:00
|
|
|
break;
|
|
|
|
case AppError:
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(msg, StdErrFormatSameLine);
|
2010-06-16 11:08:54 +02:00
|
|
|
break;
|
|
|
|
case AppStuff:
|
2011-01-07 18:57:54 +01:00
|
|
|
appendMessage(msg, NormalMessageFormat);
|
2010-06-16 11:08:54 +02:00
|
|
|
break;
|
|
|
|
}
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-08-20 14:19:25 +02:00
|
|
|
bool DebuggerRunControl::aboutToStop() const
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2010-08-20 14:19:25 +02:00
|
|
|
QTC_ASSERT(isRunning(), return true;)
|
|
|
|
|
2010-09-29 12:48:00 +02:00
|
|
|
const QString question = tr("A debugging session is still in progress. "
|
2010-08-20 14:19:25 +02:00
|
|
|
"Terminating the session in the current"
|
|
|
|
" state can leave the target in an inconsistent state."
|
|
|
|
" Would you still like to terminate it?");
|
|
|
|
|
|
|
|
const QMessageBox::StandardButton answer =
|
2010-11-10 11:39:01 +01:00
|
|
|
QMessageBox::question(debuggerCore()->mainWindow(),
|
2010-08-20 14:19:25 +02:00
|
|
|
tr("Close Debugging Session"), question,
|
|
|
|
QMessageBox::Yes|QMessageBox::No);
|
|
|
|
return answer == QMessageBox::Yes;
|
|
|
|
}
|
|
|
|
|
|
|
|
RunControl::StopResult DebuggerRunControl::stop()
|
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
QTC_ASSERT(d->m_engine, return StoppedSynchronously);
|
|
|
|
d->m_engine->quitDebugger();
|
2010-08-20 14:19:25 +02:00
|
|
|
return AsynchronousStop;
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
void DebuggerRunControl::debuggingFinished()
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
d->m_running = false;
|
2010-06-16 11:08:54 +02:00
|
|
|
emit finished();
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
bool DebuggerRunControl::isRunning() const
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
return d->m_running;
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-09-13 13:30:35 +02:00
|
|
|
DebuggerEngine *DebuggerRunControl::engine()
|
2010-06-15 11:42:49 +02:00
|
|
|
{
|
2010-09-14 08:34:07 +02:00
|
|
|
QTC_ASSERT(d->m_engine, /**/);
|
|
|
|
return d->m_engine;
|
2010-06-15 11:42:49 +02:00
|
|
|
}
|
|
|
|
|
2010-09-14 08:34:07 +02:00
|
|
|
RunConfiguration *DebuggerRunControl::runConfiguration() const
|
|
|
|
{
|
|
|
|
return d->m_myRunConfiguration.data();
|
|
|
|
}
|
2010-11-10 11:39:01 +01:00
|
|
|
|
2010-12-15 09:17:31 +01:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// DebuggerRunControlFactory
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// A factory to create DebuggerRunControls
|
|
|
|
DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
|
|
|
|
unsigned enabledEngines)
|
|
|
|
: IRunControlFactory(parent), m_enabledEngines(enabledEngines)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
|
|
|
|
{
|
|
|
|
// return mode == ProjectExplorer::Constants::DEBUGMODE;
|
|
|
|
return mode == Constants::DEBUGMODE
|
|
|
|
&& qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString DebuggerRunControlFactory::displayName() const
|
|
|
|
{
|
|
|
|
return tr("Debug");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find Qt installation by running qmake
|
|
|
|
static inline QString findQtInstallPath(const QString &qmakePath)
|
|
|
|
{
|
|
|
|
QProcess proc;
|
|
|
|
QStringList args;
|
|
|
|
args.append(QLatin1String("-query"));
|
|
|
|
args.append(QLatin1String("QT_INSTALL_HEADERS"));
|
|
|
|
proc.start(qmakePath, args);
|
|
|
|
if (!proc.waitForStarted()) {
|
|
|
|
qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(qmakePath),
|
|
|
|
qPrintable(proc.errorString()));
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
proc.closeWriteChannel();
|
|
|
|
if (!proc.waitForFinished()) {
|
|
|
|
Utils::SynchronousProcess::stopProcess(proc);
|
|
|
|
qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath));
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
if (proc.exitStatus() != QProcess::NormalExit) {
|
|
|
|
qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(qmakePath));
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
const QByteArray ba = proc.readAllStandardOutput().trimmed();
|
|
|
|
QDir dir(QString::fromLocal8Bit(ba));
|
|
|
|
if (dir.exists() && dir.cdUp())
|
|
|
|
return dir.absolutePath();
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
|
|
|
|
{
|
|
|
|
DebuggerStartParameters sp;
|
|
|
|
QTC_ASSERT(runConfiguration, return sp);
|
|
|
|
LocalApplicationRunConfiguration *rc =
|
|
|
|
qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
|
|
|
|
QTC_ASSERT(rc, return sp);
|
|
|
|
|
|
|
|
sp.startMode = StartInternal;
|
|
|
|
sp.environment = rc->environment();
|
|
|
|
sp.workingDirectory = rc->workingDirectory();
|
|
|
|
sp.executable = rc->executable();
|
|
|
|
sp.processArgs = rc->commandLineArguments();
|
|
|
|
sp.toolChainType = rc->toolChainType();
|
|
|
|
sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
|
|
|
|
sp.dumperLibrary = rc->dumperLibrary();
|
|
|
|
sp.dumperLibraryLocations = rc->dumperLibraryLocations();
|
|
|
|
|
|
|
|
if (debuggerCore()->isActiveDebugLanguage(QmlLanguage)) {
|
|
|
|
sp.qmlServerAddress = QLatin1String("127.0.0.1");
|
|
|
|
sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
|
|
|
|
|
|
|
|
sp.projectDir = runConfiguration->target()->project()->projectDirectory();
|
|
|
|
if (runConfiguration->target()->activeBuildConfiguration())
|
|
|
|
sp.projectBuildDir = runConfiguration->target()
|
|
|
|
->activeBuildConfiguration()->buildDirectory();
|
|
|
|
|
2010-12-15 13:06:39 +01:00
|
|
|
Utils::QtcProcess::addArg(&sp.processArgs, QLatin1String("-qmljsdebugger=port:")
|
|
|
|
+ QString::number(sp.qmlServerPort));
|
2010-12-15 09:17:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: If it's not yet build this will be empty and not filled
|
|
|
|
// when rebuild as the runConfiguration is not stored and therefore
|
|
|
|
// cannot be used to retrieve the dumper location.
|
|
|
|
//qDebug() << "DUMPER: " << sp.dumperLibrary << sp.dumperLibraryLocations;
|
|
|
|
sp.displayName = rc->displayName();
|
|
|
|
|
|
|
|
// Find qtInstallPath.
|
|
|
|
QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
|
|
|
|
if (!qmakePath.isEmpty())
|
|
|
|
sp.qtInstallPath = findQtInstallPath(qmakePath);
|
|
|
|
return sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
RunControl *DebuggerRunControlFactory::create
|
|
|
|
(RunConfiguration *runConfiguration, const QString &mode)
|
|
|
|
{
|
|
|
|
QTC_ASSERT(mode == Constants::DEBUGMODE, return 0);
|
|
|
|
DebuggerStartParameters sp = localStartParameters(runConfiguration);
|
|
|
|
return create(sp, runConfiguration);
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *DebuggerRunControlFactory::createConfigurationWidget
|
|
|
|
(RunConfiguration *runConfiguration)
|
|
|
|
{
|
|
|
|
// NBS TODO: Add GDB-specific configuration widget
|
|
|
|
Q_UNUSED(runConfiguration)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DebuggerRunControl *DebuggerRunControlFactory::create
|
2011-01-07 20:10:54 +01:00
|
|
|
(const DebuggerStartParameters &sp0, RunConfiguration *runConfiguration)
|
2010-12-15 09:17:31 +01:00
|
|
|
{
|
2011-01-07 20:10:54 +01:00
|
|
|
DebuggerStartParameters sp = sp0;
|
|
|
|
sp.enabledEngines = m_enabledEngines;
|
2011-01-07 19:50:41 +01:00
|
|
|
ConfigurationCheck check = checkDebugConfiguration(sp.toolChainType);
|
2010-12-15 09:34:02 +01:00
|
|
|
|
2011-01-07 19:50:41 +01:00
|
|
|
if (!check) {
|
2011-01-07 18:57:54 +01:00
|
|
|
//appendMessage(errorMessage, true);
|
2010-12-15 09:34:02 +01:00
|
|
|
Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
|
2011-01-07 19:50:41 +01:00
|
|
|
check.errorMessage, QString(), check.settingsCategory, check.settingsPage);
|
2010-12-15 09:34:02 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-15 09:17:31 +01:00
|
|
|
DebuggerRunControl *runControl =
|
2011-01-07 20:10:54 +01:00
|
|
|
new DebuggerRunControl(runConfiguration, sp);
|
2010-12-15 09:17:31 +01:00
|
|
|
if (runControl->d->m_engine)
|
|
|
|
return runControl;
|
|
|
|
delete runControl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-11 08:55:16 +02:00
|
|
|
} // namespace Debugger
|