debuggerengine.cpp 52.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 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
#include "moduleshandler.h"
David Schulz's avatar
David Schulz committed
43
#include "peutils.h"
44 45 46 47 48 49
#include "registerhandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

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

70
#include <QMessageBox>
71

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

77 78 79 80
enum { debug = 0 };

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

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

87 88 89 90 91 92
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

93 94
namespace Debugger {

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

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
118
            << " processArgs=" << sp.processArgs
119 120 121 122 123 124 125
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " symbolFileName=" << sp.symbolFileName
            << " 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.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 538
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
539
    bool newEditor = false;
540
    IEditor *editor = EditorManager::openEditor(file, Id(),
541 542 543 544 545
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
    editor->gotoLine(line, 0);
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
546

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

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

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

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

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

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

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

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

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

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

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

653 654 655
    case InferiorExitOk:
        return to == InferiorShutdownOk;

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

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

    case DebuggerFinished:
673
        return to == EngineSetupRequested; // Happens on restart.
674 675
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

845 846 847 848 849 850 851 852 853 854
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
855 856
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
857
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
858 859
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
860
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
861
    showStatusMessage(tr("Running."));
hjk's avatar
hjk committed
862
    setState(InferiorRunOk);
hjk's avatar
hjk committed
863 864 865 866
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
867
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
868 869
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();