debuggerrunner.cpp 19.6 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 33 34 35 36
#include "debuggeractions.h"
#include "debuggerconstants.h"
#include "debuggerengine.h"
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
37
#include "debuggeruiswitcher.h"
38

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

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

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

con's avatar
con committed
56 57 58
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
59
#include <QtCore/QTimer>
Friedemann Kleint's avatar
Friedemann Kleint committed
60
#include <QtCore/QStringList>
hjk's avatar
hjk committed
61

62
#include <QtGui/QAbstractItemView>
63
#include <QtGui/QTextDocument>
64
#include <QtGui/QTreeWidget>
65
#include <QtGui/QMessageBox>
con's avatar
con committed
66

67
using namespace ProjectExplorer;
68 69
using namespace Debugger::Internal;

70 71 72 73 74 75 76 77
namespace Debugger {
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 &);
79

hjk's avatar
hjk committed
80
bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
81 82 83 84 85 86 87

// 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
88 89
#ifdef CDB_ENABLED
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &);
90
bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
hjk's avatar
hjk committed
91 92 93 94
#else
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &) { return 0; }
bool checkCdbConfiguration(int, QString *, QString *) { return false; }
#endif
95

hjk's avatar
hjk committed
96
} // namespace Internal
97 98 99 100 101 102

static QString toolChainName(int toolChainType)
{
    return ToolChain::toolChainName(ToolChain::ToolChainType(toolChainType));
}

103

con's avatar
con committed
104 105
////////////////////////////////////////////////////////////////////////
//
106
// DebuggerRunControlFactory
con's avatar
con committed
107 108 109
//
////////////////////////////////////////////////////////////////////////

110 111 112 113 114 115 116
static QString msgEngineNotAvailable(const char *engine)
{
    return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
        "which is disabled.").arg(QLatin1String(engine));
}

static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
117

118
// A factory to create DebuggerRunControls
119 120 121
DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
        DebuggerEngineType enabledEngines)
    : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
con's avatar
con committed
122 123
{}

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

131
QString DebuggerRunControlFactory::displayName() const
con's avatar
con committed
132
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
133
    return tr("Debug");
con's avatar
con committed
134 135
}

136
static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
137
{
138
    DebuggerStartParameters sp;
139 140 141 142 143
    QTC_ASSERT(runConfiguration, return sp);
    LocalApplicationRunConfiguration *rc =
            qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
    QTC_ASSERT(rc, return sp);

144 145 146 147 148 149 150 151 152
    sp.startMode = StartInternal;
    sp.executable = rc->executable();
    sp.environment = rc->environment().toStringList();
    sp.workingDirectory = rc->workingDirectory();
    sp.processArgs = rc->commandLineArguments();
    sp.toolChainType = rc->toolChainType();
    sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
    sp.dumperLibrary = rc->dumperLibrary();
    sp.dumperLibraryLocations = rc->dumperLibraryLocations();
153

154 155
    DebuggerLanguages activeLangs = DebuggerUISwitcher::instance()->activeDebugLanguages();
    if (activeLangs & QmlLanguage) {
156
        sp.qmlServerAddress = QLatin1String("127.0.0.1");
157
        sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
158

159 160 161 162
        sp.projectDir = runConfiguration->target()->project()->projectDirectory();
        if (runConfiguration->target()->activeBuildConfiguration())
            sp.projectBuildDir = runConfiguration->target()->activeBuildConfiguration()->buildDirectory();

163 164 165 166
        sp.environment << QString(Constants::E_QML_DEBUG_SERVER_PORT)
                        + QLatin1Char('=') + QString::number(sp.qmlServerPort);
    }

167 168 169 170
    // 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;
171
    sp.displayName = rc->displayName();
172

173 174
    // Find qtInstallPath.
    QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
175 176 177 178 179 180 181 182 183
    if (!qmakePath.isEmpty()) {
        QProcess proc;
        QStringList args;
        args.append(QLatin1String("-query"));
        args.append(QLatin1String("QT_INSTALL_HEADERS"));
        proc.start(qmakePath, args);
        proc.waitForFinished();
        QByteArray ba = proc.readAllStandardOutput().trimmed();
        QFileInfo fi(QString::fromLocal8Bit(ba) + "/..");
184
        sp.qtInstallPath = fi.absoluteFilePath();
185 186
    }
    return sp;
187 188
}

