debuggerplugin.cpp 129 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
Eike Ziller's avatar
Eike Ziller committed
13 14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24 25 26
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
hjk's avatar
hjk committed
30

con's avatar
con committed
31 32
#include "debuggerplugin.h"

Friedemann Kleint's avatar
Friedemann Kleint committed
33
#include "debuggerstartparameters.h"
34
#include "debuggeractions.h"
35
#include "debuggerinternalconstants.h"
36
#include "debuggercore.h"
37
#include "debuggerkitconfigwidget.h"
38 39
#include "debuggerdialogs.h"
#include "debuggerengine.h"
40
#include "debuggeritemmanager.h"
41
#include "debuggermainwindow.h"
42
#include "debuggerrunconfigurationaspect.h"
43
#include "debuggerruncontrol.h"
44
#include "debuggerstringutils.h"
45
#include "debuggeroptionspage.h"
Tobias Hunger's avatar
Tobias Hunger committed
46
#include "debuggerkitinformation.h"
47
#include "memoryagent.h"
48
#include "breakhandler.h"
49
#include "breakwindow.h"
50
#include "disassemblerlines.h"
51
#include "logwindow.h"
52
#include "moduleswindow.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
53
#include "moduleshandler.h"
54 55
#include "registerwindow.h"
#include "snapshotwindow.h"
hjk's avatar
hjk committed
56
#include "stackhandler.h"
57 58 59
#include "stackwindow.h"
#include "sourcefileswindow.h"
#include "threadswindow.h"
hjk's avatar
hjk committed
60
#include "watchhandler.h"
61
#include "watchwindow.h"
hjk's avatar
hjk committed
62
#include "watchutils.h"
63
#include "unstartedappwatcherdialog.h"
64
#include "debuggertooltipmanager.h"
65
#include "localsandexpressionswindow.h"
66
#include "loadcoredialog.h"
67
#include "sourceutils.h"
68
#include <debugger/shared/hostutils.h>
69

70 71
#include "snapshothandler.h"
#include "threadshandler.h"
72
#include "commonoptionspage.h"
73
#include "gdb/startgdbserverdialog.h"
con's avatar
con committed
74

75
#include <coreplugin/actionmanager/actionmanager.h>
76
#include <coreplugin/actionmanager/actioncontainer.h>
Daniel Teske's avatar
Daniel Teske committed
77
#include <coreplugin/find/itemviewfind.h>
78
#include <coreplugin/imode.h>
con's avatar
con committed
79 80
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
81
#include <coreplugin/messagemanager.h>
con's avatar
con committed
82
#include <coreplugin/modemanager.h>
hjk's avatar
hjk committed
83

con's avatar
con committed
84
#include <cppeditor/cppeditorconstants.h>
85
#include <cpptools/cppmodelmanager.h>
hjk's avatar
hjk committed
86

87
#include <extensionsystem/invoker.h>
88

89
#include <projectexplorer/localapplicationrunconfiguration.h>
90
#include <projectexplorer/buildmanager.h>
91
#include <projectexplorer/taskhub.h>
92
#include <projectexplorer/toolchain.h>
93
#include <projectexplorer/devicesupport/deviceprocesslist.h>
94
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
95
#include <projectexplorer/projectexplorer.h>
96
#include <projectexplorer/projecttree.h>
97 98
#include <projectexplorer/projectexplorersettings.h>
#include <projectexplorer/project.h>
con's avatar
con committed
99
#include <projectexplorer/session.h>
100
#include <projectexplorer/target.h>
101

102
#include <texteditor/texteditor.h>
103
#include <texteditor/fontsettings.h>
104
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
105

106
#include <utils/basetreeview.h>
107
#include <utils/hostosinfo.h>
108
#include <utils/proxyaction.h>
109 110
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
111
#include <utils/statuslabel.h>
112
#include <utils/styledbar.h>
hjk's avatar
hjk committed
113
#include <utils/winutils.h>
con's avatar
con committed
114

Campbell Barton's avatar
Campbell Barton committed
115
#include <QApplication>
hjk's avatar
hjk committed
116
#include <QCheckBox>
117
#include <QComboBox>
118 119
#include <QDockWidget>
#include <QFileDialog>
hjk's avatar
hjk committed
120 121
#include <QHBoxLayout>
#include <QHeaderView>
hjk's avatar
hjk committed
122
#include <QInputDialog>
123 124 125
#include <QMessageBox>
#include <QTextBlock>
#include <QToolButton>
hjk's avatar
hjk committed
126
#include <QtPlugin>
127
#include <QTreeWidget>
128 129
#include <QVBoxLayout>

