debuggerengine.cpp 56.8 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 180
        m_testsPossible(true),
        m_taskHub(0)
181
    {
182
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
183
        if (sp.toolChainAbi.os() == Abi::MacOS)
con's avatar
con committed
184
            m_disassemblerAgent.setTryMixed(false);
185
    }
186 187

    ~DebuggerEnginePrivate() {}
188

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

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

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

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

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

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

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

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

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

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

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

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

    // The current state.
287 288
    DebuggerState m_state;

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

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

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

298 299 300 301 302 303 304 305
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
315

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


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

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

DebuggerEngine::~DebuggerEngine()
{
346 347
    disconnect();
    delete d;
348 349
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

583 584 585 586
    d->m_runControl = runControl;

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

882 883 884
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
885
    QTC_CHECK(state() == InferiorSetupOk);