debuggerengine.cpp 55.1 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 53
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

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

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

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

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

#include <QtCore/QDebug>
#include <QtCore/QTimer>
71
#include <QtCore/QFile>
72
#include <QtCore/QFileInfo>
73
#include <QtCore/QFutureInterface>
74

75
#include <QtGui/QMessageBox>
76

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

82 83 84 85
enum { debug = 0 };

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

87

88 89 90 91 92 93
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

94 95
namespace Debugger {

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

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

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

133

134 135 136 137 138 139
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

149
class DebuggerEnginePrivate : public QObject
150
{
151 152
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
186

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

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

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

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

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

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

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

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

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

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

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

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

    // The current state.
285 286
    DebuggerState m_state;

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

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

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

296 297 298 299 300 301 302 303
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
304
    QFutureInterface<void> m_progress;
305

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

    bool m_isStateDebugging;
312 313 314 315

    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
316
    void reportTestError(const QString &msg, int line);
317 318
    bool m_testsPossible;
    QStringList m_testContents;
319 320
    TaskHub *m_taskHub;
    QString m_testFileName;
321 322 323 324 325 326 327 328 329
};


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

330
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
331
        DebuggerLanguages languages,
332
        DebuggerEngine *parentEngine)
333
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
334
{
335
    d->m_inferiorPid = 0;
336 337 338 339
}

DebuggerEngine::~DebuggerEngine()
{
340 341
    disconnect();
    delete d;
342 343
}

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

377
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
378
{
379
    showMessage(msg, StatusBar, timeout);
380
}
381

382 383 384 385 386 387 388 389 390 391 392 393
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));
}

394 395 396 397 398
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

399 400
ModulesHandler *DebuggerEngine::modulesHandler() const
{
401 402 403
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
404 405 406 407
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
408 409 410
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
411 412 413 414
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
415 416 417 418
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
419 420 421 422
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
423 424 425
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
426 427 428 429
}

WatchHandler *DebuggerEngine::watchHandler() const
{
430 431 432
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
433 434 435 436
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
437 438 439
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
440 441 442 443
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
444
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
445 446 447
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
448 449 450 451
}

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

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

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

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

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

QAbstractItemModel *DebuggerEngine::returnModel() const
{
492
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
493 494 495
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
496 497
}

498 499 500 501 502 503 504 505
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

506 507
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
508
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
509 510 511
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
512 513
}

514
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
515 516 517 518 519 520
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
521 522 523 524 525 526 527
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

528 529 530 531 532 533 534 535
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
{
536 537 538 539
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
540 541
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
542
    debuggerCore()->showMessage(msg, channel, timeout);
543 544 545 546 547
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
548 549 550 551
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
552 553
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
554

555
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
556
    Core::FutureProgress *fp = Core::ICore::progressManager()
557 558
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
559
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
560 561
    d->m_progress.reportStarted();

562 563 564 565
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
566 567
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
568

569 570
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
571

hjk's avatar
hjk committed
572
    debuggerCore()->action(OperateByInstruction)
573
        ->setEnabled(hasCapability(DisassemblerCapability));
574

575 576
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
577 578
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
579
    d->m_progress.setProgressValue(200);
580
    d->queueSetupEngine();
581 582 583 584
}

void DebuggerEngine::resetLocation()
{
585 586
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
587 588
}

589
void DebuggerEngine::gotoLocation(const Location &loc)
590
{
Aurindam Jana's avatar
Aurindam Jana committed
591 592
     d->resetLocation();

593 594 595 596
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
597 598 599 600 601
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


602 603
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
604 605
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
606
    IEditor *editor = 0;
hjk's avatar
hjk committed
607
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
608
        editor = editorManager->openEditor(file, Core::Id(),
609 610 611 612 613 614 615
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
616
    }
617
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
618 619 620
    if (texteditor)
        texteditor->gotoLine(line, 0);

621 622 623 624 625 626
    if (loc.needsMarker()) {
        d->m_locationMark.reset(new TextEditor::BaseTextMark);
        d->m_locationMark->setLocation(file, line);
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
627 628

    // FIXME: Breaks with split views.
629
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
630
        editorManager->activateEditor(editor);
631
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
632 633
}

634 635 636
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
637
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
638
    d->m_runControl = 0;
639
    d->m_progress.setProgressValue(900);
640 641
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
642 643
}

