debuggerengine.cpp 52.2 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
8
9
10
11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12
13
14
15
16
17
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21
22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23
24
25
26
27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
31
32
33
34
**
**************************************************************************/

#include "debuggerengine.h"

35
#include "debuggerinternalconstants.h"
36
#include "debuggeractions.h"
37
#include "debuggercore.h"
38
#include "debuggerplugin.h"
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
41
#include "debuggerstartparameters.h"
42

43
44
#include "memoryagent.h"
#include "disassembleragent.h"
45
46
47
48
49
50
51
52
53
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

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

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

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

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

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

75
#include <QtGui/QMessageBox>
76

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

82
83
84
85
enum { debug = 0 };

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

87

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

94
95
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
96
97
98
99
100
101
102
103
104
Internal::Location::Location(const StackFrame &frame, bool marker)
{
    init();
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
105
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
106
107
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
119
            << " processArgs=" << sp.processArgs
120
121
122
123
124
125
126
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
127
            << " useServerStartScript=" << sp.useServerStartScript
128
            << " serverStartScript=" << sp.serverStartScript
129
            << " abi=" << sp.toolChainAbi.toString() << '\n';
130
131
132
    return str;
}

133

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

140
class DebuggerEnginePrivate : public QObject
141
{
142
143
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
176

177
public slots:
178
    void doSetupEngine();
hjk's avatar
hjk committed
179
180
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
181
182
    void doShutdownEngine();
    void doShutdownInferior();
183
    void doInterruptInferior();
hjk's avatar
hjk committed
184
    void doFinishDebugger();
hjk's avatar
hjk committed
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
    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()));
    }

200
201
    void queueRunEngine()
    {
hjk's avatar
hjk committed
202
203
204
205
206
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

207
208
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
209
210
211
212
213
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

214
215
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
216
217
218
219
220
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

221
222
    void queueFinishDebugger()
    {
223
224
225
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
226
227
228
229
230
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
231
232
    }

233
234
    void raiseApplication()
    {
235
236
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
237
238
    }

239
    void scheduleResetLocation()
240
    {
241
        m_stackHandler.scheduleResetLocation();
242
        m_threadsHandler.scheduleResetLocation();
243
        m_disassemblerAgent.scheduleResetLocation();
244
245
246
247
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

248
    void resetLocation()
249
250
251
    {
        m_locationTimer.stop();
        m_locationMark.reset();
252
        m_stackHandler.resetLocation();
253
        m_threadsHandler.resetLocation();
254
        m_disassemblerAgent.resetLocation();
255
256
    }

257
public:
hjk's avatar
hjk committed
258
    DebuggerState state() const { return m_state; }
259
260
261
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
262

263
    DebuggerEngine *m_engine; // Not owned.
264
    DebuggerEngine *m_masterEngine; // Not owned
265
266
267
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
268
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
269
270

    // The current state.
271
272
    DebuggerState m_state;

hjk's avatar
hjk committed
273
274
275
276
277
278
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

279
280
281
282
283
284
285
286
    qint64 m_inferiorPid;

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

289
290
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
291
292
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
293
294

    bool m_isStateDebugging;
295
296
297
298

    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
299
    void reportTestError(const QString &msg, int line);
300
301
    bool m_testsPossible;
    QStringList m_testContents;
302
303
    TaskHub *m_taskHub;
    QString m_testFileName;
304
305
306
307
308
309
310
311
312
};


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

313
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
314
        DebuggerLanguages languages,
315
        DebuggerEngine *parentEngine)
316
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
317
{
318
    d->m_inferiorPid = 0;
319
320
321
322
}

DebuggerEngine::~DebuggerEngine()
{
323
324
    disconnect();
    delete d;
325
326
}

327
328
329
330
331
332
333
334
335
336
337
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)
338
        SN(InferiorSetupOk)
339
340
341
342
343
344
345
346
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
347
        SN(InferiorExitOk)
348
349
350
351
352
353
354
355
356
357
358
359
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

360
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
361
{
362
    showMessage(msg, StatusBar, timeout);
363
}
364

365
366
367
368
369
370
371
372
373
374
375
376
377
378
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
{
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
{
hjk's avatar
hjk committed
393
394
395
396
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
397
398
399
400
}

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

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

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

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
422
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
423
424
425
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
426
427
428
429
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
430
    QAbstractItemModel *model = registerHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
431
432
433
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
434
435
436
437
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
438
    QAbstractItemModel *model = stackHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
439
440
441
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
442
443
444
445
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
446
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
447
448
449
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
450
451
452
453
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
454
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
455
456
457
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
458
459
460
461
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
462
    QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
463
464
465
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
466
467
468
469
}

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

