debuggerengine.cpp 54.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3 4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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
Eike Ziller's avatar
Eike Ziller committed
12 13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24
**
Eike Ziller's avatar
Eike Ziller committed
25 26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
30 31 32

#include "debuggerengine.h"

33
#include "debuggerinternalconstants.h"
34
#include "debuggeractions.h"
35
#include "debuggercore.h"
36
#include "debuggerruncontrol.h"
37
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
38
#include "debuggerstartparameters.h"
39
#include "debuggertooltipmanager.h"
40 41

#include "breakhandler.h"
David Schulz's avatar
David Schulz committed
42 43
#include "disassembleragent.h"
#include "memoryagent.h"
44 45 46 47
#include "moduleshandler.h"
#include "registerhandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
48
#include "terminal.h"
49 50
#include "threadshandler.h"
#include "watchhandler.h"
51
#include <debugger/shared/peutils.h>
52

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

hjk's avatar
hjk committed
60
#include <projectexplorer/projectexplorer.h>
61 62
#include <projectexplorer/taskhub.h>

63
#include <texteditor/texteditor.h>
64

65
#include <utils/fileinprojectfinder.h>
hjk's avatar
hjk committed
66 67 68
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
69

70
#include <qmljs/consolemanagerinterface.h>
71

72 73 74
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
75
#include <QDir>
76

hjk's avatar
hjk committed
77
using namespace Core;
78
using namespace Debugger::Internal;
hjk's avatar
hjk committed
79 80
using namespace ProjectExplorer;
using namespace TextEditor;
81

82 83 84 85
enum { debug = 0 };

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

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

92 93 94 95 96 97
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
98 99 100
// VariableManager Prefix
const char PrefixDebugExecutable[]  = "DebuggedExecutable";

101 102
namespace Debugger {

103 104
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
105 106
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
107 108 109 110 111 112 113
}

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

hjk's avatar
hjk committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138
namespace 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;
    m_from = frame.from;
}

139

140 141 142 143 144 145
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

146 147 148 149 150 151 152 153 154
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

155
class DebuggerEnginePrivate : public QObject
156
{
157 158
    Q_OBJECT

159
public:
160
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
161
      : m_engine(engine),
162
        m_masterEngine(0),
163 164 165
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
166
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
167
        m_targetState(DebuggerNotReady),
168
        m_remoteSetupState(RemoteSetupNone),
169
        m_inferiorPid(0),
170
        m_modulesHandler(engine),
171
        m_registerHandler(),
172 173
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
174
        m_threadsHandler(),
175
        m_watchHandler(engine),
176
        m_disassemblerAgent(engine),
177
        m_memoryAgent(engine),
178
        m_isStateDebugging(false)
179
    {
hjk's avatar
hjk committed
180 181 182 183
        connect(&m_locationTimer, &QTimer::timeout,
                this, &DebuggerEnginePrivate::resetLocation);
        connect(action(IntelFlavor), &Utils::SavedAction::valueChanged,
                this, &DebuggerEnginePrivate::reloadDisassembly);
184 185 186
        connect(action(OperateNativeMixed), &QAction::triggered,
                engine, &DebuggerEngine::reloadFullStack);

hjk's avatar
hjk committed
187
        Utils::globalMacroExpander()->registerFileVariables(PrefixDebugExecutable,
188
            tr("Debugged executable"),
Orgad Shaneh's avatar
Orgad Shaneh committed
189
            [this]() { return m_startParameters.executable; });
190
    }
191

192
public slots:
193
    void doSetupEngine();
hjk's avatar
hjk committed
194 195
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
196 197
    void doShutdownEngine();
    void doShutdownInferior();
198
    void doInterruptInferior();
hjk's avatar
hjk committed
199
    void doFinishDebugger();
hjk's avatar
hjk committed
200

201 202 203 204 205
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

206 207 208 209 210 211 212 213 214 215 216 217 218 219
    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()));
    }

220 221
    void queueRunEngine()
    {
hjk's avatar
hjk committed
222 223 224 225 226
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

227 228
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
229 230 231 232 233
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

234 235
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
236 237 238 239 240
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

241 242
    void queueFinishDebugger()
    {
243 244 245
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
246 247 248 249 250
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
251 252
    }

253 254
    void raiseApplication()
    {
255 256
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
257 258
    }

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

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

280
public:
hjk's avatar
hjk committed
281
    DebuggerState state() const { return m_state; }
282
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
283 284 285
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
286
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
287

288
    DebuggerEngine *m_engine; // Not owned.
289
    DebuggerEngine *m_masterEngine; // Not owned
290 291 292
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
293 294

    // The current state.
295 296
    DebuggerState m_state;

hjk's avatar
hjk committed
297 298 299 300 301 302
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

303 304 305
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

306
    Terminal m_terminal;
307 308 309 310 311 312 313 314
    qint64 m_inferiorPid;

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

317 318
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
319
    QScopedPointer<TextMark> m_locationMark;
320
    QTimer m_locationTimer;
321 322

    bool m_isStateDebugging;
323

324
    Utils::FileInProjectFinder m_fileFinder;
325 326 327 328 329 330 331 332 333
};


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

