debuggerrunner.cpp 22.3 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11 12 13 14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** 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.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30 31
#include "debuggerrunner.h"

32
#include "debuggeractions.h"
33
#include "debuggercore.h"
34
#include "debuggerengine.h"
35
#include "debuggermainwindow.h"
36 37
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
hjk's avatar
hjk committed
38
#include "gdb/gdboptionspage.h"
39
#include "lldb/lldbenginehost.h"
40

Friedemann Kleint's avatar
Friedemann Kleint committed
41 42 43 44
#ifdef Q_OS_WIN
#  include "peutils.h"
#endif

hjk's avatar
hjk committed
45
#include <projectexplorer/debugginghelper.h>
con's avatar
con committed
46
#include <projectexplorer/project.h>
47
#include <projectexplorer/toolchain.h>
con's avatar
con committed
48
#include <projectexplorer/projectexplorerconstants.h>
Tobias Hunger's avatar
Tobias Hunger committed
49
#include <projectexplorer/target.h>
50
#include <projectexplorer/buildconfiguration.h>
51
#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
con's avatar
con committed
52

53
#include <utils/synchronousprocess.h>
hjk's avatar
hjk committed
54
#include <utils/qtcassert.h>
55
#include <utils/fancymainwindow.h>
56
#include <coreplugin/icore.h>
hjk's avatar
hjk committed
57

con's avatar
con committed
58
#include <QtCore/QDir>
59
#include <QtGui/QMessageBox>
con's avatar
con committed
60

61
using namespace ProjectExplorer;
62 63
using namespace Debugger::Internal;

64
namespace Debugger {
hjk's avatar
hjk committed
65 66 67 68 69 70

namespace Cdb {
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *error);
bool isCdbEngineEnabled(); // Check the configuration page
}

71 72 73 74 75 76 77
namespace Internal {

DebuggerEngine *createGdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &);
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
78
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &);
hjk's avatar
hjk committed
79
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &);
80

hjk's avatar
hjk committed
81
extern QString msgNoBinaryForToolChain(int tc);
82 83 84 85 86 87 88

// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.

hjk's avatar
hjk committed
89
#ifdef CDB_ENABLED
hjk's avatar
hjk committed
90 91

DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *error);
92
bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
93
bool isCdbEngineEnabled(); // Check the configuration page
hjk's avatar
hjk committed
94

hjk's avatar
hjk committed
95
#else
hjk's avatar
hjk committed
96 97 98 99 100 101 102 103 104 105 106

DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, QString *)
{
    return 0;
}

bool checkCdbConfiguration(int, QString *, QString *)
{
    return false;
}

hjk's avatar
hjk committed
107
#endif
108

con's avatar
con committed
109 110
////////////////////////////////////////////////////////////////////////
//
111
// DebuggerRunControlFactory
con's avatar
con committed
112 113 114
//
////////////////////////////////////////////////////////////////////////

115 116 117 118 119 120
static QString msgEngineNotAvailable(const char *engine)
{
    return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
        "which is disabled.").arg(QLatin1String(engine));
}

121
// A factory to create DebuggerRunControls
122
DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
123
        unsigned enabledEngines)
124
    : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
con's avatar
con committed
125 126
{}

127
bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
con's avatar
con committed
128
{
129
//    return mode == ProjectExplorer::Constants::DEBUGMODE;
130
    return mode == Constants::DEBUGMODE
131
            && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
con's avatar
con committed
132 133
}

134
QString DebuggerRunControlFactory::displayName() const
con's avatar
con committed
135
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
136
    return tr("Debug");
con's avatar
con committed
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
// 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();
}

