debuggerengine.cpp 56.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 69
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

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

76
#include <QMessageBox>
77

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

83 84 85 86
enum { debug = 0 };

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

88

89 90 91 92 93 94
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

95 96
namespace Debugger {

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

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
120
            << " processArgs=" << sp.processArgs
121 122 123 124 125 126 127
            << " 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
128
            << " useServerStartScript=" << sp.useServerStartScript
129
            << " serverStartScript=" << sp.serverStartScript
130
            << " abi=" << sp.toolChainAbi.toString() << '\n';
131 132 133
    return str;
}

134

135 136 137 138 139 140
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

150
class DebuggerEnginePrivate : public QObject
151
{
152 153
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
187

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

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

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

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

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

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

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

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

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

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

278
    DebuggerEngine *m_engine; // Not owned.
279
    DebuggerEngine *m_masterEngine; // Not owned
280 281 282
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
283
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
284 285

    // The current state.
286 287
    DebuggerState m_state;

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

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

294 295 296
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

297 298 299 300 301 302 303 304
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
314 315 316 317

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


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

334
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
335
        DebuggerLanguages languages,
336
        DebuggerEngine *parentEngine)
337
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
338
{
339
    d->m_inferiorPid = 0;
340 341 342 343
}

DebuggerEngine::~DebuggerEngine()
{
344 345
    disconnect();
    delete d;
346 347
}

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

381
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
382
{
383
    showMessage(msg, StatusBar, timeout);
384
}
385

386 387 388 389 390 391 392 393 394 395 396 397
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));
}

398 399 400 401 402
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

403 404
ModulesHandler *DebuggerEngine::modulesHandler() const
{
405 406 407
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
408 409 410 411
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
412 413 414
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
415 416 417 418
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
419 420 421 422
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
423 424 425 426
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
427 428 429
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
430 431 432 433
}

WatchHandler *DebuggerEngine::watchHandler() const
{
434 435 436
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
437 438
}

439 440 441 442 443
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

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

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

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

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

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

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

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

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

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

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

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

531
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
532 533 534 535 536 537
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

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

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

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
572 573
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
574

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

582 583 584 585
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
586 587
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
588

589 590
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
591

hjk's avatar
hjk committed
592
    debuggerCore()->action(OperateByInstruction)
593
        ->setEnabled(hasCapability(DisassemblerCapability));
594

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

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

609
void DebuggerEngine::gotoLocation(const Location &loc)
610
{
Aurindam Jana's avatar
Aurindam Jana committed
611 612
     d->resetLocation();

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


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

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

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

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

663 664
// Called from RunControl.
void DebuggerEngine::handleFinished()
665
{
666
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
667
    d->m_runControl = 0;
668 669
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
670 671 672 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
    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
698
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
699 700 701 702 703 704 705 706 707
}

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

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

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

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

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

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

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

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

hjk's avatar
hjk committed
746
    case InferiorSetupRequested:
747
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
748
    case InferiorSetupFailed:
hjk's avatar
hjk committed
749
        return to == EngineShutdownRequested;
750 751
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
752 753

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

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

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
774
            || to == InferiorStopOk || InferiorExitOk;
775
    case InferiorStopFailed:
hjk's avatar
hjk committed
776
        return to == EngineShutdownRequested;
777

778 779 780
    case InferiorExitOk:
        return to == InferiorShutdownOk;

781
    case InferiorUnrunnable:
hjk's avatar
hjk committed
782 783 784 785 786
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
787
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
788
        return to == EngineShutdownRequested;
789

hjk's avatar
hjk committed
790
    case EngineShutdownRequested:
791
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
792 793 794 795 796 797
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
798
        return to == EngineSetupRequested; // Happens on restart.
799 800
    }

801
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
802 803 804
    return false;
}

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

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

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

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

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

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

void DebuggerEngine::setupSlaveInferior()
{
851
    QTC_CHECK(state() == EngineSetupOk);
852
    d->queueSetupInferior();
853 854
}

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

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

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

881 882 883
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
884
    QTC_CHECK(state() == InferiorSetupOk);
885 886 887
    d->queueRunEngine();
}

hjk's avatar
hjk committed
888 889
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
890
    m_engine->showMessage(_("CALL: RUN ENGINE"));