334 335
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
336
{}
337 338 339

DebuggerEngine::~DebuggerEngine()
{
340 341
    disconnect();
    delete d;
342 343
}

344 345 346 347 348 349 350 351 352 353 354
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)
355
        SN(InferiorSetupOk)
356 357 358 359 360 361 362 363
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
364
        SN(InferiorExitOk)
365 366 367 368 369 370 371 372 373 374 375 376
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

377
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
378
{
379
    showMessage(msg, StatusBar, timeout);
380
}
381

382 383 384 385 386 387 388 389 390 391 392 393
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));
}

394 395 396 397 398
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

399 400
ModulesHandler *DebuggerEngine::modulesHandler() const
{
401 402 403
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
404 405 406 407
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
408 409 410
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
411 412 413 414
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
415 416 417
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
418 419 420 421
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
422 423 424
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
425 426 427 428
}

WatchHandler *DebuggerEngine::watchHandler() const
{
429 430 431
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
432 433 434 435
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
436 437 438
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
439 440 441 442
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
443
   return modulesHandler()->model();
444 445 446 447
}

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

QAbstractItemModel *DebuggerEngine::stackModel() const
{
453
    return stackHandler()->model();
454 455 456 457
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
458
    return threadsHandler()->model();
459 460
}

hjk's avatar
hjk committed
461 462 463
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
464 465
}

466 467
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
468
    return sourceFilesHandler()->model();
469 470
}

471
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
472 473 474 475 476 477
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
478 479 480 481 482 483 484
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

hjk's avatar
hjk committed
485
void DebuggerEngine::setRegisterValue(const QByteArray &name, const QString &value)
486
{
hjk's avatar
hjk committed
487
    Q_UNUSED(name);
488 489 490 491 492
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
493 494 495 496
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
497 498
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
499
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
500
    if (channel == ConsoleOutput && consoleManager)
501
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
502

503
    Internal::showMessage(msg, channel, timeout);
504 505 506 507 508 509 510 511 512 513 514 515 516
    if (d->m_runControl) {
        switch (channel) {
            case AppOutput:
                d->m_runControl->appendMessage(msg, Utils::StdOutFormatSameLine);
                break;
            case AppError:
                d->m_runControl->appendMessage(msg, Utils::StdErrFormatSameLine);
                break;
            case AppStuff:
                d->m_runControl->appendMessage(msg, Utils::DebugFormat);
                break;
        }
    } else {
517
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
518
    }
519 520 521 522
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
523 524
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
525

526
    d->m_progress.setProgressRange(0, 1000);
527
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
528
        tr("Launching Debugger"), "Debugger.Launcher");
hjk's avatar
hjk committed
529
    connect(fp, &FutureProgress::canceled, this, &DebuggerEngine::quitDebugger);
530
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
531 532
    d->m_progress.reportStarted();

533 534 535 536
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
537 538
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
539

540 541
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
542

hjk's avatar
hjk committed
543
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
544

545 546
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
547 548
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
549
    d->m_progress.setProgressValue(200);
550 551 552 553 554 555 556 557 558 559 560 561 562 563

    d->m_terminal.setup();
    if (d->m_terminal.isUsable()) {
        connect(&d->m_terminal, &Terminal::stdOutReady, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::StdOutFormatSameLine);
        });
        connect(&d->m_terminal, &Terminal::stdErrReady, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::StdErrFormatSameLine);
        });
        connect(&d->m_terminal, &Terminal::error, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::ErrorMessageFormat);
        });
    }

564
    d->queueSetupEngine();
565 566 567 568
}

void DebuggerEngine::resetLocation()
{
569 570
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
571 572
}

