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

#include "debuggerengine.h"

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

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

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

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

64 65 66
#include <projectexplorer/taskhub.h>
#include <extensionsystem/pluginmanager.h>

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

71 72 73 74 75
#include <QDebug>
#include <QTimer>
#include <QFile>
#include <QFileInfo>
#include <QFutureInterface>
76

77
#include <QMessageBox>
78

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

84 85 86 87
enum { debug = 0 };

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

89

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

96 97
namespace Debugger {

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

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
121
            << " processArgs=" << sp.processArgs
122 123 124 125 126 127 128
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
129
            << " useServerStartScript=" << sp.useServerStartScript
130
            << " 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
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
158
            DebuggerLanguages languages,
159
            const DebuggerStartParameters &sp)
160
      : m_engine(engine),
161
        m_masterEngine(masterEngine),
162 163
        m_runControl(0),
        m_startParameters(sp),
164
        m_languages(languages),
165
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
166
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
167
        m_targetState(DebuggerNotReady),
168
        m_remoteSetupState(RemoteSetupNone),
169
        m_inferiorPid(0),
170
        m_modulesHandler(),
171
        m_registerHandler(),
172 173
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
174
        m_threadsHandler(),
175
        m_watchHandler(engine),
176
        m_disassemblerAgent(engine),
177
        m_memoryAgent(engine),
178
        m_isStateDebugging(false),
179
        m_testsPossible(true),
180
        m_testsRunning(false),
181
        m_taskHub(0)
182
    {
183
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
184
        if (sp.toolChainAbi.os() == Abi::MacOS)
con's avatar
con committed
185
            m_disassemblerAgent.setTryMixed(false);
186
    }
187 188

    ~DebuggerEnginePrivate() {}
189

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

199 200 201 202 203 204 205 206 207 208 209 210 211 212
    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()));
    }

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

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

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

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

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

252
    void scheduleResetLocation()
253
    {
254
        m_stackHandler.scheduleResetLocation();
255
        m_watchHandler.scheduleResetLocation();
256
        m_threadsHandler.scheduleResetLocation();
257
        m_disassemblerAgent.scheduleResetLocation();
258 259 260 261
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

262
    void resetLocation()
263 264 265
    {
        m_locationTimer.stop();
        m_locationMark.reset();
266
        m_stackHandler.resetLocation();
267
        m_watchHandler.resetLocation();
268
        m_threadsHandler.resetLocation();
269
        m_disassemblerAgent.resetLocation();
270 271
    }

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

280
    DebuggerEngine *m_engine; // Not owned.
281
    DebuggerEngine *m_masterEngine; // Not owned
282 283 284
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
285
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
286 287

    // The current state.
288 289
    DebuggerState m_state;

hjk's avatar
hjk committed
290 291 292 293 294 295
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

296 297 298
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

299 300 301 302 303 304 305 306
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
307
    QtMessageLogHandler m_qtMessageHandler;
308
    QFutureInterface<void> m_progress;
309

310 311
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
312 313
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
314 315

    bool m_isStateDebugging;
316

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


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

338
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
339
        DebuggerLanguages languages,
340
        DebuggerEngine *parentEngine)
341
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
342
{
343
    d->m_inferiorPid = 0;
344 345 346 347
}

DebuggerEngine::~DebuggerEngine()
{
348 349
    disconnect();
    delete d;
350 351
}

352 353 354 355 356 357 358 359 360 361 362
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)
363
        SN(InferiorSetupOk)
364 365 366 367 368 369 370 371
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
372
        SN(InferiorExitOk)
373 374 375 376 377 378 379 380 381 382 383 384
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

385
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
386
{
387
    showMessage(msg, StatusBar, timeout);
388
}
389

390 391 392 393 394 395 396 397 398 399 400 401
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));
}

402 403 404 405 406
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

407 408
ModulesHandler *DebuggerEngine::modulesHandler() const
{
409 410 411
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
412 413 414 415
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
416 417 418
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
419 420 421 422
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
423 424 425
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
426 427 428 429
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
430 431 432
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
433 434 435 436
}

WatchHandler *DebuggerEngine::watchHandler() const
{
437 438 439
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
440 441
}

442 443 444 445 446
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

447 448
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
449 450 451
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
452 453 454 455
}

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

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

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

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
480
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
481 482 483
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
484 485 486 487
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
488
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
489 490 491
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
492 493 494 495
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
496
    QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
497 498 499
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
500 501 502 503
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
504
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
505 506 507
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
508 509
}

510 511 512 513 514 515 516 517
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

518 519
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
520
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
521 522 523
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
524 525
}

526 527 528 529 530 531 532 533
QAbstractItemModel *DebuggerEngine::qtMessageLogModel() const
{
    QAbstractItemModel *model = qtMessageLogHandler()->model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("QtMessageLogModel"));
    return model;
}

534
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
535 536 537 538 539 540
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
541 542 543 544 545 546 547
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

