debuggerengine.cpp 57.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
hjk's avatar
hjk committed
3 4
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29 30 31

#include "debuggerengine.h"

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

40 41
#include "memoryagent.h"
#include "disassembleragent.h"
42 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"

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

#include <texteditor/itexteditor.h>
58
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
59

hjk's avatar
hjk committed
60
#include <projectexplorer/projectexplorer.h>
61 62
#include <projectexplorer/taskhub.h>

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

67
#include <qmljs/consolemanagerinterface.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(engine),
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
    QFutureInterface<void> m_progress;
301

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

    bool m_isStateDebugging;
308

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


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

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

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

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

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

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

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

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

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

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

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

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

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
432 433 434
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
435 436 437 438
}

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

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

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

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
463
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
464 465 466
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
467 468 469 470
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
hjk's avatar
hjk committed
471
    return watchHandler()->model();
472 473 474 475
}

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

QAbstractItemModel *DebuggerEngine::returnModel() const
{
hjk's avatar
hjk committed
481
    return watchHandler()->model();
482 483
}

484 485
QAbstractItemModel *DebuggerEngine::inspectorModel() const
{
hjk's avatar
hjk committed
486
    return watchHandler()->model();
487 488
}

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

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

499 500
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
501
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
502 503 504
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
505 506
}

507
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
508 509 510 511 512 513
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
514 515 516 517 518 519 520
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

521 522 523 524 525 526 527 528
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
{
529 530 531 532
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
533 534
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
535
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
536
    if (channel == ConsoleOutput && consoleManager)
537
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
538

539
    debuggerCore()->showMessage(msg, channel, timeout);
540 541 542 543 544
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
545 546 547 548
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
549 550
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
551

552
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
553
    Core::FutureProgress *fp = Core::ICore::progressManager()
554 555
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
556
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
557 558
    d->m_progress.reportStarted();

559 560 561 562
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
563 564
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
565

566 567
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
568

hjk's avatar
hjk committed
569
    debuggerCore()->action(OperateByInstruction)
570
        ->setEnabled(hasCapability(DisassemblerCapability));
571

572 573
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
574 575
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
576
    d->m_progress.setProgressValue(200);
577
    d->queueSetupEngine();
578 579 580 581
}

void DebuggerEngine::resetLocation()
{
582 583
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
584 585
}

586
void DebuggerEngine::gotoLocation(const Location &loc)
587
{
Aurindam Jana's avatar
Aurindam Jana committed
588 589
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
590 591
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
592 593 594
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
595 596 597 598 599
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


600 601
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
602
    QList<IEditor *> editors = EditorManager::instance()->editorsForFileName(file);
603
    IEditor *editor = 0;
hjk's avatar
hjk committed
604
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
605
        editor = EditorManager::openEditor(file, Core::Id(),
606 607 608 609 610 611 612
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
613
    }
614
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
615 616 617
    if (texteditor)
        texteditor->gotoLine(line, 0);

618
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
619
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
620 621
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
622
        d->m_locationMark->init();
623
    }
624 625

    // FIXME: Breaks with split views.
626
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
hjk's avatar
hjk committed
627
        EditorManager::activateEditor(editor);
628
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
629 630
}

631 632 633
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
634
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
635
    d->m_runControl = 0;
636
    d->m_progress.setProgressValue(900);
637 638
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
639 640
}

641 642
// Called from RunControl.
void DebuggerEngine::handleFinished()
643
{
644
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
645
    d->m_runControl = 0;
646 647
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
    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
669
DebuggerState DebuggerEngine::lastGoodState() const
670
{
hjk's avatar
hjk committed
671 672 673 674 675 676 677
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
679 680 681
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
682
    case DebuggerNotReady:
683
        return to == EngineSetupRequested;
684

hjk's avatar
hjk committed
685
    case EngineSetupRequested:
686 687
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
688 689 690
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
691
    case EngineSetupOk:
hjk's avatar
hjk committed
692
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
693

hjk's avatar
hjk committed
694
    case InferiorSetupRequested:
695
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
696
    case InferiorSetupFailed:
hjk's avatar
hjk committed
697
        return to == EngineShutdownRequested;
698 699
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
700 701

    case EngineRunRequested:
hjk's avatar
hjk committed
702
        return to == EngineRunFailed
703
            || to == InferiorRunRequested
hjk's avatar
hjk committed
704 705 706
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
707
    case EngineRunFailed:
708
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
709 710 711 712 713 714

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
715 716 717
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
718 719 720 721 722

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
723
            || to == InferiorStopOk || InferiorExitOk;
724
    case InferiorStopFailed:
hjk's avatar
hjk committed
725
        return to == EngineShutdownRequested;
726

727 728 729
    case InferiorExitOk:
        return to == InferiorShutdownOk;

730
    case InferiorUnrunnable:
hjk's avatar
hjk committed
731 732 733 734 735
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
736
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
737
        return to == EngineShutdownRequested;
738

hjk's avatar
hjk committed
739
    case EngineShutdownRequested:
740
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
741 742 743 744 745 746
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
747
        return to == EngineSetupRequested; // Happens on restart.
748 749
    }

750
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
751 752 753
    return false;
}

754 755
void DebuggerEngine::setupSlaveEngine()
{
756
    QTC_CHECK(state() == DebuggerNotReady);
757 758 759 760 761 762 763 764 765 766
    d->queueSetupEngine();
}

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

767
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
768
{
hjk's avatar
hjk committed
769
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
770 771 772 773 774 775 776
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

777
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
778
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
779
    if (isMasterEngine() && runControl())
780
        runControl()->startFailed();
hjk's avatar
hjk committed
781
    setState(DebuggerFinished);
hjk's avatar
hjk committed
782 783
}

784
void DebuggerEngine::notifyEngineSetupOk()
785
{
hjk's avatar
hjk committed
786
    showMessage(_("NOTE: ENGINE SETUP OK"));
787 788 789 790
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

791
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
792
    setState(EngineSetupOk);
hjk's avatar
hjk committed
793
    showMessage(_("QUEUE: SETUP INFERIOR"));
794
    if (isMasterEngine())
795 796 797 798 799
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
800
    QTC_CHECK(state() == EngineSetupOk);
801
    d->queueSetupInferior();
802 803
}

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

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
814
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
815
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
816
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
817
    setState(InferiorSetupFailed);
818 819
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
820 821 822 823
}

void DebuggerEngine::notifyInferiorSetupOk()
{
824 825 826
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
827
    showMessage(_("NOTE: INFERIOR SETUP OK"));
828 829 830 831
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
832 833
}

834 835 836
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
837
    QTC_CHECK(state() == InferiorSetupOk);
838 839 840
    d->queueRunEngine();
}

hjk's avatar
hjk committed
841 842
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
843
    m_engine->showMessage(_("CALL: RUN ENGINE"));
844
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
845
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
846 847 848
    m_engine->runEngine();
}

hjk's avatar
hjk committed
849 850
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
851
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
852 853
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
854
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
855
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
856 857 858 859 860
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
861
    showMessage(_("NOTE: ENGINE RUN FAILED"));
862
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());