debuggerplugin.cpp 133 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
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
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
hjk's avatar
hjk committed
25

con's avatar
con committed
26 27
#include "debuggerplugin.h"

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

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

hjk's avatar
hjk committed
73 74 75
#include "analyzer/analyzerconstants.h"
#include "analyzer/analyzermanager.h"

76
#include <coreplugin/actionmanager/actioncontainer.h>
77
#include <coreplugin/actionmanager/actionmanager.h>
78
#include <coreplugin/actionmanager/command.h>
79
#include <coreplugin/coreconstants.h>
80
#include <coreplugin/coreicons.h>
81 82 83 84
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/itemviewfind.h>
#include <coreplugin/findplaceholder.h>
con's avatar
con committed
85
#include <coreplugin/icore.h>
86
#include <coreplugin/imode.h>
87
#include <coreplugin/messagebox.h>
88
#include <coreplugin/messagemanager.h>
con's avatar
con committed
89
#include <coreplugin/modemanager.h>
90 91 92
#include <coreplugin/navigationwidget.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/rightpane.h>
hjk's avatar
hjk committed
93

con's avatar
con committed
94
#include <cppeditor/cppeditorconstants.h>
95
#include <cpptools/cppmodelmanager.h>
hjk's avatar
hjk committed
96

97
#include <extensionsystem/invoker.h>
98

99
#include <projectexplorer/buildmanager.h>
100
#include <projectexplorer/taskhub.h>
101
#include <projectexplorer/toolchain.h>
102
#include <projectexplorer/devicesupport/deviceprocesslist.h>
103
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
104
#include <projectexplorer/projectexplorer.h>
105
#include <projectexplorer/projectexplorericons.h>
106
#include <projectexplorer/projecttree.h>
107 108
#include <projectexplorer/projectexplorersettings.h>
#include <projectexplorer/project.h>
109
#include <projectexplorer/runconfiguration.h>
110
#include <projectexplorer/runnables.h>
con's avatar
con committed
111
#include <projectexplorer/session.h>
hjk's avatar
hjk committed
112
#include <projectexplorer/taskhub.h>
113
#include <projectexplorer/target.h>
114

115
#include <texteditor/texteditor.h>
116
#include <texteditor/textdocument.h>
117
#include <texteditor/fontsettings.h>
118
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
119

120 121
#include <utils/algorithm.h>
#include <utils/appmainwindow.h>
122
#include <utils/basetreeview.h>
123
#include <utils/fancymainwindow.h>
124
#include <utils/hostosinfo.h>
Eike Ziller's avatar
Eike Ziller committed
125
#include <utils/mimetypes/mimedatabase.h>
126
#include <utils/proxyaction.h>
127 128
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
129
#include <utils/statuslabel.h>
130
#include <utils/styledbar.h>
131
#include <utils/styledbar.h>
hjk's avatar
hjk committed
132
#include <utils/winutils.h>
con's avatar
con committed
133

134
#include <QAction>
Campbell Barton's avatar
Campbell Barton committed
135
#include <QApplication>
hjk's avatar
hjk committed
136
#include <QCheckBox>
137
#include <QComboBox>
138
#include <QDebug>
139 140
#include <QDockWidget>
#include <QFileDialog>
hjk's avatar
hjk committed
141 142
#include <QHBoxLayout>
#include <QHeaderView>
hjk's avatar
hjk committed
143
#include <QInputDialog>
144 145
#include <QMenu>
#include <QMenu>
146
#include <QMessageBox>
147
#include <QStackedWidget>
148 149 150
#include <QTextBlock>
#include <QToolButton>
#include <QTreeWidget>
151
#include <QVBoxLayout>
152
#include <QtPlugin>
153

hjk's avatar
hjk committed
154
#ifdef WITH_TESTS
155 156 157
#include <QTest>
#include <QSignalSpy>
#include <QTestEventLoop>
158 159 160 161

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

164 165
#endif // WITH_TESTS

166 167
#include <climits>

168 169 170 171 172
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
//#   define STATE_DEBUG(s)
//    do { QString msg; QTextStream ts(&msg); ts << s;
//      showMessage(msg, LogDebug); } while (0)
173
#   define STATE_DEBUG(s) do { qDebug() << s; } while (0)
174 175 176 177
#else
#   define STATE_DEBUG(s)
#endif

178 179 180 181 182 183 184 185
/*!
    \namespace Debugger
    Debugger plugin namespace
*/

/*!
    \namespace Debugger::Internal
    Internal namespace of the Debugger plugin
186
    \internal
187 188 189 190 191
*/

