debuggerengine.cpp 52.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
**
7
** Contact: Nokia Corporation (qt-info@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
29
** Nokia at qt-info@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
#include <projectexplorer/taskhub.h>
#include <extensionsystem/pluginmanager.h>

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

#include <QtCore/QDebug>
#include <QtCore/QTimer>
71
#include <QtCore/QFile>
72
#include <QtCore/QFileInfo>
73
#include <QtCore/QFutureInterface>
74

75
#include <QtGui/QMessageBox>
76

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

82 83 84 85
enum { debug = 0 };

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

87

88 89 90 91 92 93
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

94 95
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
96 97 98 99 100 101 102 103 104
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;
105
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
106 107
}

108 109
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
110 111
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
112 113 114 115 116 117 118
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
119
            << " processArgs=" << sp.processArgs
120 121 122 123 124 125 126
            << " 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
127
            << " useServerStartScript=" << sp.useServerStartScript
128
            << " serverStartScript=" << sp.serverStartScript
129
            << " abi=" << sp.toolChainAbi.toString() << '\n';
130 131 132
    return str;
}

133

134 135 136 137 138 139
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

140
class DebuggerEnginePrivate : public QObject
141
{
142 143
    Q_OBJECT

144
public:
145 146
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
147
            DebuggerLanguages languages,
148
            const DebuggerStartParameters &sp)
149
      : m_engine(engine),
150
        m_masterEngine(masterEngine),
151 152
        m_runControl(0),
        m_startParameters(sp),
153
        m_languages(languages),
154
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
155
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
156
        m_targetState(DebuggerNotReady),
157
        m_inferiorPid(0),
158
        m_modulesHandler(),
159
        m_registerHandler(),
160 161
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
162
        m_threadsHandler(),
163
        m_watchHandler(engine),
164
        m_disassemblerAgent(engine),
165
        m_memoryAgent(engine),
166
        m_isStateDebugging(false),
167 168
        m_testsPossible(true),
        m_taskHub(0)
169
    {
170
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
171
        if (sp.toolChainAbi.os() == Abi::MacOS)
con's avatar
con committed
172
            m_disassemblerAgent.setTryMixed(false);
173
    }
174 175

    ~DebuggerEnginePrivate() {}
176

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

186 187 188 189 190 191 192 193 194 195 196 197 198 199
    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()));
    }

200 201
    void queueRunEngine()
    {
hjk's avatar
hjk committed
202 203 204 205 206
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

207 208
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
209 210 211 212 213
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

214 215
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
216 217 218 219 220
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

221 222
    void queueFinishDebugger()
    {
223 224 225
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
226 227 228 229 230
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
231 232
    }

233 234
    void raiseApplication()
    {
235 236
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
237 238
    }

239
    void scheduleResetLocation()
240
    {
241
        m_stackHandler.scheduleResetLocation();
242
        m_threadsHandler.scheduleResetLocation();
243
        m_disassemblerAgent.scheduleResetLocation();
244 245 246 247
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

248
    void resetLocation()
249 250 251
    {
        m_locationTimer.stop();
        m_locationMark.reset();
252
        m_stackHandler.resetLocation();
253
        m_threadsHandler.resetLocation();
254
        m_disassemblerAgent.resetLocation();
255 256
    }

257
public:
hjk's avatar
hjk committed
258
    DebuggerState state() const { return m_state; }
259 260 261
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
262

263
    DebuggerEngine *m_engine; // Not owned.
264
    DebuggerEngine *m_masterEngine; // Not owned
265 266 267
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
268
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
269 270

    // The current state.
271 272
    DebuggerState m_state;

hjk's avatar
hjk committed
273 274 275 276 277 278
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

279 280 281 282 283 284 285 286
    qint64 m_inferiorPid;

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

289 290
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
291 292
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
293 294

    bool m_isStateDebugging;
295 296 297 298

    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
299
    void reportTestError(const QString &msg, int line);
300 301
    bool m_testsPossible;
    QStringList m_testContents;
302 303
    TaskHub *m_taskHub;
    QString m_testFileName;
304 305 306 307 308 309 310 311 312
};


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

313
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
314
        DebuggerLanguages languages,
315
        DebuggerEngine *parentEngine)
316
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
317
{
318
    d->m_inferiorPid = 0;
319 320 321 322
}

DebuggerEngine::~DebuggerEngine()
{
323 324
    disconnect();
    delete d;
325 326
}

327 328 329 330 331 332 333 334 335 336 337
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)
338
        SN(InferiorSetupOk)
339 340 341 342 343 344 345 346
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
347
        SN(InferiorExitOk)
348 349 350 351 352 353 354 355 356 357 358 359
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

360
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
361
{
362
    showMessage(msg, StatusBar, timeout);
363
}
364

365 366 367 368 369 370 371 372 373 374 375 376 377 378
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
{
379 380 381
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
382 383 384 385
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
386 387 388
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
389 390 391 392
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
393 394 395 396
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
397 398 399 400
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
401 402 403
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
404 405 406 407
}

WatchHandler *DebuggerEngine::watchHandler() const
{
408 409 410
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
411 412 413 414
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
415 416 417
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
418 419 420 421
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
422
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
423 424 425
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
426 427 428 429
}

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

QAbstractItemModel *DebuggerEngine::stackModel() const
{
438
    QAbstractItemModel *model = stackHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
439 440 441
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
442 443 444 445
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
446
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
447 448 449
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
450 451 452 453
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
454
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
455 456 457
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
458 459 460 461
}

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

QAbstractItemModel *DebuggerEngine::returnModel() const
{
470
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
471 472 473
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
474 475
}

476 477 478 479 480 481 482 483
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

484 485
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
486
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
487 488 489
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
490 491
}