644 645
// Called from RunControl.
void DebuggerEngine::handleFinished()
646
{
647
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
648
    d->m_runControl = 0;
649 650
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
    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
679
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
680 681 682 683 684 685 686 687 688
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
689
    debuggerCore()->showQtDumperLibraryWarning(details);
690 691 692 693 694 695 696 697 698 699 700 701
}

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

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

hjk's avatar
hjk committed
702
DebuggerState DebuggerEngine::lastGoodState() const
703
{
hjk's avatar
hjk committed
704 705 706 707 708 709 710
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
712 713 714
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
715
    case DebuggerNotReady:
716
        return to == EngineSetupRequested;
717

hjk's avatar
hjk committed
718
    case EngineSetupRequested:
719 720
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
721 722 723
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
724
    case EngineSetupOk:
hjk's avatar
hjk committed
725
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
726

hjk's avatar
hjk committed
727
    case InferiorSetupRequested:
728
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
729
    case InferiorSetupFailed:
hjk's avatar
hjk committed
730
        return to == EngineShutdownRequested;
731 732
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
733 734

    case EngineRunRequested:
hjk's avatar
hjk committed
735 736 737 738
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
739
    case EngineRunFailed:
740
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
741 742 743 744 745 746

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
747 748 749
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
750 751 752 753 754

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
755
            || to == InferiorStopOk || InferiorExitOk;
756
    case InferiorStopFailed:
hjk's avatar
hjk committed
757
        return to == EngineShutdownRequested;
758

759 760 761
    case InferiorExitOk:
        return to == InferiorShutdownOk;

762
    case InferiorUnrunnable:
hjk's avatar
hjk committed
763 764 765 766 767
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
768
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
769
        return to == EngineShutdownRequested;
770

hjk's avatar
hjk committed
771
    case EngineShutdownRequested:
772
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
773 774 775 776 777 778
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
779
        return to == EngineSetupRequested; // Happens on restart.
780 781
    }

782
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
783 784 785
    return false;
}

786 787
void DebuggerEngine::setupSlaveEngine()
{
788
    QTC_CHECK(state() == DebuggerNotReady);
789 790 791 792 793 794 795 796 797 798
    d->queueSetupEngine();
}

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

799
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
800
{
hjk's avatar
hjk committed
801
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
802 803 804 805 806 807 808
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

809
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
810
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
811
    if (isMasterEngine() && runControl())
812
        runControl()->startFailed();
hjk's avatar
hjk committed
813
    setState(DebuggerFinished);
hjk's avatar
hjk committed
814 815
}

816
void DebuggerEngine::notifyEngineSetupOk()
817
{
hjk's avatar
hjk committed
818
    showMessage(_("NOTE: ENGINE SETUP OK"));
819 820 821 822
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

823
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
824
    setState(EngineSetupOk);
hjk's avatar
hjk committed
825
    showMessage(_("QUEUE: SETUP INFERIOR"));
826
    if (isMasterEngine())
827 828 829 830 831
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
832
    QTC_CHECK(state() == EngineSetupOk);
833
    d->queueSetupInferior();
834 835
}

hjk's avatar
hjk committed
836
void DebuggerEnginePrivate::doSetupInferior()
837
{
838
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
839
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
840
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
841 842 843 844 845
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
847
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
848
    setState(InferiorSetupFailed);
849 850
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
851 852 853 854
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
855
    showMessage(_("NOTE: INFERIOR SETUP OK"));
856 857 858 859
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
860 861
}

862 863 864
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
865
    QTC_CHECK(state() == InferiorSetupOk);
866 867 868
    d->queueRunEngine();
}

hjk's avatar
hjk committed
869 870
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
871
    m_engine->showMessage(_("CALL: RUN ENGINE"));
872
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
873
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
874 875 876
    m_engine->runEngine();
}

hjk's avatar
hjk committed
877 878
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
879
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
880 881
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
882
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
883 884 885 886 887
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
888
    showMessage(_("NOTE: ENGINE RUN FAILED"));