hjk's avatar
hjk committed
130
#ifdef WITH_TESTS
131 132 133
#include <QTest>
#include <QSignalSpy>
#include <QTestEventLoop>
134 135 136 137

//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
hjk's avatar
hjk committed
138 139
#endif

140 141
#endif // WITH_TESTS

142 143
#include <climits>

144 145 146 147 148
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
//#   define STATE_DEBUG(s)
//    do { QString msg; QTextStream ts(&msg); ts << s;
//      showMessage(msg, LogDebug); } while (0)
149
#   define STATE_DEBUG(s) do { qDebug() << s; } while (0)
150 151 152 153
#else
#   define STATE_DEBUG(s)
#endif

154 155 156 157 158 159 160 161
/*!
    \namespace Debugger
    Debugger plugin namespace
*/

/*!
    \namespace Debugger::Internal
    Internal namespace of the Debugger plugin
162
    \internal
163 164 165 166 167
*/

/*!
    \class Debugger::DebuggerEngine

168
    \brief The DebuggerEngine class is the base class of a debugger engine.
169

Leena Miettinen's avatar
Leena Miettinen committed
170
    \note The Debugger process itself and any helper processes like
171 172
    gdbserver are referred to as 'Engine', whereas the debugged process
    is referred to as 'Inferior'.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

    Transitions marked by '---' are done in the individual engines.
    Transitions marked by '+-+' are done in the base DebuggerEngine.
    Transitions marked by '*' are done asynchronously.

    The GdbEngine->setupEngine() function is described in more detail below.

    The engines are responsible for local roll-back to the last
    acknowledged state before calling notify*Failed. I.e. before calling
    notifyEngineSetupFailed() any process started during setupEngine()
    so far must be terminated.
    \code

                        DebuggerNotReady
                         progressmanager/progressmanager.cpp      +
                      EngineSetupRequested
                               +
                  (calls *Engine->setupEngine())
                            |      |
                            |      |
                       {notify-  {notify-
                        Engine-   Engine-
                        SetupOk}  SetupFailed}
                            +      +
                            +      `+-+-+> EngineSetupFailed
                            +                   +
                            +    [calls RunControl->startFailed]
                            +                   +
                            +             DebuggerFinished
                            v
                      EngineSetupOk
                            +
             [calls RunControl->StartSuccessful]
                            +
                  InferiorSetupRequested
                            +
             (calls *Engine->setupInferior())
                         |       |
                         |       |
                    {notify-   {notify-
                     Inferior- Inferior-
                     SetupOk}  SetupFailed}
                         +       +
                         +       ` +-+-> InferiorSetupFailed +-+-+-+-+-+->.
                         +                                                +
                  InferiorSetupOk                                         +
                         +                                                +
                  EngineRunRequested                                      +
                         +                                                +
                 (calls *Engine->runEngine())                             +
               /       |            |        \                            +
             /         |            |          \                          +
            | (core)   | (attach)   |           |                         +
            |          |            |           |                         +
      {notify-    {notifyER&- {notifyER&-  {notify-                       +
      Inferior-     Inferior-   Inferior-  EngineRun-                     +
     Unrunnable}     StopOk}     RunOk}     Failed}                       +
           +           +            +           +                         +
   InferiorUnrunnable  +     InferiorRunOk      +                         +
                       +                        +                         +
                InferiorStopOk            EngineRunFailed                 +
                                                +                         v
                                                 `-+-+-+-+-+-+-+-+-+-+-+>-+
                                                                          +
                                                                          +
                       #Interrupt@InferiorRunOk#                          +
                                  +                                       +
                          InferiorStopRequested                           +
  #SpontaneousStop                +                                       +
   @InferiorRunOk#         (calls *Engine->                               +
          +               interruptInferior())                            +
      {notify-               |          |                                 +
     Spontaneous-       {notify-    {notify-                              +
      Inferior-          Inferior-   Inferior-                            +
       StopOk}           StopOk}    StopFailed}                           +
           +              +             +                                 +
            +            +              +                                 +
            InferiorStopOk              +                                 +
                  +                     +                                 +
                  +                    +                                  +
                  +                   +                                   +
        #Stop@InferiorUnrunnable#    +                                    +
          #Creator Close Event#     +                                     +
                       +           +                                      +
                InferiorShutdownRequested                                 +
                            +                                             +
           (calls *Engine->shutdownInferior())                            +
                         |        |                                       +
                    {notify-   {notify-                                   +
                     Inferior- Inferior-                                  +
                  ShutdownOk}  ShutdownFailed}                            +
                         +        +                                       +
                         +        +                                       +
  #Inferior exited#      +        +                                       +
         |               +        +                                       +
   {notifyInferior-      +        +                                       +
      Exited}            +        +                                       +
           +             +        +                                       +
     InferiorExitOk      +        +                                       +
             +           +        +                                       +
            InferiorShutdownOk InferiorShutdownFailed                     +
                      *          *                                        +
                  EngineShutdownRequested                                 +
                            +                                             +
           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
                         |        |
                         |        |
                    {notify-   {notify-
                     Engine-    Engine-
                  ShutdownOk}  ShutdownFailed}
                         +       +
            EngineShutdownOk  EngineShutdownFailed
                         *       *
                     DebuggerFinished

\endcode */
hjk's avatar
hjk committed
289

