debuggerengine.cpp 58.5 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3 4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
Eike Ziller's avatar
Eike Ziller committed
12 13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24
**
Eike Ziller's avatar
Eike Ziller committed
25 26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
30 31 32

#include "debuggerengine.h"

33
#include "debuggerinternalconstants.h"
34
#include "debuggeractions.h"
35
#include "debuggercore.h"
36
#include "debuggerruncontrol.h"
37
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
38
#include "debuggerstartparameters.h"
39
#include "debuggertooltipmanager.h"
40 41

#include "breakhandler.h"
David Schulz's avatar
David Schulz committed
42
#include "disassembleragent.h"
43
#include "logwindow.h"
David Schulz's avatar
David Schulz committed
44
#include "memoryagent.h"
45
#include "moduleshandler.h"
46
#include "gdb/gdbengine.h" // REMOVE
47 48 49
#include "registerhandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
50
#include "terminal.h"
51 52
#include "threadshandler.h"
#include "watchhandler.h"
53
#include <debugger/shared/peutils.h>
54

hjk's avatar
hjk committed
55
#include <coreplugin/editormanager/editormanager.h>
56
#include <coreplugin/editormanager/ieditor.h>
hjk's avatar
hjk committed
57
#include <coreplugin/icore.h>
58
#include <coreplugin/idocument.h>
59
#include <coreplugin/messagebox.h>
60 61
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
62

hjk's avatar
hjk committed
63
#include <projectexplorer/projectexplorer.h>
64 65
#include <projectexplorer/taskhub.h>

66
#include <texteditor/texteditor.h>
67

68
#include <utils/fileinprojectfinder.h>
hjk's avatar
hjk committed
69 70 71
#include <utils/macroexpander.h>
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
72

73
#include <qmljs/consolemanagerinterface.h>
74

75 76 77
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
78
#include <QDir>
79

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

85 86 87 88
enum { debug = 0 };

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

90 91 92 93
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
94

hjk's avatar
hjk committed
95 96 97
// VariableManager Prefix
const char PrefixDebugExecutable[]  = "DebuggedExecutable";

98 99
namespace Debugger {

100 101
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
102 103
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
104 105
}

106
QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
107 108 109 110
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
111
            << " processArgs=" << sp.processArgs
112 113 114 115 116 117
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " serverStartScript=" << sp.serverStartScript
118
            << " abi=" << sp.toolChainAbi.toString() << '\n';
119 120 121
    return str;
}

hjk's avatar
hjk committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135
namespace 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;
    m_from = frame.from;
}

136

137 138 139 140 141 142
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

152 153 154 155 156 157
struct TypeInfo
{
    TypeInfo(uint s = 0) : size(s) {}
    uint size;
};

158
class DebuggerEnginePrivate : public QObject
159
{
160 161
    Q_OBJECT

162
public:
163
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerRunParameters &sp)
164
      : m_engine(engine),
165
        m_masterEngine(0),
166
        m_runControl(0),
167
        m_runParameters(sp),
168
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
169
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
170
        m_targetState(DebuggerNotReady),
171
        m_remoteSetupState(RemoteSetupNone),
172
        m_inferiorPid(0),
173
        m_modulesHandler(engine),
174
        m_registerHandler(),
175 176
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
177
        m_threadsHandler(),
178
        m_watchHandler(engine),
179
        m_disassemblerAgent(engine),
180
        m_memoryAgent(engine),
181
        m_isStateDebugging(false)
182
    {
hjk's avatar
hjk committed
183 184 185 186
        connect(&m_locationTimer, &QTimer::timeout,
                this, &DebuggerEnginePrivate::resetLocation);
        connect(action(IntelFlavor), &Utils::SavedAction::valueChanged,
                this, &DebuggerEnginePrivate::reloadDisassembly);
187 188 189
        connect(action(OperateNativeMixed), &QAction::triggered,
                engine, &DebuggerEngine::reloadFullStack);

hjk's avatar
hjk committed
190
        Utils::globalMacroExpander()->registerFileVariables(PrefixDebugExecutable,
191
            tr("Debugged executable"),
192
            [this]() { return m_runParameters.executable; });
193
    }
