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

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

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

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

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

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

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

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

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

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

266 267
    TaskHub *taskHub();

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

276
    DebuggerEngine *m_engine; // Not owned.
277
    DebuggerEngine *m_masterEngine; // Not owned
278 279 280
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
281 282

    // The current state.
283 284
    DebuggerState m_state;

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

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

291 292 293
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

294 295 296 297 298 299 300 301
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
311

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


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

333 334
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
335 336
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
{}
337 338 339

DebuggerEngine::~DebuggerEngine()
{
340 341
    disconnect();
    delete d;
342 343
}

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

377
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
378
{
379
    showMessage(msg, StatusBar, timeout);
380
}
381

382 383 384 385 386 387 388 389 390 391 392 393
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));
}

394 395 396 397 398
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

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

RegisterHandler *DebuggerEngine::registerHandler() const
{
408 409 410
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
411 412 413 414
}

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

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
422 423 424
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
425 426 427 428
}

WatchHandler *DebuggerEngine::watchHandler() const
{
429 430 431
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
432 433
}

434 435 436 437 438
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

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

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

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

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

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

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

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

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

493 494
QAbstractItemModel *DebuggerEngine::inspectorModel() const
{
hjk's avatar
hjk committed
495
    return watchHandler()->model();
496 497
}

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

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

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

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

524
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
525 526 527 528 529 530
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

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

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

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
565 566
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
567

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

575 576 577 578
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
579 580
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
581

582 583
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
584

hjk's avatar
hjk committed
585
    debuggerCore()->action(OperateByInstruction)
586
        ->setEnabled(hasCapability(DisassemblerCapability));
587

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

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

602
void DebuggerEngine::gotoLocation(const Location &loc)
603
{
Aurindam Jana's avatar
Aurindam Jana committed
604 605
     d->resetLocation();

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


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

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

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

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

657 658
// Called from RunControl.
void DebuggerEngine::handleFinished()
659
{
660
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
661
    d->m_runControl = 0;
662 663
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
    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
685
DebuggerState DebuggerEngine::lastGoodState() const
686
{
hjk's avatar
hjk committed
687 688 689 690 691 692 693
    return d->m_lastGoodState;
}

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

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

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

hjk's avatar
hjk committed
710
    case InferiorSetupRequested:
711
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
712
    case InferiorSetupFailed:
hjk's avatar
hjk committed
713
        return to == EngineShutdownRequested;
714 715
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
716 717

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

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

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
738
            || to == InferiorStopOk || InferiorExitOk;
739
    case InferiorStopFailed:
hjk's avatar
hjk committed
740
        return to == EngineShutdownRequested;
741

742 743 744
    case InferiorExitOk:
        return to == InferiorShutdownOk;

745
    case InferiorUnrunnable:
hjk's avatar
hjk committed
746 747 748 749 750
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
751
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
752
        return to == EngineShutdownRequested;
753

hjk's avatar
hjk committed
754
    case EngineShutdownRequested:
755
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
756 757 758 759 760 761
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
762
        return to == EngineSetupRequested; // Happens on restart.
763 764
    }

765
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
766 767 768
    return false;
}

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

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

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

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

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

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

void DebuggerEngine::setupSlaveInferior()
{
815
    QTC_CHECK(state() == EngineSetupOk);
816
    d->queueSetupInferior();
817 818
}

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

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

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

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

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

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

void DebuggerEngine::notifyEngineRunFailed()
{