debuggerengine.cpp 55.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25 26 27

#include "debuggerengine.h"

28
#include "debuggerinternalconstants.h"
29
#include "debuggeractions.h"
30
#include "debuggercore.h"
31
#include "debuggericons.h"
32
#include "debuggerruncontrol.h"
33
#include "debuggertooltipmanager.h"
34 35

#include "breakhandler.h"
David Schulz's avatar
David Schulz committed
36
#include "disassembleragent.h"
37
#include "logwindow.h"
David Schulz's avatar
David Schulz committed
38
#include "memoryagent.h"
39 40 41
#include "moduleshandler.h"
#include "registerhandler.h"
#include "sourcefileshandler.h"
hjk's avatar
hjk committed
42
#include "sourceutils.h"
43
#include "stackhandler.h"
44
#include "terminal.h"
45 46
#include "threadshandler.h"
#include "watchhandler.h"
hjk's avatar
hjk committed
47 48
#include "debugger/shared/peutils.h"
#include "console/console.h"
49

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

hjk's avatar
hjk committed
58
#include <projectexplorer/projectexplorer.h>
59 60
#include <projectexplorer/taskhub.h>

61
#include <texteditor/texteditor.h>
62

63
#include <utils/fileinprojectfinder.h>
hjk's avatar
hjk committed
64
#include <utils/macroexpander.h>
65
#include <utils/processhandle.h>
hjk's avatar
hjk committed
66
#include <utils/qtcassert.h>
David Schulz's avatar
David Schulz committed
67
#include <utils/qtcprocess.h>
hjk's avatar
hjk committed
68
#include <utils/savedaction.h>
69

70 71 72
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
73
#include <QDir>
74

75 76 77 78 79
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>

hjk's avatar
hjk committed
80
using namespace Core;
81
using namespace Debugger::Internal;
hjk's avatar
hjk committed
82 83
using namespace ProjectExplorer;
using namespace TextEditor;
84
using namespace Utils;
85

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

91 92
namespace Debugger {

93 94
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
95 96
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
97 98
}

99
QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
100 101
{
    QDebug nospace = str.nospace();
102
    nospace << "executable=" << sp.inferior.executable
103
            << " coreFile=" << sp.coreFile
104 105
            << " processArgs=" << sp.inferior.commandLineArguments
            << " inferior environment=<" << sp.inferior.environment.size() << " variables>"
106
            << " debugger environment=<" << sp.debugger.environment.size() << " variables>"
107
            << " workingDir=" << sp.inferior.workingDirectory
108
            << " attachPID=" << sp.attachPID.pid()
109
            << " remoteChannel=" << sp.remoteChannel
110
            << " abi=" << sp.toolChainAbi.toString() << '\n';
111 112 113
    return str;
}

hjk's avatar
hjk committed
114 115 116 117 118 119 120 121 122 123
namespace Internal {

Location::Location(const StackFrame &frame, bool marker)
{
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
124
    m_from = frame.module;
hjk's avatar
hjk committed
125 126
}

127

hjk's avatar
hjk committed
128 129
LocationMark::LocationMark(DebuggerEngine *engine, const QString &file, int line)
    : TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION), m_engine(engine)
hjk's avatar
hjk committed
130
{
131
    setIcon(Icons::LOCATION.icon());
hjk's avatar
hjk committed
132 133
    setPriority(TextMark::HighPriority);
}
hjk's avatar
hjk committed
134

hjk's avatar
hjk committed
135 136 137 138
bool LocationMark::isDraggable() const
{
    return m_engine->hasCapability(JumpToLineCapability);
}
hjk's avatar
hjk committed
139

hjk's avatar
hjk committed
140 141 142
void LocationMark::dragToLine(int line)
{
    if (m_engine) {
143 144 145 146 147
        if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
            ContextData location = getLocationContext(textEditor->textDocument(), line);
            if (location.isValid())
                m_engine->executeJumpToLine(location);
        }
hjk's avatar
hjk committed
148
    }
hjk's avatar
hjk committed
149
}
hjk's avatar
hjk committed
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
//////////////////////////////////////////////////////////////////////
//
// MemoryAgentSet
//
//////////////////////////////////////////////////////////////////////

class MemoryAgentSet
{
public:
    ~MemoryAgentSet()
    {
        qDeleteAll(m_agents);
        m_agents.clear();
    }

