debuggermanager.cpp 47.5 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11
12
13
14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** 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.
24
**
25
** If you are unsure which license is appropriate for your use, please
26
** contact the sales department at http://www.qtsoftware.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
con's avatar
con committed
29
30
31

#include "debuggermanager.h"

32
#include "debuggeractions.h"
33
#include "debuggerrunner.h"
con's avatar
con committed
34
35
36
37
38
39
40
41
42
#include "debuggerconstants.h"
#include "idebuggerengine.h"

#include "breakwindow.h"
#include "disassemblerwindow.h"
#include "debuggeroutputwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
#include "stackwindow.h"
43
#include "sourcefileswindow.h"
con's avatar
con committed
44
45
46
47
48
49
50
51
52
53
#include "threadswindow.h"
#include "watchwindow.h"

#include "disassemblerhandler.h"
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "stackhandler.h"
#include "watchhandler.h"

54
#include "debuggerdialogs.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
55
#ifdef Q_OS_WIN
56
#  include "shared/peutils.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
57
#endif
58
#include <coreplugin/icore.h>
59
#include <utils/qtcassert.h>
60
#include <utils/fancymainwindow.h>
61
#include <projectexplorer/toolchain.h>
62

con's avatar
con committed
63
64
65
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
66
#include <QtCore/QTextStream>
con's avatar
con committed
67
#include <QtCore/QTime>
68
#include <QtCore/QTimer>
con's avatar
con committed
69

70
#include <QtGui/QApplication>
con's avatar
con committed
71
72
73
74
75
76
77
78
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
79
#include <QtGui/QPushButton>
con's avatar
con committed
80
81
82
83
84
85
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

// The creation functions take a list of options pages they can add to.
// This allows for having a "enabled" toggle on the page indepently
// of the engine.
using namespace Debugger::Internal;

IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
IDebuggerEngine *createScriptEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);


103
namespace Debugger {
104
105
namespace Internal {

106
107
108
109
110
111
112
113
114
115
116
QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
{
    QDebug nospace = str.nospace();
    const QString sep = QString(QLatin1Char(','));
    nospace << "executable=" << p.executable << " coreFile=" << p.coreFile
            << " processArgs=" << p.processArgs.join(sep)
            << " environment=<" << p.environment.size() << " variables>"
            << " workingDir=" << p.workingDir << " buildDir=" << p.buildDir
            << " attachPID=" << p.attachPID << " useTerminal=" << p.useTerminal
            << " remoteChannel=" << p.remoteChannel
            << " remoteArchitecture=" << p.remoteArchitecture
117
118
            << " serverStartScript=" << p.serverStartScript
            << " toolchain=" << p.toolChainType << '\n';
119
120
121
    return str;
}

122
using namespace Constants;
con's avatar
con committed
123
124
125

static const QString tooltipIName = "tooltip";

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
static const char *stateName(int s)
{
    switch (s) {
    case DebuggerProcessNotReady:
        return "DebuggerProcessNotReady";
    case DebuggerProcessStartingUp:
        return "DebuggerProcessStartingUp";
    case DebuggerInferiorRunningRequested:
        return "DebuggerInferiorRunningRequested";
    case DebuggerInferiorRunning:
        return "DebuggerInferiorRunning";
    case DebuggerInferiorStopRequested:
        return "DebuggerInferiorStopRequested";
    case DebuggerInferiorStopped:
        return "DebuggerInferiorStopped";
    }
    return "<unknown>";
}

con's avatar
con committed
145
146
147

///////////////////////////////////////////////////////////////////////
//
148
// DebuggerStartParameters
con's avatar
con committed
149
150
151
//
///////////////////////////////////////////////////////////////////////

152
153
DebuggerStartParameters::DebuggerStartParameters()
  : attachPID(-1),
154
155
    useTerminal(false),
    toolChainType(ProjectExplorer::ToolChain::UNKNOWN)
156
{}
157
158
159
160
161
162
163
164
165
166
167

void DebuggerStartParameters::clear()
{
    executable.clear();
    coreFile.clear();
    processArgs.clear();
    environment.clear();
    workingDir.clear();
    buildDir.clear();
    attachPID = -1;
    useTerminal = false;
168
    crashParameter.clear();
169
170
171
    remoteChannel.clear();
    remoteArchitecture.clear();
    serverStartScript.clear();
172
    toolChainType = ProjectExplorer::ToolChain::UNKNOWN;
173
174
}

175
176
177
178
179
180
181
182
183
184
185
186
187
188

///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
//
///////////////////////////////////////////////////////////////////////

static IDebuggerEngine *gdbEngine = 0;
static IDebuggerEngine *winEngine = 0;
static IDebuggerEngine *scriptEngine = 0;
static IDebuggerEngine *tcfEngine = 0;

DebuggerManager::DebuggerManager()
  : m_startParameters(new DebuggerStartParameters),
189
    m_inferiorPid(0)
con's avatar
con committed
190
{
191
    init();
con's avatar
con committed
192
193
194
195
}

DebuggerManager::~DebuggerManager()
{
196
197
198
199
200
201
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(gdbEngine);
    doDelete(winEngine);
    doDelete(scriptEngine);
    doDelete(tcfEngine);
    #undef doDelete
con's avatar
con committed
202
203
}

204
void DebuggerManager::init()
con's avatar
con committed
205
206
207
208
{
    m_status = -1;
    m_busy = false;

209
    m_runControl = 0;
con's avatar
con committed
210
211
212
213
214

    m_disassemblerHandler = 0;
    m_modulesHandler = 0;
    m_registerHandler = 0;

215
    m_statusLabel = new QLabel;
216
217
    m_statusLabel->setMinimumSize(QSize(30, 10));

con's avatar
con committed
218
219
    m_breakWindow = new BreakWindow;
    m_disassemblerWindow = new DisassemblerWindow;
220
    m_modulesWindow = new ModulesWindow(this);
con's avatar
con committed
221
222
223
    m_outputWindow = new DebuggerOutputWindow;
    m_registerWindow = new RegisterWindow;
    m_stackWindow = new StackWindow;
224
    m_sourceFilesWindow = new SourceFilesWindow;
con's avatar
con committed
225
    m_threadsWindow = new ThreadsWindow;
226
227
228
    m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
    m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this);
    //m_tooltipWindow = new WatchWindow(WatchWindow::TooltipType, this);
229
    m_statusTimer = new QTimer(this);
con's avatar
con committed
230

231
    m_mainWindow = new Core::Utils::FancyMainWindow;
con's avatar
con committed
232
233
234
235
236
237
238
239
240
241
    m_mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
    m_mainWindow->setDocumentMode(true);

