debuggerengine.cpp 53 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>
52 53
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
54

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

58 59
#include <texteditor/itexteditor.h>

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

64
#include <qmljs/consolemanagerinterface.h>
65

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

71
#include <QMessageBox>
72

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

78 79 80 81
enum { debug = 0 };

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

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

88 89 90 91 92 93
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

94 95
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
96 97 98 99 100 101 102 103 104
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;
105
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
106 107
}

108 109
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
110 111
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
112 113 114 115 116 117 118
}

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

130

131 132 133 134 135 136
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

137 138 139 140 141 142 143 144 145
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

146
class DebuggerEnginePrivate : public QObject
147
{
148 149
    Q_OBJECT

150
public:
151
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
152
      : m_engine(engine),
153
        m_masterEngine(0),
154 155 156
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
157
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
158
        m_targetState(DebuggerNotReady),
159
        m_remoteSetupState(RemoteSetupNone),
160
        m_inferiorPid(0),
161
        m_modulesHandler(engine),
162
        m_registerHandler(),
163 164
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
165
        m_threadsHandler(),
166
        m_watchHandler(engine),
167
        m_disassemblerAgent(engine),
168
        m_memoryAgent(engine),
169
        m_isStateDebugging(false)
170
    {
171
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
172
    }
173

174
public slots:
175
    void doSetupEngine();
hjk's avatar
hjk committed
176 177
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
178 179
    void doShutdownEngine();
    void doShutdownInferior();
180
    void doInterruptInferior();
hjk's avatar
hjk committed
181
    void doFinishDebugger();
hjk's avatar
hjk committed
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196
    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()));
    }

197 198
    void queueRunEngine()
    {
hjk's avatar
hjk committed
199 200 201 202 203
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

204 205
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
206 207 208 209 210
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

211 212
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
213 214 215 216 217
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

218 219
    void queueFinishDebugger()
    {
220 221 222
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
223 224 225 226 227
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
228 229
    }

230 231
    void raiseApplication()
    {
232 233
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
234 235
    }

236
    void scheduleResetLocation()
237
    {
238
        m_stackHandler.scheduleResetLocation();
239
        m_watchHandler.scheduleResetLocation();
240
        m_threadsHandler.scheduleResetLocation();
241
        m_disassemblerAgent.scheduleResetLocation();
242 243 244 245
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

246
    void resetLocation()
247 248 249
    {
        m_locationTimer.stop();
        m_locationMark.reset();
250
        m_stackHandler.resetLocation();
251
        m_watchHandler.resetLocation();
252
        m_threadsHandler.resetLocation();
253
        m_disassemblerAgent.resetLocation();
254 255
    }

256
public:
hjk's avatar
hjk committed
257
    DebuggerState state() const { return m_state; }
258
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
259 260 261
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
262
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
263

264
    DebuggerEngine *m_engine; // Not owned.
265
    DebuggerEngine *m_masterEngine; // Not owned
266 267 268
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
269 270

    // The current state.
271 272
    DebuggerState m_state;

hjk's avatar
hjk committed
273 274 275 276 277 278
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

279 280 281
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

282 283 284 285 286 287 288 289
    qint64 m_inferiorPid;

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

292 293
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
294 295
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
296 297

    bool m_isStateDebugging;
298

299
    Utils::FileInProjectFinder m_fileFinder;
300 301 302 303 304 305 306 307 308
};


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

309 310
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
311
{}
312 313 314

DebuggerEngine::~DebuggerEngine()
{
315 316
    disconnect();
    delete d;
317 318
}

319 320 321 322 323 324 325 326 327 328 329
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)
330
        SN(InferiorSetupOk)
331 332 333 334 335 336 337 338
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
339
        SN(InferiorExitOk)
340 341 342 343 344 345 346 347 348 349 350 351
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

352
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
353
{
354
    showMessage(msg, StatusBar, timeout);
355
}
356

357 358 359 360 361 362 363 364 365 366 367 368
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));
}

369 370 371 372 373
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