    // Called by engine to create a new view.
    void createBinEditor(const MemoryViewSetupData &data, DebuggerEngine *engine)
    {
        auto agent = new MemoryAgent(data, engine);
        if (agent->isUsable()) {
            m_agents.append(agent);
        } else {
            delete agent;
            AsynchronousMessageBox::warning(
                        DebuggerEngine::tr("No Memory Viewer Available"),
                        DebuggerEngine::tr("The memory contents cannot be shown as no viewer plugin "
                                           "for binary data has been loaded."));
        }
    }

    // On stack frame completed and on request.
    void updateContents()
    {
        foreach (MemoryAgent *agent, m_agents) {
            if (agent)
                agent->updateContents();
        }
    }

    void handleDebuggerFinished()
    {
        foreach (MemoryAgent *agent, m_agents) {
            if (agent)
                agent->setFinished(); // Prevent triggering updates, etc.
        }
    }

private:
    QList<MemoryAgent *> m_agents;
};



204 205 206 207 208 209
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

210
class DebuggerEnginePrivate : public QObject
211
{
212 213
    Q_OBJECT

214
public:
215
    DebuggerEnginePrivate(DebuggerEngine *engine)
216
      : m_engine(engine),
217
        m_modulesHandler(engine),
hjk's avatar
hjk committed
218
        m_registerHandler(engine),
219
        m_sourceFilesHandler(engine),
220
        m_stackHandler(engine),
221
        m_threadsHandler(engine),
222
        m_watchHandler(engine),
223
        m_disassemblerAgent(engine),
224
        m_isStateDebugging(false)
225
    {
hjk's avatar
hjk committed
226 227 228 229
        connect(&m_locationTimer, &QTimer::timeout,
                this, &DebuggerEnginePrivate::resetLocation);
        connect(action(IntelFlavor), &Utils::SavedAction::valueChanged,
                this, &DebuggerEnginePrivate::reloadDisassembly);
230
    }
231

232
    void doSetupEngine();
hjk's avatar
hjk committed
233
    void doRunEngine();
hjk's avatar
hjk committed
234 235
    void doShutdownEngine();
    void doShutdownInferior();
236
    void doInterruptInferior();
hjk's avatar
hjk committed
237

238 239 240 241 242
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

hjk's avatar
hjk committed
243
    void doFinishDebugger()
244
    {
245 246 247
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
248 249
        resetLocation();
        if (isMasterEngine()) {
hjk's avatar
hjk committed
250 251 252 253
            m_engine->showMessage("NOTE: FINISH DEBUGGER");
            QTC_ASSERT(state() == DebuggerFinished, qDebug() << m_engine << state());
            if (isMasterEngine() && m_runTool)
                m_runTool->debuggingFinished();
254
        }
hjk's avatar
hjk committed
255 256
    }

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

267
    void resetLocation()
268
    {
269
        m_lookupRequests.clear();
270 271
        m_locationTimer.stop();
        m_locationMark.reset();
272
        m_stackHandler.resetLocation();
273
        m_watchHandler.resetLocation();
274
        m_threadsHandler.resetLocation();
275
        m_disassemblerAgent.resetLocation();
hjk's avatar
hjk committed
276
        DebuggerToolTipManager::resetLocation();
277 278
    }

279
public:
hjk's avatar
hjk committed
280
    DebuggerState state() const { return m_state; }
281
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
hjk's avatar
hjk committed
282

283 284
    DebuggerEngine *m_engine = nullptr; // Not owned.
    DebuggerEngine *m_masterEngine = nullptr; // Not owned
285
    QPointer<DebuggerRunTool> m_runTool;  // Not owned.
286

hjk's avatar
hjk committed
287
    // The current state.
288
    DebuggerState m_state = DebuggerNotReady;
289

290
//    Terminal m_terminal;
291
    ProcessHandle m_inferiorPid;
292 293 294 295 296 297 298

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

301
    DisassemblerAgent m_disassemblerAgent;
302
    MemoryAgentSet m_memoryAgents;
hjk's avatar
hjk committed
303
    QScopedPointer<LocationMark> m_locationMark;
304
    QTimer m_locationTimer;
305

306
    bool m_isStateDebugging = false;
307

308
    Utils::FileInProjectFinder m_fileFinder;
hjk's avatar
hjk committed
309
    QString m_qtNamespace;
310 311

    // Safety net to avoid infinite lookups.
hjk's avatar
hjk committed
312
    QSet<QString> m_lookupRequests; // FIXME: Integrate properly.
313
    QPointer<QWidget> m_alertBox;
314 315 316 317 318 319 320 321 322
};


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