    // Stack
    m_stackHandler = new StackHandler;
    QAbstractItemView *stackView =
        qobject_cast<QAbstractItemView *>(m_stackWindow);
    stackView->setModel(m_stackHandler->stackModel());
    connect(stackView, SIGNAL(frameActivated(int)),
        this, SLOT(activateFrame(int)));
242
243
244
245
    connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
    connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
con's avatar
con committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259

    // Threads
    m_threadsHandler = new ThreadsHandler;
    QAbstractItemView *threadsView =
        qobject_cast<QAbstractItemView *>(m_threadsWindow);
    threadsView->setModel(m_threadsHandler->threadsModel());
    connect(threadsView, SIGNAL(threadSelected(int)),
        this, SLOT(selectThread(int)));

    // Disassembler
    m_disassemblerHandler = new DisassemblerHandler;
    QAbstractItemView *disassemblerView =
        qobject_cast<QAbstractItemView *>(m_disassemblerWindow);
    disassemblerView->setModel(m_disassemblerHandler->model());
260
261
    connect(m_disassemblerWindow, SIGNAL(reloadDisassemblerRequested()),
            this, SLOT(reloadDisassembler()));
con's avatar
con committed
262
263
264
265
266
267

    // Breakpoints
    m_breakHandler = new BreakHandler;
    QAbstractItemView *breakView =
        qobject_cast<QAbstractItemView *>(m_breakWindow);
    breakView->setModel(m_breakHandler->model());
268
269
270
    connect(breakView, SIGNAL(breakpointActivated(int)),
        m_breakHandler, SLOT(activateBreakpoint(int)));
    connect(breakView, SIGNAL(breakpointDeleted(int)),
con's avatar
con committed
271
        m_breakHandler, SLOT(removeBreakpoint(int)));
272
273
    connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
        this, SLOT(attemptBreakpointSynchronization()));
con's avatar
con committed
274
275
276
277
278
279
    connect(m_breakHandler, SIGNAL(gotoLocation(QString,int,bool)),
        this, SLOT(gotoLocation(QString,int,bool)));
    connect(m_breakHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
        this, SIGNAL(sessionValueRequested(QString,QVariant*)));
    connect(m_breakHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
        this, SIGNAL(setSessionValueRequested(QString,QVariant)));
280
281
    connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
        this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
282
283
    connect(breakView, SIGNAL(breakByFunctionMainRequested()),
        this, SLOT(breakByFunctionMain()), Qt::QueuedConnection);
con's avatar
con committed
284
285
286
287
288
289
290
291
292
293
294
295

    // Modules
    QAbstractItemView *modulesView =
        qobject_cast<QAbstractItemView *>(m_modulesWindow);
    m_modulesHandler = new ModulesHandler;
    modulesView->setModel(m_modulesHandler->model());
    connect(modulesView, SIGNAL(reloadModulesRequested()),
        this, SLOT(reloadModules()));
    connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
        this, SLOT(loadSymbols(QString)));
    connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
        this, SLOT(loadAllSymbols()));