/*!
    \class Debugger::DebuggerEngine

192
    \brief The DebuggerEngine class is the base class of a debugger engine.
193

Leena Miettinen's avatar
Leena Miettinen committed
194
    \note The Debugger process itself and any helper processes like
195 196
    gdbserver are referred to as 'Engine', whereas the debugged process
    is referred to as 'Inferior'.
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 289 290 291 292 293 294

    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}            +        +                                       +
           +             +        +                                       +
295
            +            +        +                                       +
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
             +           +        +                                       +
            InferiorShutdownOk InferiorShutdownFailed                     +
                      *          *                                        +
                  EngineShutdownRequested                                 +
                            +                                             +
           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+'
                         |        |
                         |        |
                    {notify-   {notify-
                     Engine-    Engine-
                  ShutdownOk}  ShutdownFailed}
                         +       +
            EngineShutdownOk  EngineShutdownFailed
                         *       *
                     DebuggerFinished

\endcode */
hjk's avatar
hjk committed
313

314 315 316
/* 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
317

318 319 320 321 322 323
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" ];
324
sg1:   InferiorSetupRequested -> InferiorSetupOk [ label="notifyInferiorSetupOk", style="dashed" ];
325
sg1:   InferiorSetupRequested -> InferiorSetupFailed [ label="notifyInferiorFailed", style="dashed" ];
326
sg1:   InferiorSetupOk -> EngineRunRequested
327 328 329 330 331 332 333 334 335 336 337 338 339 340
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
341 342
sg1:   InferiorStopOk -> InferiorShutdownRequested [ label="Close event" ];
sg1:   InferiorUnrunnable -> InferiorShutdownRequested [ label="Close event" ];
343 344
sg1:   InferiorShutdownRequested -> InferiorShutdownOk [ label= "Engine::shutdownInferior\nnotifyInferiorShutdownOk", style="dashed" ];
sg1:   InferiorShutdownRequested -> InferiorShutdownFailed [ label="Engine::shutdownInferior\nnotifyInferiorShutdownFailed", style="dashed" ];
345 346
sg1:   InferiorExited -> InferiorExitOk [ label="notifyInferiorExited", style="dashed"];
sg1:   InferiorExitOk -> InferiorShutdownOk
347 348 349 350 351 352 353 354
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
355
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
356 357


358 359
/*!
    \class Debugger::Internal::GdbEngine
360 361
    \brief The GdbEngine class implements Debugger::Engine driving a GDB
    executable.
362 363 364

    GdbEngine specific startup. All happens in EngineSetupRequested state:

Leena Miettinen's avatar
Leena Miettinen committed
365 366
    \list
        \li Transitions marked by '---' are done in the individual adapters.
367

Leena Miettinen's avatar
Leena Miettinen committed
368 369
        \li Transitions marked by '+-+' are done in the GdbEngine.
    \endlist
370 371 372 373 374 375 376 377 378 379 380 381 382

    \code
                  GdbEngine::setupEngine()
                          +
            (calls *Adapter->startAdapter())
                          |      |
                          |      `---> handleAdapterStartFailed()
                          |                   +
                          |             {notifyEngineSetupFailed}
                          |
                 handleAdapterStarted()
                          +
                 {notifyEngineSetupOk}
383 384 385



386 387 388 389 390 391 392 393 394 395 396
                GdbEngine::setupInferior()
                          +
            (calls *Adapter->prepareInferior())
                          |      |
                          |      `---> handlePrepareInferiorFailed()
                          |                   +
                          |             {notifyInferiorSetupFailed}
                          |
                handleInferiorPrepared()
                          +
                {notifyInferiorSetupOk}
397

398
\endcode */
399

con's avatar
con committed
400
using namespace Core;
hjk's avatar
hjk committed
401
using namespace Debugger::Constants;
402
using namespace Debugger::Internal;
403
using namespace ExtensionSystem;
con's avatar
con committed
404
using namespace ProjectExplorer;
hjk's avatar
hjk committed
405
using namespace TextEditor;
406
using namespace Utils;
con's avatar
con committed
407

hjk's avatar
hjk committed
408 409 410
using namespace Analyzer;
//using namespace Analyzer::Internal;

hjk's avatar
hjk committed
411 412 413
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
414 415

