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

#include "debuggerengine.h"

35
#include "debuggerinternalconstants.h"
36
#include "debuggeractions.h"
37
#include "debuggercore.h"
38
#include "debuggerplugin.h"
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
41
#include "debuggerstartparameters.h"
42

43 44
#include "memoryagent.h"
#include "disassembleragent.h"
45 46 47 48 49 50 51 52 53
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

hjk's avatar
hjk committed
54
#include <coreplugin/icore.h>
55
#include <coreplugin/ifile.h>
hjk's avatar
hjk committed
56
#include <coreplugin/editormanager/editormanager.h>
57 58
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
59 60

#include <texteditor/itexteditor.h>
61
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
62

63 64 65 66 67
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
68
#include <QtCore/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
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;
100
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
101 102
}

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

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

128

129 130 131 132 133 134
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

135
class DebuggerEnginePrivate : public QObject
136
{
137 138
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
169

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

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

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

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

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

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

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

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

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

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

256
    DebuggerEngine *m_engine; // Not owned.
257
    DebuggerEngine *m_masterEngine; // Not owned
258 259 260
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
261
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
262 263

    // The current state.
264 265
    DebuggerState m_state;

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

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

272 273 274 275 276 277 278 279
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
288 289 290 291 292 293 294 295 296
};


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

297
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
298
        DebuggerLanguages languages,
299
        DebuggerEngine *parentEngine)
300
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
301
{
302
    d->m_inferiorPid = 0;
303 304 305 306
}

DebuggerEngine::~DebuggerEngine()
{
307 308
    disconnect();
    delete d;
309 310
}

311 312 313 314 315 316 317 318 319 320 321
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)
322
        SN(InferiorSetupOk)
323 324 325 326 327 328 329 330
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
331
        SN(InferiorExitOk)
332 333 334 335 336 337 338 339 340 341 342 343
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

344
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
345
{
346
    showMessage(msg, StatusBar, timeout);
347
}
348

349 350 351 352 353 354 355 356 357 358 359 360 361 362
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
{
363 364 365
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
366 367 368 369
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
370 371 372
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
373 374 375 376
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
377 378 379 380
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
381 382 383 384
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
385 386 387
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
388 389 390 391
}

WatchHandler *DebuggerEngine::watchHandler() const
{
392 393 394
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
395 396 397 398
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
399 400 401
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
402 403 404 405
}

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

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

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

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

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

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

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

460 461 462 463 464 465 466 467
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

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

476
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
477 478 479 480 481 482
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
483 484 485 486 487 488 489
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
514 515
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
516

517 518 519 520
    d->m_progress.setProgressRange(0, 1000);
    Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
521
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
522 523
    d->m_progress.reportStarted();

524 525 526 527
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
528 529
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
530

531 532
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
533 534

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
535
    debuggerCore()->action(OperateByInstruction)
536 537
        ->setEnabled(engineCapabilities & DisassemblerCapability);

538 539
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
540 541
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
542
    d->m_progress.setProgressValue(200);
543
    d->queueSetupEngine();
544 545 546 547
}

void DebuggerEngine::resetLocation()
{
548 549
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
550 551
}

552
void DebuggerEngine::gotoLocation(const Location &loc)
553
{
554 555 556 557
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
558 559 560 561
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

562
    d->resetLocation();
563

564 565
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
566 567
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
568
    IEditor *editor = 0;
hjk's avatar
hjk committed
569
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
570
        editor = editorManager->openEditor(file, Core::Id(),
571 572 573 574 575 576 577
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
578
    }
579
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
580 581 582
    if (texteditor)
        texteditor->gotoLine(line, 0);

583 584 585 586 587 588
    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);
    }
589 590

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

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

606 607
// Called from RunControl.
void DebuggerEngine::handleFinished()
608
{
609
    showMessage("HANDLE RUNCONTROL FINISHED");
610
    d->m_runControl = 0;
611 612
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
613 614 615 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
    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
641
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
642 643 644 645 646 647 648 649 650
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
651
    debuggerCore()->showQtDumperLibraryWarning(details);
652 653 654 655 656 657 658 659 660 661 662 663
}

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

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