194

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

204 205 206 207 208
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

209 210 211 212 213 214 215 216 217 218 219 220 221 222
    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()));
    }

223 224
    void queueRunEngine()
    {
hjk's avatar
hjk committed
225 226 227 228 229
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

230 231
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
232 233 234 235 236
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

237 238
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
239 240 241 242 243
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

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

256 257
    void raiseApplication()
    {
258 259
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
260 261
    }

262
    void scheduleResetLocation()
263
    {
264
        m_stackHandler.scheduleResetLocation();
265
        m_watchHandler.scheduleResetLocation();
266
        m_threadsHandler.scheduleResetLocation();
267
        m_disassemblerAgent.scheduleResetLocation();
268 269 270 271
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

272
    void resetLocation()
273 274 275
    {
        m_locationTimer.stop();
        m_locationMark.reset();
276
        m_stackHandler.resetLocation();
277
        m_watchHandler.resetLocation();
278
        m_threadsHandler.resetLocation();
279
        m_disassemblerAgent.resetLocation();
hjk's avatar
hjk committed
280
        DebuggerToolTipManager::resetLocation();
281 282
    }

283
public:
hjk's avatar
hjk committed
284
    DebuggerState state() const { return m_state; }
285
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
286 287 288
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
289
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
290

291
    DebuggerEngine *m_engine; // Not owned.
292
    DebuggerEngine *m_masterEngine; // Not owned
293 294
    DebuggerRunControl *m_runControl;  // Not owned.

295
    DebuggerRunParameters m_runParameters;
hjk's avatar
hjk committed
296 297

    // The current state.
298 299
    DebuggerState m_state;

hjk's avatar
hjk committed
300 301 302 303 304 305
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

306 307 308
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

309
    Terminal m_terminal;
310 311 312 313 314 315 316 317
    qint64 m_inferiorPid;

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

320 321
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
322
    QScopedPointer<TextMark> m_locationMark;
323
    QTimer m_locationTimer;
324 325

    bool m_isStateDebugging;
326

327
    Utils::FileInProjectFinder m_fileFinder;
328 329
    QHash<QByteArray, TypeInfo> m_typeInfoCache;
    QByteArray m_qtNamespace;
330 331 332 333 334 335 336 337 338
};


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

339
DebuggerEngine::DebuggerEngine(const DebuggerRunParameters &startParameters)
340
  : d(new DebuggerEnginePrivate(this, startParameters))
341
{}
342 343 344

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

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

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

386 387 388 389 390 391 392 393 394 395 396 397
void DebuggerEngine::frameUp()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
}

void DebuggerEngine::frameDown()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMax(currentIndex - 1, 0));
}

398 399 400 401
void DebuggerEngine::doUpdateLocals(const UpdateParameters &)
{
}

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

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

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

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

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

WatchHandler *DebuggerEngine::watchHandler() const
{
437 438 439
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
440 441 442 443
}

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

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
451
   return modulesHandler()->model();
452 453 454 455
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
456
    return registerHandler()->model();
457 458 459 460
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
461
    return stackHandler()->model();
462 463 464 465
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
466
    return threadsHandler()->model();
467 468
}

hjk's avatar
hjk committed
469 470 471
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
472 473
}

474 475
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
476
    return sourceFilesHandler()->model();
477 478
}

479
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
480 481 482 483 484 485
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
486 487 488 489 490 491 492
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

