debuggerengine.cpp 46.2 KB
Newer Older
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.nokia.com.
30 31 32 33 34
**
**************************************************************************/

#include "debuggerengine.h"

35
#include "debuggerinternalconstants.h"
36
#include "debuggeractions.h"
37
#include "debuggercore.h"
38
#include "debuggerplugin.h"
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
41
#include "debuggerstartparameters.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 60

#include <texteditor/itexteditor.h>
61
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
62

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

77 78 79 80
enum { debug = 0 };

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

82

83 84 85 86 87 88
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

89 90
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
91 92 93 94 95 96 97 98 99 100 101
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;
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
113
            << " processArgs=" << sp.processArgs
114 115 116 117 118 119 120
            << " 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
121
            << " useServerStartScript=" << sp.useServerStartScript
122
            << " serverStartScript=" << sp.serverStartScript
123
            << " abi=" << sp.toolChainAbi.toString() << '\n';
124 125 126
    return str;
}

127

128 129 130 131 132 133
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

134
class DebuggerEnginePrivate : public QObject
135
{
136 137
    Q_OBJECT

138
public:
139 140 141
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
            const DebuggerStartParameters &sp)
142
      : m_engine(engine),
143
        m_masterEngine(masterEngine),
144 145 146
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
147
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
148
        m_targetState(DebuggerNotReady),
149
        m_inferiorPid(0),
150
        m_modulesHandler(),
151
        m_registerHandler(),
152 153
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
154
        m_threadsHandler(),
155
        m_watchHandler(engine),
156
        m_disassemblerAgent(engine),
157 158
        m_memoryAgent(engine),
        m_isStateDebugging(false)
159
    {
160
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
con's avatar
con committed
161 162
        if (sp.toolChainAbi.os() == ProjectExplorer::Abi::MacOS)
            m_disassemblerAgent.setTryMixed(false);
163
    }
164 165

    ~DebuggerEnginePrivate() {}
166

167
public slots:
168
    void doSetupEngine();
hjk's avatar
hjk committed
169 170
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
171 172
    void doShutdownEngine();
    void doShutdownInferior();
173
    void doInterruptInferior();
hjk's avatar
hjk committed
174
    void doFinishDebugger();
hjk's avatar
hjk committed
175

176 177 178 179 180 181 182 183 184 185 186 187 188 189
    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()));
    }

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

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

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

211 212
    void queueFinishDebugger()
    {
213 214 215
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
216 217 218 219 220
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
221 222
    }

223 224
    void raiseApplication()
    {
225 226
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
227 228
    }

229
    void scheduleResetLocation()
230
    {
231
        m_stackHandler.scheduleResetLocation();
232
        m_threadsHandler.scheduleResetLocation();
233
        m_disassemblerAgent.scheduleResetLocation();
234 235 236 237
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

238
    void resetLocation()
239 240 241
    {
        m_locationTimer.stop();
        m_locationMark.reset();
242
        m_stackHandler.resetLocation();
243
        m_threadsHandler.resetLocation();
244
        m_disassemblerAgent.resetLocation();
245 246
    }

247
public:
hjk's avatar
hjk committed
248
    DebuggerState state() const { return m_state; }
249 250 251
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
252

253
    DebuggerEngine *m_engine; // Not owned.
254
    DebuggerEngine *m_masterEngine; // Not owned
255 256 257
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
258 259

    // The current state.
260 261
    DebuggerState m_state;

hjk's avatar
hjk committed
262 263 264 265 266 267
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

268 269 270 271 272 273 274 275
    qint64 m_inferiorPid;

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

278 279
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
280 281
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
282 283

    bool m_isStateDebugging;
284 285 286 287 288 289 290 291 292
};


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

293 294 295
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
296
{
297
    d->m_inferiorPid = 0;
298 299 300 301
}

DebuggerEngine::~DebuggerEngine()
{
302 303
    disconnect();
    delete d;
304 305
}

306 307 308 309 310 311 312 313 314 315 316
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)
317
        SN(InferiorSetupOk)
318 319 320 321 322 323 324 325
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
326
        SN(InferiorExitOk)
327 328 329 330 331 332 333 334 335 336 337 338
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

339
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
340
{
341
    showMessage(msg, StatusBar, timeout);
342
}
343

344 345 346 347 348 349 350 351 352 353 354 355 356 357
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
{
358 359 360
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
361 362 363 364
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
365 366 367
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
368 369 370 371
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
372 373 374 375
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
376 377 378 379
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
380 381 382
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
383 384 385 386
}

WatchHandler *DebuggerEngine::watchHandler() const
{
387 388 389
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
390 391 392 393
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
394 395 396
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
397 398 399 400
}

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

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

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

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

QAbstractItemModel *DebuggerEngine::localsModel() const
{
433
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
434 435 436
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
437 438 439 440
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
441
    QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
442 443 444
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
445 446 447 448
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
449
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
450 451 452
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
453 454
}

455 456 457 458 459 460 461 462
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

463 464
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
465
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
466 467 468
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
469 470
}

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

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

485 486 487 488 489 490 491 492
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
{
493 494 495 496
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
497 498
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
499
    debuggerCore()->showMessage(msg, channel, timeout);
500 501 502 503 504
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
505 506 507 508
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
509 510
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
511

512 513 514 515 516 517 518
    d->m_progress.setProgressRange(0, 1000);
    Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
    fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
    d->m_progress.reportStarted();

519 520 521 522
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
523 524
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
525

526 527
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
528 529

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
530
    debuggerCore()->action(OperateByInstruction)
531 532
        ->setEnabled(engineCapabilities & DisassemblerCapability);

533 534
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
535 536
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
537
    d->m_progress.setProgressValue(200);
538
    d->queueSetupEngine();
539 540 541 542
}

