debuggerengine.cpp 52.3 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_watchHandler.scheduleResetLocation();
243
        m_threadsHandler.scheduleResetLocation();
244
        m_disassemblerAgent.scheduleResetLocation();
245 246 247 248
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

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

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

265
    DebuggerEngine *m_engine; // Not owned.
266
    DebuggerEngine *m_masterEngine; // Not owned
267 268 269
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
270
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
271 272

    // The current state.
273 274
    DebuggerState m_state;

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

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

281 282 283 284 285 286 287 288
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
297 298 299 300

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


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

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

DebuggerEngine::~DebuggerEngine()
{
325 326
    disconnect();
    delete d;
327 328
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

535 536 537 538
    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
539
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
540 541
    d->m_progress.reportStarted();

542 543 544 545
    d->m_runControl = runControl;

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

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

hjk's avatar
hjk committed
552
    debuggerCore()->action(OperateByInstruction)
553
        ->setEnabled(hasCapability(DisassemblerCapability));
554

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

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

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

573 574 575 576
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
577 578 579 580 581
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


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

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

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

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

624 625
// Called from RunControl.
void DebuggerEngine::handleFinished()
626
{
627
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
628
    d->m_runControl = 0;
629 630
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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 657 658
    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
659
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
660 661 662 663 664 665 666 667 668
}

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

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

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

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

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

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

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

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

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

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

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

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

739 740 741
    case InferiorExitOk:
        return to == InferiorShutdownOk;

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

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

    case DebuggerFinished:
759
        return to == EngineSetupRequested; // Happens on restart.
760 761
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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