hjk's avatar
hjk committed
664
DebuggerState DebuggerEngine::lastGoodState() const
665
{
hjk's avatar
hjk committed
666 667 668 669 670 671 672
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
674 675 676
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
677
    case DebuggerNotReady:
678
        return to == EngineSetupRequested;
679

hjk's avatar
hjk committed
680
    case EngineSetupRequested:
681 682
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
683 684 685
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
686
    case EngineSetupOk:
hjk's avatar
hjk committed
687
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
688

hjk's avatar
hjk committed
689
    case InferiorSetupRequested:
690
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
691
    case InferiorSetupFailed:
hjk's avatar
hjk committed
692
        return to == EngineShutdownRequested;
693 694
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
695 696

    case EngineRunRequested:
hjk's avatar
hjk committed
697 698 699 700
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
701
    case EngineRunFailed:
702
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
703 704 705 706 707 708

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
709 710 711
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
712 713 714 715 716

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
717
            || to == InferiorStopOk || InferiorExitOk;
718
    case InferiorStopFailed:
hjk's avatar
hjk committed
719
        return to == EngineShutdownRequested;
720

721 722 723
    case InferiorExitOk:
        return to == InferiorShutdownOk;

724
    case InferiorUnrunnable:
hjk's avatar
hjk committed
725 726 727 728 729
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
730
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
731
        return to == EngineShutdownRequested;
732

hjk's avatar
hjk committed
733
    case EngineShutdownRequested:
734
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
735 736 737 738 739 740
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
741
        return to == EngineSetupRequested; // Happens on restart.
742 743
    }

744
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
745 746 747
    return false;
}

748 749
void DebuggerEngine::setupSlaveEngine()
{
750
    QTC_CHECK(state() == DebuggerNotReady);
751 752 753 754 755 756 757 758 759 760
    d->queueSetupEngine();
}

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

761
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
762
{
hjk's avatar
hjk committed
763
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
764
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
765
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
766
    if (isMasterEngine() && runControl())
767
        runControl()->startFailed();
hjk's avatar
hjk committed
768
    setState(DebuggerFinished);
hjk's avatar
hjk committed
769 770
}

771
void DebuggerEngine::notifyEngineSetupOk()
772
{
hjk's avatar
hjk committed
773
    showMessage(_("NOTE: ENGINE SETUP OK"));
774
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
775
    setState(EngineSetupOk);
hjk's avatar
hjk committed
776
    showMessage(_("QUEUE: SETUP INFERIOR"));
777
    if (isMasterEngine())
778 779 780 781 782
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
783
    QTC_CHECK(state() == EngineSetupOk);
784
    d->queueSetupInferior();
785 786
}

hjk's avatar
hjk committed
787
void DebuggerEnginePrivate::doSetupInferior()
788
{
789
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
790
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
791
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
792 793 794 795 796
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
797
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
798
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
799
    setState(InferiorSetupFailed);
800 801
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
802 803 804 805
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
806
    showMessage(_("NOTE: INFERIOR SETUP OK"));
807 808 809 810
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
811 812
}

813 814 815
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
816
    QTC_CHECK(state() == InferiorSetupOk);
817 818 819
    d->queueRunEngine();
}

hjk's avatar
hjk committed
820 821
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
822
    m_engine->showMessage(_("CALL: RUN ENGINE"));
823
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
824
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
825 826 827
    m_engine->runEngine();
}

hjk's avatar
hjk committed
828 829
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
830
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
831 832
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
833
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
834 835 836 837 838
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
839
    showMessage(_("NOTE: ENGINE RUN FAILED"));
840
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
841 842 843
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
844
    setState(EngineRunFailed);
845 846
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
847 848 849 850
}

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

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

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
869
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
870
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
871 872 873 874 875
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
876
    showMessage(_("NOTE: INFERIOR RUN OK"));
877 878 879
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
880 881 882 883 884
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
885
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
886
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
887 888
    setState(InferiorRunFai