debuggerengine.cpp 50.4 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 66 67
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

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

71
#include <QtGui/QMessageBox>
72

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

78 79 80 81
enum { debug = 0 };

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

83

84 85 86 87 88 89
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

90 91
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
92 93 94 95 96 97 98 99 100
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;
101
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
102 103
}

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

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

129

130 131 132 133 134 135
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

136
class DebuggerEnginePrivate : public QObject
137
{
138 139
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
171

172
public slots:
173
    void doSetupEngine();
hjk's avatar
hjk committed
174 175
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
176 177
    void doShutdownEngine();
    void doShutdownInferior();
178
    void doInterruptInferior();
hjk's avatar
hjk committed
179
    void doFinishDebugger();
hjk's avatar
hjk committed
180

181 182 183 184 185 186 187 188 189 190 191 192 193 194
    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()));
    }

195 196
    void queueRunEngine()
    {
hjk's avatar
hjk committed
197 198 199 200 201
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

202 203
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
204 205 206 207 208
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

209 210
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
211 212 213 214 215
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

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

228 229
    void raiseApplication()
    {
230 231
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
232 233
    }

234
    void scheduleResetLocation()
235
    {
236
        m_stackHandler.scheduleResetLocation();
237
        m_threadsHandler.scheduleResetLocation();
238
        m_disassemblerAgent.scheduleResetLocation();
239 240 241 242
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

243
    void resetLocation()
244 245 246
    {
        m_locationTimer.stop();
        m_locationMark.reset();
247
        m_stackHandler.resetLocation();
248
        m_threadsHandler.resetLocation();
249
        m_disassemblerAgent.resetLocation();
250 251
    }

252
public:
hjk's avatar
hjk committed
253
    DebuggerState state() const { return m_state; }
254 255 256
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
257

258
    DebuggerEngine *m_engine; // Not owned.
259
    DebuggerEngine *m_masterEngine; // Not owned
260 261 262
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
263
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
264 265

    // The current state.
266 267
    DebuggerState m_state;

hjk's avatar
hjk committed
268 269 270 271 272 273
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

274 275 276 277 278 279 280 281
    qint64 m_inferiorPid;

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

284 285
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
286 287
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
288 289

    bool m_isStateDebugging;
290 291 292 293 294 295 296 297

    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
    void reportTestError(const QString &);
    bool m_testsPossible;
    QStringList m_testContents;
    QString m_testErrors;
298 299 300 301 302 303 304 305 306
};


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

307
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
308
        DebuggerLanguages languages,
309
        DebuggerEngine *parentEngine)
310
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
311
{
312
    d->m_inferiorPid = 0;
313 314 315 316
}

DebuggerEngine::~DebuggerEngine()
{
317 318
    disconnect();
    delete d;
319 320
}

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

354
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
355
{
356
    showMessage(msg, StatusBar, timeout);
357
}
358

359 360 361 362 363 364 365 366 367 368 369 370 371 372
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
{
373 374 375
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
376 377 378 379
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
380 381 382
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
383 384 385 386
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
387 388 389 390
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
391 392 393 394
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
395 396 397
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
398 399 400 401
}

WatchHandler *DebuggerEngine::watchHandler() const
{
402 403 404
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
405 406 407 408
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
409 410 411
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
412 413 414 415
}

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

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

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

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

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

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

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

470 471 472 473 474 475 476 477
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

478 479
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
480
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
481 482 483
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
484 485
}

486
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
487 488 489 490 491 492
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
493 494 495 496 497 498 499
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
524 525
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
526

527 528 529 530
    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
531
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
532 533
    d->m_progress.reportStarted();

534 535 536 537
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
538 539
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
540

541 542
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
543 544

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
545
    debuggerCore()->action(OperateByInstruction)
546 547
        ->setEnabled(engineCapabilities & DisassemblerCapability);

548 549
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
550 551
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
552
    d->m_progress.setProgressValue(200);
553
    d->queueSetupEngine();
554 555 556 557
}

void DebuggerEngine::resetLocation()
{
558 559
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
560 561
}

562
void DebuggerEngine::gotoLocation(const Location &loc)
563
{
564 565 566 567
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
568 569 570 571
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

572
    d->resetLocation();
573

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

593 594 595 596 597 598
    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);
    }