169
static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
170
{
171
    DebuggerStartParameters sp;
172 173 174 175 176
    QTC_ASSERT(runConfiguration, return sp);
    LocalApplicationRunConfiguration *rc =
            qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
    QTC_ASSERT(rc, return sp);

177
    sp.startMode = StartInternal;
178
    sp.environment = rc->environment();
179 180 181
    sp.workingDirectory = rc->workingDirectory();
    sp.executable = rc->executable();
    sp.processArgs = rc->commandLineArguments();
182 183 184 185
    sp.toolChainType = rc->toolChainType();
    sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
    sp.dumperLibrary = rc->dumperLibrary();
    sp.dumperLibraryLocations = rc->dumperLibraryLocations();
186

187
    if (debuggerCore()->isActiveDebugLanguage(QmlLanguage)) {
188
        sp.qmlServerAddress = QLatin1String("127.0.0.1");
189
        sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
190

191 192
        sp.projectDir = runConfiguration->target()->project()->projectDirectory();
        if (runConfiguration->target()->activeBuildConfiguration())
193 194
            sp.projectBuildDir = runConfiguration->target()
                ->activeBuildConfiguration()->buildDirectory();
195

196 197
        sp.processArgs.append(QLatin1String("-qmljsdebugger=port:")
            + QString::number(sp.qmlServerPort));
198 199
    }

200 201 202 203
    // 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;
204
    sp.displayName = rc->displayName();
205

206 207
    // Find qtInstallPath.
    QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
208 209
    if (!qmakePath.isEmpty())
        sp.qtInstallPath = findQtInstallPath(qmakePath);
210
    return sp;
211 212
}

213 214
RunControl *DebuggerRunControlFactory::create
    (RunConfiguration *runConfiguration, const QString &mode)
con's avatar
con committed
215
{
216
    QTC_ASSERT(mode == Constants::DEBUGMODE, return 0);
217
    DebuggerStartParameters sp = localStartParameters(runConfiguration);
218
    return create(sp, runConfiguration);
219 220
}

hjk's avatar
hjk committed
221 222
DebuggerRunControl *DebuggerRunControlFactory::create
    (const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
223
{
224 225
    DebuggerRunControl *runControl =
        new DebuggerRunControl(runConfiguration, m_enabledEngines, sp);
hjk's avatar
hjk committed
226 227 228 229 230
    if (runControl->engine())
        return runControl;
    qDebug() << "FAILED TO CREATE ENGINE";
    delete runControl;
    return 0;
con's avatar
con committed
231 232
}

233 234
QWidget *DebuggerRunControlFactory::createConfigurationWidget
    (RunConfiguration *runConfiguration)
con's avatar
con committed
235 236
{
    // NBS TODO: Add GDB-specific configuration widget
237
    Q_UNUSED(runConfiguration)
con's avatar
con committed
238 239 240
    return 0;
}

241 242
////////////////////////////////////////////////////////////////////////
//
hjk's avatar
hjk committed
243
// DebuggerRunControlPrivate
244 245 246
//
////////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
247 248 249 250 251
class DebuggerRunControlPrivate
{
public:
    DebuggerRunControlPrivate(DebuggerRunControl *parent,
        RunConfiguration *runConfiguration, unsigned enabledEngines);
252
    unsigned enabledEngines() const;
253

hjk's avatar
hjk committed
254 255 256 257 258 259 260
    DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes,
        const QString &executable);
    DebuggerEngineType engineForMode(unsigned enabledEngineTypes,
        DebuggerStartMode mode);

public:
    DebuggerRunControl *q;
261 262 263
    DebuggerEngine *m_engine;
    const QWeakPointer<RunConfiguration> m_myRunConfiguration;
    bool m_running;
264
    const unsigned m_cmdLineEnabledEngines;
265 266 267 268
    QString m_errorMessage;
    QString m_settingsIdHint;
};

hjk's avatar
hjk committed
269
unsigned DebuggerRunControlPrivate::enabledEngines() const
270 271 272
{
    unsigned rc = m_cmdLineEnabledEngines;
#ifdef CDB_ENABLED
hjk's avatar
hjk committed
273
    if (!isCdbEngineEnabled() && !Cdb::isCdbEngineEnabled())
274 275 276 277 278
        rc &= ~CdbEngineType;
#endif
    return rc;
}

