debuggerengine.cpp 53.2 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25 26 27

#include "debuggerengine.h"

28
#include "debuggerinternalconstants.h"
29
#include "debuggeractions.h"
30
#include "debuggercore.h"
31
#include "debuggericons.h"
32
#include "debuggerruncontrol.h"
33
#include "debuggertooltipmanager.h"
34 35

#include "breakhandler.h"
David Schulz's avatar
David Schulz committed
36
#include "disassembleragent.h"
37
#include "logwindow.h"
David Schulz's avatar
David Schulz committed
38
#include "memoryagent.h"
39 40 41
#include "moduleshandler.h"
#include "registerhandler.h"
#include "sourcefileshandler.h"
hjk's avatar
hjk committed
42
#include "sourceutils.h"
43
#include "stackhandler.h"
44
#include "terminal.h"
45 46
#include "threadshandler.h"
#include "watchhandler.h"
hjk's avatar
hjk committed
47 48
#include "debugger/shared/peutils.h"
#include "console/console.h"
49

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

hjk's avatar
hjk committed
58
#include <projectexplorer/projectexplorer.h>
59 60
#include <projectexplorer/taskhub.h>

61
#include <texteditor/texteditor.h>
62

63
#include <utils/fileinprojectfinder.h>
hjk's avatar
hjk committed
64
#include <utils/macroexpander.h>
65
#include <utils/processhandle.h>
hjk's avatar
hjk committed
66
#include <utils/qtcassert.h>
David Schulz's avatar
David Schulz committed
67
#include <utils/qtcprocess.h>
hjk's avatar
hjk committed
68
#include <utils/savedaction.h>
69

70 71 72
#include <QDebug>
#include <QTimer>
#include <QFileInfo>
73
#include <QDir>
74

75 76 77 78 79
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>

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
using namespace Utils;
85

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

91 92
namespace Debugger {

93 94
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
95 96
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
97 98
}

99
QDebug operator<<(QDebug str, const DebuggerRunParameters &sp)
100 101
{
    QDebug nospace = str.nospace();
102
    nospace << "executable=" << sp.inferior.executable
103
            << " coreFile=" << sp.coreFile
104 105
            << " processArgs=" << sp.inferior.commandLineArguments
            << " inferior environment=<" << sp.inferior.environment.size() << " variables>"
106
            << " debugger environment=<" << sp.debugger.environment.size() << " variables>"
107
            << " workingDir=" << sp.inferior.workingDirectory
108
            << " attachPID=" << sp.attachPID.pid()
109
            << " remoteChannel=" << sp.remoteChannel
110
            << " abi=" << sp.toolChainAbi.toString() << '\n';
111 112 113
    return str;
}

hjk's avatar
hjk committed
114 115 116 117 118 119 120 121 122 123
namespace Internal {

Location::Location(const StackFrame &frame, bool marker)
{
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
124
    m_from = frame.module;
hjk's avatar
hjk committed
125 126
}

127

hjk's avatar
hjk committed
128 129
LocationMark::LocationMark(DebuggerEngine *engine, const QString &file, int line)
    : TextMark(file, line, Constants::TEXT_MARK_CATEGORY_LOCATION), m_engine(engine)
hjk's avatar
hjk committed
130
{
131
    setIcon(Icons::LOCATION.icon());
hjk's avatar
hjk committed
132 133
    setPriority(TextMark::HighPriority);
}
hjk's avatar
hjk committed
134

hjk's avatar
hjk committed
135 136 137 138
bool LocationMark::isDraggable() const
{
    return m_engine->hasCapability(JumpToLineCapability);
}
hjk's avatar
hjk committed
139

hjk's avatar
hjk committed
140 141 142
void LocationMark::dragToLine(int line)
{
    if (m_engine) {
143 144 145 146 147
        if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
            ContextData location = getLocationContext(textEditor->textDocument(), line);
            if (location.isValid())
                m_engine->executeJumpToLine(location);
        }
hjk's avatar
hjk committed
148
    }
hjk's avatar
hjk committed
149
}
hjk's avatar
hjk committed
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
//////////////////////////////////////////////////////////////////////
//
// MemoryAgentSet
//
//////////////////////////////////////////////////////////////////////

