debuggerengine.cpp 45.7 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"
41
#include "debuggertooltip.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
42
#include "debuggerstartparameters.h"
43

44 45
#include "memoryagent.h"
#include "disassembleragent.h"
46 47 48 49 50 51 52 53 54
#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
55
#include <coreplugin/icore.h>
56
#include <coreplugin/ifile.h>
hjk's avatar
hjk committed
57
#include <coreplugin/editormanager/editormanager.h>
58 59
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
60

hjk's avatar
hjk committed
61
#include <projectexplorer/toolchain.h>
62
#include <projectexplorer/toolchaintype.h>
63

hjk's avatar
hjk committed
64
#include <texteditor/itexteditor.h>
65
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
66

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

#include <QtCore/QDebug>
#include <QtCore/QTimer>
72
#include <QtCore/QFutureInterface>
73

74
#include <QtGui/QMessageBox>
75

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

hjk's avatar
hjk committed
81 82 83 84 85 86 87
//#define DEBUG_STATE 1
#if DEBUG_STATE
#   define SDEBUG(s) qDebug() << s
#else
#   define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
88

89

90 91 92 93 94 95
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

96 97
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
98 99 100 101 102 103 104 105 106 107 108
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;
}

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

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

134

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
///////////////////////////////////////////////////////////////////////
//
// 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() {}
};



157 158 159 160 161 162
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

163
class DebuggerEnginePrivate : public QObject
164
{
165 166
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
192

193
public slots:
194
    void doSetupEngine();
hjk's avatar
hjk committed
195 196
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
197 198
    void doShutdownEngine();
    void doShutdownInferior();
199
    void doInterruptInferior();
hjk's avatar
hjk committed
200
    void doFinishDebugger();
hjk's avatar
hjk committed
201

202 203 204 205 206 207 208 209 210 211 212 213 214 215
    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()));
    }

216 217
    void queueRunEngine()
    {
hjk's avatar
hjk committed
218 219 220 221 222
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

223 224
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
225 226 227 228 229
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

230 231
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
232 233 234 235 236
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

237 238
    void queueFinishDebugger()
    {
239 240 241 242
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
hjk's avatar
hjk committed
243 244 245
        QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
    }

246 247
    void raiseApplication()
    {
248 249
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
250 251
    }

252
    void scheduleResetLocation()
253
    {
254
        m_stackHandler.scheduleResetLocation();
255 256 257 258
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

259
    void resetLocation()
260 261 262
    {
        m_locationTimer.stop();
        m_locationMark.reset();
263 264
        m_stackHandler.resetLocation();
        m_disassemblerAgent.resetLocation();
265 266
    }

267
public:
hjk's avatar
hjk committed
268
    DebuggerState state() const { return m_state; }
269 270 271
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
272

273
    DebuggerEngine *m_engine; // Not owned.
274
    DebuggerEngine *m_masterEngine; // Not owned
275 276 277
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
278 279

    // The current state.
280 281
    DebuggerState m_state;

hjk's avatar
hjk committed
282 283 284 285 286 287
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

288 289 290 291 292 293 294 295
    qint64 m_inferiorPid;

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

298 299
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
300 301
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
302 303

    bool m_isStateDebugging;
304 305 306 307 308 309 310 311 312
};


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

313 314 315
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
316 317 318 319 320
{
}

DebuggerEngine::~DebuggerEngine()
{
321 322
    disconnect();
    delete d;
323 324
}

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

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

365 366 367 368 369 370
void DebuggerEngine::removeTooltip()
{
    watchHandler()->removeTooltip();
    hideDebuggerToolTip();
}

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

RegisterHandler *DebuggerEngine::registerHandler() const
{
392 393 394
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
395 396 397 398
}

StackHandler *DebuggerEngine::stackHandler() const
{
399 400 401
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
402 403 404 405
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
406 407 408
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
409 410 411 412
}

WatchHandler *DebuggerEngine::watchHandler() const
{
413 414 415
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
416 417 418 419
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
420 421 422
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
423 424 425 426
}

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

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

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

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

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

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

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

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

489
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
490 491 492 493 494 495 496 497 498 499 500 501 502 503
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

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

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

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

530 531 532 533 534
    d->m_runControl = runControl;

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

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

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

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

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

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

567
    d->resetLocation();
568

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

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

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

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

607 608
// Called from RunControl.
void DebuggerEngine::handleFinished()
609
{
610
    showMessage("HANDLE RUNCONTROL FINISHED");
611
    d->m_runControl = 0;
612 613 614 615
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
616
    d->m_progress.setProgressValue(1000);
617
    d->m_progress.reportFinished();
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
}

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
642
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
643 644 645 646
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
hjk's avatar
hjk committed
647
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
648
        const QString customLocation =
hjk's avatar
hjk committed
649
            debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
650 651 652 653 654 655 656 657 658
        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)
{
659
    debuggerCore()->showQtDumperLibraryWarning(details);
660 661 662 663
}

QString DebuggerEngine::qtDumperLibraryName() const
{
hjk's avatar
hjk committed
664 665
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool())
        return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
666 667 668 669 670 671 672 673
    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:
707
        return to == EngineRunOk || EngineRunFailed;
hjk's avatar
hjk committed
708
    case EngineRunFailed:
709
        return to == EngineShutdownRequested;
710 711 712
    case EngineRunOk:
        return InferiorRunOk || to == InferiorStopOk
            || to == InferiorUnrunnable;
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 == InferiorStopSpontaneous
            || InferiorExitOk;
            //|| to == InferiorStopOk;
hjk's avatar
hjk committed
722 723 724

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
725 726
    case InferiorStopSpontaneous:
        return to == InferiorStopOk;
hjk's avatar
hjk committed
727 728
    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);
778 779
    if (isMasterEngine())
        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 867 868 869
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
    setState(EngineRunOk);
    if (isMasterEngine())
        setState(InferiorRunOk);
hjk's avatar
hjk committed
870 871 872 873
}

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

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

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

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

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

hjk's avatar
hjk committed
930
void DebuggerEngine::notifyInferiorSpontaneousStop()
931
{