debuggerengine.cpp 44.9 KB
Newer Older
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28 29
** If you have questions regarding the use of this file, please contact
** 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/QFutureInterface>
69

70
#include <QtGui/QMessageBox>
71

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

77 78 79 80
enum { debug = 0 };

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

82

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

89 90
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
91 92 93 94 95 96 97 98 99 100 101
Internal::Location::Location(const StackFrame &frame, bool marker)
{
    init();
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
113
            << " processArgs=" << sp.processArgs
114 115 116 117 118 119 120
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
121
            << " useServerStartScript=" << sp.useServerStartScript
122
            << " serverStartScript=" << sp.serverStartScript
123
            << " abi=" << sp.toolChainAbi.toString() << '\n';
124 125 126
    return str;
}

127

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

134
class DebuggerEnginePrivate : public QObject
135
{
136 137
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
163

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

173 174 175 176 177 178 179 180 181 182 183 184 185 186
    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()));
    }

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

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

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

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

220 221
    void raiseApplication()
    {
222 223
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
224 225
    }

226
    void scheduleResetLocation()
227
    {
228
        m_stackHandler.scheduleResetLocation();
229
        m_threadsHandler.scheduleResetLocation();
230
        m_disassemblerAgent.scheduleResetLocation();
231 232 233 234
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

235
    void resetLocation()
236 237 238
    {
        m_locationTimer.stop();
        m_locationMark.reset();
239
        m_stackHandler.resetLocation();
240
        m_threadsHandler.resetLocation();
241
        m_disassemblerAgent.resetLocation();
242 243
    }

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

250
    DebuggerEngine *m_engine; // Not owned.
251
    DebuggerEngine *m_masterEngine; // Not owned
252 253 254
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
255 256

    // The current state.
257 258
    DebuggerState m_state;

hjk's avatar
hjk committed
259 260 261 262 263 264
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

265 266 267 268 269 270 271 272
    qint64 m_inferiorPid;

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

275 276
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
277 278
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
279 280

    bool m_isStateDebugging;
281 282 283 284 285 286 287 288 289
};


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

290 291 292
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
293 294 295 296 297
{
}

DebuggerEngine::~DebuggerEngine()
{
298 299
    disconnect();
    delete d;
300 301
}

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

335
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
336
{
337
    showMessage(msg, StatusBar, timeout);
338
}
339

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

RegisterHandler *DebuggerEngine::registerHandler() const
{
361 362 363
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
364 365 366 367
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
368 369 370 371
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
372 373 374 375
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
376 377 378
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
379 380 381 382
}

WatchHandler *DebuggerEngine::watchHandler() const
{
383 384 385
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
386 387 388 389
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
390 391 392
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
393 394 395 396
}

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

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

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

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

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

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

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

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

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

467
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
468 469 470 471 472 473
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
474 475 476 477 478 479 480
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
505 506
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
507

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

515 516 517 518 519
    d->m_runControl = runControl;

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

520 521
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
522 523

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
524
    debuggerCore()->action(OperateByInstruction)
525 526
        ->setEnabled(engineCapabilities & DisassemblerCapability);

527 528
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
529 530
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
531
    d->m_progress.setProgressValue(200);
532
    d->queueSetupEngine();
533 534 535 536
}

void DebuggerEngine::resetLocation()
{
537 538
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
539 540
}

541
void DebuggerEngine::gotoLocation(const Location &loc)
542
{
543 544 545 546 547
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setTryMixed(true);
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
548 549 550 551
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

552
    d->resetLocation();
553

554 555
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
556 557
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
558
    IEditor *editor = 0;
hjk's avatar
hjk committed
559
    if (editors.isEmpty()) {
560 561 562 563 564 565 566 567
        editor = editorManager->openEditor(file, QString(),
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
568
    }
569
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
570 571 572
    if (texteditor)
        texteditor->gotoLine(line, 0);

573 574 575 576 577 578
    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);
    }
579 580

    // FIXME: Breaks with split views.
581
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
582
        editorManager->activateEditor(editor);
583
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
584 585
}

586 587 588
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
589
    showMessage("HANDLE RUNCONTROL START FAILED");
590
    d->m_runControl = 0;
591
    d->m_progress.setProgressValue(900);