class MemoryAgentSet
{
public:
    ~MemoryAgentSet()
    {
        qDeleteAll(m_agents);
        m_agents.clear();
    }

    // Called by engine to create a new view.
    void createBinEditor(const MemoryViewSetupData &data, DebuggerEngine *engine)
    {
        auto agent = new MemoryAgent(data, engine);
        if (agent->isUsable()) {
            m_agents.append(agent);
        } else {
            delete agent;
            AsynchronousMessageBox::warning(
                        DebuggerEngine::tr("No Memory Viewer Available"),
                        DebuggerEngine::tr("The memory contents cannot be shown as no viewer plugin "
                                           "for binary data has been loaded."));
        }
    }

    // On stack frame completed and on request.
    void updateContents()
    {
        foreach (MemoryAgent *agent, m_agents) {
            if (agent)
                agent->updateContents();
        }
    }

    void handleDebuggerFinished()
    {
        foreach (MemoryAgent *agent, m_agents) {
            if (agent)
                agent->setFinished(); // Prevent triggering updates, etc.
        }
    }

private:
    QList<MemoryAgent *> m_agents;
};



204 205 206 207 208 209
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

210
class DebuggerEnginePrivate : public QObject
211
{
212 213
    Q_OBJECT

214
public:
215
    DebuggerEnginePrivate(DebuggerEngine *engine)
216
      : m_engine(engine),
217
        m_modulesHandler(engine),
hjk's avatar
hjk committed
218
        m_registerHandler(engine),
219
        m_sourceFilesHandler(engine),
220
        m_stackHandler(engine),
221
        m_threadsHandler(engine),
222
        m_watchHandler(engine),
hjk's avatar
hjk committed
223
        m_disassemblerAgent(engine)
224
    {
hjk's avatar
hjk committed
225 226
        connect(&m_locationTimer, &QTimer::timeout,
                this, &DebuggerEnginePrivate::resetLocation);
227
    }
228

hjk's avatar
hjk committed
229
    void doRunEngine();
hjk's avatar
hjk committed
230 231
    void doShutdownEngine();
    void doShutdownInferior();
hjk's avatar
hjk committed
232

hjk's avatar
hjk committed
233
    void doFinishDebugger()
234
    {
235
        QTC_ASSERT(state() == EngineShutdownFinished, qDebug() << state());
236
        m_engine->setState(DebuggerFinished);
237 238
        resetLocation();
        if (isMasterEngine()) {
hjk's avatar
hjk committed
239 240 241 242 243 244 245 246 247
            if (m_runTool) {
                m_progress.setProgressValue(1000);
                m_progress.reportFinished();
                m_modulesHandler.removeAll();
                m_stackHandler.removeAll();
                m_threadsHandler.removeAll();
                m_watchHandler.cleanup();
                Internal::runControlFinished(m_runTool);
                m_runTool->reportStopped();
248
                m_runTool->appendMessage(tr("Debugging has finished"), NormalMessageFormat);
hjk's avatar
hjk committed
249 250
                m_runTool.clear();
            }
251
        }
hjk's avatar
hjk committed
252 253
    }

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

264
    void resetLocation()
265
    {
266
        m_lookupRequests.clear();
267 268
        m_locationTimer.stop();
        m_locationMark.reset();
269
        m_stackHandler.resetLocation();
270
        m_watchHandler.resetLocation();
271
        m_threadsHandler.resetLocation();
272
        m_disassemblerAgent.resetLocation();
hjk's avatar
hjk committed
273
        DebuggerToolTipManager::resetLocation();
274 275
    }

276
public:
hjk's avatar
hjk committed
277
    DebuggerState state() const { return m_state; }
278
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
hjk's avatar
hjk committed
279

280 281
    DebuggerEngine *m_engine = nullptr; // Not owned.
    DebuggerEngine *m_masterEngine = nullptr; // Not owned
282
    QPointer<DebuggerRunTool> m_runTool;  // Not owned.
283

hjk's avatar
hjk committed
284
    // The current state.
285
    DebuggerState m_state = DebuggerNotReady;
286

287
//    Terminal m_terminal;
288
    ProcessHandle m_inferiorPid;
289 290 291 292 293 294 295

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

298
    DisassemblerAgent m_disassemblerAgent;
299
    MemoryAgentSet m_memoryAgents;
hjk's avatar
hjk committed
300
    QScopedPointer<LocationMark> m_locationMark;
301
    QTimer m_locationTimer;
302

303
    Utils::FileInProjectFinder m_fileFinder;
hjk's avatar
hjk committed
304
    QString m_qtNamespace;
305 306

    // Safety net to avoid infinite lookups.
hjk's avatar
hjk committed
307
    QSet<QString> m_lookupRequests; // FIXME: Integrate properly.
308
    QPointer<QWidget> m_alertBox;
309 310 311 312 313 314 315 316 317
};


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