374 375
ModulesHandler *DebuggerEngine::modulesHandler() const
{
376 377 378
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
379 380 381 382
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
383 384 385
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
386 387 388 389
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
390 391 392
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
393 394 395 396
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
397 398 399
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
400 401 402 403
}

WatchHandler *DebuggerEngine::watchHandler() const
{
404 405 406
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
407 408 409 410
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
411 412 413
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
414 415 416 417
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
418
   return modulesHandler()->model();
419 420 421 422
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
423
    return registerHandler()->model();
424 425 426 427
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
428
    return stackHandler()->model();
429 430 431 432
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
433
    return threadsHandler()->model();
434 435
}

hjk's avatar
hjk committed
436 437 438
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
439 440
}

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

446
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
447 448 449 450 451 452
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
453 454 455 456 457 458 459
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

460 461 462 463 464 465 466 467
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
{
468 469 470 471
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
472 473
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
474
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
475
    if (channel == ConsoleOutput && consoleManager)
476
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
477

478
    debuggerCore()->showMessage(msg, channel, timeout);
479
    if (d->m_runControl)
480
        d->m_runControl->showMessage(msg, channel);
481
    else
482
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
483 484 485 486
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
487 488
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
489

490
    d->m_progress.setProgressRange(0, 1000);
491
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
492
        tr("Launching Debugger"), "Debugger.Launcher");
493
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
494 495
    d->m_progress.reportStarted();

496 497 498 499
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
500 501
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
502

503 504
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
505

hjk's avatar
hjk committed
506
    debuggerCore()->action(OperateByInstruction)
507
        ->setEnabled(hasCapability(DisassemblerCapability));
508

509 510
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
511 512
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
513
    d->m_progress.setProgressValue(200);
514
    d->queueSetupEngine();
515 516 517 518
}

void DebuggerEngine::resetLocation()
{
519 520
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
521 522
}

523
void DebuggerEngine::gotoLocation(const Location &loc)
524
{
Aurindam Jana's avatar
Aurindam Jana committed
525 526
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
527 528
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
529 530 531
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
532 533 534 535 536
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


537
    const QString file = QDir::cleanPath(loc.fileName());
538
    const int line = loc.lineNumber();
539
    bool newEditor = false;
540
    IEditor *editor = EditorManager::openEditor(file, Id(),
541 542
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
543 544 545

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

546 547
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
548

549
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
550
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
551 552
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
553
        d->m_locationMark->init();
554
    }
555 556

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

559 560 561
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
562
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
563
    d->m_runControl = 0;
564
    d->m_progress.setProgressValue(900);
565 566
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
567 568
}

569 570
// Called from RunControl.
void DebuggerEngine::handleFinished()
571
{
572
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
573
    d->m_runControl = 0;
574 575
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
    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
597
DebuggerState DebuggerEngine::lastGoodState() const
598
{
hjk's avatar
hjk committed
599 600 601 602 603 604 605
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
607 608 609
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
610
    case DebuggerNotReady:
611
        return to == EngineSetupRequested;
612

hjk's avatar
hjk committed
613
    case EngineSetupRequested:
614 615
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
616 617 618
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
619
    case EngineSetupOk:
hjk's avatar
hjk committed
620
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
621

hjk's avatar
hjk committed
622
    case InferiorSetupRequested:
623
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
624
    case InferiorSetupFailed:
hjk's avatar
hjk committed
625
        return to == EngineShutdownRequested;
626 627
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
628 629

    case EngineRunRequested:
hjk's avatar
hjk committed
630
        return to == EngineRunFailed
631
            || to == InferiorRunRequested
hjk's avatar
hjk committed
632 633 634
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
635
    case EngineRunFailed:
636
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
637 638 639 640 641 642

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
643 644 645
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
646 647 648 649 650

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
651
            || to == InferiorStopOk || InferiorExitOk;
652
    case InferiorStopFailed:
hjk's avatar
hjk committed
653
        return to == EngineShutdownRequested;
654

655 656 657
    case InferiorExitOk:
        return to == InferiorShutdownOk;

658
    case InferiorUnrunnable:
hjk's avatar
hjk committed
659 660 661 662 663
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
664
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
665
        return to == EngineShutdownRequested;
666

hjk's avatar
hjk committed
667
    case EngineShutdownRequested:
668
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
669 670 671 672 673 674
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
675
        return to == EngineSetupRequested; // Happens on restart.
676 677
    }

678
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
679 680 681
    return false;
}