void DebuggerEngine::resetLocation()
{
543 544
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
545 546
}

547
void DebuggerEngine::gotoLocation(const Location &loc)
548
{
549 550 551 552
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
553 554 555 556
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

557
    d->resetLocation();
558

559 560
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
561 562
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
563
    IEditor *editor = 0;
hjk's avatar
hjk committed
564
    if (editors.isEmpty()) {
565 566 567 568 569 570 571 572
        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
573
    }
574
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
575 576 577
    if (texteditor)
        texteditor->gotoLine(line, 0);

578 579 580 581 582 583
    if (loc.needsMarker()) {
        d->m_locationMark.reset(new TextEditor::BaseTextMark);
        d->m_locationMark->setLocation(file, line);
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
584 585

    // FIXME: Breaks with split views.
586
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
587
        editorManager->activateEditor(editor);
588
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
589 590
}

591 592 593
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
594
    showMessage("HANDLE RUNCONTROL START FAILED");
595
    d->m_runControl = 0;
596
    d->m_progress.setProgressValue(900);
597 598
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
599 600
}

601 602
// Called from RunControl.
void DebuggerEngine::handleFinished()
603
{
604
    showMessage("HANDLE RUNCONTROL FINISHED");
605
    d->m_runControl = 0;
606 607
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

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
636
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
637 638 639 640 641 642 643 644 645
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
646
    debuggerCore()->showQtDumperLibraryWarning(details);
647 648 649 650 651 652 653 654 655 656 657 658
}

QString DebuggerEngine::qtDumperLibraryName() const
{
    return startParameters().dumperLibrary;
}

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

hjk's avatar
hjk committed
659
DebuggerState DebuggerEngine::lastGoodState() const
660
{
hjk's avatar
hjk committed
661 662 663 664 665 666 667
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
669 670 671
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
672
    case DebuggerNotReady:
673
        return to == EngineSetupRequested;
674

hjk's avatar
hjk committed
675
    case EngineSetupRequested:
676 677
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
678 679 680
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
681
    case EngineSetupOk:
hjk's avatar
hjk committed
682
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
683

hjk's avatar
hjk committed
684
    case InferiorSetupRequested:
685
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
686
    case InferiorSetupFailed:
hjk's avatar
hjk committed
687
        return to == EngineShutdownRequested;
688 689
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
690 691

    case EngineRunRequested:
hjk's avatar
hjk committed
692 693 694 695
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
696
    case EngineRunFailed:
697
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
698 699 700 701 702 703

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
704 705 706
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
707 708 709 710 711

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
712
            || to == InferiorStopOk || InferiorExitOk;
713
    case InferiorStopFailed:
hjk's avatar
hjk committed
714
        return to == EngineShutdownRequested;
715

716 717 718
    case InferiorExitOk:
        return to == InferiorShutdownOk;

719
    case InferiorUnrunnable:
hjk's avatar
hjk committed
720 721 722 723 724
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
725
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
726
        return to == EngineShutdownRequested;
727

hjk's avatar
hjk committed
728
    case EngineShutdownRequested:
729
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
730 731 732 733 734 735
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
736
        return to == EngineSetupRequested; // Happens on restart.
737 738
    }

739
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
740 741 742
    return false;
}

743 744 745 746 747 748 749 750 751 752 753 754 755
void DebuggerEngine::setupSlaveEngine()
{
    QTC_ASSERT(state() == DebuggerNotReady, /**/);
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
    m_engine->setupEngine();
}

756
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
757
{
hjk's avatar
hjk committed
758
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
759
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
760
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
761
    if (isMasterEngine() && runControl())
762
        runControl()->startFailed();
hjk's avatar
hjk committed
763
    setState(DebuggerFinished);
hjk's avatar
hjk committed
764 765
}

766
void DebuggerEngine::notifyEngineSetupOk()
767
{
hjk's avatar
hjk committed
768
    showMessage(_("NOTE: ENGINE SETUP OK"));
769
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
770
    setState(EngineSetupOk);
hjk's avatar
hjk committed
771
    showMessage(_("QUEUE: SETUP INFERIOR"));
772
    if (isMasterEngine())
773 774 775 776 777 778 779
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
    QTC_ASSERT(state() == EngineSetupOk, /**/);
    d->queueSetupInferior();
780 781
}

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

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

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

808 809 810 811 812 813 814
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
    QTC_ASSERT(state() == InferiorSetupOk, /**/);
    d->queueRunEngine();
}

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

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

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

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
847 848
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
849
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
850
    setState(InferiorRunOk);
hjk's avatar
hjk committed
851 852 853 854
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
855
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
856 857
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
858
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
859
    setState(InferiorStopOk);
hjk's avatar
hjk committed
860 861 862 863
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
864
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
865
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
866 867 868 869 870
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
871
    showMessage(_("NOTE: INFERIOR RUN OK"));
872
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
873 874 875 876 877
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
878
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
879
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
880 881
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
882 883
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
884 885 886 887
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
888 889
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
890
    if (isDying()) {
hjk's avatar
hjk committed
891 892 893 894 895 896 897 898 899 900 901 902 903
        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
904
    }
905
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
906
    setState(InferiorStopOk);
hjk's avatar
hjk committed
907 908
}

hjk's avatar
hjk committed
909
void DebuggerEngine::notifyInferiorSpontaneousStop()
910
{
911
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
hjk's avatar