296
297
    connect(modulesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
hjk's avatar
hjk committed
298
299
    connect(modulesView, SIGNAL(newDockRequested(QWidget*)),
        this, SLOT(createNewDock(QWidget*)));
con's avatar
con committed
300

301
302
303
304
305
306
307
    // Source Files
    //m_sourceFilesHandler = new SourceFilesHandler;
    QAbstractItemView *sourceFilesView =
        qobject_cast<QAbstractItemView *>(m_sourceFilesWindow);
    //sourceFileView->setModel(m_stackHandler->stackModel());
    connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
        this, SLOT(reloadSourceFiles()));
308
309
    connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
con's avatar
con committed
310

311
    // Registers
con's avatar
con committed
312
313
314
315
316
    QAbstractItemView *registerView =
        qobject_cast<QAbstractItemView *>(m_registerWindow);
    m_registerHandler = new RegisterHandler;
    registerView->setModel(m_registerHandler->model());

317
318
319
320
321
322
323
324
    // Locals
    m_watchHandler = new WatchHandler;
    QTreeView *localsView = qobject_cast<QTreeView *>(m_localsWindow);
    localsView->setModel(m_watchHandler->model(LocalsWatch));

    // Watchers
    QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow);
    watchersView->setModel(m_watchHandler->model(WatchersWatch));
hjk's avatar
hjk committed
325
326
327
328
    connect(m_watchHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
        this, SIGNAL(sessionValueRequested(QString,QVariant*)));
    connect(m_watchHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
        this, SIGNAL(setSessionValueRequested(QString,QVariant)));
329
    connect(theDebuggerAction(AssignValue), SIGNAL(triggered()),
330
        this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
con's avatar
con committed
331
332

    // Tooltip
333
334
335
336
337
338
    //QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
    //tooltipView->setModel(m_watchHandler->model(TooltipsWatch));

    connect(m_watchHandler, SIGNAL(watchDataUpdateNeeded(WatchData)),
        this, SLOT(updateWatchData(WatchData)));

con's avatar
con committed
339
340
    m_continueAction = new QAction(this);
    m_continueAction->setText(tr("Continue"));
341
    m_continueAction->setIcon(QIcon(":/debugger/images/debugger_continue_small.png"));
con's avatar
con committed
342
343
344

    m_stopAction = new QAction(this);
    m_stopAction->setText(tr("Interrupt"));
345
    m_stopAction->setIcon(QIcon(":/debugger/images/debugger_interrupt_small.png"));
con's avatar
con committed
346
347
348
349
350
351
352

    m_resetAction = new QAction(this);
    m_resetAction->setText(tr("Reset Debugger"));

    m_nextAction = new QAction(this);
    m_nextAction->setText(tr("Step Over"));
    //m_nextAction->setShortcut(QKeySequence(tr("F6")));
353
    m_nextAction->setIcon(QIcon(":/debugger/images/debugger_stepover_small.png"));
con's avatar
con committed
354
355
356
357

    m_stepAction = new QAction(this);
    m_stepAction->setText(tr("Step Into"));
    //m_stepAction->setShortcut(QKeySequence(tr("F7")));
358
    m_stepAction->setIcon(QIcon(":/debugger/images/debugger_stepinto_small.png"));
con's avatar
con committed
359
360
361
362

    m_nextIAction = new QAction(this);
    m_nextIAction->setText(tr("Step Over Instruction"));
    //m_nextIAction->setShortcut(QKeySequence(tr("Shift+F6")));
363
    m_nextIAction->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png"));
con's avatar
con committed
364
365
366
367

    m_stepIAction = new QAction(this);
    m_stepIAction->setText(tr("Step One Instruction"));
    //m_stepIAction->setShortcut(QKeySequence(tr("Shift+F9")));
368
    m_stepIAction->setIcon(QIcon(":/debugger/images/debugger_steponeproc_small.png"));
con's avatar
con committed
369
370
371
372

    m_stepOutAction = new QAction(this);
    m_stepOutAction->setText(tr("Step Out"));
    //m_stepOutAction->setShortcut(QKeySequence(tr("Shift+F7")));
373
    m_stepOutAction->setIcon(QIcon(":/debugger/images/debugger_stepout_small.png"));
con's avatar
con committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

    m_runToLineAction = new QAction(this);
    m_runToLineAction->setText(tr("Run to Line"));

    m_runToFunctionAction = new QAction(this);
    m_runToFunctionAction->setText(tr("Run to Outermost Function"));

    m_jumpToLineAction = new QAction(this);
    m_jumpToLineAction->setText(tr("Jump to Line"));

    m_breakAction = new QAction(this);
    m_breakAction->setText(tr("Toggle Breakpoint"));

    m_watchAction = new QAction(this);
    m_watchAction->setText(tr("Add to Watch Window"));

390
391
392
393
394
395
    m_reverseDirectionAction = new QAction(this);
    m_reverseDirectionAction->setText(tr("Reverse Direction"));
    m_reverseDirectionAction->setCheckable(true);
    m_reverseDirectionAction->setChecked(false);
    //m_reverseDirectionAction->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png"));

con's avatar
con committed
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
    // For usuage hints oin focus{In,Out}
    connect(m_continueAction, SIGNAL(triggered()),
        this, SLOT(continueExec()));

    connect(m_stopAction, SIGNAL(triggered()),
        this, SLOT(interruptDebuggingRequest()));
    connect(m_resetAction, SIGNAL(triggered()),
        this, SLOT(exitDebugger()));
    connect(m_nextAction, SIGNAL(triggered()),
        this, SLOT(nextExec()));
    connect(m_stepAction, SIGNAL(triggered()),
        this, SLOT(stepExec()));
    connect(m_nextIAction, SIGNAL(triggered()),
        this, SLOT(nextIExec()));
    connect(m_stepIAction, SIGNAL(triggered()),
        this, SLOT(stepIExec()));
    connect(m_stepOutAction, SIGNAL(triggered()),
        this, SLOT(stepOutExec()));
    connect(m_runToLineAction, SIGNAL(triggered()),
        this, SLOT(runToLineExec()));
    connect(m_runToFunctionAction, SIGNAL(triggered()),
        this, SLOT(runToFunctionExec()));
    connect(m_jumpToLineAction, SIGNAL(triggered()),
        this, SLOT(jumpToLineExec()));
    connect(m_watchAction, SIGNAL(triggered()),
        this, SLOT(addToWatchWindow()));
    connect(m_breakAction, SIGNAL(triggered()),
        this, SLOT(toggleBreakpoint()));

425
426
    connect(m_statusTimer, SIGNAL(timeout()),
        this, SLOT(clearStatusMessage()));
con's avatar
con committed
427

428
429
    connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
        this, SLOT(executeDebuggerCommand()));
