debuggerengine.cpp 41.4 KB
Newer Older
1 2 3 4 5 6 7 8
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11 12 13 14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15 16 17 18 19 20 21 22 23 24
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
con's avatar
con committed
25 26 27 28 29 30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
31 32 33 34 35 36
**
**************************************************************************/

#include "debuggerengine.h"

#include "debuggeractions.h"
37
#include "debuggercore.h"
38
#include "debuggerplugin.h"
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
41
#include "debuggertooltip.h"
42

43 44
#include "memoryagent.h"
#include "disassembleragent.h"
45 46 47 48 49 50 51 52 53
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

hjk's avatar
hjk committed
54
#include <coreplugin/icore.h>
55
#include <coreplugin/ifile.h>
hjk's avatar
hjk committed
56
#include <coreplugin/editormanager/editormanager.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/toolchain.h>
61
#include <projectexplorer/toolchaintype.h>
62

hjk's avatar
hjk committed
63
#include <texteditor/itexteditor.h>
64
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
65

66
#include <utils/environment.h>
67 68 69 70 71
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
72
#include <QtCore/QFutureInterface>
73

74
#include <QtGui/QMessageBox>
75

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

hjk's avatar
hjk committed
81 82 83 84 85 86 87
//#define DEBUG_STATE 1
#if DEBUG_STATE
#   define SDEBUG(s) qDebug() << s
#else
#   define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
88

89

90 91 92 93 94 95
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

96 97
namespace Debugger {

98 99
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
100 101
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
102 103 104 105 106 107 108
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
109
            << " processArgs=" << sp.processArgs
110 111 112 113 114 115 116
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
117
            << " useServerStartScript=" << sp.useServerStartScript
118 119 120 121 122
            << " serverStartScript=" << sp.serverStartScript
            << " toolchain=" << sp.toolChainType << '\n';
    return str;
}

123

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

// Used in "real" editors
class LocationMark : public TextEditor::BaseTextMark
{
public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
    {}

    QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
    void removedFromEditor() {}
};



146 147 148 149 150 151
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

152
class DebuggerEnginePrivate : public QObject
153
{
154 155
    Q_OBJECT

156 157 158 159 160 161
public:
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
      : m_engine(engine),
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
162
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
163
        m_targetState(DebuggerNotReady),
164
        m_modulesHandler(),
165
        m_registerHandler(),
166 167
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
168
        m_threadsHandler(),
169
        m_watchHandler(engine),
170
        m_isSlaveEngine(false),
171 172
        m_disassemblerAgent(engine),
        m_memoryAgent(engine)
173
    {
174
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
175
    }
176 177

    ~DebuggerEnginePrivate() {}
178

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

187 188
    void queueRunEngine()
    {
hjk's avatar
hjk committed
189 190 191 192 193
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

194 195
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
196 197 198 199 200
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

201 202
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
203 204 205 206 207
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

208 209
    void queueFinishDebugger()
    {
210 211 212 213
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
hjk's avatar
hjk committed
214 215 216
        QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
    }

217 218
    void raiseApplication()
    {
hjk's avatar
hjk committed
219
        QTC_ASSERT(m_runControl, return);
220 221 222
        m_runControl->bringApplicationToForeground(m_inferiorPid);
    }

223
    void scheduleResetLocation()
224
    {
225
        m_stackHandler.scheduleResetLocation();
226 227 228 229
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

230
    void resetLocation()
231 232 233
    {
        m_locationTimer.stop();
        m_locationMark.reset();
234 235
        m_stackHandler.resetLocation();
        m_disassemblerAgent.resetLocation();
236 237
    }

238
public:
hjk's avatar
hjk committed
239 240
    DebuggerState state() const { return m_state; }

241 242 243 244
    DebuggerEngine *m_engine; // Not owned.
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
245 246

    // The current state.
247 248
    DebuggerState m_state;

hjk's avatar
hjk committed
249 250 251 252 253 254
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

255 256 257 258 259 260 261 262
    qint64 m_inferiorPid;

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

265
    bool m_isSlaveEngine;
266 267
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
268 269
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
};


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

DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
{
}

DebuggerEngine::~DebuggerEngine()
{
286 287
    disconnect();
    delete d;
288 289
}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
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)
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

321
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
322
{
323
    showMessage(msg, StatusBar, timeout);
324
}
325

326 327 328 329 330 331
void DebuggerEngine::removeTooltip()
{
    watchHandler()->removeTooltip();
    hideDebuggerToolTip();
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
void DebuggerEngine::frameUp()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
}

void DebuggerEngine::frameDown()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMax(currentIndex - 1, 0));
}

ModulesHandler *DebuggerEngine::modulesHandler() const
{
    return &d->m_modulesHandler;
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
    return &d->m_registerHandler;
}

