debuggerengine.cpp 54 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29 30 31

#include "debuggerengine.h"

32
#include "debuggerinternalconstants.h"
33
#include "debuggeractions.h"
34 35
#include "debuggercore.h"
#include "debuggerrunner.h"
36
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
37
#include "debuggerstartparameters.h"
38 39

#include "breakhandler.h"
David Schulz's avatar
David Schulz committed
40 41
#include "disassembleragent.h"
#include "memoryagent.h"
42 43 44 45 46 47
#include "moduleshandler.h"
#include "registerhandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"
48
#include <debugger/shared/peutils.h>
49

hjk's avatar
hjk committed
50
#include <coreplugin/editormanager/editormanager.h>
51
#include <coreplugin/editormanager/ieditor.h>
hjk's avatar
hjk committed
52
#include <coreplugin/icore.h>
53 54
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
55

hjk's avatar
hjk committed
56
#include <projectexplorer/projectexplorer.h>
57 58
#include <projectexplorer/taskhub.h>

59 60
#include <texteditor/itexteditor.h>

61 62
#include <utils/savedaction.h>
#include <utils/qtcassert.h>
63
#include <utils/fileinprojectfinder.h>
64

65
#include <qmljs/consolemanagerinterface.h>
66

67 68 69
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
70
#include <QDir>
71

72
#include <QMessageBox>
73

hjk's avatar
hjk committed
74
using namespace Core;
75
using namespace Debugger::Internal;
hjk's avatar
hjk committed
76 77
using namespace ProjectExplorer;
using namespace TextEditor;
78

79 80 81 82
enum { debug = 0 };

#define SDEBUG(s) if (!debug) {} else qDebug() << s;
#define XSDEBUG(s) qDebug() << s
83

84 85 86 87
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
88

89 90 91 92 93 94
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
95 96 97
// VariableManager Prefix
const char PrefixDebugExecutable[]  = "DebuggedExecutable";

98 99
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
100 101 102 103 104 105 106 107 108
Internal::Location::Location(const StackFrame &frame, bool marker)
{
    init();
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
109
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
110 111
}

112 113
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
114 115
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
116 117 118 119 120 121 122
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
123
            << " processArgs=" << sp.processArgs
124 125 126 127 128 129
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " serverStartScript=" << sp.serverStartScript
130
            << " abi=" << sp.toolChainAbi.toString() << '\n';
131 132 133
    return str;
}

134

135 136 137 138 139 140
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

141 142 143 144 145 146 147 148 149
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