323 324 325 326
DebuggerEngine::DebuggerEngine()
  : d(new DebuggerEnginePrivate(this))
{
}
327 328 329

DebuggerEngine::~DebuggerEngine()
{
330 331
    disconnect();
    delete d;
332 333
}

hjk's avatar
hjk committed
334
QString DebuggerEngine::stateName(int s)
335
{
hjk's avatar
hjk committed
336
#    define SN(x) case x: return QLatin1String(#x);
337 338 339 340 341 342 343 344
    switch (s) {
        SN(DebuggerNotReady)
        SN(EngineSetupRequested)
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
        SN(EngineRunFailed)
        SN(InferiorSetupRequested)
        SN(InferiorSetupFailed)
345
        SN(InferiorSetupOk)
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
hjk's avatar
hjk committed
362
    return QLatin1String("<unknown>");
363 364 365
#    undef SN
}

366
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
367
{
368
    showMessage(msg, StatusBar, timeout);
369
}
370

371 372 373 374 375 376 377 378 379 380 381 382
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));
}

383 384 385 386
void DebuggerEngine::doUpdateLocals(const UpdateParameters &)
{
}

387 388
ModulesHandler *DebuggerEngine::modulesHandler() const
{
389 390 391
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
392 393 394 395
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
396 397 398
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
399 400 401 402
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
403 404 405
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
406 407 408 409
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
410 411 412
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
413 414 415 416
}

WatchHandler *DebuggerEngine::watchHandler() const
{
417 418 419
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
420 421 422 423
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
424 425 426
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
427 428 429 430
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
431
   return modulesHandler()->model();
432 433 434 435
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
436
    return registerHandler()->model();
437 438 439 440
}

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

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
446
    return threadsHandler()->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
    return sourceFilesHandler()->model();
457 458
}

459
void DebuggerEngine::fetchMemory(MemoryAgent *, quint64 addr, quint64 length)
460 461 462 463 464
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

465
void DebuggerEngine::changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data)
hjk's avatar
hjk committed
466 467 468 469 470
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

hjk's avatar
hjk committed
471
void DebuggerEngine::setRegisterValue(const QString &name, const QString &value)
472
{
hjk's avatar
hjk committed
473
    Q_UNUSED(name);
474 475 476
    Q_UNUSED(value);
}

477
void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
478
{
479 480 481 482
    QTC_ASSERT(!d->m_runTool, notifyEngineSetupFailed(); return);
    d->m_runTool = runTool;
}

483
void DebuggerEngine::start()
484 485
{
    QTC_ASSERT(d->m_runTool, notifyEngineSetupFailed(); return);
486

487
    d->m_progress.setProgressRange(0, 1000);
488
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
489
        tr("Launching Debugger"), "Debugger.Launcher");
hjk's avatar
hjk committed
490
    connect(fp, &FutureProgress::canceled, this, &DebuggerEngine::quitDebugger);
491
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
492 493
    d->m_progress.reportStarted();

494
    const DebuggerRunParameters &rp = runParameters();
495
    d->m_inferiorPid = rp.attachPID.isValid() ? rp.attachPID : ProcessHandle();
496
    if (d->m_inferiorPid.isValid())
497
        d->m_runTool->runControl()->setApplicationProcessHandle(d->m_inferiorPid);
498

hjk's avatar
hjk committed
499
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
500

501 502
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
503
    d->m_progress.setProgressValue(200);
504

505 506 507 508 509 510 511 512 513 514 515 516
//    d->m_terminal.setup();
//    if (d->m_terminal.isUsable()) {
//        connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine);
//        });
//        connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine);
//        });
//        connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat);
//        });
//    }
517

hjk's avatar
hjk committed
518
    d->doSetupEngine();
519 520 521
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
}

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

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

532 533 534 535
    if (loc.canBeDisassembled()
            && ((hasCapability(OperateByInstructionCapability) && boolSetting(OperateByInstruction))
                || !loc.hasDebugInfo()) )
    {
536 537 538
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
539

540
    if (loc.fileName().isEmpty()) {
hjk's avatar
hjk committed
541
        showMessage("CANNOT GO TO THIS LOCATION");
542 543
        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

hjk's avatar
hjk committed
551
    editor->gotoLine(line, 0, !boolSetting(StationaryEditorWhileStepping));
552

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

hjk's avatar
hjk committed
556
    if (loc.needsMarker())
hjk's avatar
hjk committed
557
        d->m_locationMark.reset(new LocationMark(this, file, line));
558 559
}

560 561 562
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
hjk's avatar
hjk committed
563
    showMessage("HANDLE RUNCONTROL START FAILED");
564
    d->m_runTool.clear();
565
    d->m_progress.setProgressValue(900);
566 567
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
568 569
}

