debuggerengine.cpp 53.3 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
        connect(debuggerCore()->action(IntelFlavor), SIGNAL(valueChanged(QVariant)),
                SLOT(reloadDisassembly()));
174
    }
175

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

185 186 187 188 189
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

190 191 192 193 194 195 196 197 198 199 200 201 202 203
    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()));
    }

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

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

218 219
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
220 221 222 223 224
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

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

237 238
    void raiseApplication()
    {
239 240
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
241 242
    }

243
    void scheduleResetLocation()
244
    {
245
        m_stackHandler.scheduleResetLocation();
246
        m_watchHandler.scheduleResetLocation();
247
        m_threadsHandler.scheduleResetLocation();
248
        m_disassemblerAgent.scheduleResetLocation();
249 250 251 252
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

253
    void resetLocation()
254 255 256
    {
        m_locationTimer.stop();
        m_locationMark.reset();
257
        m_stackHandler.resetLocation();
258
        m_watchHandler.resetLocation();
259
        m_threadsHandler.resetLocation();
260
        m_disassemblerAgent.resetLocation();
261 262
    }

263
public:
hjk's avatar
hjk committed
264
    DebuggerState state() const { return m_state; }
265
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
266 267 268
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
269
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
270

271
    DebuggerEngine *m_engine; // Not owned.
272
    DebuggerEngine *m_masterEngine; // Not owned
273 274 275
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
276 277

    // The current state.
278 279
    DebuggerState m_state;

hjk's avatar
hjk committed
280 281 282 283 284 285
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

286 287 288
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

289 290 291 292 293 294 295 296
    qint64 m_inferiorPid;

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

299 300
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
301 302
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
303 304

    bool m_isStateDebugging;
305

306
    Utils::FileInProjectFinder m_fileFinder;
307 308 309 310 311 312 313 314 315
};


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

316 317
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
318
{}
319 320 321

DebuggerEngine::~DebuggerEngine()
{
322 323
    disconnect();
    delete d;
324 325
}

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

359
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
360
{
361
    showMessage(msg, StatusBar, timeout);
362
}
363

364 365 366 367 368 369 370 371 372 373 374 375
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));
}

376 377 378 379 380
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

381 382
ModulesHandler *DebuggerEngine::modulesHandler() const
{
383 384 385
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
386 387 388 389
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
390 391 392
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
393 394 395 396
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
397 398 399
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
400 401 402 403
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
404 405 406
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
407 408 409 410
}

WatchHandler *DebuggerEngine::watchHandler() const
{
411 412 413
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
414 415 416 417
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
418 419 420
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
421 422 423 424
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
425
   return modulesHandler()->model();
426 427 428 429
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
430
    return registerHandler()->model();
431 432 433 434
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
435
    return stackHandler()->model();
436 437 438 439
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
440
    return threadsHandler()->model();
441 442
}

hjk's avatar
hjk committed
443 444 445
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
446 447
}

448 449
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
450
    return sourceFilesHandler()->model();
451 452
}

453
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
454 455 456 457 458 459
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
460 461 462 463 464 465 466
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

485
    debuggerCore()->showMessage(msg, channel, timeout);
486
    if (d->m_runControl)
487
        d->m_runControl->showMessage(msg, channel);
488
    else
489
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
490 491 492 493
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
494 495
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
496

497
    d->m_progress.setProgressRange(0, 1000);
498
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
499
        tr("Launching Debugger"), "Debugger.Launcher");
500
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
501 502
    d->m_progress.reportStarted();

503 504 505 506
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
507 508
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
509

510 511
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
512

hjk's avatar
hjk committed
513
    debuggerCore()->action(OperateByInstruction)
514
        ->setEnabled(hasCapability(DisassemblerCapability));
515

516 517
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
518 519
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
520
    d->m_progress.setProgressValue(200);
521
    d->queueSetupEngine();
522 523 524 525
}

void DebuggerEngine::resetLocation()
{
526 527
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
528 529
}

530
void DebuggerEngine::gotoLocation(const Location &loc)
531
{
Aurindam Jana's avatar
Aurindam Jana committed
532 533
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
534 535
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
536 537 538
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
539 540 541 542 543
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


544
    const QString file = QDir::cleanPath(loc.fileName());
545
    const int line = loc.lineNumber();
546
    bool newEditor = false;
547
    IEditor *editor = EditorManager::openEditor(file, Id(),
548 549
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
550 551 552

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

553 554
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
555

556
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
557
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
558 559
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
560
        d->m_locationMark->init();
561
    }
562 563

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

566 567 568
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
569
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
570
    d->m_runControl = 0;
571
    d->m_progress.setProgressValue(900);
572 573
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
574 575
}

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

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

hjk's avatar
hjk committed
614 615 616
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
617
    case DebuggerNotReady:
618
        return to == EngineSetupRequested;
619