548 549 550 551 552 553 554 555
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
{
556 557 558 559
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
560 561
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
562 563 564
    if (channel == QtMessageLogOutput)
        qtMessageLogHandler()->appendMessage(QtMessageLogHandler::UndefinedType, msg);

565
    debuggerCore()->showMessage(msg, channel, timeout);
566 567 568 569 570
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
571 572 573 574
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
575 576
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
577

578
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
579
    Core::FutureProgress *fp = Core::ICore::progressManager()
580 581
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
582
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
583 584
    d->m_progress.reportStarted();

585 586 587 588
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
589 590
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
591

592 593
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
594

hjk's avatar
hjk committed
595
    debuggerCore()->action(OperateByInstruction)
596
        ->setEnabled(hasCapability(DisassemblerCapability));
597

598 599
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
600 601
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
602
    d->m_progress.setProgressValue(200);
603
    d->queueSetupEngine();
604 605 606 607
}

void DebuggerEngine::resetLocation()
{
608 609
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
610 611
}

612
void DebuggerEngine::gotoLocation(const Location &loc)
613
{
Aurindam Jana's avatar
Aurindam Jana committed
614 615
     d->resetLocation();

616 617 618 619
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
620 621 622 623 624
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


625 626
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
627 628
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
629
    IEditor *editor = 0;
hjk's avatar
hjk committed
630
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
631
        editor = editorManager->openEditor(file, Core::Id(),
632 633 634 635 636 637 638
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
639
    }
640
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
641 642 643
    if (texteditor)
        texteditor->gotoLine(line, 0);

644
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
645
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
646 647 648
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
649 650

    // FIXME: Breaks with split views.
651
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
652
        editorManager->activateEditor(editor);
653
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
654 655
}

656 657 658
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
659
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
660
    d->m_runControl = 0;
661
    d->m_progress.setProgressValue(900);
662 663
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
664 665
}

666 667
// Called from RunControl.
void DebuggerEngine::handleFinished()
668
{
669
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
670
    d->m_runControl = 0;
671 672
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

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

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


//////////////////////////////////////////////////////////////////////
//
// Dumpers. "Custom dumpers" are a library compiled against the current
// Qt containing functions to evaluate values of Qt classes
// (such as QString, taking pointers to their addresses).
// The library must be loaded into the debuggee.
//
//////////////////////////////////////////////////////////////////////

bool DebuggerEngine::qtDumperLibraryEnabled() const
{
hjk's avatar
hjk committed
701
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
702 703 704 705 706 707 708 709 710
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
711
    debuggerCore()->showQtDumperLibraryWarning(details);
712 713 714 715 716 717 718 719 720 721 722 723
}

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

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

hjk's avatar
hjk committed
724
DebuggerState DebuggerEngine::lastGoodState() const
725
{
hjk's avatar
hjk committed
726 727 728 729 730 731 732
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
734 735 736
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
737
    case DebuggerNotReady:
738
        return to == EngineSetupRequested;
739

hjk's avatar
hjk committed
740
    case EngineSetupRequested:
741 742
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
743 744 745
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
746
    case EngineSetupOk:
hjk's avatar
hjk committed
747
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
748

hjk's avatar
hjk committed
749
    case InferiorSetupRequested:
750
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
751
    case InferiorSetupFailed:
hjk's avatar
hjk committed
752
        return to == EngineShutdownRequested;
753 754
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
755 756

    case EngineRunRequested:
hjk's avatar
hjk committed
757 758 759 760
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
761
    case EngineRunFailed:
762
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
763 764 765 766 767 768

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
769 770 771
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
772 773 774 775 776

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
777
            || to == InferiorStopOk || InferiorExitOk;
778
    case InferiorStopFailed:
hjk's avatar
hjk committed
779
        return to == EngineShutdownRequested;
780

781 782 783
    case InferiorExitOk:
        return to == InferiorShutdownOk;

784
    case InferiorUnrunnable:
hjk's avatar
hjk committed
785 786 787 788 789
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
790
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
791
        return to == EngineShutdownRequested;
792

hjk's avatar
hjk committed
793
    case EngineShutdownRequested:
794
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
795 796 797 798 799 800
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
801
        return to == EngineSetupRequested; // Happens on restart.
802 803
    }

804
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
805 806 807
    return false;
}

808 809
void DebuggerEngine::setupSlaveEngine()
{
810
    QTC_CHECK(state() == DebuggerNotReady);
811 812 813 814 815 816 817 818 819 820
    d->queueSetupEngine();
}

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

821
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
822
{
hjk's avatar
hjk committed
823
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
824 825 826 827 828 829 830
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

831
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
832
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
833
    if (isMasterEngine() && runControl())
834
        runControl()->startFailed();
hjk's avatar
hjk committed
835
    setState(DebuggerFinished);
hjk's avatar
hjk committed
836 837
}

838
void DebuggerEngine::notifyEngineSetupOk()
839
{
hjk's avatar
hjk committed
840
    showMessage(_("NOTE: ENGINE SETUP OK"));
841 842 843 844
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

845
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
846
    setState(EngineSetupOk);
hjk's avatar
hjk committed
847
    showMessage(_("QUEUE: SETUP INFERIOR"));
848
    if (isMasterEngine())
849 850 851 852 853
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
854
    QTC_CHECK(state() == EngineSetupOk);
855
    d->queueSetupInferior();
856 857
}

hjk's avatar
hjk committed
858
void DebuggerEnginePrivate::doSetupInferior()
859
{
860
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
861
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
862
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
863 864 865 866 867
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
868
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
869
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
870
    setState(InferiorSetupFailed);
871 872
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
873 874 875 876
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
877
    showMessage(_("NOTE: INFERIOR SETUP OK"));
878 879 880 881
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
882 883
}

hjk's avatar