290 291 292
/* Here is a matching graph as a GraphViz graph. View it using
 * \code
grep "^sg1:" debuggerplugin.cpp | cut -c5- | dot -osg1.ps -Tps && gv sg1.ps
293

294 295 296 297 298 299
sg1: digraph DebuggerStates {
sg1:   DebuggerNotReady -> EngineSetupRequested
sg1:   EngineSetupRequested -> EngineSetupOk [ label="notifyEngineSetupOk", style="dashed" ];
sg1:   EngineSetupRequested -> EngineSetupFailed [ label= "notifyEngineSetupFailed", style="dashed"];
sg1:   EngineSetupFailed -> DebuggerFinished [ label= "RunControl::StartFailed" ];
sg1:   EngineSetupOk -> InferiorSetupRequested [ label= "RunControl::StartSuccessful" ];
300
sg1:   InferiorSetupRequested -> InferiorSetupOk [ label="notifyInferiorSetupOk", style="dashed" ];
301
sg1:   InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
302
sg1:   InferiorSetupOk -> EngineRunRequested
303 304 305 306 307 308 309 310 311 312 313 314 315 316
sg1:   InferiorSetupFailed -> EngineShutdownRequested
sg1:   EngineRunRequested -> InferiorUnrunnable [ label="notifyInferiorUnrunnable", style="dashed" ];
sg1:   EngineRunRequested -> InferiorStopOk [ label="notifyEngineRunAndInferiorStopOk", style="dashed" ];
sg1:   EngineRunRequested -> InferiorRunOk [ label="notifyEngineRunAndInferiorRunOk", style="dashed" ];
sg1:   EngineRunRequested -> EngineRunFailed [ label="notifyEngineRunFailed", style="dashed" ];
sg1:   EngineRunFailed -> EngineShutdownRequested
sg1:   InferiorRunOk -> InferiorStopOk [ label="SpontaneousStop\nnotifyInferiorSpontaneousStop", style="dashed" ];
sg1:   InferiorRunOk -> InferiorStopRequested [ label="User stop\nEngine::interruptInferior", style="dashed"];
sg1:   InferiorStopRequested -> InferiorStopOk [ label="notifyInferiorStopOk", style="dashed" ];
sg1:   InferiorStopRequested -> InferiorShutdownRequested  [ label="notifyInferiorStopFailed", style="dashed" ];
sg1:   InferiorStopOk -> InferiorRunRequested [ label="User\nEngine::continueInferior" ];
sg1:   InferiorRunRequested -> InferiorRunOk [ label="notifyInferiorRunOk", style="dashed"];
sg1:   InferiorRunRequested -> InferiorRunFailed [ label="notifyInferiorRunFailed", style="dashed"];
sg1:   InferiorRunFailed -> InferiorStopOk
317 318
sg1:   InferiorStopOk -> InferiorShutdownRequested [ label="Close event" ];
sg1:   InferiorUnrunnable -> InferiorShutdownRequested [ label="Close event" ];
319 320
sg1:   InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
sg1:   InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
321 322
sg1:   InferiorExited -> InferiorExitOk [ label="notifyInferiorExited", style="dashed"];
sg1:   InferiorExitOk -> InferiorShutdownOk
323 324 325 326 327 328 329 330
sg1:   InferiorShutdownOk -> EngineShutdownRequested
sg1:   InferiorShutdownFailed -> EngineShutdownRequested
sg1:   EngineShutdownRequested -> EngineShutdownOk [ label="Engine::shutdownEngine\nnotifyEngineShutdownOk", style="dashed" ];
sg1:   EngineShutdownRequested -> EngineShutdownFailed  [ label="Engine::shutdownEngine\nnotifyEngineShutdownFailed", style="dashed" ];
sg1:   EngineShutdownOk -> DebuggerFinished  [ style = "dotted" ];
sg1:   EngineShutdownFailed  -> DebuggerFinished [ style = "dotted" ];
sg1: }
* \endcode */
hjk's avatar
hjk committed
331
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
332 333