hjk's avatar
hjk committed
279 280 281 282
DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent,
        RunConfiguration *runConfiguration, unsigned enabledEngines)
    : q(parent)
    , m_engine(0)
283
    , m_myRunConfiguration(runConfiguration)
284
    , m_running(false)
285
    , m_cmdLineEnabledEngines(enabledEngines)
286 287
{
}
288

289 290
// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
hjk's avatar
hjk committed
291 292
DebuggerEngineType DebuggerRunControlPrivate::engineForExecutable
    (unsigned enabledEngineTypes, const QString &executable)
293
{
294
    if (executable.endsWith(_(".js"))) {
295
        if (enabledEngineTypes & ScriptEngineType)
296
            return ScriptEngineType;
hjk's avatar
hjk committed
297
        m_errorMessage = msgEngineNotAvailable("Script Engine");
298
    }
con's avatar
con committed
299

300
    if (executable.endsWith(_(".py"))) {
301
        if (enabledEngineTypes & PdbEngineType)
302
            return PdbEngineType;
hjk's avatar
hjk committed
303
        m_errorMessage = msgEngineNotAvailable("Pdb Engine");
304
    }
con's avatar
con committed
305

306 307 308
#ifdef Q_OS_WIN
    // A remote executable?
    if (!executable.endsWith(_(".exe")))
Friedemann Kleint's avatar
Friedemann Kleint committed
309
        return GdbEngineType;
310 311 312

    // If a file has PDB files, it has been compiled by VS.
    QStringList pdbFiles;
hjk's avatar
hjk committed
313
    if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) {
314
        qWarning("Cannot determine type of executable %s: %s",
hjk's avatar
hjk committed
315
                 qPrintable(executable), qPrintable(m_errorMessage));
Friedemann Kleint's avatar
Friedemann Kleint committed
316
        return NoEngineType;
317 318 319
    }
    if (pdbFiles.empty())
        return GdbEngineType;
320

321
    // We need the CDB debugger in order to be able to debug VS
hjk's avatar
hjk committed
322
    // executables.
323
   if (DebuggerRunControl::checkDebugConfiguration(ProjectExplorer::ToolChain_MSVC,
hjk's avatar
hjk committed
324
            &m_errorMessage, 0, &m_settingsIdHint)) {
325 326
        if (enabledEngineTypes & CdbEngineType)
            return CdbEngineType;
hjk's avatar
hjk committed
327
        m_errorMessage = msgEngineNotAvailable("Cdb Engine");
328 329
        return NoEngineType;
    }
330
#else
331
    if (enabledEngineTypes & GdbEngineType)
332
        return GdbEngineType;
hjk's avatar
hjk committed
333
    m_errorMessage = msgEngineNotAvailable("Gdb Engine");
334
#endif
335

336
    return NoEngineType;
337 338
}

339
// Debugger type for mode.
hjk's avatar
hjk committed
340 341
DebuggerEngineType DebuggerRunControlPrivate::engineForMode
    (unsigned enabledEngineTypes, DebuggerStartMode startMode)
342
{
343 344
    if (startMode == AttachTcf)
        return TcfEngineType;
345

346 347
#ifdef Q_OS_WIN
    // Preferably Windows debugger for attaching locally.
348
    if (startMode != AttachToRemote && (enabledEngineTypes & CdbEngineType))
349
        return CdbEngineType;
350
    if (startMode == AttachCrashedExternal) {
351
        m_errorMessage = DebuggerRunControl::tr("There is no debugging engine available for post-mortem debugging.");
352 353
        return NoEngineType;
    }
Friedemann Kleint's avatar
Friedemann Kleint committed
354
    return GdbEngineType;
355 356
#else
    Q_UNUSED(startMode)
357
    Q_UNUSED(enabledEngineTypes)
hjk's avatar
hjk committed
358
    //  >m_errorMessage = msgEngineNotAvailable("Gdb Engine");
359 360
    return GdbEngineType;
#endif
361 362
}

