debuggerengine.cpp 46.7 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
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.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
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.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
66
67
#include <utils/savedaction.h>
#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
68
#include <QtCore/QFutureInterface>
69

70
#include <QtGui/QMessageBox>
71

hjk's avatar
hjk committed
72
using namespace Core;
73
using namespace Debugger::Internal;
hjk's avatar
hjk committed
74
75
using namespace ProjectExplorer;
using namespace TextEditor;
76

77
78
79
80
enum { debug = 0 };

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

82

83
84
85
86
87
88
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

89
90
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
91
92
93
94
95
96
97
98
99
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;
100
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
101
102
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
114
            << " processArgs=" << sp.processArgs
115
116
117
118
119
120
121
            << " 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
122
            << " useServerStartScript=" << sp.useServerStartScript
123
            << " serverStartScript=" << sp.serverStartScript
124
            << " abi=" << sp.toolChainAbi.toString() << '\n';
125
126
127
    return str;
}

128

129
130
131
132
133
134
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

135
class DebuggerEnginePrivate : public QObject
136
{
137
138
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
169

170
public slots:
171
    void doSetupEngine();
hjk's avatar
hjk committed
172
173
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
174
175
    void doShutdownEngine();
    void doShutdownInferior();
176
    void doInterruptInferior();
hjk's avatar
hjk committed
177
    void doFinishDebugger();
hjk's avatar
hjk committed
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
    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()));
    }

193
194
    void queueRunEngine()
    {
hjk's avatar
hjk committed
195
196
197
198
199
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

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

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

214
215
    void queueFinishDebugger()
    {
216
217
218
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
219
220
221
222
223
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
224
225
    }

226
227
    void raiseApplication()
    {
228
229
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
230
231
    }

232
    void scheduleResetLocation()
233
    {
234
        m_stackHandler.scheduleResetLocation();
235
        m_threadsHandler.scheduleResetLocation();
236
        m_disassemblerAgent.scheduleResetLocation();
237
238
239
240
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

241
    void resetLocation()
242
243
244
    {
        m_locationTimer.stop();
        m_locationMark.reset();
245
        m_stackHandler.resetLocation();
246
        m_threadsHandler.resetLocation();
247
        m_disassemblerAgent.resetLocation();
248
249
    }

250
public:
hjk's avatar
hjk committed
251
    DebuggerState state() const { return m_state; }
252
253
254
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
hjk's avatar
hjk committed
255

256
    DebuggerEngine *m_engine; // Not owned.
257
    DebuggerEngine *m_masterEngine; // Not owned
258
259
260
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
261
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
262
263

    // The current state.
264
265
    DebuggerState m_state;

hjk's avatar
hjk committed
266
267
268
269
270
271
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

272
273
274
275
276
277
278
279
    qint64 m_inferiorPid;

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

282
283
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
284
285
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
286
287

    bool m_isStateDebugging;
288
289
290
291
292
293
294
295
296
};


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

297
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
298
        DebuggerLanguages languages,
299
        DebuggerEngine *parentEngine)
300
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
301
{
302
    d->m_inferiorPid = 0;
303
304
305
306
}

DebuggerEngine::~DebuggerEngine()
{
307
308
    disconnect();
    delete d;
309
310
}

311
312
313
314
315
316
317
318
319
320
321
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)
322
        SN(InferiorSetupOk)
323
324
325
326
327
328
329
330
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
331
        SN(InferiorExitOk)
332
333
334
335
336
337
338
339
340
341
342
343
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

344
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
345
{
346
    showMessage(msg, StatusBar, timeout);
347
}
348

349
350
351
352
353
354
355
356
357
358
359
360
361
362
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
{
363
364
365
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
366
367
368
369
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
370
371
372
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
373
374
375
376
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
377
378
379
380
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
381
382
383
384
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
385
386
387
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
388
389
390
391
}

WatchHandler *DebuggerEngine::watchHandler() const
{
392
393
394
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
395
396
397
398
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
399
400
401
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
402
403
404
405
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
406
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
407
408
409
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
410
411
412
413
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
414
    QAbstractItemModel *model = registerHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
415
416
417
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
418
419
420
421
}

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

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

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

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

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

460
461
462
463
464
465
466
467
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

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

476
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
477
478
479
480
481
482
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

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

490
491
492
493
494
495
496
497
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
{
498
499
500
501
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
502
503
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
504
    debuggerCore()->showMessage(msg, channel, timeout);
505
506
507
508
509
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
510
511
512
513
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
514
515
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
516

517
518
519
520
    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
521
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
522
523
    d->m_progress.reportStarted();

524
525
526
527
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
528
529
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
530

531
532
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
533
534

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
535
    debuggerCore()->action(OperateByInstruction)
536
537
        ->setEnabled(engineCapabilities & DisassemblerCapability);

538
539
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
540
541
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
542
    d->m_progress.setProgressValue(200);
543
    d->queueSetupEngine();
544
545
546
547
}

void DebuggerEngine::resetLocation()
{
548
549
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
550
551
}

552
void DebuggerEngine::gotoLocation(const Location &loc)
553
{
554
555
556
557
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
558
559
560
561
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

562
    d->resetLocation();
563

564
565
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
566
567
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
568
    IEditor *editor = 0;
hjk's avatar
hjk committed
569
    if (editors.isEmpty()) {
570
571
572
573
574
575
576
577
        editor = editorManager->openEditor(file, QString(),
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
578
    }
579
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
580
581
582
    if (texteditor)
        texteditor->gotoLine(line, 0);

583
584
585
586
587
588
    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);
    }
