debuggerengine.cpp 38.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "debuggerengine.h"

#include "debuggeractions.h"
#include "debuggeragents.h"
#include "debuggerrunner.h"
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
37
#include "debuggertooltip.h"
38
#include "logwindow.h"
39
40
41
42
43
44
45
46
47

#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"
hjk's avatar
hjk committed
48
#include "watchutils.h"
49
#include "breakwindow.h"
50

hjk's avatar
hjk committed
51
#include <coreplugin/icore.h>
52
#include <coreplugin/ifile.h>
53
54
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
55

56
#include <projectexplorer/toolchaintype.h>
57
58
59

#include <qt4projectmanager/qt4projectmanagerconstants.h>

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

62
#include <utils/environment.h>
63
64
65
66
67
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
68
#include <QtCore/QFutureInterface>
69
70
71
72

#include <QtGui/QAbstractItemView>
#include <QtGui/QStandardItemModel>
#include <QtGui/QAction>
73
#include <QtGui/QMenu>
74
#include <QtGui/QMessageBox>
hjk's avatar
hjk committed
75
#include <QtGui/QPlainTextEdit>
76
#include <QtGui/QPushButton>
hjk's avatar
hjk committed
77
78
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
79
#include <QtGui/QTreeWidget>
80
#include <QtGui/QMainWindow>
81

hjk's avatar
hjk committed
82
using namespace Core;
83
84
using namespace Debugger;
using namespace Debugger::Internal;
hjk's avatar
hjk committed
85
86
using namespace ProjectExplorer;
using namespace TextEditor;
87

hjk's avatar
hjk committed
88
89
90
91
92
93
94
//#define DEBUG_STATE 1
#if DEBUG_STATE
#   define SDEBUG(s) qDebug() << s
#else
#   define SDEBUG(s)
#endif
# define XSDEBUG(s) qDebug() << s
95

96

97
98
99
100
101
102
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

103
DebuggerStartParameters::DebuggerStartParameters() :
104
    isSnapshot(false),
105
106
    attachPID(-1),
    useTerminal(false),
107
108
    breakAtMain(false),
    qmlServerAddress("127.0.0.1"),
109
    qmlServerPort(0),
hjk's avatar
hjk committed
110
    useServerStartScript(false),
111
    connParams(SshConnectionParameters::NoProxy),
112
    toolChainType(ToolChain_UNKNOWN),
113
114
    startMode(NoStartMode),
    executableUid(0)
115
116
117
118
119
120
121
122
123
124
125
126
{}

void DebuggerStartParameters::clear()
{
    *this = DebuggerStartParameters();
}


namespace Debugger {

QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
127
128
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    const QString sep = QString(QLatin1Char(','));
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
            << " processArgs=" << sp.processArgs.join(sep)
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
145
            << " useServerStartScript=" << sp.useServerStartScript
146
147
148
149
150
151
152
153
154
155
            << " serverStartScript=" << sp.serverStartScript
            << " toolchain=" << sp.toolChainType << '\n';
    return str;
}

const char *DebuggerEngine::stateName(int s)
{
#    define SN(x) case x: return #x;
    switch (s) {
        SN(DebuggerNotReady)
hjk's avatar
hjk committed
156
        SN(EngineSetupRequested)
157
158
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
hjk's avatar
hjk committed
159
160
        SN(EngineRunFailed)
        SN(InferiorSetupRequested)
hjk's avatar
hjk committed
161
        SN(InferiorSetupFailed)
hjk's avatar
hjk committed
162
163
164
165
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
166
        SN(InferiorUnrunnable)
hjk's avatar
hjk committed
167
168
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
169
        SN(InferiorStopFailed)
hjk's avatar
hjk committed
170
171
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
172
        SN(InferiorShutdownFailed)
hjk's avatar
hjk committed
173
174
175
176
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
177
178
179
180
181
    }
    return "<unknown>";
#    undef SN
}

182

183
184
185
186
187
188
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