334 335
/*!
    \class Debugger::Internal::GdbEngine
336 337
    \brief The GdbEngine class implements Debugger::Engine driving a GDB
    executable.
338 339 340

    GdbEngine specific startup. All happens in EngineSetupRequested state:

Leena Miettinen's avatar
Leena Miettinen committed
341 342
    \list
        \li Transitions marked by '---' are done in the individual adapters.
343

Leena Miettinen's avatar
Leena Miettinen committed
344 345
        \li Transitions marked by '+-+' are done in the GdbEngine.
    \endlist
346 347 348 349 350 351 352 353 354 355 356 357 358

    \code
                  GdbEngine::setupEngine()
                          +
            (calls *Adapter->startAdapter())
                          |      |
                          |      `---> handleAdapterStartFailed()
                          |                   +
                          |             {notifyEngineSetupFailed}
                          |
                 handleAdapterStarted()
                          +
                 {notifyEngineSetupOk}
359 360 361



362 363 364 365 366 367 368 369 370 371 372
                GdbEngine::setupInferior()
                          +
            (calls *Adapter->prepareInferior())
                          |      |
                          |      `---> handlePrepareInferiorFailed()
                          |                   +
                          |             {notifyInferiorSetupFailed}
                          |
                handleInferiorPrepared()
                          +
                {notifyInferiorSetupOk}
373

374
\endcode */
375

con's avatar
con committed
376
using namespace Core;
hjk's avatar
hjk committed
377
using namespace Debugger::Constants;
378
using namespace Debugger::Internal;
379
using namespace ExtensionSystem;
con's avatar
con committed
380
using namespace ProjectExplorer;
hjk's avatar
hjk committed
381
using namespace TextEditor;
382
using namespace Utils;
con's avatar
con committed
383

hjk's avatar
hjk committed
384 385 386
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
387 388

namespace Debugger {
389 390
namespace Internal {

391 392 393 394 395 396 397 398 399 400 401 402 403
// To be passed through margin menu action's data
struct BreakpointMenuContextData : public ContextData
{
    enum Mode
    {
        Breakpoint,
        MessageTracePoint
    };

    BreakpointMenuContextData() : mode(Breakpoint) {}
    Mode mode;
};

404 405 406 407 408 409 410 411 412 413 414
struct TestCallBack
{
    TestCallBack() : receiver(0), slot(0) {}
    TestCallBack(QObject *ob, const char *s) : receiver(ob), slot(s) {}

    QObject *receiver;
    const char *slot;
    QVariant cookie;
};


415 416 417 418
} // namespace Internal
} // namespace Debugger

Q_DECLARE_METATYPE(Debugger::Internal::BreakpointMenuContextData)
419 420
Q_DECLARE_METATYPE(Debugger::Internal::TestCallBack)

421 422 423 424

namespace Debugger {
namespace Internal {

425 426 427 428 429 430
// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.

431
void addCdbOptionPages(QList<IOptionsPage*> *opts);
432 433 434
void addGdbOptionPages(QList<IOptionsPage*> *opts);
void addScriptOptionPages(QList<IOptionsPage*> *opts);
void addTcfOptionPages(QList<IOptionsPage*> *opts);
435

436 437 438 439
#ifdef WITH_LLDB
void addLldbOptionPages(QList<IOptionsPage*> *opts);
#endif

440 441 442 443 444 445 446
static QToolButton *toolButton(QAction *action)
{
    QToolButton *button = new QToolButton;
    button->setDefaultAction(action);
    return button;
}

Orgad Shaneh's avatar
Orgad Shaneh committed
447
static void setProxyAction(ProxyAction *proxy, Core::Id id)
448
{
hjk's avatar
hjk committed
449
    proxy->setAction(ActionManager::command(id)->action());
450 451
}

Orgad Shaneh's avatar
Orgad Shaneh committed
452
static QToolButton *toolButton(Core::Id id)
453
{
hjk's avatar
hjk committed
454
    return toolButton(ActionManager::command(id)->action());
455 456
}

457 458 459 460 461 462 463 464 465 466 467
///////////////////////////////////////////////////////////////////////
//
// DummyEngine
//
///////////////////////////////////////////////////////////////////////

class DummyEngine : public DebuggerEngine
{
    Q_OBJECT

public:
468
    DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {}
469 470 471 472 473 474 475
    ~DummyEngine() {}

