debuggerengine.cpp 45.4 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
8
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11
12
13
14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
16
17
18
19
20
21
22
23
24
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
con's avatar
con committed
25
26
27
28
29
30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
31
32
33
34
35
36
**
**************************************************************************/

#include "debuggerengine.h"

#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
100
101
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;
}

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

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

127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

// Used in "real" editors
class LocationMark : public TextEditor::BaseTextMark
{
public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
    {}

    QIcon icon() const { return debuggerCore()->locationMarkIcon(); }
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
    void removedFromEditor() {}
146
    TextEditor::ITextMark::Priority priority() const { return TextEditor::ITextMark::HighPriority; }
147
148
149
150
};



151
152
153
154
155
156
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

157
class DebuggerEnginePrivate : public QObject
158
{
159
160
    Q_OBJECT

161
public:
162
163
164
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
            const DebuggerStartParameters &sp)
165
      : m_engine(engine),
166
        m_masterEngine(masterEngine),
167
168
169
        m_runControl(0),
        m_startParameters(sp),
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
170
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
171
        m_targetState(DebuggerNotReady),
172
        m_modulesHandler(),
173
        m_registerHandler(),
174
175
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
176
        m_threadsHandler(),
177
        m_watchHandler(engine),
178
        m_disassemblerAgent(engine),
179
180
        m_memoryAgent(engine),
        m_isStateDebugging(false)
181
    {
182
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
183
    }
184
185

    ~DebuggerEnginePrivate() {}
186

187
public slots:
188
    void doSetupEngine();
hjk's avatar
hjk committed
189
190
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
191
192
    void doShutdownEngine();
    void doShutdownInferior();
193
    void doInterruptInferior();
hjk's avatar
hjk committed
194
    void doFinishDebugger();
hjk's avatar
hjk committed
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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()));
    }

210
211
    void queueRunEngine()
    {
hjk's avatar
hjk committed
212
213
214
215
216
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

217
218
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
219
220
221
222
223
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

224
225
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
226
227
228
229
230
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

231
232
    void queueFinishDebugger()
    {
233
234
235
236
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
        m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
hjk's avatar
hjk committed
237
238
239
        QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
    }

240
241
    void raiseApplication()
    {
242
243
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
244
245
    }

246
    void scheduleResetLocation()
247
    {
248
        m_stackHandler.scheduleResetLocation();
249
        m_disassemblerAgent.scheduleResetLocation();
250
251
252
253
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

254
    void resetLocation()
255
256
257
    {
        m_locationTimer.stop();
        m_locationMark.reset();
258
259
        m_stackHandler.resetLocation();
        m_disassemblerAgent.resetLocation();
260
261
    }

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

268
    DebuggerEngine *m_engine; // Not owned.
269
    DebuggerEngine *m_masterEngine; // Not owned
270
271
272
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
hjk's avatar
hjk committed
273
274

    // The current state.
275
276
    DebuggerState m_state;

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

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

283
284
285
286
287
288
289
290
    qint64 m_inferiorPid;

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

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

    bool m_isStateDebugging;
299
300
301
302
303
304
305
306
307
};


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

308
309
310
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
        DebuggerEngine *parentEngine)
  : d(new DebuggerEnginePrivate(this, parentEngine, startParameters))
311
312
313
314
315
{
}

DebuggerEngine::~DebuggerEngine()
{
316
317
    disconnect();
    delete d;
318
319
}

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

353
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
354
{
355
    showMessage(msg, StatusBar, timeout);
356
}
357

358
359
360
361
362
363
364
365
366
367
368
369
370
371
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
{
372
373
374
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
375
376
377
378
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
379
380
381
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
382
383
384
385
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
386
387
388
389
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
390
391
392
393
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
394
395
396
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
397
398
399
400
}

WatchHandler *DebuggerEngine::watchHandler() const
{
401
402
403
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
404
405
406
407
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
408
409
410
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
411
412
413
414
}

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

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

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

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

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

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

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

469
470
471
472
473
474
475
476
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

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

485
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
486
487
488
489
490
491
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
492
493
494
495
496
497
498
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

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

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
523
524
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
525

526
527
528
529
530
531
532
    d->m_progress.setProgressRange(0, 1000);
    Core::FutureProgress *fp = Core::ICore::instance()->progressManager()
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
    fp->setKeepOnFinish(Core::FutureProgress::DontKeepOnFinish);
    d->m_progress.reportStarted();

533
534
535
536
537
    d->m_runControl = runControl;

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

