debuggerengine.cpp 55 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
Eike Ziller's avatar
Eike Ziller committed
13 14
** conditions see http://www.qt.io/licensing.  For further information
** 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 25 26
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
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
    {
180
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
hjk's avatar
hjk committed
181
        connect(action(IntelFlavor), SIGNAL(valueChanged(QVariant)),
182
                SLOT(reloadDisassembly()));
183

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

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

198 199 200 201 202
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

203 204 205 206 207 208 209 210 211 212 213 214 215 216
    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()));
    }

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

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

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

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

250 251
    void raiseApplication()
    {
252 253
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
254 255
    }

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

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

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

285
    DebuggerEngine *m_engine; // Not owned.
286
    DebuggerEngine *m_masterEngine; // Not owned
287 288 289
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
290 291

    // The current state.
292 293
    DebuggerState m_state;

hjk's avatar
hjk committed
294 295 296 297 298 299
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

300 301 302
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

303
    Terminal m_terminal;
304 305 306 307 308 309 310 311
    qint64 m_inferiorPid;

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

314 315
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
316
    QScopedPointer<TextMark> m_locationMark;
317
    QTimer m_locationTimer;
318 319

    bool m_isStateDebugging;
320

321
    Utils::FileInProjectFinder m_fileFinder;
322 323 324 325 326 327 328 329 330
};


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

331 332
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
333
{}
334 335 336

DebuggerEngine::~DebuggerEngine()
{
337 338
    disconnect();
    delete d;
339 340
}

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

374
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
375
{
376
    showMessage(msg, StatusBar, timeout);
377
}
378

379 380 381 382 383 384 385 386 387 388 389 390
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));
}

391 392 393 394 395
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

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

RegisterHandler *DebuggerEngine::registerHandler() const
{
405 406 407
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
408 409 410 411
}

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

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
419 420 421
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
422 423 424 425
}

WatchHandler *DebuggerEngine::watchHandler() const
{
426 427 428
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
429 430 431 432
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
433 434 435
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
436 437 438 439
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
440
   return modulesHandler()->model();
441 442 443 444
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
445
    return registerHandler()->model();
446 447 448 449
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
450
    return stackHandler()->model();
451 452 453 454
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
455
    return threadsHandler()->model();
456 457
}

hjk's avatar
hjk committed
458 459 460
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
461 462
}

463 464
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
465
    return sourceFilesHandler()->model();
466 467
}

468
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
469 470 471 472 473 474
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

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

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

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

500
    Internal::showMessage(msg, channel, timeout);
501 502 503 504 505 506 507 508 509 510 511 512 513
    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 {
514
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
515
    }
516 517 518 519
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
520 521
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
522

523
    d->m_progress.setProgressRange(0, 1000);
524
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
525
        tr("Launching Debugger"), "Debugger.Launcher");
526
    connect(fp, SIGNAL(canceled()), this, SLOT(quitDebugger()));
527
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
528 529
    d->m_progress.reportStarted();

530 531 532 533
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
534 535
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
536

537 538
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
539

hjk's avatar
hjk committed
540
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
541

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

    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);
        });
    }

561
    d->queueSetupEngine();
562 563 564 565
}

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

570
void DebuggerEngine::gotoLocation(const Location &loc)
571
{
Aurindam Jana's avatar
Aurindam Jana committed
572 573
     d->resetLocation();

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


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

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

593 594
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
595

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

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

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

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

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

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

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

hjk's avatar
hjk committed
668
    case InferiorSetupRequested:
669
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
670
    case InferiorSetupFailed:
hjk's avatar
hjk committed
671
        return to == EngineShutdownRequested;
672 673
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
674 675

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

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

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
Orgad Shaneh's avatar
Orgad Shaneh committed
697
            || to == InferiorStopOk || to == InferiorExitOk;
698
    case InferiorStopFailed:
hjk's avatar
hjk committed
699
        return to == EngineShutdownRequested;
700

701 702 703
    case InferiorExitOk:
        return to == InferiorShutdownOk;

704
    case InferiorUnrunnable:
hjk's avatar
hjk committed
705 706 707 708 709
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
710
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
711
        return to == EngineShutdownRequested;
712

hjk's avatar
hjk committed
713
    case EngineShutdownRequested:
714
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
715 716 717 718 719 720
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
721
        return to == EngineSetupRequested; // Happens on restart.
722 723
    }

724
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
725 726 727
    return false;
}

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

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

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

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

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

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

void DebuggerEngine::setupSlaveInferior()
{
775
    QTC_CHECK(state() == EngineSetupOk);
776
    d->queueSetupInferior();
777 778
}

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

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

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

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

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

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

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