    void setupEngine() {}
    void setupInferior() {}
    void runEngine() {}
    void shutdownEngine() {}
    void shutdownInferior() {}
476
    bool hasCapability(unsigned cap) const;
477
    bool acceptsBreakpoint(BreakpointModelId) const { return false; }
478
    bool acceptsDebuggerCommands() const { return false; }
hjk's avatar
hjk committed
479
    void selectThread(ThreadId) {}
480 481
};

482
bool DummyEngine::hasCapability(unsigned cap) const
483 484
{
    // This can only be a first approximation of what to expect when running.
485
    Project *project = ProjectTree::currentProject();
486 487 488 489 490 491 492 493
    if (!project)
        return 0;
    Target *target = project->activeTarget();
    QTC_ASSERT(target, return 0);
    RunConfiguration *activeRc = target->activeRunConfiguration();
    QTC_ASSERT(activeRc, return 0);

    // This is a non-started Cdb or Gdb engine:
494
    if (activeRc->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useCppDebugger())
495
        return cap & (WatchpointByAddressCapability
496 497
               | BreakConditionCapability
               | TracePointCapability
498
               | OperateByInstructionCapability);
499 500

    // This is a Qml or unknown engine.
501
    return cap & AddWatcherCapability;
502 503
}

504 505 506 507 508 509
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

510
class DebugMode : public IMode
hjk's avatar
hjk committed
511 512
{
public:
513 514 515
    DebugMode()
    {
        setObjectName(QLatin1String("DebugMode"));
516
        setContext(Context(C_DEBUGMODE, CC::C_NAVIGATION_PANE));
517
        setDisplayName(DebuggerPlugin::tr("Debug"));
518
        setIcon(QIcon(QLatin1String(":/debugger/images/mode_debug.png")));
519
        setPriority(85);
520
        setId(MODE_DEBUG);
521
    }
hjk's avatar
hjk committed
522

hjk's avatar
hjk committed
523 524 525 526
    ~DebugMode()
    {
        delete m_widget;
    }
527
};
hjk's avatar
hjk committed
528

529 530 531 532 533 534
///////////////////////////////////////////////////////////////////////
//
// Misc
//
///////////////////////////////////////////////////////////////////////

535
static QWidget *addSearch(BaseTreeView *treeView, const QString &title,
536
    const char *objectName)
537
{
hjk's avatar
hjk committed
538
    QAction *act = action(UseAlternatingRowColors);
539
    treeView->setAlternatingRowColors(act->isChecked());
540 541
    QObject::connect(act, &QAction::toggled,
                     treeView, &BaseTreeView::setAlternatingRowColorsHelper);
542

Daniel Teske's avatar
Daniel Teske committed
543
    QWidget *widget = ItemViewFind::createSearchableWrapper(treeView);
544 545 546 547 548
    widget->setObjectName(QLatin1String(objectName));
    widget->setWindowTitle(title);
    return widget;
}

549
static std::function<bool(const Kit *)> cdbMatcher(char wordWidth = 0)
550
{
551
    return [wordWidth](const Kit *k) -> bool {
552 553
        if (DebuggerKitInformation::engineType(k) != CdbEngineType
            || !DebuggerKitInformation::isValidDebugger(k)) {
554
            return false;
555
        }
556
        if (wordWidth) {
557
            const ToolChain *tc = ToolChainKitInformation::toolChain(k);
558
            return tc && wordWidth == tc->targetAbi().wordWidth();
559
        }
560
        return true;
561 562
    };
}
563

564 565 566 567 568 569 570
// Find a CDB kit for debugging unknown processes.
// On a 64bit OS, prefer a 64bit debugger.
static Kit *findUniversalCdbKit()
{
    if (Utils::is64BitWindowsSystem()) {
        if (Kit *cdb64Kit = KitManager::find(cdbMatcher(64)))
            return cdb64Kit;
571
    }
572 573
    return KitManager::find(cdbMatcher());
}
574

575 576
static bool currentTextEditorPosition(ContextData *data)
{
577
    BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
578 579
    if (!textEditor)
        return false;
580
    const TextDocument *document = textEditor->textDocument();
581
    QTC_ASSERT(document, return false);
582
    data->fileName = document->filePath();
583
    if (document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) {
584
        int lineNumber = textEditor->currentLine();
585
        QString line = textEditor->textDocument()->plainText()
586 587 588 589
            .section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
        data->address = DisassemblerLine::addressFromDisassemblyLine(line);
    } else {
        data->lineNumber = textEditor->currentLine();
590
    }
591
    return true;
592
}
593

594 595
///////////////////////////////////////////////////////////////////////
//
596
// DebuggerPluginPrivate
597 598
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
599

600
static DebuggerPluginPrivate *dd = 0;
con's avatar
con committed
601

602 603 604 605 606 607 608 609 610 611 612 613 614 615
/*!
    \class Debugger::Internal::DebuggerCore

    This is the "internal" interface of the debugger plugin that's
    used by debugger views and debugger engines. The interface is
    implemented in DebuggerPluginPrivate.
*/

/*!
    \class Debugger::Internal::DebuggerPluginPrivate

    Implementation of DebuggerCore.
*/

616
class DebuggerPluginPrivate : public QObject
617 618
{
    Q_OBJECT
619

620 621
public:
    explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
622
    ~DebuggerPluginPrivate();
623

624
    bool initialize(const QStringList &arguments, QString *errorMessage);
625 626 627
    void extensionsInitialized();
    void aboutToShutdown();

628
    void connectEngine(DebuggerEngine *engine);
hjk's avatar
hjk committed
629
    void disconnectEngine() { connectEngine(0); }
630
    DebuggerEngine *dummyEngine();
631

632 633 634 635 636 637 638 639 640
    void setThreads(const QStringList &list, int index)
    {
        const bool state = m_threadBox->blockSignals(true);
        m_threadBox->clear();
        foreach (const QString &item, list)
            m_threadBox->addItem(item);
        m_threadBox->setCurrentIndex(index);
        m_threadBox->blockSignals(state);
    }
641
    DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process);
642

643
public slots:
644 645 646 647 648 649
    void writeSettings()
    {
        m_debuggerSettings->writeSettings();
        m_mainWindow->writeSettings();
    }

650 651
    void selectThread(int index)
    {
hjk's avatar
hjk committed
652 653
        ThreadId id = m_currentEngine->threadsHandler()->threadAt(index);
        m_currentEngine->selectThread(id);
654
    }
655

hjk's avatar
hjk committed
656
    void breakpointSetMarginActionTriggered()
657
    {
658 659
        const QAction *action = qobject_cast<const QAction *>(sender());
        QTC_ASSERT(action, return);
hjk's avatar
hjk committed
660 661
        const BreakpointMenuContextData data =
            action->data().value<BreakpointMenuContextData>();
662 663 664 665 666 667 668 669 670 671 672 673 674
        QString message;
        if (data.mode == BreakpointMenuContextData::MessageTracePoint) {
            if (data.address) {
                //: Message tracepoint: Address hit.
                message = tr("0x%1 hit").arg(data.address, 0, 16);
            } else {
                //: Message tracepoint: %1 file, %2 line %3 function hit.
                message = tr("%1:%2 %3() hit").arg(QFileInfo(data.fileName).fileName()).
                        arg(data.lineNumber).
                        arg(cppFunctionAt(data.fileName, data.lineNumber));
            }
            QInputDialog dialog; // Create wide input dialog.
            dialog.setWindowFlags(dialog.windowFlags()
hjk's avatar
hjk committed
675
              & ~(Qt::WindowContextHelpButtonHint|Qt::MSWindowsFixedSizeDialogHint));
676 677 678 679 680 681 682 683
            dialog.resize(600, dialog.height());
            dialog.setWindowTitle(tr("Add Message Tracepoint"));
            dialog.setLabelText (tr("Message:"));
            dialog.setTextValue(message);
            if (dialog.exec() != QDialog::Accepted || dialog.textValue().isEmpty())
                return;
            message = dialog.textValue();
        }
684
        if (data.address)
685
            toggleBreakpointByAddress(data.address, message);
686
        else
687
            toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message);
688
    }
689

hjk's avatar
hjk committed
690
    void breakpointRemoveMarginActionTriggered()
691
    {
hjk's avatar
hjk committed
692 693
        const QAction *act = qobject_cast<QAction *>(sender());
        QTC_ASSERT(act, return);
694
        BreakpointModelId id = act->data().value<BreakpointModelId>();
hjk's avatar
hjk committed
695
        m_breakHandler->removeBreakpoint(id);
hjk's avatar
hjk committed
696 697 698 699 700 701
     }