StackHandler *DebuggerEngine::stackHandler() const
{
    return &d->m_stackHandler;
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
    return &d->m_threadsHandler;
}

WatchHandler *DebuggerEngine::watchHandler() const
{
    return &d->m_watchHandler;
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
    return &d->m_sourceFilesHandler;
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
376 377 378 379
    QAbstractItemModel *model = d->m_modulesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
380 381 382 383
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
384 385 386 387
    QAbstractItemModel *model = d->m_registerHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
388 389 390 391
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
392 393 394 395
    QAbstractItemModel *model = d->m_stackHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
396 397 398 399
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
400 401 402 403
    QAbstractItemModel *model = d->m_threadsHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
404 405 406 407
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
408 409 410 411
    QAbstractItemModel *model = d->m_watchHandler.model(LocalsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
412 413 414 415
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
416 417 418 419
    QAbstractItemModel *model = d->m_watchHandler.model(WatchersWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
420 421 422 423
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
424 425 426 427
    QAbstractItemModel *model = d->m_watchHandler.model(ReturnWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
428 429 430 431
}

QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
432 433 434 435
    QAbstractItemModel *model = d->m_sourceFilesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
436 437
}

438
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
439 440 441 442 443 444 445 446 447 448 449 450 451 452
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
{
    Q_UNUSED(regnr);
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
453 454
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
455
    debuggerCore()->showMessage(msg, channel, timeout);
456 457 458 459 460
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
461 462 463 464
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
hjk's avatar
hjk committed
465
    if (!isSlaveEngine()) {
466
        d->m_progress.setProgressRange(0, 1000);
467 468 469
        Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
            ->addTask(d->m_progress.future(),
            tr("Launching"), _("Debugger.Launcher"));
470
        fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
471 472
        d->m_progress.reportStarted();
    }
473 474
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
475 476 477 478 479 480

    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;

481 482
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
483 484

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
485
    debuggerCore()->action(OperateByInstruction)
486 487
        ->setEnabled(engineCapabilities & DisassemblerCapability);

488 489
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
490 491
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
hjk's avatar
hjk committed
492
    setState(EngineSetupRequested);
493

494
    d->m_progress.setProgressValue(200);
hjk's avatar
hjk committed
495
    setupEngine();
496 497 498 499
}

void DebuggerEngine::resetLocation()
{
500 501
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
502 503
}

504
void DebuggerEngine::gotoLocation(const Location &loc)
505
{
506 507 508 509 510
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setTryMixed(true);
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
511 512 513 514
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

515
    d->resetLocation();
516

517 518
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
519 520
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
521
    IEditor *editor = 0;
hjk's avatar
hjk committed
522
    if (editors.isEmpty()) {
523 524 525 526 527 528 529 530
        editor = editorManager->openEditor(file, QString(),
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
531
    }
532
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
533 534 535
    if (texteditor)
        texteditor->gotoLine(line, 0);

536
    if (loc.needsMarker())
537
        d->m_locationMark.reset(new LocationMark(file, line));
538 539

    // FIXME: Breaks with split views.
540
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
541
        editorManager->activateEditor(editor);
542
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
543 544
}

545 546 547
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
548
    showMessage("HANDLE RUNCONTROL START FAILED");
549
    d->m_runControl = 0;
550
    d->m_progress.setProgressValue(900);
551 552
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
553 554
}

555 556
// Called from RunControl.
void DebuggerEngine::handleFinished()
557
{
558
    showMessage("HANDLE RUNCONTROL FINISHED");
559
    d->m_runControl = 0;
560 561 562 563
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
564
    d->m_progress.setProgressValue(1000);
565
    d->m_progress.reportFinished();
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
}

const DebuggerStartParameters &DebuggerEngine::startParameters() const
{
    return d->m_startParameters;
}

DebuggerStartParameters &DebuggerEngine::startParameters()
{
    return d->m_startParameters;
}


//////////////////////////////////////////////////////////////////////
//
// Dumpers. "Custom dumpers" are a library compiled against the current
// Qt containing functions to evaluate values of Qt classes
// (such as QString, taking pointers to their addresses).
// The library must be loaded into the debuggee.
//
//////////////////////////////////////////////////////////////////////

bool DebuggerEngine::qtDumperLibraryEnabled() const
{
hjk's avatar
hjk committed
590
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
591 592 593 594
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
hjk's avatar
hjk committed
595
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
596
        const QString customLocation =
hjk's avatar
hjk committed
597
            debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
598 599 600 601 602 603 604 605 606
        const QString location =
            tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
        return QStringList(location);
    }
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
607
    debuggerCore()->showQtDumperLibraryWarning(details);
608 609 610 611
}

QString DebuggerEngine::qtDumperLibraryName() const
{
hjk's avatar
hjk committed
612 613
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool())
        return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
614 615 616 617 618 619 620 621
    return startParameters().dumperLibrary;
}

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