namespace Debugger {
416 417
namespace Internal {

418 419 420 421 422 423 424 425 426 427 428
struct TestCallBack
{
    TestCallBack() : receiver(0), slot(0) {}
    TestCallBack(QObject *ob, const char *s) : receiver(ob), slot(s) {}

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


429 430 431
} // namespace Internal
} // namespace Debugger

432 433
Q_DECLARE_METATYPE(Debugger::Internal::TestCallBack)

434 435 436
namespace Debugger {
namespace Internal {

437
void addCdbOptionPages(QList<IOptionsPage*> *opts);
438
void addGdbOptionPages(QList<IOptionsPage*> *opts);
439
QObject *createDebuggerRunControlFactory(QObject *parent);
440

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

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

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

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

class DummyEngine : public DebuggerEngine
{
public:
467
    DummyEngine() : DebuggerEngine(DebuggerRunParameters()) {}
468 469 470 471 472 473 474
    ~DummyEngine() {}

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

481
bool DummyEngine::hasCapability(unsigned cap) const
482 483
{
    // This can only be a first approximation of what to expect when running.
484
    Project *project = ProjectTree::currentProject();
485 486 487 488 489 490 491 492
    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:
493
    if (activeRc->extraAspect<Debugger::DebuggerRunConfigurationAspect>()->useCppDebugger())
494
        return cap & (WatchpointByAddressCapability
495 496
               | BreakConditionCapability
               | TracePointCapability
497
               | OperateByInstructionCapability);
498 499

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

503 504 505 506 507 508
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

509
class DebugMode : public IMode
hjk's avatar
hjk committed
510 511
{
public:
512 513 514
    DebugMode()
    {
        setObjectName(QLatin1String("DebugMode"));
515
        setContext(Context(C_DEBUGMODE, CC::C_NAVIGATION_PANE));
516
        setDisplayName(DebuggerPlugin::tr("Debug"));
517 518
        setIcon(Utils::Icon::modeIcon(Icons::MODE_DEBUGGER_CLASSIC,
                                      Icons::MODE_DEBUGGER_FLAT, Icons::MODE_DEBUGGER_FLAT_ACTIVE));
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
// Find a CDB kit for debugging unknown processes.
// On a 64bit OS, prefer a 64bit debugger.
static Kit *findUniversalCdbKit()
{
    if (Utils::is64BitWindowsSystem()) {
Tobias Hunger's avatar
Tobias Hunger committed
569
        if (Kit *cdb64Kit = KitManager::find(KitMatcher(cdbMatcher(64))))
570
            return cdb64Kit;
571
    }
Tobias Hunger's avatar
Tobias Hunger committed
572
    return KitManager::find(KitMatcher(cdbMatcher()));
573
}
574

575 576
///////////////////////////////////////////////////////////////////////
//
577
// DebuggerPluginPrivate
578 579
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
580

581
static DebuggerPluginPrivate *dd = 0;
con's avatar
con committed
582

583 584 585 586
//class DockWidgetEventFilter : public QObject
//{
//public:
//    DockWidgetEventFilter() {}
587

588 589 590
//private:
//    bool eventFilter(QObject *obj, QEvent *event) override;
//};
591

592 593 594 595 596 597 598 599 600 601 602 603 604 605
/*!
    \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.
*/

606
class DebuggerPluginPrivate : public QObject
607 608
{
    Q_OBJECT
609

610 611
public:
    explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
612
    ~DebuggerPluginPrivate();
613

614
    bool initialize(const QStringList &arguments, QString *errorMessage);
615 616 617
    void extensionsInitialized();
    void aboutToShutdown();

618
    void connectEngine(DebuggerEngine *engine);
hjk's avatar
hjk committed
619
    void disconnectEngine() { connectEngine(0); }
620
    DebuggerEngine *dummyEngine();
621

hjk's avatar
hjk committed
622
    void setThreadBoxContents(const QStringList &list, int index)
623 624 625 626 627 628 629 630
    {
        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);
    }
631 632

    DebuggerRunControl *attachToRunningProcess(Kit *kit, DeviceProcessItem process, bool contAfterAttach);
633

634 635 636
    void writeSettings()
    {
        m_debuggerSettings->writeSettings();
637
//        writeWindowSettings();
638 639
    }

640 641
    void selectThread(int index)
    {
hjk's avatar
hjk committed
642 643
        ThreadId id = m_currentEngine->threadsHandler()->threadAt(index);
        m_currentEngine->selectThread(id);
644
    }
645

646
    void breakpointSetMarginActionTriggered(bool isMessageOnly, const ContextData &data)
647
    {
648
        QString message;
649
        if (isMessageOnly) {
650
            if (data.type == LocationByAddress) {
651 652 653 654
                //: Message tracepoint: Address hit.
                message = tr("0x%1 hit").arg(data.address, 0, 16);
            } else {
                //: Message tracepoint: %1 file, %2 line %3 function hit.
655
                message = tr("%1:%2 %3() hit").arg(FileName::fromString(data.fileName).fileName()).
656 657 658 659 660
                        arg(data.lineNumber).
                        arg(cppFunctionAt(data.fileName, data.lineNumber));
            }
            QInputDialog dialog; // Create wide input dialog.
            dialog.setWindowFlags(dialog.windowFlags()
hjk's avatar
hjk committed
661
              & ~(Qt::WindowContextHelpButtonHint|Qt::MSWindowsFixedSizeDialogHint));
662 663 664 665 666 667 668 669
            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();
        }
670
        toggleBreakpoint(data, message);
671
    }
672

673
    void updateWatchersHeader(int section, int, int newSize)
674
    {
675 676
        m_watchersView->header()->resizeSection(section, newSize);
        m_returnView->header()->resizeSection(section, newSize);
677
    }
678

679
    void sourceFilesDockToggled(bool on)
680
    {
681
        if (on && m_currentEngine->state() == InferiorStopOk)
682 683 684
            m_currentEngine->reloadSourceFiles();
    }

685
    void modulesDockToggled(bool on)
686
    {
687
        if (on && m_currentEngine->state() == InferiorStopOk)
688 689
            m_currentEngine->reloadModules();
    }
690

hjk's avatar
hjk committed
691
    void registerDockToggled(bool on)
692
    {
693
        if (on && m_currentEngine->state() == InferiorStopOk)
694 695
            m_currentEngine->reloadRegisters();
    }
696

697 698
    void synchronizeBreakpoints()
    {
699
        showMessage(QLatin1String("ATTEMPT SYNC"), LogDebug);
700
        for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
701
            if (DebuggerEngine *engine = m_snapshotHandler->at(i))
702 703 704 705
                engine->attemptBreakpointSynchronization();
        }
    }

706 707
    void editorOpened(IEditor *editor);
    void updateBreakMenuItem(IEditor *editor);
708
    void setBusyCursor(bool busy);
709 710 711
    void requestMark(TextEditorWidget *widget, int lineNumber,
                     TextMarkRequestKind kind);
    void requestContextMenu(TextEditorWidget *widget,
712
                            int lineNumber, QMenu *menu);
713

714 715
    void activatePreviousMode();
    void activateDebugMode();
716 717
    void toggleBreakpointHelper();
    void toggleBreakpoint(const ContextData &location, const QString &tracePointMessage = QString());
718
    void onModeChanged(IMode *mode);
719
    void onCoreAboutToOpen();
720
    void updateDebugWithoutDeployMenu();
721

722
    void startAndDebugApplication();
723
    void startRemoteCdbSession();
724
    void startRemoteServerAndAttachToProcess();
725
    void attachToRemoteServer();
hjk's avatar
hjk committed
726
    void attachToRunningApplication();
727
    void attachToUnstartedApplicationDialog();
728
    void attachToQmlPort();
hjk's avatar
hjk committed
729
    Q_SLOT void runScheduled();
730
    void attachCore();
731

732
    void enableReverseDebuggingTriggered(const QVariant &value);
733
    void showStatusMessage(const QString &msg, int timeout = -1);
734

735 736
    void runControlStarted(DebuggerEngine *engine);
    void runControlFinished(DebuggerEngine *engine);
737
    void remoteCommand(const QStringList &options);
738

739
    void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
740 741 742

    void dumpLog();
    void cleanupViews();
743
    void setInitialState();
744

745
    void fontSettingsChanged(const FontSettings &settings);
746 747

    void updateState(DebuggerEngine *engine);
748
    void onCurrentProjectChanged(Project *project);
749 750 751 752

    void sessionLoaded();
    void aboutToUnloadSession();
    void aboutToSaveSession();
753

754
    void coreShutdown();
755

hjk's avatar
hjk committed
756 757
#ifdef WITH_TESTS
public slots:
758
    void testLoadProject(const QString &proFile, const TestCallBack &cb);
759
    void testProjectLoaded(Project *project);
760 761
    void testProjectEvaluated();
    void testProjectBuilt(bool success);
762 763 764
    void testUnloadProject();
    void testFinished();

765
    void testRunProject(const DebuggerRunParameters &sp, const TestCallBack &cb);
hjk's avatar
hjk committed
766
    void testRunControlFinished();
767

hjk's avatar
hjk committed
768 769 770
//    void testStateMachine1();
//    void testStateMachine2();
//    void testStateMachine3();
771

772 773
    void testBenchmark1();

774
public:
hjk's avatar
hjk committed
775
    Project *m_testProject;
776 777 778
    bool m_testSuccess;
    QList<TestCallBack> m_testCallbacks;

hjk's avatar
hjk committed
779 780
#endif

hjk's avatar
hjk committed
781
public slots:
782
    void updateDebugActions();
783 784 785

    void handleExecDetach()
    {
786
        currentEngine()->resetLocation();
787 788 789 790 791
        currentEngine()->detachDebugger();
    }

    void handleExecContinue()
    {
792
        currentEngine()->resetLocation();
793 794 795 796 797
        currentEngine()->continueInferior();
    }

    void handleExecInterrupt()
    {
798
        currentEngine()->resetLocation();
799 800 801
        currentEngine()->requestInterruptInferior();
    }

802
    void handleAbort()
803
    {
804
        currentEngine()->resetLocation();
805
        currentEngine()->abortDebugger();
806
    }
hjk's avatar
hjk committed
807

808 809 810 811 812 813
    void handleReset()
    {
        currentEngine()->resetLocation();
        currentEngine()->resetInferior();
    }

hjk's avatar
hjk committed
814 815
    void handleExecStep()
    {
816
        if (currentEngine()->state() == DebuggerNotReady) {
817
            ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN);
818 819 820 821 822 823 824
        } else {
            currentEngine()->resetLocation();
            if (boolSetting(OperateByInstruction))
                currentEngine()->executeStepI();
            else
                currentEngine()->executeStep();
        }
hjk's avatar
hjk committed
825 826 827 828
    }

    void handleExecNext()
    {
829
        if (currentEngine()->state() == DebuggerNotReady) {
830
            ProjectExplorerPlugin::runStartupProject(ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN);
831 832 833 834 835 836 837
        } else {
            currentEngine()->resetLocation();
            if (boolSetting(OperateByInstruction))
                currentEngine()->executeNextI();
            else
                currentEngine()->executeNext();
        }
hjk's avatar
hjk committed
838 839
    }

840 841
    void handleExecStepOut()
    {
842
        currentEngine()->resetLocation();
843 844 845 846 847
        currentEngine()->executeStepOut();
    }

    void handleExecReturn()
    {
848
        currentEngine()->resetLocation();
849 850
        currentEngine()->executeReturn();
    }
hjk's avatar
hjk committed
851 852 853

    void handleExecJumpToLine()
    {
854
        currentEngine()->resetLocation();
855 856 857 858 859 860
        if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
            ContextData location = getLocationContext(textEditor->textDocument(),
                                                      textEditor->currentLine());
            if (location.isValid())
                currentEngine()->executeJumpToLine(location);
        }
hjk's avatar
hjk committed
861 862 863 864
    }