    void breakpointEnableMarginActionTriggered()
    {
        const QAction *act = qobject_cast<QAction *>(sender());
        QTC_ASSERT(act, return);
702
        BreakpointModelId id = act->data().value<BreakpointModelId>();
hjk's avatar
hjk committed
703
        breakHandler()->setEnabled(id, true);
hjk's avatar
hjk committed
704 705 706 707 708 709
    }

    void breakpointDisableMarginActionTriggered()
    {
        const QAction *act = qobject_cast<QAction *>(sender());
        QTC_ASSERT(act, return);
Nikolai Kosjar's avatar
Nikolai Kosjar committed
710
        BreakpointModelId id = act->data().value<BreakpointModelId>();
hjk's avatar
hjk committed
711
        breakHandler()->setEnabled(id, false);
712 713
    }

714
    void updateWatchersHeader(int section, int, int newSize)
715
    {
716 717
        m_watchersView->header()->resizeSection(section, newSize);
        m_returnView->header()->resizeSection(section, newSize);
718
    }
719

720
    void sourceFilesDockToggled(bool on)
721
    {
722
        if (on && m_currentEngine->state() == InferiorStopOk)
723 724 725
            m_currentEngine->reloadSourceFiles();
    }

726
    void modulesDockToggled(bool on)
727
    {
728
        if (on && m_currentEngine->state() == InferiorStopOk)
729 730
            m_currentEngine->reloadModules();
    }
731

hjk's avatar
hjk committed
732
    void registerDockToggled(bool on)
733
    {
734
        if (on && m_currentEngine->state() == InferiorStopOk)
735 736
            m_currentEngine->reloadRegisters();
    }
737

738 739
    void synchronizeBreakpoints()
    {
740
        showMessage(QLatin1String("ATTEMPT SYNC"), LogDebug);
741
        for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
742
            if (DebuggerEngine *engine = m_snapshotHandler->at(i))
743 744 745 746
                engine->attemptBreakpointSynchronization();
        }
    }