150
class DebuggerEnginePrivate : public QObject
151
{
152 153
    Q_OBJECT

154
public:
155
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
156
      : m_engine(engine),
157
        m_masterEngine(0),
158 159 160
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
161
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
162
        m_targetState(DebuggerNotReady),
163
        m_remoteSetupState(RemoteSetupNone),
164
        m_inferiorPid(0),
165
        m_modulesHandler(engine),
166
        m_registerHandler(),
167 168
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
169
        m_threadsHandler(),
170
        m_watchHandler(engine),
171
        m_disassemblerAgent(engine),
172
        m_memoryAgent(engine),
173
        m_isStateDebugging(false)
174
    {
175
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
176 177
        connect(debuggerCore()->action(IntelFlavor), SIGNAL(valueChanged(QVariant)),
                SLOT(reloadDisassembly()));
hjk's avatar
hjk committed
178
        VariableManager::registerFileVariables(PrefixDebugExecutable,
hjk's avatar
hjk committed
179 180
                                               tr("Debugged executable"));
        connect(VariableManager::instance(), SIGNAL(variableUpdateRequested(QByteArray)),
181
                SLOT(updateVariable(QByteArray)));
182
    }
183

184
public slots:
185
    void doSetupEngine();
hjk's avatar
hjk committed
186 187
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
188 189
    void doShutdownEngine();
    void doShutdownInferior();
190
    void doInterruptInferior();
hjk's avatar
hjk committed
191
    void doFinishDebugger();
hjk's avatar
hjk committed
192

hjk's avatar
hjk committed
193
    void updateVariable(const QByteArray &variable)
hjk's avatar
hjk committed
194
    {
hjk's avatar
hjk committed
195 196 197
        if (VariableManager::isFileVariable(variable, PrefixDebugExecutable))
            VariableManager::insert(variable,
                VariableManager::fileVariableValue(variable, PrefixDebugExecutable, m_startParameters.executable));
198 199
    }

200 201 202 203 204
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

205 206 207 208 209 210 211 212 213 214 215 216 217 218
    void queueSetupEngine()
    {
        m_engine->setState(EngineSetupRequested);
        m_engine->showMessage(_("QUEUE: SETUP ENGINE"));
        QTimer::singleShot(0, this, SLOT(doSetupEngine()));
    }

    void queueSetupInferior()
    {
        m_engine->setState(InferiorSetupRequested);
        m_engine->showMessage(_("QUEUE: SETUP INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doSetupInferior()));
    }

219 220
    void queueRunEngine()
    {
hjk's avatar
hjk committed
221 222 223 224 225
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

226 227
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
228 229 230 231 232
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

233 234
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
235 236 237 238 239
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

240 241
    void queueFinishDebugger()
    {
242 243 244
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
245 246 247 248 249
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
250 251
    }

252 253
    void raiseApplication()
    {
254 255
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
256 257
    }

258
    void scheduleResetLocation()
259
    {
260
        m_stackHandler.scheduleResetLocation();
261
        m_watchHandler.scheduleResetLocation();
262
        m_threadsHandler.scheduleResetLocation();
263
        m_disassemblerAgent.scheduleResetLocation();
264 265 266 267
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

268
    void resetLocation()
269 270 271
    {
        m_locationTimer.stop();
        m_locationMark.reset();
272
        m_stackHandler.resetLocation();
273
        m_watchHandler.resetLocation();
274
        m_threadsHandler.resetLocation();
275
        m_disassemblerAgent.resetLocation();
276 277
    }

278
public:
hjk's avatar
hjk committed
279
    DebuggerState state() const { return m_state; }
280
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
281 282 283
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
284
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
285

286
    DebuggerEngine *m_engine; // Not owned.
287
    DebuggerEngine *m_masterEngine; // Not owned
288 289 290
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
291 292

    // The current state.
293 294
    DebuggerState m_state;

hjk's avatar
hjk committed
295 296 297 298 299 300
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

    // The state we are aiming for.
    DebuggerState m_targetState;

301 302 303
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

304 305 306 307 308 309 310 311
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
312
    QFutureInterface<void> m_progress;
313

314 315
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
316 317
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
318 319

    bool m_isStateDebugging;
320

321
    Utils::FileInProjectFinder m_fileFinder;
322

323 324 325 326 327 328 329 330 331
};


//////////////////////////////////////////////////////////////////////
//
// DebuggerEngine
//
//////////////////////////////////////////////////////////////////////

332 333
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
334
{}
335 336 337

DebuggerEngine::~DebuggerEngine()
{
338 339
    disconnect();
    delete d;
340 341
}

342 343 344 345 346 347 348 349 350 351 352
const char *DebuggerEngine::stateName(int s)
{
#    define SN(x) case x: return #x;
    switch (s) {
        SN(DebuggerNotReady)
        SN(EngineSetupRequested)
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
        SN(EngineRunFailed)
        SN(InferiorSetupRequested)
        SN(InferiorSetupFailed)
353
        SN(InferiorSetupOk)
354 355 356 357 358 359 360 361
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
362
        SN(InferiorExitOk)
363 364 365 366 367 368 369 370 371 372 373 374
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

375
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
376
{
377
    showMessage(msg, StatusBar, timeout);
378
}
379

380 381 382 383 384 385 386 387 388 389 390 391
void DebuggerEngine::frameUp()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
}

void DebuggerEngine::frameDown()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMax(currentIndex - 1, 0));
}

392 393 394 395 396
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

397 398
ModulesHandler *DebuggerEngine::modulesHandler() const
{
399 400 401
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
402 403 404 405
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
406 407 408
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
409 410 411 412
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
413 414 415
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
416 417 418 419
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
420 421 422
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
423 424 425 426
}

WatchHandler *DebuggerEngine::watchHandler() const
{
427 428 429
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
430 431 432 433
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
434 435 436
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
437 438 439 440
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
441
   return modulesHandler()->model();
442 443 444 445
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
446
    return registerHandler()->model();
447 448 449 450
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
451
    return stackHandler()->model();
452 453 454 455
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
456
    return threadsHandler()->model();
457 458
}

hjk's avatar
hjk committed
459 460 461
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
462 463
}

464 465
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
466
    return sourceFilesHandler()->model();
467 468
}

469
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
470 471 472 473 474 475
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
476 477 478 479 480 481 482
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

483 484 485 486 487 488 489 490
void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
{
    Q_UNUSED(regnr);
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
491 492 493 494
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
495 496
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
497
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
498
    if (channel == ConsoleOutput && consoleManager)
499
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
500

501
    debuggerCore()->showMessage(msg, channel, timeout);
502
    if (d->m_runControl)
503
        d->m_runControl->showMessage(msg, channel);
504
    else
505
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
506 507 508 509
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
510 511
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
512

513
    d->m_progress.setProgressRange(0, 1000);
514
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
515
        tr("Launching Debugger"), "Debugger.Launcher");
516
    connect(fp, SIGNAL(canceled()), this, SLOT(quitDebugger()));
517
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
518 519
    d->m_progress.reportStarted();

520 521 522 523
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
524 525
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
526

527 528
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
529

hjk's avatar
hjk committed
530
    debuggerCore()->action(OperateByInstruction)
531
        ->setEnabled(hasCapability(DisassemblerCapability));
532

533 534
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
535 536
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
537
    d->m_progress.setProgressValue(200);
538
    d->queueSetupEngine();
539 540 541 542
}