318 319 320 321
DebuggerEngine::DebuggerEngine()
  : d(new DebuggerEnginePrivate(this))
{
}
322 323 324

DebuggerEngine::~DebuggerEngine()
{
325 326
    disconnect();
    delete d;
327 328
}

hjk's avatar
hjk committed
329
QString DebuggerEngine::stateName(int s)
330
{
hjk's avatar
hjk committed
331
#    define SN(x) case x: return QLatin1String(#x);
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    switch (s) {
        SN(DebuggerNotReady)
        SN(EngineSetupRequested)
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
        SN(EngineRunFailed)
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
        SN(InferiorShutdownRequested)
347
        SN(InferiorShutdownFinished)
348
        SN(EngineShutdownRequested)
349
        SN(EngineShutdownFinished)
350 351
        SN(DebuggerFinished)
    }
hjk's avatar
hjk committed
352
    return QLatin1String("<unknown>");
353 354 355
#    undef SN
}

356
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
357
{
358
    showMessage(msg, StatusBar, timeout);
359
}
360

361 362 363 364 365 366 367 368 369 370 371 372
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));
}

373 374 375 376
void DebuggerEngine::doUpdateLocals(const UpdateParameters &)
{
}

377 378
ModulesHandler *DebuggerEngine::modulesHandler() const
{
379 380 381
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
382 383 384 385
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
386 387 388
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
389 390 391 392
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
393 394 395
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
396 397 398 399
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
400 401 402
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
403 404 405 406
}

WatchHandler *DebuggerEngine::watchHandler() const
{
407 408 409
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
410 411 412 413
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
414 415 416
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
417 418 419 420
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
421
   return modulesHandler()->model();
422 423 424 425
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
426
    return registerHandler()->model();
427 428 429 430
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
431
    return stackHandler()->model();
432 433 434 435
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
436
    return threadsHandler()->model();
437 438
}

hjk's avatar
hjk committed
439 440 441
QAbstractItemModel *DebuggerEngine::watchModel() const
{
    return watchHandler()->model();
442 443
}

444 445
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
446
    return sourceFilesHandler()->model();
447 448
}

449
void DebuggerEngine::fetchMemory(MemoryAgent *, quint64 addr, quint64 length)
450 451 452 453 454
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

455
void DebuggerEngine::changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data)
hjk's avatar
hjk committed
456 457 458 459 460
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

hjk's avatar
hjk committed
461
void DebuggerEngine::setRegisterValue(const QString &name, const QString &value)
462
{
hjk's avatar
hjk committed
463
    Q_UNUSED(name);
464 465 466
    Q_UNUSED(value);
}

467
void DebuggerEngine::setRunTool(DebuggerRunTool *runTool)
468
{
469 470 471 472
    QTC_ASSERT(!d->m_runTool, notifyEngineSetupFailed(); return);
    d->m_runTool = runTool;
}