430
431
    connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
        this, SLOT(watchPoint()));
con's avatar
con committed
432

433
    m_breakDock = m_mainWindow->addDockForWidget(m_breakWindow);
con's avatar
con committed
434

435
    m_disassemblerDock = m_mainWindow->addDockForWidget(m_disassemblerWindow);
con's avatar
con committed
436
437
438
    connect(m_disassemblerDock->toggleViewAction(), SIGNAL(toggled(bool)),
        this, SLOT(reloadDisassembler()), Qt::QueuedConnection);

439
    m_modulesDock = m_mainWindow->addDockForWidget(m_modulesWindow);
con's avatar
con committed
440
441
442
    connect(m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
        this, SLOT(reloadModules()), Qt::QueuedConnection);

443
    m_registerDock = m_mainWindow->addDockForWidget(m_registerWindow);
con's avatar
con committed
444
445
446
    connect(m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
        this, SLOT(reloadRegisters()), Qt::QueuedConnection);

447
    m_outputDock = m_mainWindow->addDockForWidget(m_outputWindow);
con's avatar
con committed
448

449
    m_stackDock = m_mainWindow->addDockForWidget(m_stackWindow);
con's avatar
con committed
450

451
    m_sourceFilesDock = m_mainWindow->addDockForWidget(m_sourceFilesWindow);
452
453
454
    connect(m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
        this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);

455
    m_threadsDock = m_mainWindow->addDockForWidget(m_threadsWindow);
con's avatar
con committed
456

457
458
459
460
    QSplitter *localsAndWatchers = new QSplitter(Qt::Vertical, 0);
    localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
    localsAndWatchers->addWidget(m_localsWindow);
    localsAndWatchers->addWidget(m_watchersWindow);
461
    //localsAndWatchers->addWidget(m_tooltipWindow);
462
463
    localsAndWatchers->setStretchFactor(0, 3);
    localsAndWatchers->setStretchFactor(1, 1);
464
    localsAndWatchers->setStretchFactor(2, 1);
465
    m_watchDock = m_mainWindow->addDockForWidget(localsAndWatchers);
466

con's avatar
con committed
467
    setStatus(DebuggerProcessNotReady);
468
469
}

470
QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
471
472
{
    QList<Core::IOptionsPage*> rc;
473
474
475
476
477
478
479
    if (enabledTypeFlags & GdbEngineType)
        gdbEngine = createGdbEngine(this, &rc);
    winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
    if (enabledTypeFlags & ScriptEngineType)
        scriptEngine = createScriptEngine(this, &rc);
    if (enabledTypeFlags & TcfEngineType)
        tcfEngine = createTcfEngine(this, &rc);
480
    m_engine = 0;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
481
    if (Debugger::Constants::Internal::debug)
482
483
        qDebug() << Q_FUNC_INFO << gdbEngine << winEngine << scriptEngine << rc.size();
    return rc;
con's avatar
con committed
484
485
486
487
488
489
490
491
492
493
494
495
}