void DebuggerEngine::resetLocation()
{
543 544
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
545 546
}

547
void DebuggerEngine::gotoLocation(const Location &loc)
548
{
Aurindam Jana's avatar
Aurindam Jana committed
549 550
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
551 552
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
553 554 555
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
556 557 558 559 560
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


561
    const QString file = QDir::cleanPath(loc.fileName());
562
    const int line = loc.lineNumber();
563
    bool newEditor = false;
564
    IEditor *editor = EditorManager::openEditor(file, Id(),
565 566
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
567 568 569

    editor->gotoLine(line, 0, !debuggerCore()->boolSetting(StationaryEditorWhileStepping));

570 571
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
572

573
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
574
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
575 576
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
577
        d->m_locationMark->init();
578
    }
579 580

    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
581 582
}

583 584 585
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
586
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
587
    d->m_runControl = 0;
588
    d->m_progress.setProgressValue(900);
589 590
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
591 592
}

593 594
// Called from RunControl.
void DebuggerEngine::handleFinished()
595
{
596
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
597
    d->m_runControl = 0;
598 599
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

const DebuggerStartParameters &DebuggerEngine::startParameters() const
{
    return d->m_startParameters;
}

DebuggerStartParameters &DebuggerEngine::startParameters()
{
    return d->m_startParameters;
}

DebuggerState DebuggerEngine::state() const
{
    return d->m_state;
}

hjk's avatar
hjk committed
621
DebuggerState DebuggerEngine::lastGoodState() const
622
{
hjk's avatar
hjk committed
623 624 625 626 627 628 629
    return d->m_lastGoodState;
}

DebuggerState DebuggerEngine::targetState() const
{
    return d->m_targetState;
}
630

hjk's avatar
hjk committed
631 632 633
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
634
    case DebuggerNotReady:
635
        return to == EngineSetupRequested;
636

hjk's avatar
hjk committed
637
    case EngineSetupRequested:
638 639
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
640 641 642
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
643
    case EngineSetupOk:
hjk's avatar
hjk committed
644
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
645

hjk's avatar
hjk committed
646
    case InferiorSetupRequested:
647
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
648
    case InferiorSetupFailed:
hjk's avatar
hjk committed
649
        return to == EngineShutdownRequested;
650 651
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
652 653

    case EngineRunRequested:
hjk's avatar
hjk committed
654
        return to == EngineRunFailed
655
            || to == InferiorRunRequested
hjk's avatar
hjk committed
656 657 658
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
659
    case EngineRunFailed:
660
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
661 662 663 664 665 666

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
667 668 669
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
670 671 672 673 674

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
Orgad Shaneh's avatar
Orgad Shaneh committed
675
            || to == InferiorStopOk || to == InferiorExitOk;
676
    case InferiorStopFailed:
hjk's avatar
hjk committed
677
        return to == EngineShutdownRequested;
678

679 680 681
    case InferiorExitOk:
        return to == InferiorShutdownOk;

682
    case InferiorUnrunnable:
hjk's avatar
hjk committed
683 684 685 686 687
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
688
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
689
        return to == EngineShutdownRequested;
690

hjk's avatar
hjk committed
691
    case EngineShutdownRequested:
692
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
693 694 695 696 697 698
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
699
        return to == EngineSetupRequested; // Happens on restart.
700 701
    }