189
class DebuggerEnginePrivate : public QObject
190
{
191
192
    Q_OBJECT

193
194
195
196
public:
    DebuggerEnginePrivate(DebuggerEngine *engine, const DebuggerStartParameters &sp)
      : m_engine(engine),
        m_runControl(0),
197
        m_isActive(false),
198
199
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
200
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
201
        m_targetState(DebuggerNotReady),
202
        m_modulesHandler(),
203
        m_registerHandler(),
204
205
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
206
        m_threadsHandler(),
207
        m_watchHandler(engine),
208
        m_disassemblerViewAgent(engine),
209
        m_isSlaveEngine(false)
210
    {}
211
212

    ~DebuggerEnginePrivate() {}
213

214
public slots:
hjk's avatar
hjk committed
215
216
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
217
218
    void doShutdownEngine();
    void doShutdownInferior();
219
    void doInterruptInferior();
hjk's avatar
hjk committed
220
    void doFinishDebugger();
hjk's avatar
hjk committed
221

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

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

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

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

252
253
    void raiseApplication()
    {
hjk's avatar
hjk committed
254
        QTC_ASSERT(m_runControl, return);
255
256
257
        m_runControl->bringApplicationToForeground(m_inferiorPid);
    }

258
public:
hjk's avatar
hjk committed
259
260
    DebuggerState state() const { return m_state; }

261
262
    DebuggerEngine *m_engine; // Not owned.
    DebuggerRunControl *m_runControl;  // Not owned.
263
    bool m_isActive;
264
265

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
266
267

    // The current state.
268
269
    DebuggerState m_state;

hjk's avatar
hjk committed
270
271
272
273
274
275
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

276
277
278
279
280
281
282
283
284
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
    DisassemblerViewAgent m_disassemblerViewAgent;
285
    QFutureInterface<void> m_progress;
286

287
    bool m_isSlaveEngine;
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
};


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

DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters)
  : d(new DebuggerEnginePrivate(this, startParameters))
{
}

DebuggerEngine::~DebuggerEngine()
{
304
305
    disconnect();
    delete d;
306
307
}

308
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
309
{
310
    showMessage(msg, StatusBar, timeout);
311
}
312

313
314
315
316
317
318
void DebuggerEngine::removeTooltip()
{
    watchHandler()->removeTooltip();
    hideDebuggerToolTip();
}

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
void DebuggerEngine::showModuleSymbols
    (const QString &moduleName, const Symbols &symbols)
{
    QTreeWidget *w = new QTreeWidget;
    w->setColumnCount(3);
    w->setRootIsDecorated(false);
    w->setAlternatingRowColors(true);
    w->setSortingEnabled(true);
    w->setHeaderLabels(QStringList() << tr("Symbol") << tr("Address") << tr("Code"));
    w->setWindowTitle(tr("Symbols in \"%1\"").arg(moduleName));
    foreach (const Symbol &s, symbols) {
        QTreeWidgetItem *it = new QTreeWidgetItem;
        it->setData(0, Qt::DisplayRole, s.name);
        it->setData(1, Qt::DisplayRole, s.address);
        it->setData(2, Qt::DisplayRole, s.state);
        w->addTopLevelItem(it);
    }
    plugin()->createNewDock(w);
}

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

ModulesHandler *DebuggerEngine::modulesHandler() const
{
    return &d->m_modulesHandler;
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
    return &d->m_registerHandler;
}

StackHandler *DebuggerEngine::stackHandler() const
{
    return &d->m_stackHandler;
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
    return &d->m_threadsHandler;
}

WatchHandler *DebuggerEngine::watchHandler() const
{
    return &d->m_watchHandler;
}

376
377
378
379
//SnapshotHandler *DebuggerEngine::snapshotHandler() const
//{
//    return &d->m_snapshotHandler;
//}
380
381
382
383
384
385
386
387

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
    return &d->m_sourceFilesHandler;
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
388
389
390
391
    QAbstractItemModel *model = d->m_modulesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
392
393
394
395
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
396
397
398
399
    QAbstractItemModel *model = d->m_registerHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
