debuggerengine.cpp 59.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
        if (sp.toolChainAbi.os() == Abi::MacOS)
con's avatar
con committed
189
            m_disassemblerAgent.setTryMixed(false);
190
    }
191 192

    ~DebuggerEnginePrivate() {}
193

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

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

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

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

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

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

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

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

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

276 277
    TaskHub *taskHub();

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

286
    DebuggerEngine *m_engine; // Not owned.
287
    DebuggerEngine *m_masterEngine; // Not owned
288 289 290
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
291
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
292 293

    // The current state.
294 295
    DebuggerState m_state;

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

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

302 303 304
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

305 306 307 308 309 310 311 312
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
322

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


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

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

DebuggerEngine::~DebuggerEngine()
{
354 355
    disconnect();
    delete d;
356 357
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

532 533
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
534
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
535 536 537
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
538 539
}

540 541 542 543 544 545 546 547
QAbstractItemModel *DebuggerEngine::qtMessageLogModel() const
{
    QAbstractItemModel *model = qtMessageLogHandler()->model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("QtMessageLogModel"));
    return model;
}

548
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
549 550 551 552 553 554
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
555 556 557 558 559 560 561
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

562 563 564 565 566 567 568 569
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
{
570 571 572 573
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
574 575
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
576 577 578
    if (channel == QtMessageLogOutput)
        qtMessageLogHandler()->appendMessage(QtMessageLogHandler::UndefinedType, msg);

579
    debuggerCore()->showMessage(msg, channel, timeout);
580 581 582 583 584
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
585 586 587 588
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
589 590
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
591

592
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
593
    Core::FutureProgress *fp = Core::ICore::progressManager()
594 595
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
596
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
597 598
    d->m_progress.reportStarted();

599 600 601 602
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
603 604
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
605

606 607
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
608

hjk's avatar
hjk committed
609
    debuggerCore()->action(OperateByInstruction)
610
        ->setEnabled(hasCapability(DisassemblerCapability));
611

612 613
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
614 615
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
616
    d->m_progress.setProgressValue(200);
617
    d->queueSetupEngine();
618 619 620 621
}

void DebuggerEngine::resetLocation()
{
622 623
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
624 625
}

626
void DebuggerEngine::gotoLocation(const Location &loc)
627
{
Aurindam Jana's avatar
Aurindam Jana committed
628 629
     d->resetLocation();

Aurindam Jana's avatar
Aurindam Jana committed
630 631
    if ((hasCapability(OperateByInstructionCapability) &&
            debuggerCore()->boolSetting(OperateByInstruction)) || !loc.hasDebugInfo()) {
632 633 634
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
635 636 637 638 639
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


640 641
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
642 643
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
644
    IEditor *editor = 0;
hjk's avatar
hjk committed
645
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
646
        editor = editorManager->openEditor(file, Core::Id(),
647 648 649 650 651 652 653
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
654
    }
655
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
656 657 658
    if (texteditor)
        texteditor->gotoLine(line, 0);

659
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
660
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
661 662
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
663
        d->m_locationMark->init();
664
    }
665 666

    // FIXME: Breaks with split views.
667
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
668
        editorManager->activateEditor(editor);
669
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
670 671
}

672 673 674
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
675
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
676
    d->m_runControl = 0;
677
    d->m_progress.setProgressValue(900);
678 679
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
680 681
}

682 683
// Called from RunControl.
void DebuggerEngine::handleFinished()
684
{
685
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
686
    d->m_runControl = 0;
687 688
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
    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
717
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
718 719 720 721 722 723 724 725 726
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
727
    debuggerCore()->showQtDumperLibraryWarning(details);
728 729 730 731 732 733 734 735 736 737 738 739
}

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

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

hjk's avatar
hjk committed
740
DebuggerState DebuggerEngine::lastGoodState() const
741
{
hjk's avatar
hjk committed
742 743 744 745 746 747 748
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
750 751 752
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
753
    case DebuggerNotReady:
754
        return to == EngineSetupRequested;
755

hjk's avatar
hjk committed
756
    case EngineSetupRequested:
757 758
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
759 760 761
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
762
    case EngineSetupOk:
hjk's avatar
hjk committed
763
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
764

hjk's avatar
hjk committed
765
    case InferiorSetupRequested:
766
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
767
    case InferiorSetupFailed:
hjk's avatar
hjk committed
768
        return to == EngineShutdownRequested;
769 770
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
771 772

    case EngineRunRequested:
hjk's avatar
hjk committed
773 774 775 776
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
777
    case EngineRunFailed:
778
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
779 780 781 782 783 784

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
785 786 787
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
788 789 790 791 792

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
793
            || to == InferiorStopOk || InferiorExitOk;
794
    case InferiorStopFailed:
hjk's avatar
hjk committed
795
        return to == EngineShutdownRequested;
796

797 798 799
    case InferiorExitOk:
        return to == InferiorShutdownOk;

800
    case InferiorUnrunnable:
hjk's avatar
hjk committed
801 802 803 804 805
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
806
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
807
        return to == EngineShutdownRequested;
808

hjk's avatar
hjk committed
809
    case EngineShutdownRequested:
810
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
811 812 813 814 815 816
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
817
        return to == EngineSetupRequested; // Happens on restart.
818 819
    }

820
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
821 822 823
    return false;
}

824 825
void DebuggerEngine::setupSlaveEngine()
{
826
    QTC_CHECK(state() == DebuggerNotReady);
827 828 829 830 831 832 833 834 835 836
    d->queueSetupEngine();
}

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

837
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
838
{
hjk's avatar
hjk committed
839
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
840 841 842 843 844 845 846
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

847
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
848
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
849
    if (isMasterEngine() && runControl())
850
        runControl()->startFailed();
hjk's avatar
hjk committed
851
    setState(DebuggerFinished);
hjk's avatar
hjk committed
852 853
}

854
void DebuggerEngine::notifyEngineSetupOk()
855
{
hjk's avatar
hjk committed
856
    showMessage(_("NOTE: ENGINE SETUP OK"));
857 858 859 860
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

861
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
862
    setState(EngineSetupOk);
hjk's avatar
hjk committed
863
    showMessage(_("QUEUE: SETUP INFERIOR"));
864
    if (isMasterEngine())
865 866 867 868 869
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
870
    QTC_CHECK(state() == EngineSetupOk);
871
    d->queueSetupInferior();
872 873
}

hjk's avatar
hjk committed
874
void DebuggerEnginePrivate::doSetupInferior()
875
{
876
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
877
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
878
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
879 880 881 882 883
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
884
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));