debuggerengine.cpp 57.1 KB
Newer Older
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
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.
**
28 29 30 31 32
**
**************************************************************************/

#include "debuggerengine.h"

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

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

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

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

hjk's avatar
hjk committed
62
#include <projectexplorer/projectexplorer.h>
63 64
#include <projectexplorer/taskhub.h>

65 66
#include <utils/savedaction.h>
#include <utils/qtcassert.h>
67
#include <utils/fileinprojectfinder.h>
68

69 70 71 72 73
#include <QDebug>
#include <QTimer>
#include <QFile>
#include <QFileInfo>
#include <QFutureInterface>
74

75
#include <QMessageBox>
76

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

82 83 84 85
enum { debug = 0 };

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

87 88 89 90
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
91

92 93 94 95 96 97
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

98 99
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
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
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
110 111
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
123
            << " processArgs=" << sp.processArgs
124 125 126 127 128 129 130
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " symbolFileName=" << sp.symbolFileName
            << " serverStartScript=" << sp.serverStartScript
131
            << " abi=" << sp.toolChainAbi.toString() << '\n';
132 133 134
    return str;
}

135

136 137 138 139 140 141
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

142 143 144 145 146 147 148 149 150
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

151
class DebuggerEnginePrivate : public QObject
152
{
153 154
    Q_OBJECT

155
public:
156
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
157
      : m_engine(engine),
158
        m_masterEngine(0),
159 160 161
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
162
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
163
        m_targetState(DebuggerNotReady),
164
        m_remoteSetupState(RemoteSetupNone),
165
        m_inferiorPid(0),
166
        m_modulesHandler(),
167
        m_registerHandler(),
168 169
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
170
        m_threadsHandler(),
171
        m_watchHandler(engine),
172
        m_disassemblerAgent(engine),
173
        m_memoryAgent(engine),
174
        m_isStateDebugging(false),
175
        m_testsPossible(true),
176
        m_testsRunning(false),
177
        m_taskHub(0)
178
    {
179
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
180
    }
181

182
public slots:
183
    void doSetupEngine();
hjk's avatar
hjk committed
184 185
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
186 187
    void doShutdownEngine();
    void doShutdownInferior();
188
    void doInterruptInferior();
hjk's avatar
hjk committed
189
    void doFinishDebugger();
hjk's avatar
hjk committed
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204
    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()));
    }

205 206
    void queueRunEngine()
    {
hjk's avatar
hjk committed
207 208 209 210 211
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

212 213
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
214 215 216 217 218
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

219 220
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
221 222 223 224 225
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

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

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

244
    void scheduleResetLocation()
245
    {
246
        m_stackHandler.scheduleResetLocation();
247
        m_watchHandler.scheduleResetLocation();
248
        m_threadsHandler.scheduleResetLocation();
249
        m_disassemblerAgent.scheduleResetLocation();
250 251 252 253
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

254
    void resetLocation()
255 256 257
    {
        m_locationTimer.stop();
        m_locationMark.reset();
258
        m_stackHandler.resetLocation();
259
        m_watchHandler.resetLocation();
260
        m_threadsHandler.resetLocation();
261
        m_disassemblerAgent.resetLocation();
262 263
    }

264 265
    TaskHub *taskHub();

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

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

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
279 280

    // The current state.
281 282
    DebuggerState m_state;

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

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

289 290 291
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

292 293 294 295 296 297 298 299
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
300
    QtMessageLogHandler m_qtMessageHandler;
301
    QFutureInterface<void> m_progress;
302

303 304
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
305 306
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
307 308

    bool m_isStateDebugging;
309

310
    Utils::FileInProjectFinder m_fileFinder;
311 312 313
    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
314
    void reportTestError(const QString &msg, int line);
315
    bool m_testsPossible;
316
    bool m_testsRunning;
David Schulz's avatar
David Schulz committed
317 318
    bool m_breakOnError;
    bool m_foundError;
319
    QStringList m_testContents;
320 321
    TaskHub *m_taskHub;
    QString m_testFileName;
322 323 324 325 326 327 328 329 330
};


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

331 332
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
333
{}
334 335 336

DebuggerEngine::~DebuggerEngine()
{
337 338
    disconnect();
    delete d;
339 340
}

341 342 343 344 345 346 347 348 349 350 351
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)
352
        SN(InferiorSetupOk)
353 354 355 356 357 358 359 360
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
361
        SN(InferiorExitOk)
362 363 364 365 366 367 368 369 370 371 372 373
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

374
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
375
{
376
    showMessage(msg, StatusBar, timeout);
377
}
378

379 380 381 382 383 384 385 386 387 388 389 390
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));
}

391 392 393 394 395
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

396 397
ModulesHandler *DebuggerEngine::modulesHandler() const
{
398 399 400
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
401 402 403 404
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
405 406 407
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
408 409 410 411
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
412 413 414
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
415 416 417 418
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
419 420 421
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
422 423 424 425
}

WatchHandler *DebuggerEngine::watchHandler() const
{
426 427 428
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
429 430
}

431 432 433 434 435
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

436 437
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
438 439 440
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
441 442 443 444
}

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

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

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

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

QAbstractItemModel *DebuggerEngine::localsModel() const
{
hjk's avatar
hjk committed
477
    return watchHandler()->model();
478 479 480 481
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
hjk's avatar
hjk committed
482
    return watchHandler()->model();
483 484 485 486
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
hjk's avatar
hjk committed
487
    return watchHandler()->model();
488 489
}

490 491
QAbstractItemModel *DebuggerEngine::inspectorModel() const
{
hjk's avatar
hjk committed
492
    return watchHandler()->model();
493 494
}

495 496
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
hjk's avatar
hjk committed
497 498 499 500 501 502
    return watchHandler()->model();
}

QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
503 504
}

505 506
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
507
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
508 509 510
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
511 512
}

513 514 515 516 517 518 519 520
QAbstractItemModel *DebuggerEngine::qtMessageLogModel() const
{
    QAbstractItemModel *model = qtMessageLogHandler()->model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("QtMessageLogModel"));
    return model;
}

521
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
522 523 524 525 526 527
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
528 529 530 531 532 533 534
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

535 536 537 538 539 540 541 542
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
{
543 544 545 546
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
547 548
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
549 550 551
    if (channel == QtMessageLogOutput)
        qtMessageLogHandler()->appendMessage(QtMessageLogHandler::UndefinedType, msg);

552
    debuggerCore()->showMessage(msg, channel, timeout);
553 554 555 556 557
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
558 559 560 561
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
562 563
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
564

565
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
566
    Core::FutureProgress *fp = Core::ICore::progressManager()
567 568
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
569
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
570 571
    d->m_progress.reportStarted();

572 573 574 575
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
576 577
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
578

579 580
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
581

hjk's avatar
hjk committed
582
    debuggerCore()->action(OperateByInstruction)
583
        ->setEnabled(hasCapability(DisassemblerCapability));
584

585 586
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
587 588
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
589
    d->m_progress.setProgressValue(200);
590
    d->queueSetupEngine();
591 592 593 594
}

void DebuggerEngine::resetLocation()
{
595 596
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
597 598
}

599
void DebuggerEngine::gotoLocation(const Location &loc)
600
{
Aurindam Jana's avatar
Aurindam Jana committed
601 602
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
603 604
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
605 606 607
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
608 609 610 611 612
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


613 614
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
615
    QList<IEditor *> editors = EditorManager::instance()->editorsForFileName(file);
616
    IEditor *editor = 0;
hjk's avatar
hjk committed
617
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
618
        editor = EditorManager::openEditor(file, Core::Id(),
619 620 621 622 623 624 625
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
626
    }
627
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
628 629 630
    if (texteditor)
        texteditor->gotoLine(line, 0);

631
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
632
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
633 634
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
635
        d->m_locationMark->init();
636
    }
637 638

    // FIXME: Breaks with split views.
639
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
hjk's avatar
hjk committed
640
        EditorManager::activateEditor(editor);
641
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
642 643
}

644 645 646
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
647
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
648
    d->m_runControl = 0;
649
    d->m_progress.setProgressValue(900);