hjk's avatar
hjk committed
363 364 365
} // namespace Internal


hjk's avatar
hjk committed
366 367 368 369 370 371 372 373 374 375 376 377 378 379
////////////////////////////////////////////////////////////////////////
//
// DebuggerRunControl
//
////////////////////////////////////////////////////////////////////////

static DebuggerEngineType engineForToolChain(int toolChainType)
{
    switch (toolChainType) {
        case ProjectExplorer::ToolChain_LINUX_ICC:
        case ProjectExplorer::ToolChain_MinGW:
        case ProjectExplorer::ToolChain_GCC:
        case ProjectExplorer::ToolChain_WINSCW: // S60
        case ProjectExplorer::ToolChain_GCCE:
380 381
        case ProjectExplorer::ToolChain_RVCT2_ARMV5:
        case ProjectExplorer::ToolChain_RVCT2_ARMV6:
hjk's avatar
hjk committed
382 383 384
        case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
        case ProjectExplorer::ToolChain_GCCE_GNUPOC:
        case ProjectExplorer::ToolChain_GCC_MAEMO:
385 386 387 388 389
#ifdef WITH_LLDB
            // lldb override
            if (Core::ICore::instance()->settings()->value("LLDB/enabled").toBool())
                return LldbEngineType;
#endif
hjk's avatar
hjk committed
390 391
            return GdbEngineType;

392

hjk's avatar
hjk committed
393 394 395 396 397 398 399 400 401 402 403 404 405
        case ProjectExplorer::ToolChain_MSVC:
        case ProjectExplorer::ToolChain_WINCE:
            return CdbEngineType;

        case ProjectExplorer::ToolChain_OTHER:
        case ProjectExplorer::ToolChain_UNKNOWN:
        case ProjectExplorer::ToolChain_INVALID:
        default:
            break;
    }
    return NoEngineType;
}

hjk's avatar
hjk committed
406 407 408 409
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
        unsigned enabledEngines, const DebuggerStartParameters &startParams)
    : RunControl(runConfiguration, Constants::DEBUGMODE),
      d(new DebuggerRunControlPrivate(this, runConfiguration, enabledEngines))
