debuggerengine.cpp 41.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "debuggerengine.h"

#include "debuggeractions.h"
33
#include "debuggercore.h"
34
#include "debuggerplugin.h"
35
#include "debuggerrunner.h"
36
#include "debuggerstringutils.h"
37
#include "debuggertooltip.h"
38

39 40
#include "memoryagent.h"
#include "disassembleragent.h"
41 42 43 44 45 46 47 48 49
#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
50
#include <coreplugin/icore.h>
51
#include <coreplugin/ifile.h>
52 53
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
54

hjk's avatar
hjk committed
55
#include <projectexplorer/toolchain.h>
56
#include <projectexplorer/toolchaintype.h>
57

hjk's avatar
hjk committed
58
#include <texteditor/itexteditor.h>
59 60
#include <texteditor/basetexteditor.h>
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
61

62
#include <utils/environment.h>
63 64 65 66 67
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
68
#include <QtCore/QFutureInterface>
69

70
#include <QtGui/QMessageBox>
71

hjk's avatar
hjk committed
72
using namespace Core;
73
using namespace Debugger::Internal;
hjk's avatar
hjk committed
74 75
using namespace ProjectExplorer;
using namespace TextEditor;
76

hjk's avatar
hjk committed
77 78 79 80 81 82 83
//#define DEBUG_STATE 1
#if DEBUG_STATE
#   define SDEBUG(s) qDebug() << s
#else
#   define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
84

85

86 87 88 89 90 91
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

92 93
namespace Debugger {

94
DebuggerStartParameters::DebuggerStartParameters() :
95
    isSnapshot(false),
96 97
    attachPID(-1),
    useTerminal(false),
98
    qmlServerAddress("127.0.0.1"),
99
    qmlServerPort(0),
hjk's avatar
hjk committed
100
    useServerStartScript(false),
101
    connParams(SshConnectionParameters::NoProxy),
102
    toolChainType(ToolChain_UNKNOWN),
103 104
    startMode(NoStartMode),
    executableUid(0)
105 106
{}

hjk's avatar
hjk committed
107
QString DebuggerStartParameters::toolChainName() const
108
{
hjk's avatar
hjk committed
109
    return ToolChain::toolChainName(ProjectExplorer::ToolChainType(toolChainType));
110 111 112 113
}

QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
114 115
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
116 117 118 119 120 121 122
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
123
            << " processArgs=" << sp.processArgs
124 125 126 127 128 129 130
            << " 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
131
            << " useServerStartScript=" << sp.useServerStartScript
132 133 134 135 136 137 138 139 140 141
            << " serverStartScript=" << sp.serverStartScript
            << " toolchain=" << sp.toolChainType << '\n';
    return str;
}

const char *DebuggerEngine::stateName(int s)
{
#    define SN(x) case x: return #x;
    switch (s) {
        SN(DebuggerNotReady)
hjk's avatar
hjk committed
142
        SN(EngineSetupRequested)
143 144
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
hjk's avatar
hjk committed
145 146
        SN(EngineRunFailed)
        SN(InferiorSetupRequested)
hjk's avatar
hjk committed
147
        SN(InferiorSetupFailed)
hjk's avatar
hjk committed
148 149 150 151
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
152
        SN(InferiorUnrunnable)
hjk's avatar
hjk committed
153 154
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
155
        SN(InferiorStopFailed)
hjk's avatar
hjk committed
156 157
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
158
        SN(InferiorShutdownFailed)
hjk's avatar
hjk committed
159 160 161 162
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
163 164 165 166 167
    }
    return "<unknown>";
#    undef SN
}

168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
///////////////////////////////////////////////////////////////////////
//
// 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() {}
};



191 192 193 194 195 196
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

197
class DebuggerEnginePrivate : public QObject
198
{
199 200
    Q_OBJECT

201 202 203 204 205 206
public:
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
      : m_engine(engine),
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
207
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
208
        m_targetState(DebuggerNotReady),
209
        m_modulesHandler(),
210
        m_registerHandler(),
211 212
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
213
        m_threadsHandler(),
214
        m_watchHandler(engine),
215
        m_isSlaveEngine(false),
216 217
        m_disassemblerAgent(engine),
        m_memoryAgent(engine)
218 219 220
    {
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(doRemoveLocationMark()));
    }
221 222

    ~DebuggerEnginePrivate() {}
223

224
public slots:
hjk's avatar
hjk committed
225 226
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
227 228
    void doShutdownEngine();
    void doShutdownInferior();
229
    void doInterruptInferior();
hjk's avatar
hjk committed
230
    void doFinishDebugger();
hjk's avatar
hjk committed
231

232 233
    void queueRunEngine()
    {
hjk's avatar
hjk committed
234 235 236 237 238
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

239 240
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
241 242 243 244 245
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

246 247
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
248 249 250 251 252
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

253 254
    void queueFinishDebugger()
    {
255 256 257 258
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
hjk's avatar
hjk committed
259 260 261
        QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
    }

262 263
    void raiseApplication()
    {
hjk's avatar
hjk committed
264
        QTC_ASSERT(m_runControl, return);
265 266 267
        m_runControl->bringApplicationToForeground(m_inferiorPid);
    }

268 269 270 271 272 273 274 275 276 277 278 279
    void removeLocationMark()
    {
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

    void doRemoveLocationMark()
    {
        m_locationTimer.stop();
        m_locationMark.reset();
    }

280
public:
hjk's avatar
hjk committed
281 282
    DebuggerState state() const { return m_state; }

283 284 285 286
    DebuggerEngine *m_engine; // Not owned.
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
287 288

    // The current state.
289 290
    DebuggerState m_state;

hjk's avatar
hjk committed
291 292 293 294 295 296
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

297 298 299 300 301 302 303 304
    qint64 m_inferiorPid;

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

307
    bool m_isSlaveEngine;
308 309
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
310 311
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
};


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

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

DebuggerEngine::~DebuggerEngine()
{
328 329
    disconnect();
    delete d;
330 331
}

332
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
333
{
334
    showMessage(msg, StatusBar, timeout);
335
}
336

337 338 339 340 341 342
void DebuggerEngine::removeTooltip()
{
    watchHandler()->removeTooltip();
    hideDebuggerToolTip();
}

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 376 377 378 379 380 381 382 383 384 385 386
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
387 388 389 390
    QAbstractItemModel *model = d->m_modulesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
391 392 393 394
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
395 396 397 398
    QAbstractItemModel *model = d->m_registerHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
399 400 401 402
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
403 404 405 406
    QAbstractItemModel *model = d->m_stackHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
407 408 409 410
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
411 412 413 414
    QAbstractItemModel *model = d->m_threadsHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
415 416 417 418
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
419 420 421 422
    QAbstractItemModel *model = d->m_watchHandler.model(LocalsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
423 424 425 426
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
427 428 429 430
    QAbstractItemModel *model = d->m_watchHandler.model(WatchersWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
431 432 433 434
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
435 436 437 438
    QAbstractItemModel *model = d->m_watchHandler.model(ReturnWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
439 440 441 442
}

QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
443 444 445 446
    QAbstractItemModel *model = d->m_sourceFilesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
447 448
}

449
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
450 451 452 453 454 455 456 457 458 459 460 461 462 463
        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
{
464 465
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
466
    debuggerCore()->showMessage(msg, channel, timeout);
467 468 469 470 471
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
472 473 474 475
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
hjk's avatar
hjk committed
476
    if (!isSlaveEngine()) {
477
        d->m_progress.setProgressRange(0, 1000);
478 479 480
        Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
            ->addTask(d->m_progress.future(),
            tr("Launching"), _("Debugger.Launcher"));
481
        fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
482 483
        d->m_progress.reportStarted();
    }
484 485
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
486 487 488 489 490 491

    d->m_runControl = runControl;

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

492 493
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
494 495

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
496
    debuggerCore()->action(OperateByInstruction)
497 498
        ->setEnabled(engineCapabilities & DisassemblerCapability);

499 500
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
501 502
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
hjk's avatar
hjk committed
503
    setState(EngineSetupRequested);
504

505
    d->m_progress.setProgressValue(200);
hjk's avatar
hjk committed
506
    setupEngine();
507 508 509 510
}

void DebuggerEngine::resetLocation()
{
511
    d->m_disassemblerAgent.resetLocation();
512
    d->removeLocationMark();
513 514
}

515
void DebuggerEngine::gotoLocation(const QString &file, int line, bool setMarker)
516
{
517 518 519 520 521 522
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

    d->doRemoveLocationMark();

hjk's avatar
hjk committed
523 524 525 526 527 528 529 530 531 532 533
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
    if (editors.isEmpty()) {
        editors.append(editorManager->openEditor(file, QString(),
            EditorManager::IgnoreNavigationHistory));
        editors.back()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
    }
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editors.back());
    if (texteditor)
        texteditor->gotoLine(line, 0);

534 535
    if (setMarker)
        d->m_locationMark.reset(new LocationMark(file, line));
536 537 538 539
}

void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{
540
    if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable())
541
        d->m_disassemblerAgent.setFrame(frame, true, setMarker);
542
    else
543
        gotoLocation(frame.file, frame.line, setMarker);
544 545
}

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

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

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
591
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
592 593 594 595
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
hjk's avatar
hjk committed
596
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
597
        const QString customLocation =
hjk's avatar
hjk committed
598
            debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
599 600 601 602 603 604 605 606 607
        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)
{
608
    debuggerCore()->showQtDumperLibraryWarning(details);
609 610 611 612
}

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

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

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

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

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

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

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

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

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

    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;
672
    case InferiorStopFailed:
hjk's avatar
hjk committed
673
        return to == EngineShutdownRequested;
674 675

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
817 818
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
819
    if (isDying()) {
hjk's avatar
hjk committed
820 821 822 823 824 825 826 827 828 829 830 831 832
        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
833
    }
hjk's avatar
hjk committed
834 835
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
    setState(InferiorStopOk);
hjk's avatar
hjk committed
836 837
}

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

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

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

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

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

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

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
889
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
890 891 892 893 894 895 896 897 898 899 900
    // 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
901
    d->queueShutdownInferior();
hjk's avatar
hjk committed
902 903 904 905
}

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

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

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

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

void DebuggerEngine::notifyEngineIll()
{
hjk's avatar
hjk committed
941
    showMessage(_("NOTE: ENGINE ILL ******"));
hjk's avatar
hjk committed
942 943
    d->m_targetState = DebuggerFinished;
    d->m_lastGoodState = d->m_state;
hjk's avatar
hjk committed
944 945 946
    switch (state()) {
        case InferiorRunRequested:
        case InferiorRunOk:
947 948 949 950 951 952 953
            // 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
954 955
        case InferiorStopRequested:
        case InferiorStopOk:
956
            showMessage(_("FORWARDING STATE TO InferiorShutdownFailed"));
hjk's avatar
hjk committed
957
            setState(InferiorShutdownFailed, true);