hjk's avatar
hjk committed
622
DebuggerState DebuggerEngine::lastGoodState() const
623
{
hjk's avatar
hjk committed
624 625 626 627 628 629 630
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
632 633 634
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
635
    case DebuggerNotReady:
636
        return to == EngineSetupRequested;
637

hjk's avatar
hjk committed
638
    case EngineSetupRequested:
639 640
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
641 642 643
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
644
    case EngineSetupOk:
hjk's avatar
hjk committed
645
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
646

hjk's avatar
hjk committed
647 648
    case InferiorSetupRequested:
        return to == EngineRunRequested || to == InferiorSetupFailed;
hjk's avatar
hjk committed
649
    case InferiorSetupFailed:
hjk's avatar
hjk committed
650 651 652 653 654 655 656
        return to == EngineShutdownRequested;

    case EngineRunRequested:
        return to == InferiorRunRequested || to == InferiorStopRequested
            || to == InferiorUnrunnable || to == EngineRunFailed;

    case EngineRunFailed:
657
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
658 659 660 661 662 663 664 665 666 667 668 669 670

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
        return to == InferiorStopRequested || to == InferiorStopOk;

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
            || to == InferiorStopOk;
671
    case InferiorStopFailed:
hjk's avatar
hjk committed
672
        return to == EngineShutdownRequested;
673 674

    case InferiorUnrunnable:
hjk's avatar
hjk committed
675 676 677 678 679
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
680
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
681
        return to == EngineShutdownRequested;
682

hjk's avatar
hjk committed
683
    case EngineShutdownRequested:
684
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
685 686 687 688 689 690
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
691
        return to == EngineSetupRequested; // Happens on restart.
692 693
    }

694
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
695 696 697
    return false;
}

698
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
699
{
hjk's avatar
hjk committed
700
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
hjk's avatar
hjk committed
701
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
702
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
703 704
    QTC_ASSERT(d->m_runControl, return);
    d->m_runControl->startFailed();
hjk's avatar
hjk committed
705
    setState(DebuggerFinished);
hjk's avatar
hjk committed
706 707
}

708
void DebuggerEngine::notifyEngineSetupOk()
709
{
hjk's avatar
hjk committed
710
    showMessage(_("NOTE: ENGINE SETUP OK"));
hjk's avatar
hjk committed
711
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
712
    setState(EngineSetupOk);
hjk's avatar
hjk committed
713
    QTC_ASSERT(d->m_runControl, return);
hjk's avatar
hjk committed
714
    showMessage(_("QUEUE: SETUP INFERIOR"));
hjk's avatar
hjk committed
715
    QTimer::singleShot(0, d, SLOT(doSetupInferior()));
716 717
}

hjk's avatar
hjk committed
718
void DebuggerEnginePrivate::doSetupInferior()
719
{
720
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
hjk's avatar
hjk committed
721
    QTC_ASSERT(state() == EngineSetupOk, qDebug() << state());
722
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
723
    m_engine->setState(InferiorSetupRequested);
hjk's avatar
hjk committed
724 725 726 727 728
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
729
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
hjk's avatar
hjk committed
730
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
hjk's avatar
hjk committed
731
    setState(InferiorSetupFailed);
hjk's avatar
hjk committed
732
    d->queueShutdownEngine();
hjk's avatar
hjk committed
733 734 735 736
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
737
    showMessage(_("NOTE: INFERIOR SETUP OK"));
hjk's avatar
hjk committed
738
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
hjk's avatar
hjk committed
739
    d->queueRunEngine();
hjk's avatar
hjk committed
740 741 742 743
}

void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
744
    m_engine->showMessage(_("CALL: RUN ENGINE"));
hjk's avatar
hjk committed
745
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
746
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
747 748 749
    m_engine->runEngine();
}

hjk's avatar
hjk committed
750 751
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
752
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
753 754
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
755 756 757 758 759 760
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
761
    showMessage(_("NOTE: ENGINE RUN FAILED"));
hjk's avatar
hjk committed
762
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
763 764 765
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
766
    setState(EngineRunFailed);
767
    d->queueShutdownEngine();
hjk's avatar
hjk committed
768 769 770 771
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
772
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
773 774
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
775 776 777 778 779 780 781
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorRunRequested);
    notifyInferiorRunOk();
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
782
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
783 784
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
785 786 787 788 789 790 791
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorStopRequested);
    notifyInferiorStopOk();
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
792
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
hjk's avatar
hjk committed
793 794 795 796 797 798
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
799
    showMessage(_("NOTE: INFERIOR RUN OK"));
