debuggerengine.cpp 51.9 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_watchHandler.scheduleResetLocation();
243
        m_threadsHandler.scheduleResetLocation();
244
        m_disassemblerAgent.scheduleResetLocation();
245
246
247
248
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

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

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

265
    DebuggerEngine *m_engine; // Not owned.
266
    DebuggerEngine *m_masterEngine; // Not owned
267
268
269
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
270
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
271
272

    // The current state.
273
274
    DebuggerState m_state;

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

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

281
282
283
284
285
286
287
288
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
297
298
299
300

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


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

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

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

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

362
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
363
{
364
    showMessage(msg, StatusBar, timeout);
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));
}

379
380
381
382
383
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

384
385
ModulesHandler *DebuggerEngine::modulesHandler() const
{
386
387
388
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
389
390
391
392
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
393
394
395
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
396
397
398
399
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
400
401
402
403
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
404
405
406
407
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
408
409
410
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
411
412
413
414
}

WatchHandler *DebuggerEngine::watchHandler() const
{
415
416
417
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
418
419
420
421
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
422
423
424
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
425
426
427
428
}

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

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

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

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

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

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

QAbstractItemModel *DebuggerEngine::returnModel() const
{
477
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
478
479
480
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
481
482
}

483
484
485
486
487
488
489
490
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

491
492
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
493
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
494
495
496
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
497
498
}

499
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
500
501
502
503
504
505
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
506
507
508
509
510
511
512
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
537
538
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
539

540
541
542
543
    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
544
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
545
546
    d->m_progress.reportStarted();

547
548
549
550
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
551
552
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
553

554
555
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
556

hjk's avatar
hjk committed
557
    debuggerCore()->action(OperateByInstruction)
558
        ->setEnabled(hasCapability(DisassemblerCapability));
559

560
561
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
562
563
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
564
    d->m_progress.setProgressValue(200);
565
    d->queueSetupEngine();
566
567
568
569
}

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

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

578
579
580
581
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
582
583
584
585
586
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


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

606
607
608
609
610
611
    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);
    }
612
613

    // FIXME: Breaks with split views.
614
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
615
        editorManager->activateEditor(editor);
616
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
617
618
}

619
620
621
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
622
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
623
    d->m_runControl = 0;
624
    d->m_progress.setProgressValue(900);
625
626
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
627
628
}

629
630
// Called from RunControl.
void DebuggerEngine::handleFinished()
631
{
632
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
633
    d->m_runControl = 0;
634
635
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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
    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
664
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
665
666
667
668
669
670
671
672
673
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
674
    debuggerCore()->showQtDumperLibraryWarning(details);
675
676
677
678
679
680
681
682
683
684
685
686
}

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

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

hjk's avatar
hjk committed
687
DebuggerState DebuggerEngine::lastGoodState() const
688
{
hjk's avatar
hjk committed
689
690
691
692
693
694
695
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
697
698
699
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
700
    case DebuggerNotReady:
701
        return to == EngineSetupRequested;
702

hjk's avatar
hjk committed
703
    case EngineSetupRequested:
704
705
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
706
707
708
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
709
    case EngineSetupOk:
hjk's avatar
hjk committed
710
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
711

hjk's avatar
hjk committed
712
    case InferiorSetupRequested:
713
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
714
    case InferiorSetupFailed:
hjk's avatar
hjk committed
715
        return to == EngineShutdownRequested;
716
717
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
718
719

    case EngineRunRequested:
hjk's avatar
hjk committed
720
721
722
723
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
724
    case EngineRunFailed:
725
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
726
727
728
729
730
731

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
732
733
734
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
735
736
737
738
739

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
740
            || to == InferiorStopOk || InferiorExitOk;
741
    case InferiorStopFailed:
hjk's avatar
hjk committed
742
        return to == EngineShutdownRequested;
743

744
745
746
    case InferiorExitOk:
        return to == InferiorShutdownOk;

747
    case InferiorUnrunnable:
hjk's avatar
hjk committed
748
749
750
751
752
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
753
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
754
        return to == EngineShutdownRequested;
755

hjk's avatar
hjk committed
756
    case EngineShutdownRequested:
757
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
758
759
760
761
762
763
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
764
        return to == EngineSetupRequested; // Happens on restart.
765
766
    }

767
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
768
769
770
    return false;
}