IDebuggerEngine *DebuggerManager::engine()
{
    return m_engine;
}

IDebuggerManagerAccessForEngines *DebuggerManager::engineInterface()
{
    return dynamic_cast<IDebuggerManagerAccessForEngines *>(this);
}

hjk's avatar
hjk committed
496
497
498
499
500
501
502
503
504
505
void DebuggerManager::createNewDock(QWidget *widget)
{
    QDockWidget *dockWidget = new QDockWidget(widget->windowTitle(), m_mainWindow);
    dockWidget->setObjectName(widget->windowTitle());
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
    dockWidget->setWidget(widget);
    m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
    dockWidget->show();
}

con's avatar
con committed
506
507
void DebuggerManager::setSimpleDockWidgetArrangement()
{
508
509
    m_mainWindow->setTrackingEnabled(false);
    QList<QDockWidget *> dockWidgets = m_mainWindow->dockWidgets();
510
511
    foreach (QDockWidget *dockWidget, dockWidgets) {
        dockWidget->setFloating(false);
con's avatar
con committed
512
        m_mainWindow->removeDockWidget(dockWidget);
513
    }
con's avatar
con committed
514

515
    foreach (QDockWidget *dockWidget, dockWidgets) {
con's avatar
con committed
516
517
518
519
520
521
522
523
524
525
        m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
        dockWidget->show();
    }

    m_mainWindow->tabifyDockWidget(m_watchDock, m_breakDock);
    m_mainWindow->tabifyDockWidget(m_watchDock, m_disassemblerDock);
    m_mainWindow->tabifyDockWidget(m_watchDock, m_modulesDock);
    m_mainWindow->tabifyDockWidget(m_watchDock, m_outputDock);
    m_mainWindow->tabifyDockWidget(m_watchDock, m_registerDock);
    m_mainWindow->tabifyDockWidget(m_watchDock, m_threadsDock);
526
    m_mainWindow->tabifyDockWidget(m_watchDock, m_sourceFilesDock);
con's avatar
con committed
527

528
529
    // They following views are rarely used in ordinary debugging. Hiding them
    // saves cycles since the corresponding information won't be retrieved.
530
    m_sourceFilesDock->hide();
con's avatar
con committed
531
532
533
534
    m_registerDock->hide();
    m_disassemblerDock->hide();
    m_modulesDock->hide();
    m_outputDock->hide();
535
    m_mainWindow->setTrackingEnabled(true);
con's avatar
con committed
536
537
538
539
540
541
542
}

QAbstractItemModel *DebuggerManager::threadsModel()
{
    return qobject_cast<ThreadsWindow*>(m_threadsWindow)->model();
}

543
544
545
546
547
void DebuggerManager::clearStatusMessage()
{
    m_statusLabel->setText(m_lastPermanentStatusMessage);
}

con's avatar
con committed
548
549
550
void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
{
    Q_UNUSED(timeout)
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
551
552
    if (Debugger::Constants::Internal::debug)
        qDebug() << "STATUS MSG: " << msg;
553
    showDebuggerOutput(LogStatus, msg);
hjk's avatar
hjk committed
554
    m_statusLabel->setText(QLatin1String("   ") + msg);
555
556
557
558
559
560
561
    if (timeout > 0) {
        m_statusTimer->setSingleShot(true);
        m_statusTimer->start(timeout);
    } else {
        m_lastPermanentStatusMessage = msg;
        m_statusTimer->stop();
    }
con's avatar
con committed
562
563
}

564
565
566
567
568
569
void DebuggerManager::notifyInferiorStopRequested()
{
    setStatus(DebuggerInferiorStopRequested);
    showStatusMessage(tr("Stop requested..."), 5000);
}

con's avatar
con committed
570
571
572
573
574
575
576
577
578
579
void DebuggerManager::notifyInferiorStopped()
{
    resetLocation();
    setStatus(DebuggerInferiorStopped);
    showStatusMessage(tr("Stopped."), 5000);
}

void DebuggerManager::notifyInferiorRunningRequested()
{
    setStatus(DebuggerInferiorRunningRequested);
580
    showStatusMessage(tr("Running requested..."), 5000);
con's avatar
con committed
581
582
583
584
585
586
587
588
589
590
}

void DebuggerManager::notifyInferiorRunning()
{
    setStatus(DebuggerInferiorRunning);
    showStatusMessage(tr("Running..."), 5000);
}

void DebuggerManager::notifyInferiorExited()
{
hjk's avatar
hjk committed
591
    setStatus(DebuggerProcessNotReady);
con's avatar
con committed
592
593
594
    showStatusMessage(tr("Stopped."), 5000);
}