400
401
402
403
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
404
405
406
407
    QAbstractItemModel *model = d->m_stackHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
408
409
410
411
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
412
413
414
415
    QAbstractItemModel *model = d->m_threadsHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
416
417
418
419
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
420
421
422
423
    QAbstractItemModel *model = d->m_watchHandler.model(LocalsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
424
425
426
427
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
428
429
430
431
    QAbstractItemModel *model = d->m_watchHandler.model(WatchersWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
432
433
434
435
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
436
437
438
439
    QAbstractItemModel *model = d->m_watchHandler.model(ReturnWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
440
441
442
443
}

QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
Friedemann Kleint's avatar
Friedemann Kleint committed
444
445
446
447
    QAbstractItemModel *model = d->m_sourceFilesHandler.model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
}

void DebuggerEngine::fetchMemory(MemoryViewAgent *, QObject *,
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
{
    Q_UNUSED(regnr);
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
465
466
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
467
    plugin()->showMessage(msg, channel, timeout);
468
469
470
471
472
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
473
474
475
476
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
hjk's avatar
hjk committed
477
    if (!isSlaveEngine()) {
478
        d->m_progress.setProgressRange(0, 1000);
479
480
481
        Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
            ->addTask(d->m_progress.future(),
            tr("Launching"), _("Debugger.Launcher"));
482
        fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
483
484
        d->m_progress.reportStarted();
    }
485
486
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
487
488
489
490
491
492
493

    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;

    if (d->m_startParameters.environment.empty())
494
        d->m_startParameters.environment = Utils::Environment().toStringList();
495
496
497
498
499
500
501
502

    if (d->m_startParameters.breakAtMain)
        breakByFunctionMain();

    const unsigned engineCapabilities = debuggerCapabilities();
    theDebuggerAction(OperateByInstruction)
        ->setEnabled(engineCapabilities & DisassemblerCapability);

503
504
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
hjk's avatar
hjk committed
505
    setState(EngineSetupRequested);
506

507
    d->m_progress.setProgressValue(200);
hjk's avatar
hjk committed
508
    setupEngine();
509
510
511
512
513
514
515
516
517
518
519
520
521
522
}

void DebuggerEngine::breakByFunctionMain()
{
#ifdef Q_OS_WIN
    // FIXME: wrong on non-Qt based binaries
    emit breakByFunction("qMain");
#else
    emit breakByFunction("main");
#endif
}

void DebuggerEngine::breakByFunction(const QString &functionName)
{
523
524
    breakHandler()->breakByFunction(functionName);
    breakHandler()->synchronizeBreakpoints();
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
}

void DebuggerEngine::resetLocation()
{
    d->m_disassemblerViewAgent.resetLocation();
    d->m_stackHandler.setCurrentIndex(-1);
    plugin()->resetLocation();
}

void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
{
    StackFrame frame;
    frame.file = fileName;
    frame.line = lineNumber;
    gotoLocation(frame, setMarker);
}

void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{
    if (theDebuggerBoolSetting(OperateByInstruction) || !frame.isUsable()) {
        if (setMarker)
            plugin()->resetLocation();
        d->m_disassemblerViewAgent.setFrame(frame);
    } else {
        plugin()->gotoLocation(frame.file, frame.line, setMarker);
    }
}


hjk's avatar
hjk committed
554
void DebuggerEngine::executeRunToLine()
555
{
556
557
558
559
560
561
    QString fileName;
    int lineNumber;
    if (currentTextEditorPosition(&fileName, &lineNumber)) {
        resetLocation();
        executeRunToLine(fileName, lineNumber);
    }
562
563
}

hjk's avatar
hjk committed
564
void DebuggerEngine::executeRunToFunction()
565
{
hjk's avatar
hjk committed
566
    ITextEditor *textEditor = currentTextEditor();
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
    QTC_ASSERT(textEditor, return);
    QPlainTextEdit *ed = qobject_cast<QPlainTextEdit*>(textEditor->widget());
    if (!ed)
        return;
    QTextCursor cursor = ed->textCursor();
    QString functionName = cursor.selectedText();
    if (functionName.isEmpty()) {
        const QTextBlock block = cursor.block();
        const QString line = block.text();
        foreach (const QString &str, line.trimmed().split('(')) {
            QString a;
            for (int i = str.size(); --i >= 0; ) {
                if (!str.at(i).isLetterOrNumber())
                    break;
                a = str.at(i) + a;
            }
            if (!a.isEmpty()) {
                functionName = a;
                break;
            }
        }
    }

hjk's avatar
hjk committed
590
591
592
593
    if (functionName.isEmpty())
        return;
    resetLocation();
    executeRunToFunction(functionName);
594
595
}

hjk's avatar
hjk committed
596
void DebuggerEngine::executeJumpToLine()
597
{
598
599
600
601
    QString fileName;
    int lineNumber;
    if (currentTextEditorPosition(&fileName, &lineNumber))
        executeJumpToLine(fileName, lineNumber);
602
603
}

604
605
606
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
607
    showMessage("HANDLE RUNCONTROL START FAILED");
608
    d->m_runControl = 0;
609
    d->m_progress.setProgressValue(900);
610
611
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
612
613
}

614
615
// Called from RunControl.
void DebuggerEngine::handleFinished()
616
{
617
    showMessage("HANDLE RUNCONTROL FINISHED");
618
    d->m_runControl = 0;
619
620
621
622
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
623
    d->m_progress.setProgressValue(1000);
624
    d->m_progress.reportFinished();
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
}

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

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


//////////////////////////////////////////////////////////////////////
//
// Dumpers. "Custom dumpers" are a library compiled against the current
// Qt containing functions to evaluate values of Qt classes
// (such as QString, taking pointers to their addresses).
// The library must be loaded into the debuggee.
//
//////////////////////////////////////////////////////////////////////

bool DebuggerEngine::qtDumperLibraryEnabled() const
{
    return theDebuggerBoolSetting(UseDebuggingHelpers);
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
    if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool()) {
        const QString customLocation =
            theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
        const QString location =
            tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
        return QStringList(location);
    }
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
666
    QMessageBox dialog(plugin()->mainWindow());
Leena Miettinen's avatar
Leena Miettinen committed
667
    QPushButton *qtPref = dialog.addButton(tr("Open Qt4 Options"),
668
        QMessageBox::ActionRole);
Leena Miettinen's avatar
Leena Miettinen committed
669
    QPushButton *helperOff = dialog.addButton(tr("Turn off Helper Usage"),
670
        QMessageBox::ActionRole);
Leena Miettinen's avatar
Leena Miettinen committed
671
    QPushButton *justContinue = dialog.addButton(tr("Continue Anyway"),
672
673
        QMessageBox::AcceptRole);
    dialog.setDefaultButton(justContinue);
Leena Miettinen's avatar
Leena Miettinen committed
674
    dialog.setWindowTitle(tr("Debugging Helper Missing"));
675
676
677
678
679
    dialog.setText(tr("The debugger could not load the debugging helper library."));
    dialog.setInformativeText(tr(
        "The debugging helper is used to nicely format the values of some Qt "
        "and Standard Library data types. "
        "It must be compiled for each used Qt version separately. "
Leena Miettinen's avatar
Leena Miettinen committed
680
681
        "On the Qt4 options page, select a Qt installation "
        "and click Rebuild."));
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
    if (!details.isEmpty())
        dialog.setDetailedText(details);
    dialog.exec();
    if (dialog.clickedButton() == qtPref) {
        Core::ICore::instance()->showOptionsDialog(
            _(Qt4ProjectManager::Constants::QT_SETTINGS_CATEGORY),
            _(Qt4ProjectManager::Constants::QTVERSION_SETTINGS_PAGE_ID));
    } else if (dialog.clickedButton() == helperOff) {
        theDebuggerAction(UseDebuggingHelpers)
            ->setValue(qVariantFromValue(false), false);
    }
}