682 683
void DebuggerEngine::setupSlaveEngine()
{
684
    QTC_CHECK(state() == DebuggerNotReady);
685 686 687 688 689 690 691
    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
692
    m_engine->checkForReleaseBuild(m_startParameters);
693 694 695
    m_engine->setupEngine();
}

696
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
697
{
hjk's avatar
hjk committed
698
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
699 700 701 702 703 704 705
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

706
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
707
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
708
    if (isMasterEngine() && runControl())
709
        runControl()->startFailed();
hjk's avatar
hjk committed
710
    setState(DebuggerFinished);
hjk's avatar
hjk committed
711 712
}

713
void DebuggerEngine::notifyEngineSetupOk()
714
{
hjk's avatar
hjk committed
715
    showMessage(_("NOTE: ENGINE SETUP OK"));
716 717 718 719
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

720
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
721
    setState(EngineSetupOk);
hjk's avatar
hjk committed
722
    showMessage(_("QUEUE: SETUP INFERIOR"));
723
    if (isMasterEngine())
724 725 726 727 728
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
729
    QTC_CHECK(state() == EngineSetupOk);
730
    d->queueSetupInferior();
731 732
}

hjk's avatar
hjk committed
733
void DebuggerEnginePrivate::doSetupInferior()
734
{
735
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
736
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
737
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
738 739 740 741 742
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
743
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
744
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
745
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
746
    setState(InferiorSetupFailed);
747 748
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
749 750 751 752
}

void DebuggerEngine::notifyInferiorSetupOk()
{
753 754 755
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
756
    showMessage(_("NOTE: INFERIOR SETUP OK"));
757 758 759 760
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
761 762
}

763 764 765
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
766
    QTC_CHECK(state() == InferiorSetupOk);
767 768 769
    d->queueRunEngine();
}

hjk's avatar
hjk committed
770 771
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
772
    m_engine->showMessage(_("CALL: RUN ENGINE"));
773
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
774
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
775 776 777
    m_engine->runEngine();
}

hjk's avatar
hjk committed
778 779
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
780
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
781 782
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
783
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
784
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
785 786 787 788 789
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
790
    showMessage(_("NOTE: ENGINE RUN FAILED"));
791
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
792 793 794
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
795
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
796
    setState(EngineRunFailed);
797 798
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
799 800
}

801 802 803 804 805 806 807 808 809 810 811
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
812 813 814 815 816
void DebuggerEngine::notifyEngineRemoteServerRunning(const QByteArray &, int /*pid*/)
{
    showMessage(_("NOTE: REMOTE SERVER RUNNING IN MULTIMODE"));
}

817
void DebuggerEngine::notifyEngineRemoteSetupDone(int gdbServerPort, int qmlPort)
818
{
819 820
    showMessage(_("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1  QML PORT %2")
                .arg(gdbServerPort).arg(qmlPort));
821 822 823 824 825 826 827 828 829 830 831 832 833 834
    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);
}

835
void DebuggerEngine::notifyEngineRemoteSetupFailed(const QString &message)
836
{
837
    showMessage(_("NOTE: REMOTE SETUP FAILED: ") + message);
838 839 840 841 842 843 844 845 846
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

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

847 848 849 850 851 852 853 854 855 856
void DebuggerEngine::notifyEngineRunOkAndInferiorRunRequested()
{
    showMessage(_("NOTE: ENGINE RUN OK AND INFERIOR RUN REQUESTED"));
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
    showStatusMessage(tr("Running."));
    setState(InferiorRunRequested);
}

hjk's avatar
hjk committed
857 858
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
859
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
860 861
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
862
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
863
    showStatusMessage(tr("Running."));
hjk's avatar
hjk committed
864
    setState(InferiorRunOk);
hjk's avatar
hjk committed
865