747
    void editorOpened(Core::IEditor *editor);
748
    void updateBreakMenuItem(Core::IEditor *editor);
749
    void setBusyCursor(bool busy);
750
    void requestMark(TextEditor::TextEditorWidget *widget, int lineNumber,
751
                     TextEditor::TextMarkRequestKind kind);
752 753
    void requestContextMenu(TextEditor::TextEditorWidget *widget,
                            int lineNumber, QMenu *menu);
754

755 756 757
    void activatePreviousMode();
    void activateDebugMode();
    void toggleBreakpoint();
758 759 760 761
    void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber,
                                       const QString &tracePointMessage = QString());
    void toggleBreakpointByAddress(quint64 address,
                                   const QString &tracePointMessage = QString());
762
    void onModeChanged(Core::IMode *mode);
763
    void onCoreAboutToOpen();
764
    void showSettingsDialog();
765
    void updateDebugWithoutDeployMenu();
766

767
    void debugProject();
768
    void debugProjectWithoutDeploy();
769
    void debugProjectBreakMain();
770
    void startAndDebugApplication();
771
    void startRemoteCdbSession();
772
    void startRemoteServer();
773
    void attachToRemoteServer();
774
    void attachToProcess(bool startServerOnly);
hjk's avatar
hjk committed
775
    void attachToRunningApplication();
776 777 778
    void attachToUnstartedApplicationDialog();
    void attachToFoundProcess();
    void continueOnAttach(Debugger::DebuggerState state);
779
    void attachToQmlPort();
780
    void runScheduled();
781
    void attachCore();
782

783
    void enableReverseDebuggingTriggered(const QVariant &value);
784
    void showStatusMessage(const QString &msg, int timeout = -1);
785

hjk's avatar
hjk committed
786
    DebuggerMainWindow *mainWindow() const { return m_mainWindow; }
hjk's avatar
hjk committed
787

788
    bool isDockVisible(const QString &objectName) const
hjk's avatar
hjk committed
789 790 791 792
    {
        QDockWidget *dock = mainWindow()->findChild<QDockWidget *>(objectName);
        return dock && dock->toggleViewAction()->isChecked();
    }
793

794 795
    void runControlStarted(DebuggerEngine *engine);
    void runControlFinished(DebuggerEngine *engine);
796 797
    void remoteCommand(const QStringList &options, const QStringList &);

798
    void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
799 800 801

    void dumpLog();
    void cleanupViews();
802
    void setInitialState();
