debuggerengine.cpp 56.2 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 43
#include "disassembleragent.h"
#include "memoryagent.h"
44 45 46 47
#include "moduleshandler.h"
#include "registerhandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
48
#include "terminal.h"
49 50
#include "threadshandler.h"
#include "watchhandler.h"
51
#include <debugger/shared/peutils.h>
52

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

hjk's avatar
hjk committed
61
#include <projectexplorer/projectexplorer.h>
62 63
#include <projectexplorer/taskhub.h>

64
#include <texteditor/texteditor.h>
65

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

71
#include <qmljs/consolemanagerinterface.h>
72

73 74 75
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
76
#include <QDir>
77

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

83 84 85 86
enum { debug = 0 };

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

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

93 94 95 96 97 98
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
99 100 101
// VariableManager Prefix
const char PrefixDebugExecutable[]  = "DebuggedExecutable";

102 103
namespace Debugger {

104 105
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
106 107
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
108 109 110 111 112 113 114
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
115
            << " processArgs=" << sp.processArgs
116 117 118 119 120 121
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " serverStartScript=" << sp.serverStartScript
122
            << " abi=" << sp.toolChainAbi.toString() << '\n';
123 124 125
    return str;
}

hjk's avatar
hjk committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139
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;
}

140

141 142 143 144 145 146
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

156
class DebuggerEnginePrivate : public QObject
157
{
158 159
    Q_OBJECT

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

hjk's avatar
hjk committed
188
        Utils::globalMacroExpander()->registerFileVariables(PrefixDebugExecutable,
189
            tr("Debugged executable"),
Orgad Shaneh's avatar
Orgad Shaneh committed
190
            [this]() { return m_startParameters.executable; });
191
    }
192

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

202 203 204 205 206
    void reloadDisassembly()
    {
        m_disassemblerAgent.reload();
    }

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

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

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

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

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

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

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

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

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

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

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
294 295

    // The current state.
296 297
    DebuggerState m_state;

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

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

304 305 306
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

307
    Terminal m_terminal;
308 309 310 311 312 313 314 315
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
324

325
    Utils::FileInProjectFinder m_fileFinder;
326 327 328 329 330 331 332 333 334
};


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

335 336
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
337
{}
338 339 340

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

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

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

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

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

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

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

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
416 417 418
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &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
   return modulesHandler()->model();
445 446 447 448
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
449
    return registerHandler()->model();
450 451 452 453
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
454
    return stackHandler()->model();
455 456 457 458
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
459
    return threadsHandler()->model();
460 461
}

hjk's avatar
hjk committed
462 463 464
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
465 466
}

467 468
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
469
    return sourceFilesHandler()->model();
470 471
}

472
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
473 474 475 476 477 478
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
479 480 481 482 483 484 485
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

hjk's avatar
hjk committed
486
void DebuggerEngine::setRegisterValue(const QByteArray &name, const QString &value)
487
{
hjk's avatar
hjk committed
488
    Q_UNUSED(name);
489 490 491 492 493
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
494 495 496 497
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
498 499
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
500
    QmlJS::ConsoleManagerInterface *consoleManager = QmlJS::ConsoleManagerInterface::instance();
501
    if (channel == ConsoleOutput && consoleManager)
502
        consoleManager->printToConsolePane(QmlJS::ConsoleItem::UndefinedType, msg);
503

504
    Internal::showMessage(msg, channel, timeout);
505 506 507 508 509 510 511 512 513 514 515 516 517
    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 {
518
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
519
    }
520 521 522 523
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
524 525
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
526

527
    d->m_progress.setProgressRange(0, 1000);
528
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
529
        tr("Launching Debugger"), "Debugger.Launcher");
hjk's avatar
hjk committed
530
    connect(fp, &FutureProgress::canceled, this, &DebuggerEngine::quitDebugger);
531
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
532 533
    d->m_progress.reportStarted();

534 535 536 537
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
538 539
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
540

541 542
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
543

hjk's avatar
hjk committed
544
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
545

546 547
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
548 549
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
550
    d->m_progress.setProgressValue(200);
551 552 553 554 555 556 557 558 559 560 561 562 563 564

    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);
        });
    }

565
    d->queueSetupEngine();
566 567 568 569
}

void DebuggerEngine::resetLocation()
{
570 571
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
572 573
}