538
539
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
540
541

    const unsigned engineCapabilities = debuggerCapabilities();
hjk's avatar
hjk committed
542
    debuggerCore()->action(OperateByInstruction)
543
544
        ->setEnabled(engineCapabilities & DisassemblerCapability);

545
546
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
547
548
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
549
    d->m_progress.setProgressValue(200);
550
    d->queueSetupEngine();
551
552
553
554
}

void DebuggerEngine::resetLocation()
{
555
556
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
557
558
}

559
void DebuggerEngine::gotoLocation(const Location &loc)
560
{
561
562
563
564
565
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setTryMixed(true);
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
566
567
568
569
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;

570
    d->resetLocation();
571

572
573
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
574
575
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
576
    IEditor *editor = 0;
hjk's avatar
hjk committed
577
    if (editors.isEmpty()) {
578
579
580
581
582
583
584
585
        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
586
    }
587
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
588
589
590
    if (texteditor)
        texteditor->gotoLine(line, 0);

591
    if (loc.needsMarker())
592
        d->m_locationMark.reset(new LocationMark(file, line));
593
594

    // FIXME: Breaks with split views.
595
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
596
        editorManager->activateEditor(editor);
597
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
598
599
}

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

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

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
hjk's avatar
hjk committed
650
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool()) {
651
        const QString customLocation =
hjk's avatar
hjk committed
652
            debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
653
654
655
656
657
658
659
660
661
        const QString location =
            tr("%1 (explicitly set in the Debugger Options)").arg(customLocation);
        return QStringList(location);
    }
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
662
    debuggerCore()->showQtDumperLibraryWarning(details);
663
664
665
666
}

QString DebuggerEngine::qtDumperLibraryName() const
{
hjk's avatar
hjk committed
667
668
    if (debuggerCore()->action(UseCustomDebuggingHelperLocation)->value().toBool())
        return debuggerCore()->action(CustomDebuggingHelperLocation)->value().toString();
669
670
671
672
673
674
675
676
    return startParameters().dumperLibrary;
}

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

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

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

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

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

hjk's avatar
hjk committed
702
    case InferiorSetupRequested:
703
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
704
    case InferiorSetupFailed:
hjk's avatar
hjk committed
705
        return to == EngineShutdownRequested;
706
707
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
708
709

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

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

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
730
            || to == InferiorStopOk || InferiorExitOk;
731
    case InferiorStopFailed:
hjk's avatar
hjk committed
732
        return to == EngineShutdownRequested;
733

734
735
736
    case InferiorExitOk:
        return to == InferiorShutdownOk;

737
    case InferiorUnrunnable:
hjk's avatar
hjk committed
738
739
740
741
742
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
743
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
744
        return to == EngineShutdownRequested;
745

hjk's avatar
hjk committed
746
    case EngineShutdownRequested:
747
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
748
749
750
751
752
753
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
754
        return to == EngineSetupRequested; // Happens on restart.
755
756
    }

757
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
758
759
760
    return false;
}

761
762
763
764
765
766
767
768
769
770
771
772
773
void DebuggerEngine::setupSlaveEngine()
{
    QTC_ASSERT(state() == DebuggerNotReady, /**/);
    d->queueSetupEngine();
}

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

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

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

void DebuggerEngine::setupSlaveInferior()
{
    QTC_ASSERT(state() == EngineSetupOk, /**/);
    d->queueSetupInferior();
798
799
}

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

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

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

826
827
828
829
830
831
832
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
    QTC_ASSERT(state() == InferiorSetupOk, /**/);
    d->queueRunEngine();
}

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

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

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

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

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

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

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
889
    showMessage(_("NOTE: INFERIOR RUN OK"));
890
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
891
892
893
894
895
    setState(InferiorRunOk);
}

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

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

hjk's avatar
hjk committed
927
void DebuggerEngine::notifyInferiorSpontaneousStop()
928
{
hjk's avatar
hjk committed
929
    showMessage(_("NOTE: INFERIOR SPONTANEOUES STOP"));
930
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
931
    setState(InferiorStopOk);
932
933
}

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

void DebuggerEnginePrivate::doInterruptInferior()
{
945
946
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
hjk's avatar
hjk committed
947
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
948
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
949
950
951
    m_engine->interruptInferior();
}

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

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

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

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

998
999
void DebuggerEngine::shutdownSlaveEngine()
{
1000
    QTC_ASSERT(isAllowedTransition(state(),EngineShutdownRequested), /**/);
For faster browsing, not all history is shown. View entire blame