hjk's avatar
hjk committed
620
    case EngineSetupRequested:
621 622
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
623 624 625
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
626
    case EngineSetupOk:
hjk's avatar
hjk committed
627
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
628

hjk's avatar
hjk committed
629
    case InferiorSetupRequested:
630
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
631
    case InferiorSetupFailed:
hjk's avatar
hjk committed
632
        return to == EngineShutdownRequested;
633 634
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
635 636

    case EngineRunRequested:
hjk's avatar
hjk committed
637
        return to == EngineRunFailed
638
            || to == InferiorRunRequested
hjk's avatar
hjk committed
639 640 641
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
642
    case EngineRunFailed:
643
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
644 645 646 647 648 649

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
650 651 652
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
653 654 655 656 657

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
Orgad Shaneh's avatar
Orgad Shaneh committed
658
            || to == InferiorStopOk || to == InferiorExitOk;
659
    case InferiorStopFailed:
hjk's avatar
hjk committed
660
        return to == EngineShutdownRequested;
661

662 663 664
    case InferiorExitOk:
        return to == InferiorShutdownOk;

665
    case InferiorUnrunnable:
hjk's avatar
hjk committed
666 667 668 669 670
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
671
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
672
        return to == EngineShutdownRequested;
673

hjk's avatar
hjk committed
674
    case EngineShutdownRequested:
675
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
676 677 678 679 680 681
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
682
        return to == EngineSetupRequested; // Happens on restart.
683 684
    }

685
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
686 687 688
    return false;
}

689 690
void DebuggerEngine::setupSlaveEngine()
{
691
    QTC_CHECK(state() == DebuggerNotReady);
692 693 694 695 696 697 698
    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
699
    m_engine->checkForReleaseBuild(m_startParameters);
700 701 702
    m_engine->setupEngine();
}

703
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
704
{
hjk's avatar
hjk committed
705
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
706 707 708 709 710 711 712
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

713
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
714
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
715
    if (isMasterEngine() && runControl())
716
        runControl()->startFailed();
hjk's avatar
hjk committed
717
    setState(DebuggerFinished);
hjk's avatar
hjk committed
718 719
}

720
void DebuggerEngine::notifyEngineSetupOk()
721
{
hjk's avatar
hjk committed
722
    showMessage(_("NOTE: ENGINE SETUP OK"));
723 724 725 726
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

727
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
728
    setState(EngineSetupOk);
hjk's avatar
hjk committed
729
    showMessage(_("QUEUE: SETUP INFERIOR"));
730
    if (isMasterEngine())
731 732 733 734 735
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
736
    QTC_CHECK(state() == EngineSetupOk);
737
    d->queueSetupInferior();
738 739
}

hjk's avatar
hjk committed
740
void DebuggerEnginePrivate::doSetupInferior()
741
{
742
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
743
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
744
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
745 746 747 748 749
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
750
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
751
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
752
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
753
    setState(InferiorSetupFailed);
754 755
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
756 757 758 759
}

void DebuggerEngine::notifyInferiorSetupOk()
{
760 761 762
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
763
    showMessage(_("NOTE: INFERIOR SETUP OK"));
764 765 766 767
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
768 769
}

770 771 772
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
773
    QTC_CHECK(state() == InferiorSetupOk);
774 775 776
    d->queueRunEngine();
}

hjk's avatar
hjk committed
777 778
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
779
    m_engine->showMessage(_("CALL: RUN ENGINE"));
780
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
781
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
782 783 784
    m_engine->runEngine();
}

hjk's avatar
hjk committed
785 786
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
787
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
788 789
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
790
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
791
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
792 793 794 795 796
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
797
    showMessage(_("NOTE: ENGINE RUN FAILED"));
798
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
799 800 801
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
802
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
803
    setState(EngineRunFailed);
804 805
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
806 807
}

808 809 810 811 812 813 814 815 816 817 818
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
819 820 821 822 823
void DebuggerEngine::notifyEngineRemoteServerRunning(const QByteArray &, int /*pid*/)
{
    showMessage(_("NOTE: REMOTE SERVER RUNNING IN MULTIMODE"));
}

824
void DebuggerEngine::notifyEngineRemoteSetupDone(int gdbServerPort, int qmlPort)
825
{
826 827
    showMessage(_("NOTE: REMOTE SETUP DONE: GDB SERVER PORT: %1  QML PORT %2")
                .arg(gdbServerPort).arg(qmlPort));
828 829 830 831 832 833 834 835 836 837 838 839 840 841
    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);
}

842
void DebuggerEngine::notifyEngineRemoteSetupFailed(const QString &message)
843
{
844
    showMessage(_("NOTE: REMOTE SETUP FAILED: ") + message);
845 846 847 848 849 850 851 852 853
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

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

854 855 856 857 858 859 860 861 862 863
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
864 865
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
866
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
867 868
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
869
    QTC_ASSERT(