599 600

    // FIXME: Breaks with split views.
601
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
602
        editorManager->activateEditor(editor);
603
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
604 605
}

606 607 608
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
609
    showMessage("HANDLE RUNCONTROL START FAILED");
610
    d->m_runControl = 0;
611
    d->m_progress.setProgressValue(900);
612 613
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
614 615
}

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

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
661
    debuggerCore()->showQtDumperLibraryWarning(details);
662 663 664 665 666 667 668 669 670 671 672 673
}

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

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

hjk's avatar
hjk committed
674
DebuggerState DebuggerEngine::lastGoodState() const
675
{
hjk's avatar
hjk committed
676 677 678 679 680 681 682
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
684 685 686
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
687
    case DebuggerNotReady:
688
        return to == EngineSetupRequested;
689

hjk's avatar
hjk committed
690
    case EngineSetupRequested:
691 692
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
693 694 695
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
696
    case EngineSetupOk:
hjk's avatar
hjk committed
697
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
698

hjk's avatar
hjk committed
699
    case InferiorSetupRequested:
700
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
701
    case InferiorSetupFailed:
hjk's avatar
hjk committed
702
        return to == EngineShutdownRequested;
703 704
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
705 706

    case EngineRunRequested:
hjk's avatar
hjk committed
707 708 709 710
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
711
    case EngineRunFailed:
712
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
713 714 715 716 717 718

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
719 720 721
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
722 723 724 725 726

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
727
            || to == InferiorStopOk || InferiorExitOk;
728
    case InferiorStopFailed:
hjk's avatar
hjk committed
729
        return to == EngineShutdownRequested;
730

731 732 733
    case InferiorExitOk:
        return to == InferiorShutdownOk;

734
    case InferiorUnrunnable:
hjk's avatar
hjk committed
735 736 737 738 739
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
740
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
741
        return to == EngineShutdownRequested;
742

hjk's avatar
hjk committed
743
    case EngineShutdownRequested:
744
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
745 746 747 748 749 750
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
751
        return to == EngineSetupRequested; // Happens on restart.
752 753
    }

754
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
755 756 757
    return false;
}

758 759
void DebuggerEngine::setupSlaveEngine()
{
760
    QTC_CHECK(state() == DebuggerNotReady);
761 762 763 764 765 766 767 768 769 770
    d->queueSetupEngine();
}

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

771
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
772
{
hjk's avatar
hjk committed
773
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
774
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
775
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
776
    if (isMasterEngine() && runControl())
777
        runControl()->startFailed();
hjk's avatar
hjk committed
778
    setState(DebuggerFinished);
hjk's avatar
hjk committed
779 780
}

781
void DebuggerEngine::notifyEngineSetupOk()
782
{
hjk's avatar
hjk committed
783
    showMessage(_("NOTE: ENGINE SETUP OK"));
784
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
785
    setState(EngineSetupOk);
hjk's avatar
hjk committed
786
    showMessage(_("QUEUE: SETUP INFERIOR"));
787
    if (isMasterEngine())
788 789 790 791 792
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
793
    QTC_CHECK(state() == EngineSetupOk);
794
    d->queueSetupInferior();
795 796
}

hjk's avatar
hjk committed
797
void DebuggerEnginePrivate::doSetupInferior()
798
{
799
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
800
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
801
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
802 803 804 805 806
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
807
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
808
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
809
    setState(InferiorSetupFailed);
810 811
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
812 813 814 815
}

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

823 824 825
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
826
    QTC_CHECK(state() == InferiorSetupOk);
827 828 829
    d->queueRunEngine();
}

hjk's avatar
hjk committed
830 831
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
832
    m_engine->showMessage(_("CALL: RUN ENGINE"));
833
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
834
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
835 836 837
    m_engine->runEngine();
}

hjk's avatar
hjk committed
838 839
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
840
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
841 842
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
843
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
844 845 846 847 848
    setState(InferiorUnrunnable);
}

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

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
861
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
862 863
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
864
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
865
    setState(InferiorRunOk);
hjk's avatar
hjk committed
866 867 868 869
}

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

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
879
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
880
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
881 882 883 884 885
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
886
    showMessage(_("NOTE: INFERIOR RUN OK"));
887 888 889
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());