492
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
493 494 495 496 497 498
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
499 500 501 502 503 504 505
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

506 507 508 509 510 511 512 513
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
{
514 515 516 517
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
518 519
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
520
    debuggerCore()->showMessage(msg, channel, timeout);
521 522 523 524 525
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
526 527 528 529
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
530 531
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
532

533 534 535 536
    d->m_progress.setProgressRange(0, 1000);
    Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
537
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
538 539
    d->m_progress.reportStarted();

540 541 542 543
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
544 545
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
546

547 548
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
549 550

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
551
    debuggerCore()->action(OperateByInstruction)
552 553
        ->setEnabled(engineCapabilities & DisassemblerCapability);

554 555
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
556 557
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
558
    d->m_progress.setProgressValue(200);
559
    d->queueSetupEngine();
560 561 562 563
}

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

568
void DebuggerEngine::gotoLocation(const Location &loc)
569
{
570 571 572 573
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
574 575 576 577
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

578
    d->resetLocation();
579

580 581
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
582 583
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
584
    IEditor *editor = 0;
hjk's avatar
hjk committed
585
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
586
        editor = editorManager->openEditor(file, Core::Id(),
587 588 589 590 591 592 593
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
594
    }
595
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
596 597 598
    if (texteditor)
        texteditor->gotoLine(line, 0);

599 600 601 602 603 604
    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);
    }
605 606

    // FIXME: Breaks with split views.
607
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
608
        editorManager->activateEditor(editor);
609
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
610 611
}

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

622 623
// Called from RunControl.
void DebuggerEngine::handleFinished()
624
{
625
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
626
    d->m_runControl = 0;
627 628
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
    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
657
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
658 659 660 661 662 663 664 665 666
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
667
    debuggerCore()->showQtDumperLibraryWarning(details);
668 669 670 671 672 673 674 675 676 677 678 679
}

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

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

hjk's avatar
hjk committed
680
DebuggerState DebuggerEngine::lastGoodState() const
681
{
hjk's avatar
hjk committed
682 683 684 685 686 687 688
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
690 691 692
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
693
    case DebuggerNotReady:
694
        return to == EngineSetupRequested;
695

hjk's avatar
hjk committed
696
    case EngineSetupRequested:
697 698
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
699 700 701
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
702
    case EngineSetupOk:
hjk's avatar
hjk committed
703
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
704

hjk's avatar
hjk committed
705
    case InferiorSetupRequested:
706
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
707
    case InferiorSetupFailed:
hjk's avatar
hjk committed
708
        return to == EngineShutdownRequested;
709 710
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
711 712

    case EngineRunRequested:
hjk's avatar
hjk committed
713 714 715 716
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
717
    case EngineRunFailed:
718
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
719 720 721 722 723 724

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
725 726 727
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
728 729 730 731 732

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
733
            || to == InferiorStopOk || InferiorExitOk;
734
    case InferiorStopFailed:
hjk's avatar
hjk committed
735
        return to == EngineShutdownRequested;
736

737 738 739
    case InferiorExitOk:
        return to == InferiorShutdownOk;

740
    case InferiorUnrunnable:
hjk's avatar
hjk committed
741 742 743 744 745
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
746
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
747
        return to == EngineShutdownRequested;
748

hjk's avatar
hjk committed
749
    case EngineShutdownRequested:
750
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
751 752 753 754 755 756
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
757
        return to == EngineSetupRequested; // Happens on restart.
758 759
    }

760
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
761 762 763
    return false;
}

764 765
void DebuggerEngine::setupSlaveEngine()
{
766
    QTC_CHECK(state() == DebuggerNotReady);
767 768 769 770 771 772 773 774 775 776
    d->queueSetupEngine();
}

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

777
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
778
{
hjk's avatar
hjk committed
779
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
780
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
781
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
782
    if (isMasterEngine() && runControl())
783
        runControl()->startFailed();
hjk's avatar
hjk committed
784
    setState(DebuggerFinished);
hjk's avatar
hjk committed
785 786
}

787
void DebuggerEngine::notifyEngineSetupOk()
788
{
hjk's avatar
hjk committed
789
    showMessage(_("NOTE: ENGINE SETUP OK"));
790
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
791
    setState(EngineSetupOk);
hjk's avatar
hjk committed
792
    showMessage(_("QUEUE: SETUP INFERIOR"));
793
    if (isMasterEngine())
794 795 796 797 798
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
799
    QTC_CHECK(state() == EngineSetupOk);
800
    d->queueSetupInferior();
801 802
}

hjk's avatar
hjk committed
803
void DebuggerEnginePrivate::doSetupInferior()
804
{
805
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
806
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
807
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
808 809 810 811 812
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
813
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
814
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
815
    setState(InferiorSetupFailed);
816 817
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
818 819 820 821
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
822
    showMessage(_("NOTE: INFERIOR SETUP OK"));
823 824 825 826
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
827 828
}

829 830 831
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
832
    QTC_CHECK(state() == InferiorSetupOk);
833 834 835
    d->queueRunEngine();
}

hjk's avatar
hjk committed
836 837
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
838
    m_engine->showMessage(_("CALL: RUN ENGINE"));
839
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
840
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
841 842 843
    m_engine->runEngine();
}

hjk's avatar
hjk committed
844 845
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
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 851 852 853 854
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
855
    showMessage(_("NOTE: ENGINE RUN FAILED"));
856
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
857 858 859
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
860
    setState(EngineRunFailed);
861 862
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
863 864 865 866
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
867
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
868 869
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
870
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
871
    setState(InferiorRunOk);
hjk's avatar
hjk committed
872 873 874 875
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
876
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
877 878
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
879
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
880
    setState(InferiorStopOk);
hjk's avatar
hjk committed
881 882 883 884
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar