debuggerengine.cpp 45.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 8
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11 12 13 14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15 16 17 18 19 20 21 22 23 24
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
con's avatar
con committed
25 26 27 28 29 30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
31 32 33 34 35 36
**
**************************************************************************/

#include "debuggerengine.h"

#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 134 135 136 137 138 139 140 141 142 143 144 145
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

// Used in "real" editors
class LocationMark : public TextEditor::BaseTextMark
{
public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
    {}

    QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
    void removedFromEditor() {}
146
    TextEditor::ITextMark::Priority priority() const { return TextEditor::ITextMark::HighPriority; }
147 148 149 150
};



151 152 153 154 155 156
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

157
class DebuggerEnginePrivate : public QObject
158
{
159 160
    Q_OBJECT

161
public:
162 163 164
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
            const DebuggerStartParameters &sp)
165
      : m_engine(engine),
166
        m_masterEngine(masterEngine),
167 168 169
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
170
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
171
        m_targetState(DebuggerNotReady),
172
        m_modulesHandler(),
173
        m_registerHandler(),
174 175
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
176
        m_threadsHandler(),
177
        m_watchHandler(engine),
178
        m_disassemblerAgent(engine),
179 180
        m_memoryAgent(engine),
        m_isStateDebugging(false)
181
    {
182
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
183
    }
184 185

    ~DebuggerEnginePrivate() {}
186

187
public slots:
188
    void doSetupEngine();
hjk's avatar
hjk committed
189 190
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
191 192
    void doShutdownEngine();
    void doShutdownInferior();
193
    void doInterruptInferior();
hjk's avatar
hjk committed
194
    void doFinishDebugger();
hjk's avatar
hjk committed
195

196 197 198 199 200 201 202 203 204 205 206 207 208 209
    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()));
    }

210 211
    void queueRunEngine()
    {
hjk's avatar
hjk committed
212 213 214 215 216
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

217 218
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
219 220 221 222 223
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

224 225
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
226 227 228 229 230
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

231 232
    void queueFinishDebugger()
    {
233 234 235 236
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
hjk's avatar
hjk committed
237 238 239
        QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
    }

240 241
    void raiseApplication()
    {
242 243
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
244 245
    }

246
    void scheduleResetLocation()
247
    {
248
        m_stackHandler.scheduleResetLocation();
249 250 251 252
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

253
    void resetLocation()
254 255 256
    {
        m_locationTimer.stop();
        m_locationMark.reset();
257 258
        m_stackHandler.resetLocation();
        m_disassemblerAgent.resetLocation();
259 260
    }

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

267
    DebuggerEngine *m_engine; // Not owned.
268
    DebuggerEngine *m_masterEngine; // Not owned
269 270 271
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
272 273

    // The current state.
274 275
    DebuggerState m_state;

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

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

282 283 284 285 286 287 288 289
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
298 299 300 301 302 303 304 305 306
};


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

307 308 309
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
310 311 312 313 314
{
}

DebuggerEngine::~DebuggerEngine()
{
315 316
    disconnect();
    delete d;
317 318
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

525 526 527 528 529 530 531
    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();

532 533 534 535 536
    d->m_runControl = runControl;

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

537 538
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
539 540

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
541
    debuggerCore()->action(OperateByInstruction)
542 543
        ->setEnabled(engineCapabilities & DisassemblerCapability);

544 545
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
546 547
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
548
    d->m_progress.setProgressValue(200);
549
    d->queueSetupEngine();
550 551 552 553
}

void DebuggerEngine::resetLocation()
{
554 555
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
556 557
}

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

569
    d->resetLocation();
570

571 572
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
573 574
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
575
    IEditor *editor = 0;
hjk's avatar
hjk committed
576
    if (editors.isEmpty()) {
577 578 579 580 581 582 583 584
        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
585
    }
586
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
587 588 589
    if (texteditor)
        texteditor->gotoLine(line, 0);

590
    if (loc.needsMarker())
591
        d->m_locationMark.reset(new LocationMark(file, line));
592 593

    // FIXME: Breaks with split views.
594
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
595
        editorManager->activateEditor(editor);
596
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
597 598
}

599 600 601
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
602
    showMessage("HANDLE RUNCONTROL START FAILED");
603
    d->m_runControl = 0;
604
    d->m_progress.setProgressValue(900);
605 606
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
607 608
}

609 610
// Called from RunControl.
void DebuggerEngine::handleFinished()
611
{
612
    showMessage("HANDLE RUNCONTROL FINISHED");
613
    d->m_runControl = 0;
614 615
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
    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
644
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
645 646 647 648
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
hjk's avatar
hjk committed
649
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
650
        const QString customLocation =
hjk's avatar
hjk committed
651
            debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
652 653 654 655 656 657 658 659 660
        const QString location =
            tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
        return QStringList(location);
    }
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
661
    debuggerCore()->showQtDumperLibraryWarning(details);
662 663 664 665
}

QString DebuggerEngine::qtDumperLibraryName() const
{
hjk's avatar
hjk committed
666 667
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool())
        return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
668 669 670 671 672 673 674 675
    return startParameters().dumperLibrary;
}

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

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

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

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

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

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

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

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

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

733 734 735
    case InferiorExitOk:
        return to == InferiorShutdownOk;

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

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

    case DebuggerFinished:
753
        return to == EngineSetupRequested; // Happens on restart.
754 755
    }

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

760 761 762 763 764 765 766 767 768 769 770 771 772
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();
}

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

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

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

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

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

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

825 826 827 828 829 830 831
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
    QTC_ASSERT(state() == InferiorSetupOk, /**/);
    d->queueRunEngine();
}

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

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

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

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

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

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

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
888
    showMessage(_("NOTE: INFERIOR RUN OK"));
889
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
890 891 892 893 894
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
895
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
896
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
897 898
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
899 900
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
901 902 903 904
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
905 906
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
907
    if (isDying()) {
hjk's avatar
hjk committed
908 909 910 911 912 913 914 915 916 917 918 919 920
        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
921
    }
922
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
923
    setState(InferiorStopOk);
hjk's avatar
hjk committed
924 925
}

hjk's avatar
hjk committed
926
void DebuggerEngine::notifyInferiorSpontaneousStop()
927
{
hjk's avatar
hjk committed
928
    showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
929
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
930
    setState(InferiorStopOk);
hjk's avatar