589
590

    // FIXME: Breaks with split views.
591
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
592
        editorManager->activateEditor(editor);
593
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
594
595
}

596
597
598
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
599
    showMessage("HANDLE RUNCONTROL START FAILED");
600
    d->m_runControl = 0;
601
    d->m_progress.setProgressValue(900);
602
603
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
604
605
}

606
607
// Called from RunControl.
void DebuggerEngine::handleFinished()
608
{
609
    showMessage("HANDLE RUNCONTROL FINISHED");
610
    d->m_runControl = 0;
611
612
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
    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
641
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
642
643
644
645
646
647
648
649
650
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
651
    debuggerCore()->showQtDumperLibraryWarning(details);
652
653
654
655
656
657
658
659
660
661
662
663
}

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

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

hjk's avatar
hjk committed
664
DebuggerState DebuggerEngine::lastGoodState() const
665
{
hjk's avatar
hjk committed
666
667
668
669
670
671
672
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
674
675
676
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
677
    case DebuggerNotReady:
678
        return to == EngineSetupRequested;
679

hjk's avatar
hjk committed
680
    case EngineSetupRequested:
681
682
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
683
684
685
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
686
    case EngineSetupOk:
hjk's avatar
hjk committed
687
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
688

hjk's avatar
hjk committed
689
    case InferiorSetupRequested:
690
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
691
    case InferiorSetupFailed:
hjk's avatar
hjk committed
692
        return to == EngineShutdownRequested;
693
694
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
695
696

    case EngineRunRequested:
hjk's avatar
hjk committed
697
698
699
700
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
701
    case EngineRunFailed:
702
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
703
704
705
706
707
708

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
709
710
711
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
712
713
714
715
716

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
717
            || to == InferiorStopOk || InferiorExitOk;
718
    case InferiorStopFailed:
hjk's avatar
hjk committed
719
        return to == EngineShutdownRequested;
720

721
722
723
    case InferiorExitOk:
        return to == InferiorShutdownOk;

724
    case InferiorUnrunnable:
hjk's avatar
hjk committed
725
726
727
728
729
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
730
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
731
        return to == EngineShutdownRequested;
732

hjk's avatar
hjk committed
733
    case EngineShutdownRequested:
734
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
735
736
737
738
739
740
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
741
        return to == EngineSetupRequested; // Happens on restart.
742
743
    }

744
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
745
746
747
    return false;
}

748
749
void DebuggerEngine::setupSlaveEngine()
{
750
    QTC_CHECK(state() == DebuggerNotReady);
751
752
753
754
755
756
757
758
759
760
    d->queueSetupEngine();
}

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

761
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
762
{
hjk's avatar
hjk committed
763
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
764
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
765
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
766
    if (isMasterEngine() && runControl())
767
        runControl()->startFailed();
hjk's avatar
hjk committed
768
    setState(DebuggerFinished);
hjk's avatar
hjk committed
769
770
}

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

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

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

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

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

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

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

hjk's avatar
hjk committed
828
829
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
830
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
831
832
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
833
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
834
835
836
837
838
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
839
    showMessage(_("NOTE: ENGINE RUN FAILED"));
840
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
841
842
843
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
844
    setState(EngineRunFailed);
845
846
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
847
848
849
850
}

void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
851
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
852
853
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
854
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
855
    setState(InferiorRunOk);
hjk's avatar
hjk committed
856
857
858
859
}

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

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
869
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
870
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
871
872
873
874
875
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
876
    showMessage(_("NOTE: INFERIOR RUN OK"));
877
878
879
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
880
881
882
883
884
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
885
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
886
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
887
888
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
889
890
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
891
892
893
894
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
895
896
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
897
    if (isDying()) {
hjk's avatar
hjk committed
898
899
900
901
902
903
904
905
906
907
908
909
910
        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
911
    }
912
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
913
    setState(InferiorStopOk);
hjk's avatar
hjk committed
914
915
}

hjk's avatar
hjk committed
916
void DebuggerEngine::notifyInferiorSpontaneousStop()
917
{
918
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
919
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
920
    setState(InferiorStopOk);
921
922
}

hjk's avatar
hjk committed
923
void DebuggerEngine::notifyInferiorStopFailed()
924
{
hjk's avatar
hjk committed
925
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
926
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
927
    setState(InferiorStopFailed);
928
929
    if (isMasterEngine())
        d->queueShutdownEngine();
930
931
932
933
}

void DebuggerEnginePrivate::doInterruptInferior()
{
934
935
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
hjk's avatar
hjk committed
936
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
937
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
938
939
940
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
941
942
void DebuggerEnginePrivate::doShutdownInferior()
{
943
944
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << m_engine << state());
945
    resetLocation();
hjk's avatar
hjk committed
946
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
947
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
948
949
950
951
952
953
    m_engine->shutdownInferior();
}

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

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

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
972
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
973
974
975
976
977
978
979
980
981
982
983
    // 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
984
    d->queueShutdownInferior();
hjk's avatar
hjk committed
985
986
}

987
988
void DebuggerEngine::shutdownSlaveEngine()
{
989
    QTC_CHECK(isAllowedTransition(state(),EngineShutdownRequested));
990
991
992
993
    setState(EngineShutdownRequested);
    shutdownEngine();
}

hjk's avatar
hjk committed
994
995
void DebuggerEnginePrivate::doShutdownEngine()
{
996
997
    QTC_ASSERT(isMasterEngine(), qDebug() << m_engine; return);
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << m_engine << state());
hjk's avatar
hjk committed
998
    m_targetState = DebuggerFinished;