476
477
478
479
480
481
482
483
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

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

492
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
493
494
495
496
497
498
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
499
500
501
502
503
504
505
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

506
507
508
509
510
511
512
513
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
{
514
515
516
517
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
518
519
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
520
    debuggerCore()->showMessage(msg, channel, timeout);
521
522
523
524
525
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
526
527
528
529
}

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

533
534
535
536
    d->m_progress.setProgressRange(0, 1000);
    Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
537
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
538
539
    d->m_progress.reportStarted();

540
541
542
543
    d->m_runControl = runControl;

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

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

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
551
    debuggerCore()->action(OperateByInstruction)
552
553
        ->setEnabled(engineCapabilities & DisassemblerCapability);

554
555
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
556
557
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
558
    d->m_progress.setProgressValue(200);
559
    d->queueSetupEngine();
560
561
562
563
}

void DebuggerEngine::resetLocation()
{
564
565
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
566
567
}

568
void DebuggerEngine::gotoLocation(const Location &loc)
569
{
570
571
572
573
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
574
575
576
577
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

578
    d->resetLocation();
579

580
581
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
582
583
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
584
    IEditor *editor = 0;
hjk's avatar
hjk committed
585
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
586
        editor = editorManager->openEditor(file, Core::Id(),
587
588
589
590
591
592
593
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
594
    }
595
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
596
597
598
    if (texteditor)
        texteditor->gotoLine(line, 0);

599
600
601
602
603
604
    if (loc.needsMarker()) {
        d->m_locationMark.reset(new TextEditor::BaseTextMark);
        d->m_locationMark->setLocation(file, line);
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
605
606

    // FIXME: Breaks with split views.
607
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
608
        editorManager->activateEditor(editor);
609
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
610
611
}

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

622
623
// Called from RunControl.
void DebuggerEngine::handleFinished()
624
{
625
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
626
    d->m_runControl = 0;
627
628
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

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

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


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

bool DebuggerEngine::qtDumperLibraryEnabled() const
{
hjk's avatar
hjk committed
657
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
658
659
660
661
662
663
664
665
666
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
667
    debuggerCore()->showQtDumperLibraryWarning(details);
668
669
670
671
672
673
674
675
676
677
678
679
}

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

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

hjk's avatar
hjk committed
680
DebuggerState DebuggerEngine::lastGoodState() const
681
{
hjk's avatar
hjk committed
682
683
684
685
686
687
688
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
690
691
692
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
693
    case DebuggerNotReady:
694
        return to == EngineSetupRequested;
695

hjk's avatar
hjk committed
696
    case EngineSetupRequested:
697
698
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
699
700
701
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
702
    case EngineSetupOk:
hjk's avatar
hjk committed
703
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
704

hjk's avatar
hjk committed
705
    case InferiorSetupRequested:
706
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
707
    case InferiorSetupFailed:
hjk's avatar
hjk committed
708
        return to == EngineShutdownRequested;
709
710
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
711
712

    case EngineRunRequested:
hjk's avatar
hjk committed
713
714
715
716
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
717
    case EngineRunFailed:
718
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
719
720
721
722
723
724

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
725
726
727
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
728
729
730
731
732

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
733
            || to == InferiorStopOk || InferiorExitOk;
734
    case InferiorStopFailed:
hjk's avatar
hjk committed
735
        return to == EngineShutdownRequested;
736

737
738
739
    case InferiorExitOk:
        return to == InferiorShutdownOk;

740
    case InferiorUnrunnable:
hjk's avatar
hjk committed
741
742
743
744
745
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
746
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
747
        return to == EngineShutdownRequested;
748

hjk's avatar
hjk committed
749
    case EngineShutdownRequested:
750
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
751
752
753
754
755
756
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
757
        return to == EngineSetupRequested; // Happens on restart.
758
759
    }

760
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
761
762
763
    return false;
}

764
765
void DebuggerEngine::setupSlaveEngine()
{
766
    QTC_CHECK(state() == DebuggerNotReady);
767
768
769
770
771
772
773
774
775
776
    d->queueSetupEngine();
}

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

777
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
778
{
hjk's avatar
hjk committed
779
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
780
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
781
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
782
    if (isMasterEngine() && runControl())
783
        runControl()->startFailed();
hjk's avatar
hjk committed
784
    setState(DebuggerFinished);
hjk's avatar
hjk committed
785
786
}

787
void DebuggerEngine::notifyEngineSetupOk()
788
{
hjk's avatar
hjk committed
789
    showMessage(_("NOTE: ENGINE SETUP OK"));
790
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
791
    setState(EngineSetupOk);
hjk's avatar
hjk committed
792
    showMessage(_("QUEUE: SETUP INFERIOR"));
793
    if (isMasterEngine())
794
795
796
797
798
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
799
    QTC_CHECK(state() == EngineSetupOk);
800
    d->queueSetupInferior();
801
802
}

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

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

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

829
830
831
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
832
    QTC_CHECK(state() == InferiorSetupOk);
833
834
835
    d->queueRunEngine();
}

