debuggerengine.cpp 53.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/icore.h>
hjk's avatar
hjk committed
51
#include <coreplugin/editormanager/editormanager.h>
52
#include <coreplugin/editormanager/ieditor.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

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 126
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " symbolFileName=" << sp.symbolFileName
            << " serverStartScript=" << sp.serverStartScript
127
            << " abi=" << sp.toolChainAbi.toString() << '\n';
128 129 130
    return str;
}

131

132 133 134 135 136 137
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

147
class DebuggerEnginePrivate : public QObject
148
{
149 150
    Q_OBJECT

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

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

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

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

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

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

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

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

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

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

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

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

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
270 271

    // The current state.
272 273
    DebuggerState m_state;

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

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

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

283 284 285 286 287 288 289 290
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
299

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


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

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

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

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

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

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

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

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

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

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

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

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

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

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
419
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
420 421 422
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
423 424 425 426
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
427
    QAbstractItemModel *model = registerHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
428 429 430
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
431 432 433 434
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
435
    QAbstractItemModel *model = stackHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
436 437 438
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
439 440 441 442
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
443
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
444 445 446
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
447 448
}

hjk's avatar
hjk committed
449 450 451
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
452 453
}

454 455
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
456
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
457 458 459
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
460 461
}

462
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
463 464 465 466 467 468
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
469 470 471 472 473 474 475
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

476 477 478 479 480 481 482 483
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
{
484 485 486 487
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
488 489
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
490
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
491
    if (channel == ConsoleOutput && consoleManager)
492
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
493

494
    debuggerCore()->showMessage(msg, channel, timeout);
495
    if (d->m_runControl)
496
        d->m_runControl->showMessage(msg, channel);
497
    else
498
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
499 500 501 502
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
503 504
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
505

506
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
507
    Core::FutureProgress *fp = Core::ICore::progressManager()
508 509
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
510
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
511 512
    d->m_progress.reportStarted();

513 514 515 516
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
517 518
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
519

520 521
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
522

hjk's avatar
hjk committed
523
    debuggerCore()->action(OperateByInstruction)
524
        ->setEnabled(hasCapability(DisassemblerCapability));
525

526 527
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
528 529
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
530
    d->m_progress.setProgressValue(200);
531
    d->queueSetupEngine();
532 533 534 535
}

void DebuggerEngine::resetLocation()
{
536 537
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
538 539
}

540
void DebuggerEngine::gotoLocation(const Location &loc)
541
{
Aurindam Jana's avatar
Aurindam Jana committed
542 543
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
544 545
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
546 547 548
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
549 550 551 552 553
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


554 555
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
556 557 558 559 560 561 562
    bool newEditor = false;
    IEditor *editor = EditorManager::openEditor(file, Core::Id(),
                                                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
563

564
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
565
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
566 567
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
568
        d->m_locationMark->init();
569
    }
570 571

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

574 575 576
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
577
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
578
    d->m_runControl = 0;
579
    d->m_progress.setProgressValue(900);
580 581
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
582 583
}

584 585
// Called from RunControl.
void DebuggerEngine::handleFinished()
586
{
587
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
588
    d->m_runControl = 0;
589 590
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
    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
612
DebuggerState DebuggerEngine::lastGoodState() const
613
{
hjk's avatar
hjk committed
614 615 616 617 618 619 620
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
622 623 624
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
625
    case DebuggerNotReady:
626
        return to == EngineSetupRequested;
627

hjk's avatar
hjk committed
628
    case EngineSetupRequested:
629 630
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
631 632 633
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
634
    case EngineSetupOk:
hjk's avatar
hjk committed
635
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
636

hjk's avatar
hjk committed
637
    case InferiorSetupRequested:
638
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
639
    case InferiorSetupFailed:
hjk's avatar
hjk committed
640
        return to == EngineShutdownRequested;
641 642
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
643 644

    case EngineRunRequested:
hjk's avatar
hjk committed
645
        return to == EngineRunFailed
646
            || to == InferiorRunRequested
hjk's avatar
hjk committed
647 648 649
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
650
    case EngineRunFailed:
651
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
652 653 654 655 656 657

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
658 659 660
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
661 662 663 664 665

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
666
            || to == InferiorStopOk || InferiorExitOk;
667
    case InferiorStopFailed:
hjk's avatar
hjk committed
668
        return to == EngineShutdownRequested;
669

670 671 672
    case InferiorExitOk:
        return to == InferiorShutdownOk;

673
    case InferiorUnrunnable:
hjk's avatar
hjk committed
674 675 676 677 678
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
679
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
680
        return to == EngineShutdownRequested;
681

hjk's avatar
hjk committed
682
    case EngineShutdownRequested:
683
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
684 685 686 687 688 689
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
690
        return to == EngineSetupRequested; // Happens on restart.
691 692
    }

693
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
694 695 696
    return false;
}