595
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
con's avatar
con committed
596
{
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
597
    if (Debugger::Constants::Internal::debug)
598
599
600
601
602
603
        qDebug() << Q_FUNC_INFO << m_inferiorPid << pid;

    if (m_inferiorPid != pid) {
        m_inferiorPid = pid;
        emit inferiorPidChanged(pid);
    }
con's avatar
con committed
604
605
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
606
void DebuggerManager::showApplicationOutput(const QString &str)
con's avatar
con committed
607
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
608
     emit applicationOutputAvailable(str);
con's avatar
con committed
609
610
611
612
}

void DebuggerManager::shutdown()
{
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
613
614
615
616
    if (Debugger::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << m_engine;

    if (m_engine)
617
618
619
        m_engine->shutdown();
    m_engine = 0;

620
621
622
623
624
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(scriptEngine);
    doDelete(gdbEngine);
    doDelete(winEngine);
    doDelete(tcfEngine);
625

con's avatar
con committed
626
627
    // Delete these manually before deleting the manager
    // (who will delete the models for most views)
628
629
630
631
632
633
634
635
    doDelete(m_breakWindow);
    doDelete(m_disassemblerWindow);
    doDelete(m_modulesWindow);
    doDelete(m_outputWindow);
    doDelete(m_registerWindow);
    doDelete(m_stackWindow);
    doDelete(m_sourceFilesWindow);
    doDelete(m_threadsWindow);
636
    //doDelete(m_tooltipWindow);
637
638
639
640
641
642
643
644
645
646
647
    doDelete(m_watchersWindow);
    doDelete(m_localsWindow);

    doDelete(m_breakHandler);
    doDelete(m_disassemblerHandler);
    doDelete(m_threadsHandler);
    doDelete(m_modulesHandler);
    doDelete(m_registerHandler);
    doDelete(m_stackHandler);
    doDelete(m_watchHandler);
    #undef doDelete
con's avatar
con committed
648
649
}

650
651
652
653
654
655
656
657
BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lineNumber)
{
    if (!m_breakHandler)
        return 0;
    int index = m_breakHandler->findBreakpoint(fileName, lineNumber);
    return index == -1 ? 0 : m_breakHandler->at(index);
}

con's avatar
con committed
658
659
660
661
662
663
664
665
666
667
668
669
void DebuggerManager::toggleBreakpoint()
{
    QString fileName;
    int lineNumber = -1;
    queryCurrentTextEditor(&fileName, &lineNumber, 0);
    if (lineNumber == -1)
        return;
    toggleBreakpoint(fileName, lineNumber);
}

void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
670
671
672
    if (Debugger::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << fileName << lineNumber;

673
    QTC_ASSERT(m_breakHandler, return);
hjk's avatar
hjk committed
674
    if (status() != DebuggerInferiorRunning
675
         && status() != DebuggerInferiorStopped
hjk's avatar
hjk committed
676
         && status() != DebuggerProcessNotReady) {
677
678
679
680
681
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

682
    int index = m_breakHandler->findBreakpoint(fileName, lineNumber);
con's avatar
con committed
683
    if (index == -1)
684
        m_breakHandler->setBreakpoint(fileName, lineNumber);
con's avatar
con committed
685
    else
686
        m_breakHandler->removeBreakpoint(index);
687

hjk's avatar
hjk committed
688
    attemptBreakpointSynchronization();
con's avatar
con committed
689
690
}

691
692
693
694
695
696
697
void DebuggerManager::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
{
    if (Debugger::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << fileName << lineNumber;

    QTC_ASSERT(m_breakHandler, return);
    if (status() != DebuggerInferiorRunning
698
         && status() != DebuggerInferiorStopped
699
700
701
702
703
704
705
         && status() != DebuggerProcessNotReady) {
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

    m_breakHandler->toggleBreakpointEnabled(fileName, lineNumber);
hjk's avatar
hjk committed
706
707

    attemptBreakpointSynchronization();
708
709
}

710
711
void DebuggerManager::attemptBreakpointSynchronization()
{
hjk's avatar
hjk committed
712
713
    if (m_engine)
        m_engine->attemptBreakpointSynchronization();
714
715
}

716
void DebuggerManager::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
con's avatar
con committed
717
{
hjk's avatar
hjk committed
718
    if (m_engine)
719
        m_engine->setToolTipExpression(mousePos, editor, cursorPos);
con's avatar
con committed
720
721
}

722
723
724
725
726
727
void DebuggerManager::updateWatchData(const WatchData &data)
{
    if (m_engine)
        m_engine->updateWatchData(data);
}

con's avatar
con committed
728
729
QVariant DebuggerManager::sessionValue(const QString &name)
{
730
    // this is answered by the plugin
con's avatar
con committed
731
732
733
734
735
    QVariant value;
    emit sessionValueRequested(name, &value);
    return value;
}

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
static inline QString msgEngineNotAvailable(const char *engine)
{
    return DebuggerManager::tr("The application requires the debugger engine '%1', which is disabled.").arg(QLatin1String(engine));
}

static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::ToolChainType tc)
{
    IDebuggerEngine *rc = 0;
    switch (tc) {
    case ProjectExplorer::ToolChain::LinuxICC:
    case ProjectExplorer::ToolChain::MinGW:
    case ProjectExplorer::ToolChain::GCC:
        rc = gdbEngine;
        break;
    case ProjectExplorer::ToolChain::MSVC:
    case ProjectExplorer::ToolChain::WINCE:
        rc = winEngine;
        break;
    case ProjectExplorer::ToolChain::OTHER:
    case ProjectExplorer::ToolChain::UNKNOWN:
    case ProjectExplorer::ToolChain::INVALID:
        break;
    }
    if (Debugger::Constants::Internal::debug)
        qDebug()  << "Toolchain" << tc << rc;
    return rc;
}

// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
766
static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
767
768
769
                                                int toolChainType,
                                                QString *errorMessage,
                                                QString *settingsIdHint)
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
770
{
771
772
773
774
775
776
777
778
    if (IDebuggerEngine *tce = debuggerEngineForToolChain(static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChainType)))
        return tce;

    if (executable.endsWith(_(".js"))) {
        if (!scriptEngine) {
            *errorMessage = msgEngineNotAvailable("Script Engine");
            return 0;
        }
779
        return scriptEngine;
780
    }
781

782
#ifndef Q_OS_WIN    
783
    Q_UNUSED(settingsIdHint)
784
785
786
787
788
    if (!gdbEngine) {
        *errorMessage = msgEngineNotAvailable("Gdb Engine");
        return 0;
    }

789
    return gdbEngine;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
790
791
792
793
#else
    // If a file has PDB files, it has been compiled by VS.
    QStringList pdbFiles;
    if (!getPDBFiles(executable, &pdbFiles, errorMessage))
794
        return 0;
795
    if (pdbFiles.empty())
796
        return gdbEngine;
797

Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
798
799
800
    // We need the CDB debugger in order to be able to debug VS
    // executables
    if (!winEngine) {
801
802
        *errorMessage = DebuggerManager::tr("Debugging VS executables is currently not enabled.");
        *settingsIdHint = QLatin1String("Cdb");
803
        return 0;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
804
    }
805
    return winEngine;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
806
807
808
#endif
}