hjk's avatar
hjk committed
836
837
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
838
    m_engine->showMessage(_("CALL: RUN ENGINE"));
839
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
840
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
841
842
843
    m_engine->runEngine();
}

hjk's avatar
hjk committed
844
845
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
847
848
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
849
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
850
851
852
853
854
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
855
    showMessage(_("NOTE: ENGINE RUN FAILED"));
856
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
857
858
859
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
860
    setState(EngineRunFailed);
861
862
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
863
864
865
866
}

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

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
876
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
877
878
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
879
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
880
    setState(InferiorStopOk);
hjk's avatar
hjk committed
881
882
883
884
}

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

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
892
    showMessage(_("NOTE: INFERIOR RUN OK"));
893
894
895
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
896
897
898
899
900
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
901
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
902
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
903
904
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
905
906
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
907
908
909
910
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
911
912
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
913
    if (isDying()) {
hjk's avatar
hjk committed
914
915
916
917
918
919
920
921
922
923
924
925
926
        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
927
    }
928
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
929
    setState(InferiorStopOk);
hjk's avatar
hjk committed
930
931
}

hjk's avatar
hjk committed
932
void DebuggerEngine::notifyInferiorSpontaneousStop()
933
{
934
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
935
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
936
    setState(InferiorStopOk);
937
938
}

hjk's avatar
hjk committed
939
void DebuggerEngine::notifyInferiorStopFailed()
940
{
hjk's avatar
hjk committed
941
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
942
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
943
    setState(InferiorStopFailed);
944
945
    if (isMasterEngine())
        d->queueShutdownEngine();
946
947
948
949
}

void DebuggerEnginePrivate::doInterruptInferior()
{
950
951
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
hjk's avatar
hjk committed
952
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
953
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
954
955
956
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
957
958
void DebuggerEnginePrivate::doShutdownInferior()
{
959
960
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << m_engine << state());
961
    resetLocation();
hjk's avatar
hjk committed
962
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
963
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
964
965
966
967
968
969
    m_engine->shutdownInferior();
}

void DebuggerEngine::notifyInferiorShutdownOk()
{
    showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
970
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
971
972
    d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
    setState(InferiorShutdownOk);
973
974
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
975
976
977
978
979
}

void DebuggerEngine::notifyInferiorShutdownFailed()
{
    showMessage(_("INFERIOR SHUTDOWN FAILED"));
Friedemann Kleint's avatar
Friedemann Kleint committed
980
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
981
    setState(InferiorShutdownFailed);
982
983
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
984
985
986
987
}

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
988
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
989
990
991
992
993
994
995
996
997
998
999
    // 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
1000
    d->queueShutdownInferior();
hjk's avatar
hjk committed
1001
1002
}

1003
1004
void DebuggerEngine::shutdownSlaveEngine()
{
1005
    QTC_CHECK(isAllowedTransition(state(),EngineShutdownRequested));
1006
1007
1008
1009
    setState(EngineShutdownRequested);
    shutdownEngine();
}

hjk's avatar
hjk committed
1010
1011
void DebuggerEnginePrivate::doShutdownEngine()
{
1012
1013
    QTC_ASSERT(isMasterEngine(), qDebug() << m_engine; return);
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << m_engine << state());
hjk's avatar
hjk committed
1014
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
1015
    m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
hjk's avatar
hjk committed
1016
1017
1018
1019
1020
    m_engine->shutdownEngine();
}

void DebuggerEngine::notifyEngineShutdownOk()
{
hjk's avatar
hjk committed
1021
    showMessage(_("NOTE: ENGINE SHUTDOWN OK"));