QString DebuggerEngine::qtDumperLibraryName() const
{
    if (theDebuggerAction(UseCustomDebuggingHelperLocation)->value().toBool())
        return theDebuggerAction(CustomDebuggingHelperLocation)->value().toString();
    return startParameters().dumperLibrary;
}

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

hjk's avatar
hjk committed
707
DebuggerState DebuggerEngine::lastGoodState() const
708
{
hjk's avatar
hjk committed
709
710
711
712
713
714
715
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
717
718
719
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
720
    case DebuggerNotReady:
721
        return to == EngineSetupRequested;
722

hjk's avatar
hjk committed
723
    case EngineSetupRequested:
724
725
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
726
        // FIXME: In therory it's the engine's task to go into a
727
728
729
        // proper "Shutdown" state before calling notifyEngineSetupFailed
        //return to == DebuggerFinished;
        return to == EngineShutdownRequested;
730
    case EngineSetupOk:
hjk's avatar
hjk committed
731
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
732

hjk's avatar
hjk committed
733
734
    case InferiorSetupRequested:
        return to == EngineRunRequested || to == InferiorSetupFailed;
hjk's avatar
hjk committed
735
    case InferiorSetupFailed:
hjk's avatar
hjk committed
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
        return to == EngineShutdownRequested;

    case EngineRunRequested:
        return to == InferiorRunRequested || to == InferiorStopRequested
            || to == InferiorUnrunnable || to == EngineRunFailed;

    case EngineRunFailed:
        return to == InferiorShutdownRequested;

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
        return to == InferiorStopRequested || to == InferiorStopOk;

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

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

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

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

    qDebug() << "UNKNOWN STATE:" << from;
    return false;
}