hjk's avatar
hjk committed
800 801 802 803 804 805
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
    setState(InferiorRunOk);
}

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

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

hjk's avatar
hjk committed
837
void DebuggerEngine::notifyInferiorSpontaneousStop()
838
{
hjk's avatar
hjk committed
839
    showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
hjk's avatar
hjk committed
840 841
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
    setState(InferiorStopOk);
842 843
}

hjk's avatar
hjk committed
844
void DebuggerEngine::notifyInferiorStopFailed()
845
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
hjk's avatar
hjk committed
847 848
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
    setState(InferiorStopFailed);
hjk's avatar
hjk committed
849
    d->queueShutdownEngine();
850 851 852 853
}

void DebuggerEnginePrivate::doInterruptInferior()
{
hjk's avatar
hjk committed
854 855
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
856
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
857 858 859
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
860 861
void DebuggerEnginePrivate::doShutdownInferior()
{
862
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
863
    resetLocation();
hjk's avatar
hjk committed
864
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
865
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
866 867 868 869 870 871
    m_engine->shutdownInferior();
}

void DebuggerEngine::notifyInferiorShutdownOk()
{
    showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
hjk's avatar
hjk committed
872
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
hjk's avatar
hjk committed
873 874
    d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
    setState(InferiorShutdownOk);
hjk's avatar
hjk committed
875
    d->queueShutdownEngine();
hjk's avatar
hjk committed
876 877 878 879 880
}

void DebuggerEngine::notifyInferiorShutdownFailed()
{
    showMessage(_("INFERIOR SHUTDOWN FAILED"));
Friedemann Kleint's avatar
Friedemann Kleint committed
881
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
882
    setState(InferiorShutdownFailed);
hjk's avatar
hjk committed
883
    d->queueShutdownEngine();
hjk's avatar
hjk committed
884 885 886 887
}

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
888
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
889 890 891 892 893 894 895 896 897 898 899
    // This can be issued in almost any state. The inferior could still be
    // alive as some previous notifications might have been bogus.
    d->m_targetState = DebuggerFinished;
    d->m_lastGoodState = d->m_state;
    if (state() == InferiorRunRequested) {
        // We asked for running, but did not see a response.
        // Assume the inferior is dead.
        // FIXME: Use timeout?
        setState(InferiorRunFailed);
        setState(InferiorStopOk);
    }
hjk's avatar
hjk committed
900
    d->queueShutdownInferior();
hjk's avatar
hjk committed
901 902 903 904
}

void DebuggerEnginePrivate::doShutdownEngine()
{
905
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
hjk's avatar
hjk committed
906
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
907
    m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
hjk's avatar
hjk committed
908 909 910 911 912
    m_engine->shutdownEngine();
}

void DebuggerEngine::notifyEngineShutdownOk()
{
hjk's avatar
hjk committed
913
    showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
hjk's avatar
hjk committed
914 915
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    setState(EngineShutdownOk);
916
    d->queueFinishDebugger();
hjk's avatar
hjk committed
917 918 919
}

void DebuggerEngine::notifyEngineShutdownFailed()
hjk's avatar
hjk committed
920
{
hjk's avatar
hjk committed
921
    showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
hjk's avatar
hjk committed
922 923
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    setState(EngineShutdownFailed);
924
    d->queueFinishDebugger();
hjk's avatar
hjk committed
925 926 927 928
}

void DebuggerEnginePrivate::doFinishDebugger()
{
hjk's avatar
hjk committed
929
    m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
930
    QTC_ASSERT(state() == DebuggerFinished, qDebug() << state());
931
    resetLocation();
932 933 934 935
    if (!m_engine->isSlaveEngine()) {
        QTC_ASSERT(m_runControl, return);
        m_runControl->debuggingFinished();
    }
hjk's avatar
hjk committed
936 937 938 939
}

void DebuggerEngine::notifyEngineIll()
{
hjk's avatar
hjk committed
940
    showMessage(_("NOTE: ENGINE ILL ******"));
hjk's avatar
hjk committed
941 942
    d->m_targetState = DebuggerFinished;
    d->m_lastGoodState = d->m_state;
hjk's avatar
hjk committed
943 944 945
    switch (state()) {
        case InferiorRunRequested:
        case InferiorRunOk:
946 947 948 949 950 951 952
            // The engine does not look overly ill right now, so attempt to
            // properly interrupt at least once. If that fails, we are on the
            // shutdown path due to d->m_targetState anyways.
            setState(InferiorStopRequested, true);
            showMessage(_("ATTEMPT TO INTERRUPT INFERIOR"));
            interruptInferior();
            break;
hjk's avatar
hjk committed
953 954
        case InferiorStopRequested:
        case InferiorStopOk:
955
            showMessage(_("FORWARDING STATE TO InferiorShutdownFailed"));