189 190
RunControl *DebuggerRunControlFactory::create
    (RunConfiguration *runConfiguration, const QString &mode)
con's avatar
con committed
191
{
hjk's avatar
hjk committed
192
    QTC_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE, return 0);
193
    DebuggerStartParameters sp = localStartParameters(runConfiguration);
194
    return create(sp, runConfiguration);
195 196
}

197 198
DebuggerRunControl *DebuggerRunControlFactory::create(
    const DebuggerStartParameters &sp,
199
    RunConfiguration *runConfiguration)
200
{
201 202
    DebuggerRunControl *runControl =
        new DebuggerRunControl(runConfiguration, m_enabledEngines, sp);
203 204 205 206 207 208
    if (!runControl->engine()) {
        qDebug() << "FAILED TO CREATE ENGINE";
        delete runControl;
        return 0;
    }
    return runControl;
con's avatar
con committed
209 210
}

211 212
QWidget *DebuggerRunControlFactory::createConfigurationWidget
    (RunConfiguration *runConfiguration)
con's avatar
con committed
213 214
{
    // NBS TODO: Add GDB-specific configuration widget
215
    Q_UNUSED(runConfiguration)
con's avatar
con committed
216 217 218 219
    return 0;
}


220 221
////////////////////////////////////////////////////////////////////////
//
222
// DebuggerRunControl
223 224 225
//
////////////////////////////////////////////////////////////////////////

226
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
227 228 229 230 231
        DebuggerEngineType enabledEngines, const DebuggerStartParameters &sp)
    : RunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE)
    , m_myRunConfiguration(runConfiguration)
    , m_running(false)
    , m_started(false)
232
    , m_enabledEngines(enabledEngines)
233

234
{
Friedemann Kleint's avatar
Friedemann Kleint committed
235
    connect(this, SIGNAL(finished()), this, SLOT(handleFinished()));
236 237
    DebuggerStartParameters startParams = sp;
    createEngine(startParams);
238 239
}

240 241 242 243 244 245 246 247 248
DebuggerRunControl::~DebuggerRunControl()
{
    disconnect();
    DebuggerEngine *engine = m_engine;
    m_engine = 0;
    engine->disconnect();
    delete engine;
}

249 250 251 252 253 254
const DebuggerStartParameters &DebuggerRunControl::startParameters() const
{
    QTC_ASSERT(m_engine, return *(new DebuggerStartParameters()));
    return m_engine->startParameters();
}

255 256 257 258 259 260 261 262 263 264 265 266
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:
        case ProjectExplorer::ToolChain::RVCT_ARMV5:
        case ProjectExplorer::ToolChain::RVCT_ARMV6:
        case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
        case ProjectExplorer::ToolChain::GCCE_GNUPOC:
267
        case ProjectExplorer::ToolChain::GCC_MAEMO:
268 269 270 271 272 273 274 275 276 277 278 279 280
            return GdbEngineType;

        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;
281 282
}

283 284 285 286

// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
DebuggerEngineType DebuggerRunControl::engineForExecutable(const QString &executable)
287
{
288 289 290 291 292
    if (executable.endsWith(_("qmlviewer"))) {
        if (m_enabledEngines & QmlEngineType)
            return QmlEngineType;
        m_errorMessage = msgEngineNotAvailable("Qml Engine");
    }
293

294 295 296 297 298
    if (executable.endsWith(_(".js"))) {
        if (m_enabledEngines & ScriptEngineType)
            return ScriptEngineType;
        m_errorMessage = msgEngineNotAvailable("Script Engine");
    }
con's avatar
con committed
299

300 301 302 303 304
    if (executable.endsWith(_(".py"))) {
        if (m_enabledEngines & PdbEngineType)
            return PdbEngineType;
        m_errorMessage = msgEngineNotAvailable("Pdb Engine");
    }
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;
Friedemann Kleint's avatar
Friedemann Kleint committed
313
    if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) {
314 315
        qWarning("Cannot determine type of executable %s: %s",
                 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 322
    // We need the CDB debugger in order to be able to debug VS
    // executables
Friedemann Kleint's avatar
Friedemann Kleint committed
323
    if (checkDebugConfiguration(ToolChain::MSVC, &m_errorMessage, 0, &m_settingsIdHint))
324 325 326 327 328 329
        return CdbEngineType;
#else
    if (m_enabledEngines & GdbEngineType)
        return GdbEngineType;
    m_errorMessage = msgEngineNotAvailable("Gdb Engine");
#endif
330

331
    return NoEngineType;
332 333
}

334 335
// Debugger type for mode.
DebuggerEngineType DebuggerRunControl::engineForMode(DebuggerStartMode startMode)
336
{
337 338
    if (startMode == AttachTcf)
        return TcfEngineType;
339

340 341
#ifdef Q_OS_WIN
    // Preferably Windows debugger for attaching locally.
Friedemann Kleint's avatar
Friedemann Kleint committed
342
    if (startMode != AttachToRemote)
343
        return CdbEngineType;
Friedemann Kleint's avatar
Friedemann Kleint committed
344
    return GdbEngineType;
345 346 347 348 349 350 351
    m_errorMessage = msgEngineNotAvailable("Gdb Engine");
    return NoEngineType;
#else
    Q_UNUSED(startMode)
    //  m_errorMessage = msgEngineNotAvailable("Gdb Engine");
    return GdbEngineType;
#endif
352 353
}

354
void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams)
355
{
356 357
    DebuggerStartParameters sp = startParams;

358 359
    // Figure out engine according to toolchain, executable, attach or default.
    DebuggerEngineType engineType = NoEngineType;
360
    DebuggerLanguages activeLangs = DebuggerPlugin::instance()->activeLanguages();
361 362 363 364 365
    bool isQmlExecutable = sp.executable.endsWith(_("qmlviewer")) || sp.executable.endsWith(_("qmlobserver"));
#ifdef Q_OS_MAC
    isQmlExecutable = sp.executable.endsWith(_("QMLViewer.app")) || sp.executable.endsWith(_("QMLObserver.app"));
#endif
    if (isQmlExecutable)
366 367 368 369 370 371 372 373
        engineType = QmlEngineType;
    else if (sp.executable.endsWith(_(".js")))
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
    else
        engineType = engineForToolChain(sp.toolChainType);

374 375 376 377
    // Fixme: 1 of 3 testing hacks.
    if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
        engineType = GdbEngineType;

378 379 380 381 382 383 384 385
    if (engineType == NoEngineType
            && sp.startMode != AttachToRemote
            && !sp.executable.isEmpty())
        engineType = engineForExecutable(sp.executable);

    if (!engineType)
        engineType = engineForMode(sp.startMode);

386
    if (engineType != QmlEngineType && (activeLangs & QmlLanguage)) {
387
        if (activeLangs & CppLanguage) {
388 389 390 391 392 393 394
            sp.cppEngineType = engineType;
            engineType = QmlCppEngineType;
        } else {
            engineType = QmlEngineType;
        }
    }

Friedemann Kleint's avatar
Friedemann Kleint committed
395
    // qDebug() << "USING ENGINE : " << engineType;
396 397 398 399

    switch (engineType) {
        case GdbEngineType:
            m_engine = createGdbEngine(sp);
400
            break;
401 402
        case ScriptEngineType:
            m_engine = createScriptEngine(sp);
403
            break;
404 405
        case CdbEngineType:
            m_engine = createCdbEngine(sp);
406
            break;
407 408
        case PdbEngineType:
            m_engine = createPdbEngine(sp);
409
            break;
410 411
        case TcfEngineType:
            m_engine = createTcfEngine(sp);
412
            break;
413 414 415
        case QmlEngineType:
            m_engine = createQmlEngine(sp);
            break;
416 417 418
        case QmlCppEngineType:
            m_engine = createQmlCppEngine(sp);
            break;
419 420
        default: {
            // Could not find anything suitable.
421
            debuggingFinished();
422 423 424 425 426 427
            // Create Message box with possibility to go to settings
            const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
                .arg(sp.executable, toolChainName(sp.toolChainType), m_errorMessage);
            Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
                msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
                m_settingsIdHint);
428
            break;
429
        }
430
    }