473
void DebuggerEngine::start()
474 475
{
    QTC_ASSERT(d->m_runTool, notifyEngineSetupFailed(); return);
476

477
    d->m_progress.setProgressRange(0, 1000);
478
    FutureProgress *fp = ProgressManager::addTask(d->m_progress.future(),
479
        tr("Launching Debugger"), "Debugger.Launcher");
hjk's avatar
hjk committed
480
    connect(fp, &FutureProgress::canceled, this, &DebuggerEngine::quitDebugger);
481
    fp->setKeepOnFinish(FutureProgress::HideOnFinish);
482 483
    d->m_progress.reportStarted();

484
    const DebuggerRunParameters &rp = runParameters();
485
    d->m_inferiorPid = rp.attachPID.isValid() ? rp.attachPID : ProcessHandle();
486
    if (d->m_inferiorPid.isValid())
487
        d->m_runTool->runControl()->setApplicationProcessHandle(d->m_inferiorPid);
488

hjk's avatar
hjk committed
489
    action(OperateByInstruction)->setEnabled(hasCapability(DisassemblerCapability));
490

491 492
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
493
    d->m_progress.setProgressValue(200);
494

495 496 497 498 499 500 501 502 503 504 505 506
//    d->m_terminal.setup();
//    if (d->m_terminal.isUsable()) {
//        connect(&d->m_terminal, &Terminal::stdOutReady, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::StdOutFormatSameLine);
//        });
//        connect(&d->m_terminal, &Terminal::stdErrReady, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::StdErrFormatSameLine);
//        });
//        connect(&d->m_terminal, &Terminal::error, [this](const QString &msg) {
//            d->m_runTool->appendMessage(msg, Utils::ErrorMessageFormat);
//        });
//    }
507

508 509 510
    setState(EngineSetupRequested);
    showMessage("CALL: SETUP ENGINE");
    setupEngine();
511 512
}

513 514
void DebuggerEngine::resetLocation()
{
515 516
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
517 518
}

519
void DebuggerEngine::gotoLocation(const Location &loc)
520
{
Aurindam Jana's avatar
Aurindam Jana committed
521 522
     d->resetLocation();

523 524 525 526
    if (loc.canBeDisassembled()
            && ((hasCapability(OperateByInstructionCapability) && boolSetting(OperateByInstruction))
                || !loc.hasDebugInfo()) )
    {
527 528 529
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
530

531
    if (loc.fileName().isEmpty()) {
hjk's avatar
hjk committed
532
        showMessage("CANNOT GO TO THIS LOCATION");
533 534
        return;
    }
535
    const QString file = QDir::cleanPath(loc.fileName());
536
    const int line = loc.lineNumber();
537
    bool newEditor = false;
538
    IEditor *editor = EditorManager::openEditor(file, Id(),
539 540
                                                EditorManager::IgnoreNavigationHistory, &newEditor);
    QTC_ASSERT(editor, return); // Unreadable file?
541

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

544 545
    if (newEditor)
        editor->document()->setProperty(Constants::OPENED_BY_DEBUGGER, true);
hjk's avatar
hjk committed
546

hjk's avatar
hjk committed
547
    if (loc.needsMarker())
hjk's avatar
hjk committed
548
        d->m_locationMark.reset(new LocationMark(this, file, line));
549 550
}

551
const DebuggerRunParameters &DebuggerEngine::runParameters() const
552
{
553
    return runTool()->runParameters();
554 555 556 557 558 559 560
}

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

hjk's avatar
hjk committed
561 562 563
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
564
    case DebuggerNotReady:
565
        return to == EngineSetupRequested;
566

hjk's avatar
hjk committed
567
    case EngineSetupRequested:
568 569
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
570 571 572
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
573
    case EngineSetupOk:
574
        return to == EngineRunRequested || to == EngineShutdownRequested;
hjk's avatar
hjk committed
575 576

    case EngineRunRequested:
hjk's avatar
hjk committed
577
        return to == EngineRunFailed
578
            || to == InferiorRunRequested
hjk's avatar
hjk committed
579 580 581
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
582
    case EngineRunFailed:
583
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
584 585 586 587 588 589

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
590
        return to == InferiorStopRequested
591 592
            || to == InferiorStopOk             // A spontaneous stop.
            || to == InferiorShutdownFinished;  // A spontaneous exit.
hjk's avatar
hjk committed
593 594 595 596 597

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
598
            || to == InferiorStopOk || to == InferiorShutdownFinished;
599
    case InferiorStopFailed:
hjk's avatar
hjk committed
600
        return to == EngineShutdownRequested;
601 602

    case InferiorUnrunnable:
hjk's avatar
hjk committed
603 604
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
605 606
        return to == InferiorShutdownFinished;
    case InferiorShutdownFinished:
hjk's avatar
hjk committed
607
        return to == EngineShutdownRequested;
608

hjk's avatar
hjk committed
609
    case EngineShutdownRequested:
610 611
        return to == EngineShutdownFinished;
    case EngineShutdownFinished:
hjk's avatar
hjk committed
612 613 614
        return to == DebuggerFinished;

    case DebuggerFinished:
615
        return to == EngineSetupRequested; // Happens on restart.
616 617
    }