803 804 805 806

    void fontSettingsChanged(const TextEditor::FontSettings &settings);

    void updateState(DebuggerEngine *engine);
hjk's avatar
hjk committed
807
    void updateWatchersWindow(bool showWatch, bool showReturn);
808
    void onCurrentProjectChanged(ProjectExplorer::Project *project);
809 810 811 812

    void sessionLoaded();
    void aboutToUnloadSession();
    void aboutToSaveSession();
813

814
    void coreShutdown();
815

hjk's avatar
hjk committed
816 817
#ifdef WITH_TESTS
public slots:
818
    void testLoadProject(const QString &proFile, const TestCallBack &cb);
hjk's avatar
hjk committed
819
    void testProjectLoaded(ProjectExplorer::Project *project);
820 821
    void testProjectEvaluated();
    void testProjectBuilt(bool success);
822 823 824 825
    void testUnloadProject();
    void testFinished();

    void testRunProject(const DebuggerStartParameters &sp, const TestCallBack &cb);
hjk's avatar
hjk committed
826
    void testRunControlFinished();
827

hjk's avatar
hjk committed
828 829 830
//    void testStateMachine1();
//    void testStateMachine2();
//    void testStateMachine3();
831

832 833
    void testBenchmark1();

834
public:
hjk's avatar
hjk committed
835
    Project *m_testProject;
836 837 838
    bool m_testSuccess;
    QList<TestCallBack> m_testCallbacks;

hjk's avatar
hjk committed
839 840
#endif

hjk's avatar
hjk committed
841
public slots:
842
    void updateDebugActions();
843 844 845

    void handleExecDetach()
    {
846
        currentEngine()->resetLocation();
847 848 849 850 851
        currentEngine()->detachDebugger();
    }

    void handleExecContinue()
    {
852
        currentEngine()->resetLocation();
853 854 855 856 857
        currentEngine()->continueInferior();
    }

    void handleExecInterrupt()
    {
858
        currentEngine()->resetLocation();
859 860 861
        currentEngine()->requestInterruptInferior();
    }

862
    void handleAbort()
863
    {
864
        currentEngine()->resetLocation();
865
        currentEngine()->abortDebugger();
866
    }
hjk's avatar
hjk committed
867

868 869 870 871 872 873
    void handleReset()
    {
        currentEngine()->resetLocation();
        currentEngine()->resetInferior();
    }

hjk's avatar
hjk committed
874 875
    void handleExecStep()
    {
876 877 878 879 880 881 882 883 884
        if (currentEngine()->state() == DebuggerNotReady) {
            debugProjectBreakMain();
        } else {
            currentEngine()->resetLocation();
            if (boolSetting(OperateByInstruction))
                currentEngine()->executeStepI();
            else
                currentEngine()->executeStep();
        }
hjk's avatar
hjk committed
885 886 887 888
    }

    void handleExecNext()
    {
889 890 891 892 893 894 895 896 897
        if (currentEngine()->state() == DebuggerNotReady) {
            debugProjectBreakMain();
        } else {
            currentEngine()->resetLocation();
            if (boolSetting(OperateByInstruction))
                currentEngine()->executeNextI();
            else
                currentEngine()->executeNext();
        }
hjk's avatar
hjk committed
898 899
    }

900 901
    void handleExecStepOut()
    {
902
        currentEngine()->resetLocation();
903 904 905 906 907
        currentEngine()->executeStepOut();
    }

    void handleExecReturn()
    {
908
        currentEngine()->resetLocation();
909 910
        currentEngine()->executeReturn();
    }
hjk's avatar
hjk committed
911 912 913

    void handleExecJumpToLine()
    {
914
        currentEngine()->resetLocation();
915 916 917
        ContextData data;
        if (currentTextEditorPosition(&data))
            currentEngine()->executeJumpToLine(data);
hjk's avatar
hjk committed
918 919 920 921
    }

    void handleExecRunToLine()
    {
922
        currentEngine()->resetLocation();
923 924 925
        ContextData data;
        if (currentTextEditorPosition(&data))
            currentEngine()->executeRunToLine(data);
hjk's avatar
hjk committed
926 927
    }

928
    void handleExecRunToSelectedFunction()
hjk's avatar
hjk committed
929
    {
930
        BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
931
        QTC_ASSERT(textEditor, return);
932
        QTextCursor cursor = textEditor->textCursor();
933 934 935 936
        QString functionName = cursor.selectedText();
        if (functionName.isEmpty()) {
            const QTextBlock block = cursor.block();
            const QString line = block.text();