771
772
void DebuggerEngine::setupSlaveEngine()
{
773
    QTC_CHECK(state() == DebuggerNotReady);
774
775
776
777
778
779
780
781
782
783
    d->queueSetupEngine();
}

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

784
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
785
{
hjk's avatar
hjk committed
786
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
787
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
788
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
789
    if (isMasterEngine() && runControl())
790
        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"));
797
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
798
    setState(EngineSetupOk);
hjk's avatar
hjk committed
799
    showMessage(_("QUEUE: SETUP INFERIOR"));
800
    if (isMasterEngine())
801
802
803
804
805
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
806
    QTC_CHECK(state() == EngineSetupOk);
807
    d->queueSetupInferior();
808
809
}

hjk's avatar
hjk committed
810
void DebuggerEnginePrivate::doSetupInferior()
811
{
812
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
813
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
814
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
815
816
817
818
819
    m_engine->setupInferior();
}

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

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
829
    showMessage(_("NOTE: INFERIOR SETUP OK"));
830
831
832
833
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
834
835
}

836
837
838
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
839
    QTC_CHECK(state() == InferiorSetupOk);
840
841
842
    d->queueRunEngine();
}

hjk's avatar
hjk committed
843
844
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
845
    m_engine->showMessage(_("CALL: RUN ENGINE"));
846
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
847
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
848
849
850
    m_engine->runEngine();
}

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

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
862
    showMessage(_("NOTE: ENGINE RUN FAILED"));
863
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
864
865
866
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
867
    setState(EngineRunFailed);
868
869
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
870
871
872
873
}

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

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
883
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
884
885
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
886
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
887
    setState(InferiorStopOk);
hjk's avatar
hjk committed
888
889
890
891
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
892
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
893
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
894
895
896
897
898
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
899
    showMessage(_("NOTE: INFERIOR RUN OK"));
900
901
902
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
903
904
905
906
907
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
908
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
909
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
910
911
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
912
913
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
914
915
916
917
}

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

hjk's avatar
hjk committed
939
void DebuggerEngine::notifyInferiorSpontaneousStop()
940
{
941
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
942
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
943
    setState(InferiorStopOk);
944
945
}

hjk's avatar
hjk committed
946
void DebuggerEngine::notifyInferiorStopFailed()
947
{
hjk's avatar
hjk committed
948
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
949
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
950
    setState(InferiorStopFailed);
951
952
    if (isMasterEngine())
        d->queueShutdownEngine();
953
954
955
956
}

void DebuggerEnginePrivate::doInterruptInferior()
{
957
958
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
hjk's avatar
hjk committed
959
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
960
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
961
962
963
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
964
965
void DebuggerEnginePrivate::doShutdownInferior()
{
966
967
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << m_engine << state());
968
    resetLocation();
hjk's avatar
hjk committed
969
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
970
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
971
972
973
974
975
976
    m_engine->shutdownInferior();
}

void DebuggerEngine::notifyInferiorShutdownOk()
{
    showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
977
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
978
979
    d->m_lastGoodState = DebuggerNotReady; // A "neutral" value.
    setState(InferiorShutdownOk);
980
981
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
982
983
984
985
986
}

void DebuggerEngine::notifyInferiorShutdownFailed()
{
    showMessage(_("INFERIOR SHUTDOWN FAILED"));
Friedemann Kleint's avatar
Friedemann Kleint committed
987
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
hjk's avatar
hjk committed
988
    setState(InferiorShutdownFailed);
989
990
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
991
992
993
994
}

void DebuggerEngine::notifyInferiorIll()
{
hjk's avatar
hjk committed
995
    showMessage(_("NOTE: INFERIOR ILL"));
hjk's avatar
hjk committed
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
    // 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
1007
    d->queueShutdownInferior();
hjk's avatar
hjk committed
1008
1009
}

1010
1011
void DebuggerEngine::shutdownSlaveEngine()
{
1012
    QTC_CHECK(isAllowedTransition(state(),EngineShutdownRequested));
1013
1014
1015
1016
    setState(EngineShutdownRequested);
    shutdownEngine();
}

hjk's avatar
hjk committed
1017
1018
void DebuggerEnginePrivate::doShutdownEngine()
{
1019
1020
    QTC_ASSERT(isMasterEngine(), qDebug() << m_engine; return);
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << m_engine << state());
hjk's avatar
hjk committed
1021
    m_targetState = DebuggerFinished;