debuggerengine.cpp 55 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();

577 578 579 580
    if (loc.canBeDisassembled()
            && ((hasCapability(OperateByInstructionCapability) && boolSetting(OperateByInstruction))
                || !loc.hasDebugInfo()) )
    {
581 582 583
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
584

585 586 587 588
    if (loc.fileName().isEmpty()) {
        showMessage(QLatin1String("CANNOT GO TO THIS LOCATION"));
        return;
    }
589
    const QString file = QDir::cleanPath(loc.fileName());
590
    const int line = loc.lineNumber();
591
    bool newEditor = false;
592
    IEditor *editor = EditorManager::openEditor(file, Id(),
593 594
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
595

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

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

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

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

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

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

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

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

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

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

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

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

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

706 707 708
    case InferiorExitOk:
        return to == InferiorShutdownOk;

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

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

    case DebuggerFinished:
726
        return to == EngineSetupRequested; // Happens on restart.
727 728
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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