570 571
// Called from RunControl.
void DebuggerEngine::handleFinished()
572
{
hjk's avatar
hjk committed
573
    showMessage("HANDLE RUNCONTROL FINISHED");
574
    d->m_runTool.clear();
575 576
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
577 578 579 580 581 582
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

583
const DebuggerRunParameters &DebuggerEngine::runParameters() const
584
{
585
    return runTool()->runParameters();
586 587 588 589 590 591 592
}

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

hjk's avatar
hjk committed
593 594 595
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
596
    case DebuggerNotReady:
597
        return to == EngineSetupRequested;
598

hjk's avatar
hjk committed
599
    case EngineSetupRequested:
600 601
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
602 603 604
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
605
    case EngineSetupOk:
hjk's avatar
hjk committed
606
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
607

hjk's avatar
hjk committed
608
    case InferiorSetupRequested:
609
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
610
    case InferiorSetupFailed:
hjk's avatar
hjk committed
611
        return to == EngineShutdownRequested;
612 613
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
614 615

    case EngineRunRequested:
hjk's avatar
hjk committed
616
        return to == EngineRunFailed
617
            || to == InferiorRunRequested
hjk's avatar
hjk committed
618 619 620
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
621
    case EngineRunFailed:
622
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
623 624 625 626 627 628

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
629
        return to == InferiorStopRequested
630 631
            || to == InferiorStopOk       // A spontaneous stop.
            || to == InferiorShutdownOk;  // A spontaneous exit.
hjk's avatar
hjk committed
632 633 634 635 636

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
637
            || to == InferiorStopOk || to == InferiorShutdownOk;
638
    case InferiorStopFailed:
hjk's avatar
hjk committed
639
        return to == EngineShutdownRequested;
640 641

    case InferiorUnrunnable:
hjk's avatar
hjk committed
642 643 644 645 646
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
647
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
648
        return to == EngineShutdownRequested;
649

hjk's avatar
hjk committed
650
    case EngineShutdownRequested:
651
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
652 653 654 655 656 657
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
658
        return to == EngineSetupRequested; // Happens on restart.
659 660
    }

661
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
662 663 664
    return false;
}

665 666
void DebuggerEngine::setupSlaveEngine()
{
667
    QTC_CHECK(state() == DebuggerNotReady);
hjk's avatar
hjk committed
668
    d->doSetupEngine();
669 670 671 672
}

void DebuggerEnginePrivate::doSetupEngine()
{
hjk's avatar
hjk committed
673
    m_engine->setState(EngineSetupRequested);
hjk's avatar
hjk committed
674
    m_engine->showMessage("CALL: SETUP ENGINE");
675 676 677
    m_engine->setupEngine();
}

678
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
679
{
hjk's avatar
hjk committed
680
    showMessage("NOTE: ENGINE SETUP FAILED");
681
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
682
    setState(EngineSetupFailed);
683 684
    if (isMasterEngine() && runTool())
        runTool()->startFailed();
hjk's avatar
hjk committed
685
    setState(DebuggerFinished);
hjk's avatar
hjk committed
686 687
}

688
void DebuggerEngine::notifyEngineSetupOk()
689
{
hjk's avatar
hjk committed
690
    showMessage("NOTE: ENGINE SETUP OK");
691
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
692
    setState(EngineSetupOk);
693
    if (isMasterEngine() && runTool())
hjk's avatar
hjk committed
694
        runTool()->reportStarted();
695

696 697 698 699
    setState(InferiorSetupRequested);
    showMessage("CALL: SETUP INFERIOR");
    d->m_progress.setProgressValue(250);
    setupInferior();
hjk's avatar
hjk committed
700 701 702 703
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
704
    showMessage("NOTE: INFERIOR SETUP FAILED");
705
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
706
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
707
    setState(InferiorSetupFailed);
708
    if (isMasterEngine())
hjk's avatar
hjk committed
709
        d->doShutdownEngine();
hjk's avatar
hjk committed
710 711 712 713
}

void DebuggerEngine::notifyInferiorSetupOk()
{
714 715 716
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
717 718
    if (isMasterEngine())
        runTool()->aboutToNotifyInferiorSetupOk(); // FIXME: Remove, only used for Android.
hjk's avatar
hjk committed
719
    showMessage("NOTE: INFERIOR SETUP OK");
720 721 722
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
hjk's avatar
hjk committed
723
        d->doRunEngine();
hjk's avatar
hjk committed
724 725
}