Friedemann Kleint's avatar
Friedemann Kleint committed
809
// Figure out the debugger type of a PID
810
static IDebuggerEngine *determineDebuggerEngine(int  /* pid */,
811
812
                                                int toolChainType,
                                                QString *errorMessage)
Friedemann Kleint's avatar
Friedemann Kleint committed
813
{
814
815
    if (IDebuggerEngine *tce = debuggerEngineForToolChain(static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChainType)))
        return tce;
Friedemann Kleint's avatar
Friedemann Kleint committed
816
817
#ifdef Q_OS_WIN
    // Preferably Windows debugger
818
819
820
821
822
823
    if (winEngine)
        return winEngine;
    if (gdbEngine)
        return gdbEngine;
    *errorMessage = msgEngineNotAvailable("Gdb Engine");
    return 0;
Friedemann Kleint's avatar
Friedemann Kleint committed
824
#else
825
826
827
828
829
    if (!gdbEngine) {
        *errorMessage = msgEngineNotAvailable("Gdb Engine");
        return 0;
    }

830
    return gdbEngine;
Friedemann Kleint's avatar
Friedemann Kleint committed
831
832
833
#endif
}

834
835
void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl,
    const QSharedPointer<DebuggerStartParameters> &startParameters)
con's avatar
con committed
836
{
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
837
    if (Debugger::Constants::Internal::debug)
838
839
840
841
842
        qDebug() << Q_FUNC_INFO << '\n' << *startParameters;

    m_startParameters  = startParameters;
    m_inferiorPid = startParameters->attachPID > 0 ? startParameters->attachPID : 0;
    m_runControl = runControl;
843
    const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(m_startParameters->toolChainType));
con's avatar
con committed
844
845

    emit debugModeRequested();
846
847
    showDebuggerOutput(LogStatus,
        tr("Starting debugger for tool chain '%1'...").arg(toolChainName));
848
    showDebuggerOutput(LogDebug, DebuggerSettings::instance()->dump());
con's avatar
con committed
849

Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
850
    QString errorMessage;
851
852
853
    QString settingsIdHint;
    switch (startMode()) {
    case AttachExternal:
854
    case AttachCrashedExternal:
855
        m_engine = determineDebuggerEngine(m_startParameters->attachPID, m_startParameters->toolChainType, &errorMessage);
856
857
        break;
    case AttachTcf:
858
        m_engine = tcfEngine;
859
860
        break;
    default:
861
        m_engine = determineDebuggerEngine(m_startParameters->executable, m_startParameters->toolChainType, &errorMessage, &settingsIdHint);
862
863
        break;
    }
864