592 593
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
594 595
}

596 597
// Called from RunControl.
void DebuggerEngine::handleFinished()
598
{
599
    showMessage("HANDLE RUNCONTROL FINISHED");
600
    d->m_runControl = 0;
601 602
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
    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
631
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
632 633 634 635 636 637 638 639 640
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
641
    debuggerCore()->showQtDumperLibraryWarning(details);
642 643 644 645 646 647 648 649 650 651 652 653
}

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

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

hjk's avatar
hjk committed
654
DebuggerState DebuggerEngine::lastGoodState() const
655
{
hjk's avatar
hjk committed
656 657 658 659 660 661 662
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
664 665 666
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
667
    case DebuggerNotReady:
668
        return to == EngineSetupRequested;
669

hjk's avatar
hjk committed
670
    case EngineSetupRequested:
671 672
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
673 674 675
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
676
    case EngineSetupOk:
hjk's avatar
hjk committed
677
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
678

hjk's avatar
hjk committed
679
    case InferiorSetupRequested:
680
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
681
    case InferiorSetupFailed:
hjk's avatar
hjk committed
682
        return to == EngineShutdownRequested;
683 684
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
685 686

    case EngineRunRequested:
hjk's avatar
hjk committed
687 688 689 690
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
691
    case EngineRunFailed:
692
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
693 694 695 696 697 698

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
699 700 701
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
702 703 704 705 706

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
707
            || to == InferiorStopOk || InferiorExitOk;
708
    case InferiorStopFailed:
hjk's avatar
hjk committed
709
        return to == EngineShutdownRequested;
710

711 712 713
    case InferiorExitOk:
        return to == InferiorShutdownOk;

714
    case InferiorUnrunnable:
hjk's avatar
hjk committed
715 716 717 718 719
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
720
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
721
        return to == EngineShutdownRequested;
722

hjk's avatar
hjk committed
723
    case EngineShutdownRequested:
724
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
725 726 727 728 729 730
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
731
        return to == EngineSetupRequested; // Happens on restart.
732 733
    }

734
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
735 736 737
    return false;
}

738 739 740 741 742 743 744 745 746 747 748 749 750
void DebuggerEngine::setupSlaveEngine()
{
    QTC_ASSERT(state() == DebuggerNotReady, /**/);
    d->queueSetupEngine();
}

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

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

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

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

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

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

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
796
    showMessage(_("NOTE: INFERIOR SETUP OK"));
797 798 799 800
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
801 802
}

803 804 805 806 807 808 809
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
    QTC_ASSERT(state() == InferiorSetupOk, /**/);
    d->queueRunEngine();
}

hjk's avatar
hjk committed
810 811
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
812
    m_engine->showMessage(_("CALL: RUN ENGINE"));
813
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
814
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
815 816 817
    m_engine->runEngine();
}

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

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

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

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

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
859
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
860
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
861 862 863 864 865
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
866
    showMessage(_("NOTE: INFERIOR RUN OK"));
867
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
868 869 870 871 872
    setState(InferiorRunOk);
}

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

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
883 884
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
885
    if (isDying()) {
hjk's avatar
hjk committed
886 887 888 889 890 891 892 893 894 895 896 897 898
        showMessage(_("NOTE: ... WHILE DYING. "));
        // Forward state to "StopOk" if needed.
        if (state() == InferiorStopRequested
                || state() == InferiorRunRequested
                || state() == InferiorRunOk) {
            showMessage(_("NOTE: ... FORWARDING TO 'STOP OK'. "));
            setState(InferiorStopOk);
        }
        if (state() == InferiorStopOk || state() == InferiorStopFailed) {
            d->queueShutdownInferior();
        }
        showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
        return;
hjk's avatar
hjk committed
899
    }
900
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
901
    setState(InferiorStopOk);
hjk's avatar
hjk committed
902 903
}

hjk's avatar
hjk committed
904
void DebuggerEngine::notifyInferiorSpontaneousStop()
905
{
906
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
907
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
908
    setState(InferiorStopOk);
909 910
}

hjk's avatar
hjk committed
911
void DebuggerEngine::notifyInferiorStopFailed()
912
{
hjk's avatar
hjk committed
913
    showMessage(_("NOTE: INFERIOR STOP FAILED"));