702
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
703 704 705
    return false;
}

706 707
void DebuggerEngine::setupSlaveEngine()
{
708
    QTC_CHECK(state() == DebuggerNotReady);
709 710 711 712 713 714 715
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
David Schulz's avatar
David Schulz committed
716
    m_engine->checkForReleaseBuild(m_startParameters);
717 718 719
    m_engine->setupEngine();
}

720
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
721
{
hjk's avatar
hjk committed
722
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
723 724 725 726 727 728 729
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

730
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
731
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
732
    if (isMasterEngine() && runControl())
733
        runControl()->startFailed();
hjk's avatar
hjk committed
734
    setState(DebuggerFinished);
hjk's avatar
hjk committed
735 736
}

737
void DebuggerEngine::notifyEngineSetupOk()
738
{
hjk's avatar
hjk committed
739
    showMessage(_("NOTE: ENGINE SETUP OK"));
740 741 742 743
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

744
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
745
    setState(EngineSetupOk);
hjk's avatar
hjk committed
746
    showMessage(_("QUEUE: SETUP INFERIOR"));
747
    if (isMasterEngine())
748 749 750 751 752
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
753
    QTC_CHECK(state() == EngineSetupOk);
754
    d->queueSetupInferior();
755 756
}

hjk's avatar
hjk committed
757
void DebuggerEnginePrivate::doSetupInferior()
758
{
759
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
760
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
761
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
762 763 764 765 766
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
767
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
768
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
769
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
770
    setState(InferiorSetupFailed);
771 772
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
773 774 775 776
}

void DebuggerEngine::notifyInferiorSetupOk()
{
777 778 779
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
780
    showMessage(_("NOTE: INFERIOR SETUP OK"));
781 782 783 784
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
785 786
}

787 788 789
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
790
    QTC_CHECK(state() == InferiorSetupOk);
791 792 793
    d->queueRunEngine();
}

hjk's avatar
hjk committed
794 795
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
796
    m_engine->showMessage(_("CALL: RUN ENGINE"));
797
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
798
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
799 800 801
    m_engine->runEngine();
}

hjk's avatar
hjk committed
802 803
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
804
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
805 806
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
807
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
808
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
809 810 811 812 813
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
814
    showMessage(_("NOTE: ENGINE RUN FAILED"));
815
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
816 817 818
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
819
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
820
    setState(EngineRunFailed);
821 822
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
823 824
}

825 826 827 828 829 830 831 832 833 834 835
void DebuggerEngine::notifyEngineRequestRemoteSetup()
{
    showMessage(_("NOTE: REQUEST REMOTE SETUP"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone, qDebug() << this
               << "remoteSetupState" << d->remoteSetupState());

    d->setRemoteSetupState(RemoteSetupRequested);
    emit requestRemoteSetup();
}

hjk's avatar
hjk committed
836 837 838 839 840
void DebuggerEngine::notifyEngineRemoteServerRunning(const QByteArray &, int /*pid*/)
{
    showMessage(_("NOTE: REMOTE SERVER RUNNING IN MULTIMODE"));
}

841
void DebuggerEngine::notifyEngineRemoteSetupDone(int gdbServerPort, int qmlPort)
842
{
843 844
    showMessage(_("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1  QML PORT %2")
                .arg(gdbServerPort).arg(qmlPort));
845 846 847 848 849 850 851 852 853 854 855 856 857 858
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

    QTC_ASSERT(d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupCancelled,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

    if (d->remoteSetupState() == RemoteSetupCancelled)
        return;

    d->setRemoteSetupState(RemoteSetupSucceeded);
}

859
void DebuggerEngine::notifyEngineRemoteSetupFailed(const QString &message)