784
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
785
{
hjk's avatar
hjk committed
786
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
hjk's avatar
hjk committed
787
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
788
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
789
790
    QTC_ASSERT(d->m_runControl, return);
    d->m_runControl->startFailed();
hjk's avatar
hjk committed
791
    setState(DebuggerFinished);
hjk's avatar
hjk committed
792
793
}

794
void DebuggerEngine::notifyEngineSetupOk()
795
{
hjk's avatar
hjk committed
796
    showMessage(_("NOTE: ENGINE SETUP OK"));
hjk's avatar
hjk committed
797
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
798
    setState(EngineSetupOk);
hjk's avatar
hjk committed
799
    QTC_ASSERT(d->m_runControl, return);
hjk's avatar
hjk committed
800
    showMessage(_("QUEUE: SETUP INFERIOR"));
hjk's avatar
hjk committed
801
    QTimer::singleShot(0, d, SLOT(doSetupInferior()));
802
803
}

hjk's avatar
hjk committed
804
void DebuggerEnginePrivate::doSetupInferior()
805
{
806
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
hjk's avatar
hjk committed
807
    QTC_ASSERT(state() == EngineSetupOk, qDebug() << state());
808
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
809
    m_engine->setState(InferiorSetupRequested);
hjk's avatar
hjk committed
810
811
812
813
814
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
815
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
hjk's avatar
hjk committed
816
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
hjk's avatar
hjk committed
817
    setState(InferiorSetupFailed);
hjk's avatar
hjk committed
818
    d->queueShutdownEngine();
hjk's avatar
hjk committed
819
820
821
822
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
823
    showMessage(_("NOTE: INFERIOR SETUP OK"));
hjk's avatar
hjk committed
824
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
hjk's avatar
hjk committed
825
    d->queueRunEngine();
hjk's avatar
hjk committed
826
827
828
829
}

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

hjk's avatar
hjk committed
836
837
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
838
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
839
840
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
841
842
843
844
845
846
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
847
    showMessage(_("NOTE: ENGINE RUN FAILED"));
hjk's avatar
hjk committed
848
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
849
850
851
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
852
    setState(EngineRunFailed);
853
    d->queueShutdownEngine();