574
void DebuggerEngine::gotoLocation(const Location &loc)
575
{
Aurindam Jana's avatar
Aurindam Jana committed
576 577
     d->resetLocation();

578 579 580 581
    if (loc.canBeDisassembled()
            && ((hasCapability(OperateByInstructionCapability) && boolSetting(OperateByInstruction))
                || !loc.hasDebugInfo()) )
    {
582 583 584
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
585

586 587 588 589
    if (loc.fileName().isEmpty()) {
        showMessage(QLatin1String("CANNOT GO TO THIS LOCATION"));
        return;
    }
590
    const QString file = QDir::cleanPath(loc.fileName());
591
    const int line = loc.lineNumber();
592
    bool newEditor = false;
593
    IEditor *editor = EditorManager::openEditor(file, Id(),
594 595
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
596

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

599 600
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
601

602
    if (loc.needsMarker()) {
603
        d->m_locationMark.reset(new TextMark(file, line));
604
        d->m_locationMark->setIcon(Internal::locationMarkIcon());
605
        d->m_locationMark->setPriority(TextMark::HighPriority);
606
    }
607 608

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

611 612 613
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
614
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
615
    d->m_runControl = 0;
616
    d->m_progress.setProgressValue(900);
617 618
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
619 620
}

621 622
// Called from RunControl.
void DebuggerEngine::handleFinished()
623
{
624
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
625
    d->m_runControl = 0;
626 627
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

const DebuggerStartParameters &DebuggerEngine::startParameters() const
{
    return d->m_startParameters;
}

DebuggerStartParameters &DebuggerEngine::startParameters()
{
    return d->m_startParameters;
}

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

hjk's avatar
hjk committed
649
DebuggerState DebuggerEngine::lastGoodState() const
650
{
hjk's avatar
hjk committed
651 652 653 654 655 656 657
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
659 660 661
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
662
    case DebuggerNotReady:
663
        return to == EngineSetupRequested;
664

hjk's avatar
hjk committed
665
    case EngineSetupRequested:
666 667
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
668 669 670
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
671
    case EngineSetupOk:
hjk's avatar
hjk committed
672
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
673

hjk's avatar
hjk committed
674
    case InferiorSetupRequested:
675
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
676
    case InferiorSetupFailed:
hjk's avatar
hjk committed
677
        return to == EngineShutdownRequested;
678 679
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
680 681

    case EngineRunRequested:
hjk's avatar
hjk committed
682
        return to == EngineRunFailed
683
            || to == InferiorRunRequested
hjk's avatar
hjk committed
684 685 686
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
687
    case EngineRunFailed:
688
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
689 690 691 692 693 694

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
695 696 697
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
698 699 700 701 702

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
Orgad Shaneh's avatar
Orgad Shaneh committed
703
            || to == InferiorStopOk || to == InferiorExitOk;
704
    case InferiorStopFailed:
hjk's avatar
hjk committed
705
        return to == EngineShutdownRequested;
706

707 708 709
    case InferiorExitOk:
        return to == InferiorShutdownOk;

710
    case InferiorUnrunnable:
hjk's avatar
hjk committed
711 712 713 714 715
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
716
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
717
        return to == EngineShutdownRequested;
718

hjk's avatar
hjk committed
719
    case EngineShutdownRequested:
720
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
721 722 723 724 725 726
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
727
        return to == EngineSetupRequested; // Happens on restart.
728 729
    }

730
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
731 732 733
    return false;
}

734 735
void DebuggerEngine::setupSlaveEngine()
{
736
    QTC_CHECK(state() == DebuggerNotReady);
737 738 739 740 741 742 743
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
744
    m_engine->validateExecutable(&m_startParameters);
745 746 747
    m_engine->setupEngine();
}

748
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
749
{
hjk's avatar
hjk committed
750
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
751 752 753 754 755 756 757
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

758
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
759
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
760
    if (isMasterEngine() && runControl())
761
        runControl()->startFailed();
hjk's avatar
hjk committed
762
    setState(DebuggerFinished);
hjk's avatar
hjk committed
763 764
}

765
void DebuggerEngine::notifyEngineSetupOk()
766
{
hjk's avatar
hjk committed
767
    showMessage(_("NOTE: ENGINE SETUP OK"));
768 769 770 771
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

772
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
773
    setState(EngineSetupOk);
hjk's avatar
hjk committed
774
    showMessage(_("QUEUE: SETUP INFERIOR"));
775
    if (isMasterEngine())
776 777 778 779 780
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
781
    QTC_CHECK(state() == EngineSetupOk);
782
    d->queueSetupInferior();
783 784
}

hjk's avatar
hjk committed
785
void DebuggerEnginePrivate::doSetupInferior()
786
{
787
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
788
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
789
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
790 791 792 793 794
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
795
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
796
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
797
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
798
    setState(InferiorSetupFailed);
799 800
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
801 802 803 804
}

void DebuggerEngine::notifyInferiorSetupOk()
{
805 806 807
#ifdef WITH_BENCHMARK
    CALLGRIND_START_INSTRUMENTATION;
#endif
hjk's avatar
hjk committed
808
    aboutToNotifyInferiorSetupOk();
hjk's avatar
hjk committed
809
    showMessage(_("NOTE: INFERIOR SETUP OK"));
810 811 812 813
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
814 815
}

816 817 818
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
819
    QTC_CHECK(state() == InferiorSetupOk);
820 821 822
    d->queueRunEngine();
}

hjk's avatar
hjk committed
823 824
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
825
    m_engine->showMessage(_("CALL: RUN ENGINE"));
826
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
827
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
828 829 830
    m_engine->runEngine();
}

hjk's avatar
hjk committed
831
void DebuggerEngine::notifyEngineRunOkAndInferiorUnrunnable()
hjk's avatar
hjk committed
832
{
hjk's avatar
hjk committed
833
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
834 835
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
836
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
837
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
838 839 840 841 842
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
843
    showMessage(_("NOTE: ENGINE RUN FAILED"));
844
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
845 846 847
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
848
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
849
    setState(EngineRunFailed);