865
    if (!m_engine) {
866
        debuggingFinished();
867
868
        // Create Message box with possibility to go to settings
        QAbstractButton *settingsButton = 0;
869
870
871
872
        QMessageBox msgBox(QMessageBox::Warning, tr("Warning"),
            tr("Cannot debug '%1' (tool chain: '%2'): %3").
            arg(m_startParameters->executable, toolChainName, errorMessage),
            QMessageBox::Ok);
873
874
875
876
877
        if (!settingsIdHint.isEmpty())
            settingsButton = msgBox.addButton(tr("Settings..."), QMessageBox::AcceptRole);
        msgBox.exec();
        if (msgBox.clickedButton() == settingsButton)
            Core::ICore::instance()->showOptionsDialog(_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
878
        return;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
879
    }
880

Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
881
    if (Debugger::Constants::Internal::debug)
882
        qDebug() << m_startParameters->executable << m_engine;
con's avatar
con committed
883

884
    setBusyCursor(false);
hjk's avatar
hjk committed
885
    setStatus(DebuggerProcessStartingUp);
886
    if (!m_engine->startDebugger(m_startParameters)) {
hjk's avatar
hjk committed
887
        setStatus(DebuggerProcessNotReady);
888
889
        debuggingFinished();
        return;
hjk's avatar
hjk committed
890
    }
con's avatar
con committed
891
892
893
894
895
896
897
898
899
900
901
}

void DebuggerManager::cleanupViews()
{
    resetLocation();
    breakHandler()->setAllPending();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    disassemblerHandler()->removeAll();
    modulesHandler()->removeAll();
    watchHandler()->cleanup();
902
    m_sourceFilesWindow->removeAll();
con's avatar
con committed
903
904
905
906
}

void DebuggerManager::exitDebugger()
{
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
907
908
909
    if (Debugger::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO;

hjk's avatar
hjk committed
910
911
    if (m_engine)
        m_engine->exitDebugger();
con's avatar
con committed
912
913
914
915
916
917
    cleanupViews();
    setStatus(DebuggerProcessNotReady);
    setBusyCursor(false);
    emit debuggingFinished();
}

918
919
920
921
922
923
924
925
926
927
QSharedPointer<DebuggerStartParameters> DebuggerManager::startParameters() const
{
    return m_startParameters;
}

void DebuggerManager::setQtDumperLibraryName(const QString &dl)
{
    m_dumperLib = dl;
}

928
929
930
931
932
void DebuggerManager::setQtDumperLibraryLocations(const QStringList &dl)
{
    m_dumperLibLocations = dl;
}

933
934
935
936
937
qint64 DebuggerManager::inferiorPid() const
{
    return m_inferiorPid;
}

938
939
940
void DebuggerManager::assignValueInDebugger()
{
    if (QAction *action = qobject_cast<QAction *>(sender())) {
941
942
943
944
        QString str = action->data().toString();
        int i = str.indexOf('=');
        if (i != -1)
            assignValueInDebugger(str.left(i), str.mid(i + 1));
945
946
    }
}
947

con's avatar
con committed
948
949
void DebuggerManager::assignValueInDebugger(const QString &expr, const QString &value)
{
950
951
    QTC_ASSERT(m_engine, return);
    m_engine->assignValueInDebugger(expr, value);
con's avatar
con committed
952
953
954
955
}

void DebuggerManager::activateFrame(int index)
{
956
957
    QTC_ASSERT(m_engine, return);
    m_engine->activateFrame(index);
con's avatar
con committed
958
959
960
961
}

void DebuggerManager::selectThread(int index)
{
962
963
    QTC_ASSERT(m_engine, return);
    m_engine->selectThread(index);
con's avatar
con committed
964
965
966
967
}

void DebuggerManager::loadAllSymbols()
{
968
969
    QTC_ASSERT(m_engine, return);
    m_engine->loadAllSymbols();
con's avatar
con committed
970
971
972
973
}

void DebuggerManager::loadSymbols(const QString &module)
{
974
975
    QTC_ASSERT(m_engine, return);
    m_engine->loadSymbols(module);
con's avatar
con committed
976
977
}

978
979
980
981
982
983
QList<Symbol> DebuggerManager::moduleSymbols(const QString &moduleName)
{
    QTC_ASSERT(m_engine, return QList<Symbol>());
    return m_engine->moduleSymbols(moduleName);
}

con's avatar
con committed
984
985
void DebuggerManager::stepExec()
{
986
    QTC_ASSERT(m_engine, return);
con's avatar
con committed
987
    resetLocation();
988
    m_engine->stepExec();
989
}
con's avatar
con committed
990
991
992

void DebuggerManager::stepOutExec()
{
993
    QTC_ASSERT(m_engine, return);
con's avatar
con committed
994
    resetLocation();
995
    m_engine->stepOutExec();
con's avatar
con committed
996
997
998
999
}

void DebuggerManager::nextExec()
{
1000
    QTC_ASSERT(m_engine, return);