hjk's avatar
hjk committed
493
void DebuggerEngine::setRegisterValue(const QByteArray &name, const QString &value)
494
{
hjk's avatar
hjk committed
495
    Q_UNUSED(name);
496 497 498 499 500
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
501 502 503 504
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
505 506
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
507
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
508
    if (channel == ConsoleOutput && consoleManager)
509
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
510

511
    Internal::showMessage(msg, channel, timeout);
512 513 514 515 516 517 518 519 520 521 522 523 524
    if (d->m_runControl) {
        switch (channel) {
            case AppOutput:
                d->m_runControl->appendMessage(msg, Utils::StdOutFormatSameLine);
                break;
            case AppError:
                d->m_runControl->appendMessage(msg, Utils::StdErrFormatSameLine);
                break;
            case AppStuff:
                d->m_runControl->appendMessage(msg, Utils::DebugFormat);
                break;
        }
    } else {
525
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
526
    }
527 528 529 530
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
531 532
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
533

534
    d->m_progress.setProgressRange(0, 1000);
535
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
536
        tr("Launching Debugger"), "Debugger.Launcher");
hjk's avatar
hjk committed
537
    connect(fp, &FutureProgress::canceled, this, &DebuggerEngine::quitDebugger);
538
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
539 540
    d->m_progress.reportStarted();

541 542
    d->m_runControl = runControl;

543 544
    d->m_inferiorPid = d->m_runParameters.attachPID > 0
        ? d->m_runParameters.attachPID : 0;
545 546
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
547

548 549
    if (!d->m_runParameters.environment.size())
        d->m_runParameters.environment = Utils::Environment();
550

551 552 553
    if (isNativeMixedActive())
        d->m_runParameters.environment.set(QLatin1String("QV4_FORCE_INTERPRETER"), QLatin1String("1"));

hjk's avatar
hjk committed
554
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
555

556 557
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
558 559
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
560
    d->m_progress.setProgressValue(200);
561 562 563 564 565 566 567 568 569 570 571 572 573 574

    d->m_terminal.setup();
    if (d->m_terminal.isUsable()) {
        connect(&d->m_terminal, &Terminal::stdOutReady, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::StdOutFormatSameLine);
        });
        connect(&d->m_terminal, &Terminal::stdErrReady, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::StdErrFormatSameLine);
        });
        connect(&d->m_terminal, &Terminal::error, [this, runControl](const QString &msg) {
            runControl->appendMessage(msg, Utils::ErrorMessageFormat);
        });
    }

575
    d->queueSetupEngine();
576 577 578 579
}

void DebuggerEngine::resetLocation()
{
580 581
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
582 583
}

584
void DebuggerEngine::gotoLocation(const Location &loc)
585
{
Aurindam Jana's avatar
Aurindam Jana committed
586 587
     d->resetLocation();

588 589 590 591
    if (loc.canBeDisassembled()
            && ((hasCapability(OperateByInstructionCapability) && boolSetting(OperateByInstruction))
                || !loc.hasDebugInfo()) )
    {
592 593 594
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
595

596 597 598 599
    if (loc.fileName().isEmpty()) {
        showMessage(QLatin1String("CANNOT GO TO THIS LOCATION"));
        return;
    }
600
    const QString file = QDir::cleanPath(loc.fileName());
601
    const int line = loc.lineNumber();
602
    bool newEditor = false;
603
    IEditor *editor = EditorManager::openEditor(file, Id(),
604 605
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
606

hjk's avatar
hjk committed
607
    editor->gotoLine(line, 0, !boolSetting(StationaryEditorWhileStepping));
608

609 610
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
611

612
    if (loc.needsMarker()) {
613
        d->m_locationMark.reset(new TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION));
614
        d->m_locationMark->setIcon(Internal::locationMarkIcon());
615
        d->m_locationMark->setPriority(TextMark::HighPriority);
616
    }
617 618

    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
619 620
}

621 622 623
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
624
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
625
    d->m_runControl = 0;
626
    d->m_progress.setProgressValue(900);
627 628
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
629 630
}