hjk's avatar
hjk committed
854
855
856
857
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
858
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
859
860
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
861
862
863
864
865
866
867
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorRunRequested);
    notifyInferiorRunOk();
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
868
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
869
870
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
871
872
873
874
875
876
877
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
    setState(InferiorStopRequested);
    notifyInferiorStopOk();
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
878
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
hjk's avatar
hjk committed
879
880
881
882
883
884
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
885
    showMessage(_("NOTE: INFERIOR RUN OK"));
hjk's avatar
hjk committed
886
887
888
889
890
891
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
892
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
hjk's avatar
hjk committed
893
894
895
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
896
897
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
898
899
900
901
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
902
903
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
904
    if (isDying()) {
hjk's avatar
hjk committed
905
906
907
908
909
910
911
912
913
914
915
916
917
        showMessage(_("NOTE: ... WHILE DYING. "));
        // Forward state to "StopOk" if needed.
        if (state() == InferiorStopRequested
                || state() == InferiorRunRequested
                || state() == InferiorRunOk) {
            showMessage(_("NOTE: ... FORWARDING TO 'STOP OK'. "));
            setState(InferiorStopOk);
        }
        if (state() == InferiorStopOk || state() == InferiorStopFailed) {
            d->queueShutdownInferior();
        }
        showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
        return;
hjk's avatar
hjk committed
918
    }
hjk's avatar
hjk committed
919
920
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
    setState(InferiorStopOk);
hjk's avatar
hjk committed
921
922
}

hjk's avatar
hjk committed
923
void DebuggerEngine::notifyInferiorSpontaneousStop()
924
{
hjk's avatar
hjk committed
925
    showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
hjk's avatar
hjk committed
926
927
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
    setState(InferiorStopOk);
928
929
}

hjk's avatar
hjk committed
930
void DebuggerEngine::notifyInferiorStopFailed()
931
{
hjk's avatar
hjk committed
932
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
hjk's avatar
hjk committed
933
934
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
    setState(InferiorStopFailed);
hjk's avatar
hjk committed
935
    d->queueShutdownEngine();
936
937
938
939
}

void DebuggerEnginePrivate::doInterruptInferior()
{
hjk's avatar
hjk committed
940
941
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << state());
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
942
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
943
944
945
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
946
947
void DebuggerEnginePrivate::doShutdownInferior()
{
948
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
hjk's avatar
hjk committed
949
950
    m_engine->resetLocation();
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
951
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
952
953
954
955
956
957
    m_engine->shutdownInferior();
}

void DebuggerEngine::notifyInferiorShutdownOk()
{
    showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
hjk's avatar
hjk committed
958
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
hjk's avatar
hjk committed
959
960
    d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
    setState(InferiorShutdownOk);
hjk's avatar
hjk committed
961
    d->queueShutdownEngine();
hjk's avatar
hjk committed
962
963
964
965
966
}

void DebuggerEngine::notifyInferiorShutdownFailed()
{
    showMessage(_("INFERIOR SHUTDOWN FAILED"));
Friedemann Kleint's avatar
Friedemann Kleint committed
967
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
968
    setState(InferiorShutdownFailed);
hjk's avatar
hjk committed
969
    d->queueShutdownEngine();
hjk's avatar
hjk committed
970
971
972
973
}

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
974
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
975
976
977
978
979
980
981
982
983
984
985
    // This can be issued in almost any state. The inferior could still be
    // alive as some previous notifications might have been bogus.
    d->m_targetState = DebuggerFinished;
    d->m_lastGoodState = d->m_state;
    if (state() == InferiorRunRequested) {
        // We asked for running, but did not see a response.
        // Assume the inferior is dead.
        // FIXME: Use timeout?
        setState(InferiorRunFailed);
        setState(InferiorStopOk);
    }
hjk's avatar
hjk committed
986
    d->queueShutdownInferior();
hjk's avatar
hjk committed
987
988
989
990
}

void DebuggerEnginePrivate::doShutdownEngine()
{
991
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
hjk's avatar
hjk committed
992
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
993
    m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
hjk's avatar
hjk committed
994
995
996
997
998
    m_engine->shutdownEngine();
}