697 698
void DebuggerEngine::setupSlaveEngine()
{
699
    QTC_CHECK(state() == DebuggerNotReady);
700 701 702 703 704 705 706
    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
707
    m_engine->checkForReleaseBuild(m_startParameters);
708 709 710
    m_engine->setupEngine();
}

711
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
712
{
hjk's avatar
hjk committed
713
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
714 715 716 717 718 719 720
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

721
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
722
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
723
    if (isMasterEngine() && runControl())
724
        runControl()->startFailed();
hjk's avatar
hjk committed
725
    setState(DebuggerFinished);
hjk's avatar
hjk committed
726 727
}

728
void DebuggerEngine::notifyEngineSetupOk()
729
{
hjk's avatar
hjk committed
730
    showMessage(_("NOTE: ENGINE SETUP OK"));
731 732 733 734
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

735
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
736
    setState(EngineSetupOk);
hjk's avatar
hjk committed
737
    showMessage(_("QUEUE: SETUP INFERIOR"));
738
    if (isMasterEngine())
739 740 741 742 743
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
744
    QTC_CHECK(state() == EngineSetupOk);
745
    d->queueSetupInferior();
746 747
}

hjk's avatar
hjk committed
748
void DebuggerEnginePrivate::doSetupInferior()
749
{
750
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
751
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
752
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
753 754 755 756 757
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
758
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
759
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
760
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
761
    setState(InferiorSetupFailed);
762 763
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
764 765 766 767
}

void DebuggerEngine::notifyInferiorSetupOk()
{
768 769 770
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
771
    showMessage(_("NOTE: INFERIOR SETUP OK"));
772 773 774 775
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
776 777
}

778 779 780
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
781
    QTC_CHECK(state() == InferiorSetupOk);
782 783 784
    d->queueRunEngine();
}

hjk's avatar
hjk committed
785 786
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
787
    m_engine->showMessage(_("CALL: RUN ENGINE"));
788
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
789
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
790 791 792
    m_engine->runEngine();
}

hjk's avatar
hjk committed
793 794
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
795
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
796 797
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
798
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
799
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
800 801 802 803 804
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
805
    showMessage(_("NOTE: ENGINE RUN FAILED"));
806
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
807 808 809
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
810
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
811
    setState(EngineRunFailed);
812 813
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
814 815
}

816 817 818 819 820 821 822 823 824 825 826
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
827 828 829 830 831
void DebuggerEngine::notifyEngineRemoteServerRunning(const QByteArray &, int /*pid*/)
{
    showMessage(_("NOTE: REMOTE SERVER RUNNING IN MULTIMODE"));
}

832
void DebuggerEngine::notifyEngineRemoteSetupDone(int gdbServerPort, int qmlPort)
833
{
834 835
    showMessage(_("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1  QML PORT %2")
                .arg(gdbServerPort).arg(qmlPort));
836 837 838 839 840 841 842 843 844 845 846 847 848 849
    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);
}

850
void DebuggerEngine::notifyEngineRemoteSetupFailed(const QString &message)
851
{
852
    showMessage(_("NOTE: REMOTE SETUP FAILED: ") + message);
853 854 855 856 857 858 859 860 861
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

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

862 863 864 865 866 867 868 869 870 871
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
872 873
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
874
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
875 876
    d->m_progress