618
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
619 620 621
    return false;
}

622 623
void DebuggerEngine::setupSlaveEngine()
{
624
    QTC_CHECK(state() == DebuggerNotReady);
625 626 627
    setState(EngineSetupRequested);
    showMessage("CALL: SETUP SLAVE ENGINE");
    setupEngine();
628 629
}

630
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
631
{
hjk's avatar
hjk committed
632
    showMessage("NOTE: ENGINE SETUP FAILED");
633
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
634
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
635 636 637 638 639 640 641 642
    if (isMasterEngine() && runTool()) {
        showMessage(tr("Debugging has failed"), NormalMessageFormat);
        d->m_runTool.clear();
        d->m_progress.setProgressValue(900);
        d->m_progress.reportCanceled();
        d->m_progress.reportFinished();
    }

hjk's avatar
hjk committed
643
    setState(DebuggerFinished);
hjk's avatar
hjk committed
644 645
}

646
void DebuggerEngine::notifyEngineSetupOk()
647
{
648 649 650
//#ifdef WITH_BENCHMARK
//    CALLGRIND_START_INSTRUMENTATION;
//#endif
hjk's avatar
hjk committed
651
    showMessage("NOTE: ENGINE SETUP OK");
652
    d->m_progress.setProgressValue(250);
653
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
654
    setState(EngineSetupOk);
655 656
    if (isMasterEngine() && runTool()) {
        runTool()->aboutToNotifyInferiorSetupOk(); // FIXME: Remove, only used for Android.
hjk's avatar
hjk committed
657
        runTool()->reportStarted();
658
    }
659

660 661
    if (isMasterEngine()) {
        // Slaves will get called setupSlaveInferior() below.
662 663 664 665
        setState(EngineRunRequested);
        showMessage("CALL: RUN ENGINE");
        d->m_progress.setProgressValue(300);
        runEngine();
666
    }
667 668
}

669 670 671
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
672 673 674 675 676
    QTC_CHECK(state() == EngineSetupOk);
    setState(EngineRunRequested);
    showMessage("CALL: RUN SLAVE ENGINE");
    d->m_progress.setProgressValue(300);
    runEngine();
677 678
}

hjk's avatar
hjk committed
679