631 632
// Called from RunControl.
void DebuggerEngine::handleFinished()
633
{
634
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
635
    d->m_runControl = 0;
636 637
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
638 639 640 641 642 643
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

644
const DebuggerRunParameters &DebuggerEngine::runParameters() const
645
{
646
    return d->m_runParameters;
647 648
}

649
DebuggerRunParameters &DebuggerEngine::runParameters()
650
{
651
    return d->m_runParameters;
652 653 654 655 656 657 658
}

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

hjk's avatar
hjk committed
659
DebuggerState DebuggerEngine::lastGoodState() const
660
{
hjk's avatar
hjk committed
661 662 663 664 665 666 667
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
669 670 671
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
672
    case DebuggerNotReady:
673
        return to == EngineSetupRequested;
674

hjk's avatar
hjk committed
675
    case EngineSetupRequested:
676 677
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
678 679 680
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
681
    case EngineSetupOk:
hjk's avatar
hjk committed
682
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
683

hjk's avatar
hjk committed
684
    case InferiorSetupRequested:
685
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
686
    case InferiorSetupFailed:
hjk's avatar
hjk committed
687
        return to == EngineShutdownRequested;
688 689
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
690 691

    case EngineRunRequested:
hjk's avatar
hjk committed
692
        return to == EngineRunFailed
693
            || to == InferiorRunRequested
hjk's avatar
hjk committed
694 695 696
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
697
    case EngineRunFailed:
698
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
699 700 701 702 703 704

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
705
        return to == InferiorStopRequested
706 707
            || to == InferiorStopOk       // A spontaneous stop.
            || to == InferiorShutdownOk;  // A spontaneous exit.
hjk's avatar
hjk committed
708 709 710 711 712

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
713
            || to == InferiorStopOk || to == InferiorShutdownOk;
714
    case InferiorStopFailed:
hjk's avatar
hjk committed
715
        return to == EngineShutdownRequested;
716 717

    case InferiorUnrunnable:
hjk's avatar
hjk committed
718 719 720 721 722
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
723
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
724
        return to == EngineShutdownRequested;
725

hjk's avatar
hjk committed
726
    case EngineShutdownRequested:
727
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
728 729 730 731 732 733
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
734
        return to == EngineSetupRequested; // Happens on restart.
735 736
    }

737
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
738 739 740
    return false;
}

741 742
void DebuggerEngine::setupSlaveEngine()
{
743
    QTC_CHECK(state() == DebuggerNotReady);
744 745 746 747 748 749 750
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
751
    m_engine->validateExecutable(&m_runParameters);
752 753 754
    m_engine->setupEngine();
}

755
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
756
{
hjk's avatar
hjk committed
757
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
758 759 760 761 762 763 764
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

765
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
766
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
767
    if (isMasterEngine() && runControl())
768
        runControl()->startFailed();
hjk's avatar
hjk committed
769
    setState(DebuggerFinished);
hjk's avatar
hjk committed
770 771
}

772
void DebuggerEngine::notifyEngineSetupOk()
773
{
hjk's avatar
hjk committed
774
    showMessage(_("NOTE: ENGINE SETUP OK"));
775 776 777 778
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

779
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
780
    setState(EngineSetupOk);
hjk's avatar
hjk committed
781
    showMessage(_("QUEUE: SETUP INFERIOR"));
782
    if (isMasterEngine())
783 784 785 786 787
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
788
    QTC_CHECK(state() == EngineSetupOk);
789
    d->queueSetupInferior();
790 791
}

hjk's avatar
hjk committed
792
void DebuggerEnginePrivate::doSetupInferior()
793
{
794
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
795
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
796
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
797 798 799 800 801
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
802
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
803
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
804
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
805
    setState(InferiorSetupFailed);
806 807
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
808 809 810 811
}

void DebuggerEngine::notifyInferiorSetupOk()
{
812 813 814
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
815
    aboutToNotifyInferiorSetupOk();
hjk's avatar
hjk committed
816
    showMessage(_("NOTE: INFERIOR SETUP OK"));
817 818 819 820
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
821 822
}

823 824 825
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
826
    QTC_CHECK(state() == InferiorSetupOk);
827 828 829
    d->queueRunEngine();
}

hjk's avatar
hjk committed
830 831
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
832
    m_engine->showMessage(_("CALL: RUN ENGINE"));
833
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());