573
void DebuggerEngine::gotoLocation(const Location &loc)
574
{
Aurindam Jana's avatar
Aurindam Jana committed
575 576
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
577
    if ((hasCapability(OperateByInstructionCapability) &&
hjk's avatar
hjk committed
578
            boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
579 580 581
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
582 583 584 585 586
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


587
    const QString file = QDir::cleanPath(loc.fileName());
588
    const int line = loc.lineNumber();
589
    bool newEditor = false;
590
    IEditor *editor = EditorManager::openEditor(file, Id(),
591 592
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
593

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

596 597
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
598

599
    if (loc.needsMarker()) {
600
        d->m_locationMark.reset(new TextMark(file, line));
601
        d->m_locationMark->setIcon(Internal::locationMarkIcon());
602
        d->m_locationMark->setPriority(TextMark::HighPriority);
603
    }
604 605

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

608 609 610
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
611
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
612
    d->m_runControl = 0;
613
    d->m_progress.setProgressValue(900);
614 615
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
616 617
}

618 619
// Called from RunControl.
void DebuggerEngine::handleFinished()
620
{
621
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
622
    d->m_runControl = 0;
623 624
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
    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
646
DebuggerState DebuggerEngine::lastGoodState() const
647
{
hjk's avatar
hjk committed
648 649 650 651 652 653 654
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
656 657 658
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
659
    case DebuggerNotReady:
660
        return to == EngineSetupRequested;
661

hjk's avatar
hjk committed
662
    case EngineSetupRequested:
663 664
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
665 666 667
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
668
    case EngineSetupOk:
hjk's avatar
hjk committed
669
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
670

hjk's avatar
hjk committed
671
    case InferiorSetupRequested:
672
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
673
    case InferiorSetupFailed:
hjk's avatar
hjk committed
674
        return to == EngineShutdownRequested;
675 676
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
677 678

    case EngineRunRequested:
hjk's avatar
hjk committed
679
        return to == EngineRunFailed
680
            || to == InferiorRunRequested
hjk's avatar
hjk committed
681 682 683
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
684
    case EngineRunFailed:
685
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
686 687 688 689 690 691

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
692 693 694
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
695 696 697 698 699

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
Orgad Shaneh's avatar
Orgad Shaneh committed
700
            || to == InferiorStopOk || to == InferiorExitOk;
701
    case InferiorStopFailed:
hjk's avatar
hjk committed
702
        return to == EngineShutdownRequested;
703

704 705 706
    case InferiorExitOk:
        return to == InferiorShutdownOk;

707
    case InferiorUnrunnable:
hjk's avatar
hjk committed
708 709 710 711 712
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
713
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
714
        return to == EngineShutdownRequested;
715

hjk's avatar
hjk committed
716
    case EngineShutdownRequested:
717
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
718 719 720 721 722 723
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
724
        return to == EngineSetupRequested; // Happens on restart.
725 726
    }

727
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
728 729 730
    return false;
}

731 732
void DebuggerEngine::setupSlaveEngine()
{
733
    QTC_CHECK(state() == DebuggerNotReady);
734 735 736 737 738 739 740
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
741
    m_engine->validateExecutable(&m_startParameters);
742 743 744
    m_engine->setupEngine();
}

745
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
746
{
hjk's avatar
hjk committed
747
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
748 749 750 751 752 753 754
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

755
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
756
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
757
    if (isMasterEngine() && runControl())
758
        runControl()->startFailed();
hjk's avatar
hjk committed
759
    setState(DebuggerFinished);
hjk's avatar
hjk committed
760 761
}

762
void DebuggerEngine::notifyEngineSetupOk()
763
{
hjk's avatar
hjk committed
764
    showMessage(_("NOTE: ENGINE SETUP OK"));
765 766 767 768
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

769
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
770
    setState(EngineSetupOk);
hjk's avatar
hjk committed
771
    showMessage(_("QUEUE: SETUP INFERIOR"));
772
    if (isMasterEngine())
773 774 775 776 777
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
778
    QTC_CHECK(state() == EngineSetupOk);
779
    d->queueSetupInferior();
780 781
}

hjk's avatar
hjk committed
782
void DebuggerEnginePrivate::doSetupInferior()
783
{
784
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
785
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
786
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
787 788 789 790 791
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
792
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
793
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
794
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
795
    setState(InferiorSetupFailed);
796 797
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
798 799 800 801
}

void DebuggerEngine::notifyInferiorSetupOk()
{
802 803 804
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
805
    aboutToNotifyInferiorSetupOk();
hjk's avatar
hjk committed
806
    showMessage(_("NOTE: INFERIOR SETUP OK"));
807 808 809 810
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
811 812
}

813 814 815
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
816
    QTC_CHECK(state() == InferiorSetupOk);
817 818 819
    d->queueRunEngine();
}

hjk's avatar
hjk committed
820 821
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
822
    m_engine->showMessage(_("CALL: RUN ENGINE"));
823
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
824
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
825 826 827
    m_engine->runEngine();
}

hjk's avatar
hjk committed
828
void DebuggerEngine::notifyEngineRunOkAndInferiorUnrunnable()
hjk's avatar
hjk committed
829
{
hjk's avatar
hjk committed
830
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
831 832
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
833
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
834
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
835 836 837 838 839
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
840
    showMessage(_("NOTE: ENGINE RUN FAILED"));
841
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
842 843 844
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
845
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
846
    setState(EngineRunFailed);
847 848
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
849