hjk's avatar
hjk committed
680
void DebuggerEngine::notifyEngineRunOkAndInferiorUnrunnable()
hjk's avatar
hjk committed
681
{
hjk's avatar
hjk committed
682
    showMessage("NOTE: INFERIOR UNRUNNABLE");
683 684
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
685
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
686
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
687 688 689 690 691
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
692
    showMessage("NOTE: ENGINE RUN FAILED");
693
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
694 695 696
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
697
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
698
    setState(EngineRunFailed);
699
    if (isMasterEngine())
hjk's avatar
hjk committed
700
        d->doShutdownEngine();
hjk's avatar
hjk committed
701 702 703 704
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
705
    showMessage("NOTE: ENGINE RUN AND INFERIOR RUN OK");
706 707
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
708
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
709
    showStatusMessage(tr("Running."));
hjk's avatar
hjk committed
710
    setState(InferiorRunOk);
hjk's avatar
hjk committed
711 712 713 714
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
715
    showMessage("NOTE: ENGINE RUN AND INFERIOR STOP OK");
716 717
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
718
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
719
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
720
    setState(InferiorStopOk);
hjk's avatar
hjk committed
721 722 723 724
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
725
    showMessage("NOTE: INFERIOR RUN REQUESTED");
726
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
727
    showStatusMessage(tr("Run requested..."));
hjk's avatar
hjk committed
728 729 730 731 732
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
733
    if (state() == InferiorRunOk) {
hjk's avatar
hjk committed
734
        showMessage("NOTE: INFERIOR RUN OK - REPEATED.");
735 736
        return;
    }
hjk's avatar
hjk committed
737
    showMessage("NOTE: INFERIOR RUN OK");
738
    showStatusMessage(tr("Running."));
739
    // Transition from StopRequested can happen in remotegdbadapter.
740
    QTC_ASSERT(state() == InferiorRunRequested
741
        || state() == InferiorStopOk
742
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
743 744 745 746 747
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
748
    showMessage("NOTE: INFERIOR RUN FAILED");
749
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
750 751
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
752
    if (isDying())
hjk's avatar
hjk committed
753
        d->doShutdownInferior();
hjk's avatar
hjk committed
754 755 756 757
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
758
    showMessage("NOTE: INFERIOR STOP OK");
hjk's avatar
hjk committed
759
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
760
    if (isDying()) {
hjk's avatar
hjk committed
761
        showMessage("NOTE: ... WHILE DYING. ");
hjk's avatar
hjk committed
762 763 764 765
        // Forward state to "StopOk" if needed.
        if (state() == InferiorStopRequested
                || state() == InferiorRunRequested
                || state() == InferiorRunOk) {
hjk's avatar
hjk committed
766
            showMessage("NOTE: ... FORWARDING TO 'STOP OK'. ");
hjk's avatar
hjk committed
767 768
            setState(InferiorStopOk);
        }
769
        if (state() == InferiorStopOk || state() == InferiorStopFailed)
hjk's avatar
hjk committed
770
            d->doShutdownInferior();
hjk's avatar
hjk committed
771
        showMessage("NOTE: ... IGNORING STOP MESSAGE");
hjk's avatar
hjk committed
772
        return;
hjk's avatar
hjk committed
773
    }
774
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
775
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
776
    setState(InferiorStopOk);
hjk's avatar
hjk committed
777 778
}

hjk's avatar
hjk committed
779
void DebuggerEngine::notifyInferiorSpontaneousStop()
780
{
hjk's avatar
hjk committed
781
    showMessage("NOTE: INFERIOR SPONTANEOUS STOP");
782
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
783
    showStatusMessage(tr("Stopped."));
784
    setState(InferiorStopOk);
hjk's avatar
hjk committed
785
    if (boolSetting(RaiseOnInterrupt))
786
        ICore::raiseWindow(Internal::mainWindow());
787 788
}

hjk's avatar
hjk committed
789
void DebuggerEngine::notifyInferiorStopFailed()
790
{
hjk's avatar
hjk committed
791
    showMessage("NOTE: INFERIOR STOP FAILED");
792
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
793
    setState(InferiorStopFailed);
794
    if (isMasterEngine())
hjk's avatar
hjk committed
795
        d->doShutdownEngine();
796 797
}

hjk's avatar
hjk committed
798 799
void DebuggerEnginePrivate::doShutdownInferior()
{
hjk's avatar
hjk committed
800
    m_engine->setState(InferiorShutdownRequested);
801
    //QTC_ASSERT(isMasterEngine(), return);
802
    resetLocation();
hjk's avatar
hjk committed
803
    m_engine->showMessage("CALL: SHUTDOWN INFERIOR");
hjk's avatar
hjk committed
804 805 806
    m_engine->shutdownInferior();
}

807
void DebuggerEngine::notifyInferiorShutdownFinished()
hjk's avatar
hjk committed
808
{
809
    showMessage("INFERIOR FINISHED SHUT DOWN");
Friedemann Kleint's avatar
Friedemann Kleint committed