726 727 728
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
729
    QTC_CHECK(state() == InferiorSetupOk);
hjk's avatar
hjk committed
730
    d->doRunEngine();
731 732
}

hjk's avatar
hjk committed
733 734
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
735
    m_engine->setState(EngineRunRequested);
hjk's avatar
hjk committed
736
    m_engine->showMessage("CALL: RUN ENGINE");
737
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
738 739 740
    m_engine->runEngine();
}

hjk's avatar
hjk committed
741
void DebuggerEngine::notifyEngineRunOkAndInferiorUnrunnable()
hjk's avatar
hjk committed
742
{
hjk's avatar
hjk committed
743
    showMessage("NOTE: INFERIOR UNRUNNABLE");
744 745
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
746
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
747
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
748 749 750 751 752
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
753
    showMessage("NOTE: ENGINE RUN FAILED");
754
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
755 756 757
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
758
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
759
    setState(EngineRunFailed);
760
    if (isMasterEngine())
hjk's avatar
hjk committed
761
        d->doShutdownEngine();
hjk's avatar
hjk committed
762 763 764 765
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
766
    showMessage("NOTE: ENGINE RUN AND INFERIOR RUN OK");
767 768
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
769
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
770
    showStatusMessage(tr("Running."));
hjk's avatar
hjk committed
771
    setState(InferiorRunOk);
hjk's avatar
hjk committed
772 773 774 775
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
776
    showMessage("NOTE: ENGINE RUN AND INFERIOR STOP OK");
777 778
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
779
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
780
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
781
    setState(InferiorStopOk);
hjk's avatar
hjk committed
782 783 784 785
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
786
    showMessage("NOTE: INFERIOR RUN REQUESTED");
787
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
788
    showStatusMessage(tr("Run requested..."));
hjk's avatar
hjk committed
789 790 791 792 793
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
794
    if (state() == InferiorRunOk) {
hjk's avatar
hjk committed
795
        showMessage("NOTE: INFERIOR RUN OK - REPEATED.");
796 797
        return;
    }
hjk's avatar
hjk committed
798
    showMessage("NOTE: INFERIOR RUN OK");
799
    showStatusMessage(tr("Running."));
800
    // Transition from StopRequested can happen in remotegdbadapter.
801
    QTC_ASSERT(state() == InferiorRunRequested
802
        || state() == InferiorStopOk
803
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
804 805 806 807 808
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
809
    showMessage("NOTE: INFERIOR RUN FAILED");
810
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
811 812
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
813
    if (isDying())
hjk's avatar
hjk committed
814
        d->doShutdownInferior();
hjk's avatar
hjk committed
815 816 817 818
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
819
    showMessage("NOTE: INFERIOR STOP OK");
hjk's avatar
hjk committed
820
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
821
    if (isDying()) {
hjk's avatar
hjk committed
822
        showMessage("NOTE: ... WHILE DYING. ");
hjk's avatar
hjk committed
823 824 825 826
        // Forward state to "StopOk" if needed.
        if (state() == InferiorStopRequested
                || state() == InferiorRunRequested
                || state() == InferiorRunOk) {
hjk's avatar
hjk committed
827
            showMessage("NOTE: ... FORWARDING TO 'STOP OK'. ");
hjk's avatar
hjk committed
828 829
            setState(InferiorStopOk);
        }
830
        if (state() == InferiorStopOk || state() == InferiorStopFailed)
hjk's avatar
hjk committed
831
            d->doShutdownInferior();
hjk's avatar
hjk committed
832
        showMessage("NOTE: ... IGNORING STOP MESSAGE");
hjk's avatar
hjk committed
833
        return;
hjk's avatar
hjk committed
834
    }
835
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
836
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
837
    setState(InferiorStopOk);
hjk's avatar
hjk committed
838 839
}

hjk's avatar
hjk committed
840
void DebuggerEngine::notifyInferiorSpontaneousStop()
841
{
hjk's avatar
hjk committed
842
    showMessage("NOTE: INFERIOR SPONTANEOUS STOP");
843
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
844
    showStatusMessage(tr("Stopped."));
845
    setState(InferiorStopOk);
hjk's avatar
hjk committed
846
    if (boolSetting(RaiseOnInterrupt))
847
        ICore::raiseWindow(Internal::mainWindow());