    void handleExecRunToLine()
    {
865
        currentEngine()->resetLocation();
866 867 868 869 870 871
        if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
            ContextData location = getLocationContext(textEditor->textDocument(),
                                                      textEditor->currentLine());
            if (location.isValid())
                currentEngine()->executeRunToLine(location);
        }
hjk's avatar
hjk committed
872 873
    }

874
    void handleExecRunToSelectedFunction()
hjk's avatar
hjk committed
875
    {
876
        BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
877
        QTC_ASSERT(textEditor, return);
878
        QTextCursor cursor = textEditor->textCursor();
879 880 881 882
        QString functionName = cursor.selectedText();
        if (functionName.isEmpty()) {
            const QTextBlock block = cursor.block();
            const QString line = block.text();
883
            foreach (const QString &str, line.trimmed().split(QLatin1Char('('))) {
884 885 886 887 888 889 890 891 892 893 894 895 896
                QString a;
                for (int i = str.size(); --i >= 0; ) {
                    if (!str.at(i).isLetterOrNumber())
                        break;
                    a = str.at(i) + a;
                }
                if (!a.isEmpty()) {
                    functionName = a;
                    break;
                }
            }
        }

897 898 899 900 901 902
        if (functionName.isEmpty()) {
            showStatusMessage(tr("No function selected."));
        } else {
            showStatusMessage(tr("Running to function \"%1\".")
                .arg(functionName));
            currentEngine()->resetLocation();
903
            currentEngine()->executeRunToFunction(functionName);
904
        }
hjk's avatar
hjk committed
905 906 907 908 909
    }

    void handleAddToWatchWindow()
    {
        // Requires a selection, but that's the only case we want anyway.
910
        BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
hjk's avatar
hjk committed
911 912
        if (!textEditor)
            return;
913
        QTextCursor tc = textEditor->textCursor();
hjk's avatar
hjk committed
914 915 916 917 918
        QString exp;
        if (tc.hasSelection()) {
            exp = tc.selectedText();
        } else {
            int line, column;
919
            exp = cppExpressionAt(textEditor->editorWidget(), tc.position(), &line, &column);