void DebuggerEngine::notifyEngineShutdownOk()
{
hjk's avatar
hjk committed
999
    showMessage(_("NOTE: ENGINE SHUTDOWN OK"));
hjk's avatar
hjk committed
1000
1001
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    setState(EngineShutdownOk);
1002
    d->queueFinishDebugger();
hjk's avatar
hjk committed
1003
1004
1005
}

void DebuggerEngine::notifyEngineShutdownFailed()
hjk's avatar
hjk committed
1006
{
hjk's avatar
hjk committed
1007
    showMessage(_("NOTE: ENGINE SHUTDOWN FAILED"));
hjk's avatar
hjk committed
1008
1009
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    setState(EngineShutdownFailed);
1010
    d->queueFinishDebugger();
hjk's avatar
hjk committed
1011
1012
1013
1014
}

void DebuggerEnginePrivate::doFinishDebugger()
{
hjk's avatar
hjk committed
1015
    m_engine->showMessage(_("NOTE: FINISH DEBUGGER"));
1016
    QTC_ASSERT(state() == DebuggerFinished, qDebug() << state());
hjk's avatar
hjk committed
1017
    m_engine->resetLocation();
hjk's avatar
hjk committed
1018
    QTC_ASSERT(m_runControl, return);
hjk's avatar
hjk committed
1019
1020
1021
1022
1023
    m_runControl->debuggingFinished();
}

void DebuggerEngine::notifyEngineIll()
{
hjk's avatar
hjk committed
1024
    showMessage(_("NOTE: ENGINE ILL ******"));
hjk's avatar
hjk committed
1025
1026
    d->m_targetState = DebuggerFinished;
    d->m_lastGoodState = d->m_state;
hjk's avatar
hjk committed
1027
1028
1029
    switch (state()) {
        case InferiorRunRequested:
        case InferiorRunOk:
1030
1031
1032
1033
1034
1035
1036
            // The engine does not look overly ill right now, so attempt to
            // properly interrupt at least once. If that fails, we are on the
            // shutdown path due to d->m_targetState anyways.
            setState(InferiorStopRequested, true);
            showMessage(_("ATTEMPT TO INTERRUPT INFERIOR"));
            interruptInferior();
            break;
hjk's avatar
hjk committed
1037
1038
        case InferiorStopRequested:
        case InferiorStopOk:
1039
            showMessage(_("FORWARDING STATE TO InferiorShutdownFailed"));
hjk's avatar
hjk committed
1040
            setState(InferiorShutdownFailed, true);
1041
            d->queueShutdownEngine();
hjk's avatar
hjk committed
1042
1043
            break;
        default:
1044
            d->queueShutdownEngine();
hjk's avatar
hjk committed
1045
            break;
hjk's avatar
hjk committed
1046
1047
1048
1049
1050
    }
}

void DebuggerEngine::notifyEngineSpontaneousShutdown()
{
hjk's avatar
hjk committed
1051
    showMessage(_("NOTE: ENGINE SPONTANEOUS SHUTDOWN"));
1052
    setState(EngineShutdownOk, true);
hjk's avatar
hjk committed
1053
    d->queueFinishDebugger();
hjk's avatar
hjk committed
1054
1055
1056
1057
}

void DebuggerEngine::notifyInferiorExited()
{
hjk's avatar
hjk committed
1058
    showMessage(_("NOTE: INFERIOR EXITED"));
hjk's avatar
hjk committed
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
    resetLocation();

    // This can be issued in almost any state. We assume, though,
    // that at this point of time the inferior is not running anymore,
    // even if stop notification were not issued or got lost.
    if (state() == InferiorRunOk) {
        setState(InferiorStopRequested);
        setState(InferiorStopOk);
    }
    setState(InferiorShutdownRequested);
    setState(InferiorShutdownOk);
1070
    d->queueShutdownEngine();
1071
1072
}

