debuggerengine.cpp 58.5 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

hjk's avatar
hjk committed
64
#include <projectexplorer/projectexplorer.h>
65 66
#include <projectexplorer/taskhub.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
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
93

94 95 96 97 98 99
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

100 101
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
102 103 104 105 106 107 108 109 110
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;
111
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
112 113
}

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

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

139

140 141 142 143 144 145
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

146 147 148 149 150 151 152 153 154
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

155
class DebuggerEnginePrivate : public QObject
156
{
157 158
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
191

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

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

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

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

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

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

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

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

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

274 275
    TaskHub *taskHub();

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

284
    DebuggerEngine *m_engine; // Not owned.
285
    DebuggerEngine *m_masterEngine; // Not owned
286 287 288
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
289
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
290 291

    // The current state.
292 293
    DebuggerState m_state;

hjk's avatar
hjk committed
294 295 296 297 298 299
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

300 301 302
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

303 304 305 306 307 308 309 310
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
311
    QtMessageLogHandler m_qtMessageHandler;
312
    QFutureInterface<void> m_progress;
313

314 315
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
316 317
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
318 319

    bool m_isStateDebugging;
320

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


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

342
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
343
        DebuggerLanguages languages,
344
        DebuggerEngine *parentEngine)
345
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
346
{
347
    d->m_inferiorPid = 0;
348 349 350 351
}

DebuggerEngine::~DebuggerEngine()
{
352 353
    disconnect();
    delete d;
354 355
}

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

389
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
390
{
391
    showMessage(msg, StatusBar, timeout);
392
}
393

394 395 396 397 398 399 400 401 402 403 404 405
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));
}

406 407 408 409 410
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

411 412
ModulesHandler *DebuggerEngine::modulesHandler() const
{
413 414 415
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
416 417 418 419
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
420 421 422
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
423 424 425 426
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
427 428 429
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
430 431 432 433
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
434 435 436
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
437 438 439 440
}

WatchHandler *DebuggerEngine::watchHandler() const
{
441 442 443
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
444 445
}

446 447 448 449 450
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

451 452
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
453 454 455
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
456 457 458 459
}

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

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

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

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

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

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

QAbstractItemModel *DebuggerEngine::returnModel() const
{
hjk's avatar
hjk committed
502
    return watchHandler()->model();
503 504
}

505 506
QAbstractItemModel *DebuggerEngine::inspectorModel() const
{
hjk's avatar
hjk committed
507
    return watchHandler()->model();
508 509
}

510 511
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
hjk's avatar
hjk committed
512 513 514 515 516 517
    return watchHandler()->model();
}

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

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

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

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

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

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

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

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

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

587 588 589 590
    d->m_runControl = runControl;

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

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

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

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

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

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

Aurindam Jana's avatar
Aurindam Jana committed
618 619
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
620 621 622
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
623 624 625 626 627
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


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

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

    // FIXME: Breaks with split views.
654
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
hjk's avatar
hjk committed
655
        EditorManager::activateEditor(editor);
656
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
657 658
}

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

669 670
// Called from RunControl.
void DebuggerEngine::handleFinished()
671
{
672
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
673
    d->m_runControl = 0;
674 675
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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 701 702 703
    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
704
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
705 706 707 708 709 710 711 712 713
}

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

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

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

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

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

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

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

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

hjk's avatar
hjk committed
752
    case InferiorSetupRequested:
753
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
754
    case InferiorSetupFailed:
hjk's avatar
hjk committed
755
        return to == EngineShutdownRequested;
756 757
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
758 759

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

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

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
780
            || to == InferiorStopOk || InferiorExitOk;
781
    case InferiorStopFailed:
hjk's avatar
hjk committed
782
        return to == EngineShutdownRequested;
783

784 785 786
    case InferiorExitOk:
        return to == InferiorShutdownOk;

787
    case InferiorUnrunnable:
hjk's avatar
hjk committed
788 789 790 791 792
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
793
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
794
        return to == EngineShutdownRequested;
795

hjk's avatar
hjk committed
796
    case EngineShutdownRequested:
797
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
798 799 800 801 802 803
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
804
        return to == EngineSetupRequested; // Happens on restart.
805 806
    }

807
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
808 809 810
    return false;
}

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

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

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

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

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

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

void DebuggerEngine::setupSlaveInferior()
{
857
    QTC_CHECK(state() == EngineSetupOk);
858
    d->queueSetupInferior();
859 860
}

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

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
871
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
872
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
873
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
874
    setState(InferiorSetupFailed);
875 876
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
877 878