431 432
}

433
QString DebuggerRunControl::displayName() const
434
{
435 436
    QTC_ASSERT(m_engine, return QString());
    return m_engine->startParameters().displayName;
437 438
}

439
void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env)
440
{
441
    m_engine->startParameters().environment = env.toStringList();
442 443
}

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
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;

    switch(toolChain) {
    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:
    case ProjectExplorer::ToolChain::RVCT_ARMV5:
    case ProjectExplorer::ToolChain::RVCT_ARMV6:
        success = checkGdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success)
468
            *errorMessage += msgEngineNotAvailable("Gdb");
469 470 471 472
        break;
    case ProjectExplorer::ToolChain::MSVC:
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
473
            *errorMessage += msgEngineNotAvailable("Cdb");
474 475 476 477 478 479 480
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
481

482
    return success;
483 484
}

485
void DebuggerRunControl::start()
486
{
487 488
    QTC_ASSERT(m_engine, return);
    const DebuggerStartParameters &sp = m_engine->startParameters();
489

490 491 492
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
493

494 495 496 497 498 499
    if (!checkDebugConfiguration(sp.toolChainType,
            &errorMessage, &settingsCategory, &settingsPage)) {
        emit appendMessage(this, errorMessage, true);
        emit finished();
        Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
            errorMessage, QString(), settingsCategory, settingsPage);
500
        return;
501
    }
502

503
    plugin()->activateDebugMode();
504
    DebuggerUISwitcher::instance()->aboutToStartDebugger();
Friedemann Kleint's avatar
Friedemann Kleint committed
505 506 507 508

    const QString message = tr("Starting debugger '%1' for tool chain '%2'...").
                  arg(m_engine->objectName(), toolChainName(sp.toolChainType));
    plugin()->showMessage(message, StatusBar);
509
    plugin()->showMessage(DebuggerSettings::instance()->dump(), LogDebug);
Friedemann Kleint's avatar
Friedemann Kleint committed
510
    plugin()->runControlStarted(this);
511

512 513
    engine()->startDebugger(this);
    m_running = true;
514 515
    emit addToOutputWindowInline(this, tr("Debugging starts"), false);
    emit addToOutputWindowInline(this, "\n", false);
516
    emit started();
517 518
}

519
void DebuggerRunControl::startFailed()
520
{
521
    emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
522 523
    m_running = false;
    emit finished();
524
    engine()->handleStartFailed();
525 526
}

527
void DebuggerRunControl::handleFinished()
528
{
529
    emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
530
    engine()->handleFinished();
531
    plugin()->runControlFinished(this);
532 533
}

534
void DebuggerRunControl::showMessage(const QString &msg, int channel)
535
{
536 537 538 539 540 541 542 543 544 545 546
    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;
    }
547 548
}

549
bool DebuggerRunControl::aboutToStop() const
550
{
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    QTC_ASSERT(isRunning(), return true;)

    const QString question = tr("A debugging session are still in progress. "
            "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 =
            QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(),
                                  tr("Close Debugging Session"), question,
                                  QMessageBox::Yes|QMessageBox::No);
    return answer == QMessageBox::Yes;
}

RunControl::StopResult DebuggerRunControl::stop()
{
    QTC_ASSERT(m_engine, return StoppedSynchronously);
568
    m_engine->quitDebugger();
569
    return AsynchronousStop;
570 571
}

572
void DebuggerRunControl::debuggingFinished()
573
{
574 575
    m_running = false;
    emit finished();
576 577
}

578
bool DebuggerRunControl::isRunning() const
579
{
580
    return m_running;
581 582
}

Friedemann Kleint's avatar
Friedemann Kleint committed
583 584 585 586 587 588
DebuggerState DebuggerRunControl::state() const
{
    QTC_ASSERT(m_engine, return DebuggerNotReady);
    return m_engine->state();
}

589
Internal::DebuggerEngine *DebuggerRunControl::engine()
590
{
591 592
    QTC_ASSERT(m_engine, /**/);
    return m_engine;
593 594
}

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