1073
1074
void DebuggerEngine::setState(DebuggerState state, bool forced)
{
1075
    //qDebug() << "STATUS CHANGE: FROM " << stateName(d->m_state)
1076
    //         << " TO " << stateName(state);
1077

1078
1079
1080
    DebuggerState oldState = d->m_state;
    d->m_state = state;

hjk's avatar
hjk committed
1081
1082
1083
    QString msg = _("State changed%5 from %1(%2) to %3(%4).")
     .arg(stateName(oldState)).arg(oldState).arg(stateName(state)).arg(state)
     .arg(forced ? " BY FORCE" : "");
1084
    if (!forced && !isAllowedTransition(oldState, state))
1085
1086
        qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;

1087
1088
1089
1090
    const bool running = d->m_state == InferiorRunOk;
    if (running)
        threadsHandler()->notifyRunning();

1091
    showMessage(msg, LogDebug);
1092
    updateViews();
1093
1094
1095
1096

    emit stateChanged(d->m_state);
}

1097
1098
void DebuggerEngine::updateViews()
{
1099
1100
1101
    // The slave engines are not entitled to change the view. Their wishes
    // should be coordinated by their master engine.
    if (isSlaveEngine())
hjk's avatar
x    
hjk committed
1102
1103
        return;
    plugin()->updateState(this);
1104
1105
}

1106
1107
1108
1109
1110
1111
bool DebuggerEngine::isSlaveEngine() const
{
    return d->m_isSlaveEngine;
}

void DebuggerEngine::setSlaveEngine(bool value)
1112
{
1113
    d->m_isSlaveEngine = value;
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
}

bool DebuggerEngine::debuggerActionsEnabled() const
{
    return debuggerActionsEnabled(d->m_state);
}

bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
{
    switch (state) {
hjk's avatar
hjk committed
1124
1125
    case InferiorSetupRequested:
    case InferiorRunOk:
1126
    case InferiorUnrunnable:
hjk's avatar
hjk committed
1127
    case InferiorStopOk:
1128
        return true;
hjk's avatar
hjk committed
1129
1130
1131
    case InferiorStopRequested:
    case InferiorRunRequested:
    case InferiorRunFailed:
1132
    case DebuggerNotReady:
hjk's avatar
hjk committed
1133
    case EngineSetupRequested:
1134
1135
    case EngineSetupOk:
    case EngineSetupFailed:
hjk's avatar
hjk committed
1136
1137
    case EngineRunRequested:
    case EngineRunFailed:
hjk's avatar
hjk committed
1138
    case InferiorSetupFailed:
1139
    case InferiorStopFailed:
hjk's avatar
hjk committed
1140
1141
    case InferiorShutdownRequested:
    case InferiorShutdownOk:
1142
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
1143
1144
1145
1146
    case EngineShutdownRequested:
    case EngineShutdownOk:
    case EngineShutdownFailed:
    case DebuggerFinished:
hjk's avatar
hjk committed
1147
        return false;
1148
1149
1150
1151
1152
1153
    }
    return false;
}

void DebuggerEngine::notifyInferiorPid(qint64 pid)
{
ck's avatar
ck committed
1154
    showMessage(tr("Taking notice of pid %1").arg(pid));
1155
1156
1157
    if (d->m_inferiorPid == pid)
        return;
    d->m_inferiorPid = pid;
1158
    QTimer::singleShot(0, d, SLOT(raiseApplication()));
1159
1160
1161
1162
1163
1164
1165
}

qint64 DebuggerEngine::inferiorPid() const
{
    return d->m_inferiorPid;
}

1166
DebuggerPlugin *DebuggerEngine::plugin()
1167
1168
1169
1170
1171
1172
1173
1174
1175
{
    return DebuggerPlugin::instance();
}

bool DebuggerEngine::isReverseDebugging() const
{
    return plugin()->isReverseDebugging();
}

1176
1177
bool DebuggerEngine::isActive() const
{
hjk's avatar
hjk committed
1178
    return d->m_isActive;
1179
1180
1181
1182
}

void DebuggerEngine::setActive