410
{
hjk's avatar
hjk committed
411
    connect(this, SIGNAL(finished()), SLOT(handleFinished()));
412

413 414
    // Figure out engine according to toolchain, executable, attach or default.
    DebuggerEngineType engineType = NoEngineType;
415
    DebuggerLanguages activeLangs = debuggerCore()->activeLanguages();
hjk's avatar
hjk committed
416
    DebuggerStartParameters sp = startParams;
417
    const unsigned enabledEngineTypes = d->enabledEngines();
418
    if (sp.executable.endsWith(_(".js")))
419 420 421
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
422
    else {
423
        engineType = engineForToolChain(sp.toolChainType);
424 425 426 427 428
        if (engineType == CdbEngineType && !(enabledEngineTypes & CdbEngineType)) {
            d->m_errorMessage = msgEngineNotAvailable("Cdb Engine");
            engineType = NoEngineType;
        }
    }
429

430 431 432
    // Fixme: unclean ipc override. Someone please have a better idea
    if (sp.startMode == StartRemoteEngine)
        // for now thats the only supported ipc engine
433 434
        engineType = LldbEngineType;

435
    // Fixme: 1 of 3 testing hacks.
436
    if (sp.processArgs.startsWith(__("@tcf@ ")))
437 438
        engineType = GdbEngineType;

439 440 441
    if (engineType == NoEngineType
            && sp.startMode != AttachToRemote
            && !sp.executable.isEmpty())
hjk's avatar
hjk committed
442
        engineType = d->engineForExecutable(enabledEngineTypes, sp.executable);
443

444
    if (engineType == NoEngineType)
hjk's avatar
hjk committed
445
        engineType = d->engineForMode(enabledEngineTypes, sp.startMode);
446

447 448
    if ((engineType != QmlEngineType && engineType != NoEngineType)
        && (activeLangs & QmlLanguage)) {
449
        if (activeLangs & CppLanguage) {
450 451 452 453 454 455 456
            sp.cppEngineType = engineType;
            engineType = QmlCppEngineType;
        } else {
            engineType = QmlEngineType;
        }
    }

Friedemann Kleint's avatar
Friedemann Kleint committed
457
    // qDebug() << "USING ENGINE : " << engineType;
458 459 460

    switch (engineType) {
        case GdbEngineType:
461
            d->m_engine = createGdbEngine(sp);
462
            break;
463
        case ScriptEngineType:
hjk's avatar
hjk committed
464
            d->m_engine = createScriptEngine(sp);
465
            break;
466
        case CdbEngineType:
467
            // Try new engine, fall back to old.
hjk's avatar
hjk committed
468 469 470 471
            if (Cdb::isCdbEngineEnabled())
                d->m_engine = Cdb::createCdbEngine(sp, &d->m_errorMessage);
            else
                d->m_engine = Internal::createCdbEngine(sp, &d->m_errorMessage);
472
            break;
473
        case PdbEngineType:
hjk's avatar
hjk committed
474
            d->m_engine = createPdbEngine(sp);
475
            break;
476
        case TcfEngineType:
hjk's avatar
hjk committed
477
            d->m_engine = createTcfEngine(sp);
478
            break;
479
        case QmlEngineType:
hjk's avatar
hjk committed
480
            d->m_engine = createQmlEngine(sp);
481
            break;
482
        case QmlCppEngineType:
hjk's avatar
hjk committed
483
            d->m_engine = createQmlCppEngine(sp);
484
            break;
hjk's avatar
hjk committed
485 486
        case LldbEngineType:
            d->m_engine = createLldbEngine(sp);
487 488
        case NoEngineType:
        case AllEngineTypes:
489
            break;
490 491 492 493 494
    }

    if (!d->m_engine) {
        // Could not find anything suitable.
        debuggingFinished();
hjk's avatar
hjk committed
495
        // Create Message box with possibility to go to settings.
496
        const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
hjk's avatar
hjk committed
497
            .arg(sp.executable, sp.toolChainName(), d->m_errorMessage);
498
        Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
hjk's avatar
hjk committed
499 500
            msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
            d->m_settingsIdHint);
501
    }
502 503
}

hjk's avatar
hjk committed
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
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();
}

520
QString DebuggerRunControl::displayName() const
521
{
522 523
    QTC_ASSERT(d->m_engine, return QString());
    return d->m_engine->startParameters().displayName;
524 525
}

526
void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
527
{
528
    d->m_engine->startParameters().environment = env;
529 530
}

531 532 533 534 535 536 537 538 539 540 541 542 543
bool DebuggerRunControl::checkDebugConfiguration(int toolChain,
                                              QString *errorMessage,
                                              QString *settingsCategory /* = 0 */,
                                              QString *settingsPage /* = 0 */)
{
    errorMessage->clear();
    if (settingsCategory)
        settingsCategory->clear();
    if (settingsPage)
        settingsPage->clear();

    bool success = true;

544
    if (!(debuggerCore()->activeLanguages() & CppLanguage))
545 546
        return success;

547
    switch(toolChain) {
548 549 550 551 552 553
    case ProjectExplorer::ToolChain_GCC:
    case ProjectExplorer::ToolChain_LINUX_ICC:
    case ProjectExplorer::ToolChain_MinGW:
    case ProjectExplorer::ToolChain_WINCE: // S60
    case ProjectExplorer::ToolChain_WINSCW:
    case ProjectExplorer::ToolChain_GCCE:
554 555
    case ProjectExplorer::ToolChain_RVCT2_ARMV5:
    case ProjectExplorer::ToolChain_RVCT2_ARMV6:
hjk's avatar
hjk committed
556 557 558
        if (debuggerCore()->gdbBinaryForToolChain(toolChain).isEmpty()) {
            *errorMessage = msgNoBinaryForToolChain(toolChain);
            *settingsPage = GdbOptionsPage::settingsId();
559
            *errorMessage += msgEngineNotAvailable("Gdb");
hjk's avatar
hjk committed
560 561 562 563
            success = false;
        } else {
            success = true;
        }
564
        break;
565
    case ProjectExplorer::ToolChain_MSVC:
566 567
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
568
            *errorMessage += msgEngineNotAvailable("Cdb");
569 570 571 572 573 574 575
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
576

577
    return success;
578 579
}

580
void DebuggerRunControl::start()
581
{
582 583
    QTC_ASSERT(d->m_engine, return);
    const DebuggerStartParameters &sp = d->m_engine->startParameters();
584

585 586 587
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
588

589 590 591 592 593 594
    if (!checkDebugConfiguration(sp.toolChainType,
            &errorMessage, &settingsCategory, &settingsPage)) {
        emit appendMessage(this, errorMessage, true);
        emit finished();
        Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
            errorMessage, QString(), settingsCategory, settingsPage);
595
        return;
596
    }
597

598
    debuggerCore()->runControlStarted(engine());
599

600 601
    // We might get a synchronous startFailed() notification on Windows,
    // when launching the process fails. Emit a proper finished() sequence.
602
    emit started();
603 604 605 606 607 608 609 610
    d->m_running = true;

    engine()->startDebugger(this);

    if (d->m_running) {
        emit addToOutputWindowInline(this, tr("Debugging starts"), false);
        emit addToOutputWindowInline(this, "\n", false);
    }
611 612
}

613
void DebuggerRunControl::startFailed()
614
{
615
    emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
616
    d->m_running = false;
617
    emit finished();
618
    engine()->handleStartFailed();
619 620
}

621
void DebuggerRunControl::handleFinished()
622
{
623
    emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
624 625
    if (engine())
        engine()->handleFinished();
626
    debuggerCore()->runControlFinished(engine());
627 628
}

629
void DebuggerRunControl::showMessage(const QString &msg, int channel)
630
{
631 632 633 634 635 636 637 638 639 640 641
    switch (channel) {
        case AppOutput:
            emit addToOutputWindowInline(this, msg, false);
            break;
        case AppError:
            emit addToOutputWindowInline(this, msg, true);
            break;
        case AppStuff:
            emit appendMessage(this, msg, true);
            break;
    }
642 643
}

644
bool DebuggerRunControl::aboutToStop() const
645
{
646 647
    QTC_ASSERT(isRunning(), return true;)

Jarek Kobus's avatar
Jarek Kobus committed
648
    const QString question = tr("A debugging session is still in progress. "
649 650 651 652 653
            "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 =
654
            QMessageBox::question(debuggerCore()->mainWindow(),
655 656 657 658 659 660 661
                                  tr("Close Debugging Session"), question,
                                  QMessageBox::Yes|QMessageBox::No);
    return answer == QMessageBox::Yes;
}

RunControl::StopResult DebuggerRunControl::stop()
{
662 663
    QTC_ASSERT(d->m_engine, return StoppedSynchronously);
    d->m_engine->quitDebugger();
664
    return AsynchronousStop;
665 666
}

667
void DebuggerRunControl::debuggingFinished()
668
{
669
    d->m_running = false;
670
    emit finished();
671 672
}

673
bool DebuggerRunControl::isRunning() const
674
{
675
    return d->m_running;
676 677
}

678
DebuggerEngine *DebuggerRunControl::engine()
679
{
680 681
    QTC_ASSERT(d->m_engine, /**/);
    return d->m_engine;
682 683
}

684 685 686 687
RunConfiguration *DebuggerRunControl::runConfiguration() const
{
    return d->m_myRunConfiguration.data();
}
688

hjk's avatar
hjk committed
689
} // namespace Debugger