650 651
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
652 653
}

654 655
// Called from RunControl.
void DebuggerEngine::handleFinished()
656
{
657
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
658
    d->m_runControl = 0;
659 660
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

const DebuggerStartParameters &DebuggerEngine::startParameters() const
{
    return d->m_startParameters;
}

DebuggerStartParameters &DebuggerEngine::startParameters()
{
    return d->m_startParameters;
}

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

hjk's avatar
hjk committed
682
DebuggerState DebuggerEngine::lastGoodState() const
683
{
hjk's avatar
hjk committed
684 685 686 687 688 689 690
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
692 693 694
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
695
    case DebuggerNotReady:
696
        return to == EngineSetupRequested;
697

hjk's avatar
hjk committed
698
    case EngineSetupRequested:
699 700
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
701 702 703
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
704
    case EngineSetupOk:
hjk's avatar
hjk committed
705
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
706

hjk's avatar
hjk committed
707
    case InferiorSetupRequested:
708
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
709
    case InferiorSetupFailed:
hjk's avatar
hjk committed
710
        return to == EngineShutdownRequested;
711 712
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
713 714

    case EngineRunRequested:
hjk's avatar
hjk committed
715 716 717 718
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
719
    case EngineRunFailed:
720
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
721 722 723 724 725 726

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
727 728 729
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
730 731 732 733 734

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
735
            || to == InferiorStopOk || InferiorExitOk;
736
    case InferiorStopFailed:
hjk's avatar
hjk committed
737
        return to == EngineShutdownRequested;
738

739 740 741
    case InferiorExitOk:
        return to == InferiorShutdownOk;

742
    case InferiorUnrunnable:
hjk's avatar
hjk committed
743 744 745 746 747
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
748
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
749
        return to == EngineShutdownRequested;
750

hjk's avatar
hjk committed
751
    case EngineShutdownRequested:
752
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
753 754 755 756 757 758
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
759
        return to == EngineSetupRequested; // Happens on restart.
760 761
    }

762
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
763 764 765
    return false;
}

766 767
void DebuggerEngine::setupSlaveEngine()
{
768
    QTC_CHECK(state() == DebuggerNotReady);
769 770 771 772 773 774 775 776 777 778
    d->queueSetupEngine();
}

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

779
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
780
{
hjk's avatar
hjk committed
781
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
782 783 784 785 786 787 788
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

789
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
790
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
791
    if (isMasterEngine() && runControl())
792
        runControl()->startFailed();
hjk's avatar
hjk committed
793
    setState(DebuggerFinished);
hjk's avatar
hjk committed
794 795
}

796
void DebuggerEngine::notifyEngineSetupOk()
797
{
hjk's avatar
hjk committed
798
    showMessage(_("NOTE: ENGINE SETUP OK"));
799 800 801 802
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

803
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
804
    setState(EngineSetupOk);
hjk's avatar
hjk committed
805
    showMessage(_("QUEUE: SETUP INFERIOR"));
806
    if (isMasterEngine())
807 808 809 810 811
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
812
    QTC_CHECK(state() == EngineSetupOk);
813
    d->queueSetupInferior();
814 815
}

hjk's avatar
hjk committed
816
void DebuggerEnginePrivate::doSetupInferior()
817
{
818
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
819
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
820
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
821 822 823 824 825
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
826
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
827
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
828
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
829
    setState(InferiorSetupFailed);
830 831
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
832 833 834 835
}

void DebuggerEngine::notifyInferiorSetupOk()
{
836 837 838
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
839
    showMessage(_("NOTE: INFERIOR SETUP OK"));
840 841 842 843
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
844 845
}

846 847 848
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
849
    QTC_CHECK(state() == InferiorSetupOk);
850 851 852
    d->queueRunEngine();
}

hjk's avatar
hjk committed
853 854
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
855
    m_engine->showMessage(_("CALL: RUN ENGINE"));
856
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
857
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
858 859 860
    m_engine->runEngine();
}

hjk's avatar
hjk committed
861 862
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
863
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
864 865
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
866
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
867
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
868 869 870 871 872
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed