debuggerengine.h 16.8 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
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
****************************************************************************/
25

hjk's avatar
hjk committed
26
#pragma once
27 28 29

#include "debugger_global.h"
#include "debuggerconstants.h"
30
#include "debuggeritem.h"
31
#include "debuggerprotocol.h"
32 33

#include <projectexplorer/devicesupport/idevice.h>
34
#include <projectexplorer/runnables.h>
hjk's avatar
hjk committed
35
#include <texteditor/textmark.h>
36

37
#include <QObject>
38
#include <QProcess>
39 40 41 42

QT_BEGIN_NAMESPACE
class QDebug;
class QPoint;
Friedemann Kleint's avatar
Friedemann Kleint committed
43
class QAbstractItemModel;
44 45
QT_END_NAMESPACE

46
namespace Core { class IOptionsPage; }
47

48
namespace Utils { class MacroExpander; }
49 50 51

namespace Debugger {

52
class DebuggerRunTool;
53 54 55 56 57

DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state);

namespace Internal {

hjk's avatar
hjk committed
58
class DebuggerEnginePrivate;
59
class DebuggerPluginPrivate;
60 61
class DisassemblerAgent;
class MemoryAgent;
62
class WatchItem;
63
class BreakHandler;
hjk's avatar
hjk committed
64
class LocationMark;
65 66 67 68 69 70 71
class ModulesHandler;
class RegisterHandler;
class StackHandler;
class StackFrame;
class SourceFilesHandler;
class ThreadsHandler;
class WatchHandler;
72
class Breakpoint;
73
class QmlCppEngine;
74
class DebuggerToolTipContext;
hjk's avatar
hjk committed
75
class MemoryViewSetupData;
76
class Terminal;
77
class TerminalRunner;
78
class ThreadId;
79

80
class DebuggerRunParameters
81 82
{
public:
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    DebuggerStartMode startMode = NoStartMode;
    DebuggerCloseMode closeMode = KillAtClose;

    ProjectExplorer::StandardRunnable inferior;
    QString displayName; // Used in the Snapshots view.
    Utils::ProcessHandle attachPID;
    QStringList solibSearchPath;

    // Used by Qml debugging.
    QUrl qmlServer;

    // Used by general remote debugging.
    QString remoteChannel;
    bool useExtendedRemote = false; // Whether to use GDB's target extended-remote or not.
    QString symbolFile;

    // Used by Mer plugin (3rd party)
    QMap<QString, QString> sourcePathMap;

    // Used by baremetal plugin
    QString commandsForReset; // commands used for resetting the inferior
    bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used
    QString commandsAfterConnect; // additional commands to post after connection to debug target

    // Used by Valgrind
    QStringList expectedSignals;

    // For QNX debugging
    bool useCtrlCStub = false;

    // Used by Android to avoid false positives on warnOnRelease
    bool skipExecutableValidation = false;
    bool useTargetAsync = false;
    QStringList additionalSearchDirectories;

    // Used by iOS.
    QString platform;
    QString deviceSymbolsRoot;
    bool continueAfterAttach = false;
    QString sysRoot;

    // Used by general core file debugging. Public access requested in QTCREATORBUG-17158.
    QString coreFile;

    // Macro-expanded and passed to debugger startup.
    QString additionalStartupCommands;
129

130 131
    DebuggerEngineType cppEngineType = NoEngineType;

132 133
    bool isCppDebugging = true;
    bool isQmlDebugging = false;
134 135 136
    bool breakOnMain = false;
    bool multiProcess = false; // Whether to set detach-on-fork off.

137
    ProjectExplorer::StandardRunnable debugger;
138 139 140 141
    QString overrideStartScript; // Used in attach to core and remote debugging
    QString startMessage; // First status message shown.
    QString debugInfoLocation; // Gdb "set-debug-file-directory".
    QStringList debugSourceLocation; // Gdb "directory"
142
    bool isSnapshot = false; // Set if created internally.
143 144 145 146
    ProjectExplorer::Abi toolChainAbi;

    QString projectSourceDirectory;
    QStringList projectSourceFiles;
147

hjk's avatar
hjk committed
148 149 150 151
    // Used by Script debugging
    QString interpreter;
    QString mainScript;

152 153 154
    // Used by AttachCrashedExternal.
    QString crashParameter;

155 156
    bool nativeMixedEnabled = false;

157 158 159
    bool isNativeMixedDebugging() const;
    void validateExecutable();

160 161
    Utils::MacroExpander *macroExpander = 0;

162
    // For Debugger testing.
163
    int testCase = 0;
164 165

    QStringList validationErrors;
166 167
};

168 169 170
class UpdateParameters
{
public:
171 172
    UpdateParameters(const QString &partialVariable = QString()) :
        partialVariable(partialVariable) {}
173

hjk's avatar
hjk committed
174
    QStringList partialVariables() const
175
    {
hjk's avatar
hjk committed
176
        QStringList result;
177 178 179 180 181
        if (!partialVariable.isEmpty())
            result.append(partialVariable);
        return result;
    }

hjk's avatar
hjk committed
182
    QString partialVariable;
183 184
};

185 186 187
class Location
{
public:
hjk's avatar
hjk committed
188 189 190
    Location() {}
    Location(quint64 address) { m_address = address; }
    Location(const QString &file) { m_fileName = file; }
191
    Location(const QString &file, int line, bool marker = true)
hjk's avatar
hjk committed
192
        { m_lineNumber = line; m_fileName = file; m_needsMarker = marker; }
Friedemann Kleint's avatar
Friedemann Kleint committed
193
    Location(const StackFrame &frame, bool marker = true);
194 195
    QString fileName() const { return m_fileName; }
    QString functionName() const { return m_functionName; }
196
    QString from() const { return m_from; }
197 198 199 200
    int lineNumber() const { return m_lineNumber; }
    void setNeedsRaise(bool on) { m_needsRaise = on; }
    void setNeedsMarker(bool on) { m_needsMarker = on; }
    void setFileName(const QString &fileName) { m_fileName = fileName; }
hjk's avatar
hjk committed
201
    void setUseAssembler(bool on) { m_hasDebugInfo = !on; }
202 203 204
    bool needsRaise() const { return m_needsRaise; }
    bool needsMarker() const { return m_needsMarker; }
    bool hasDebugInfo() const { return m_hasDebugInfo; }
205 206
    bool canBeDisassembled() const
        { return m_address != quint64(-1) || !m_functionName.isEmpty(); }
207 208 209
    quint64 address() const { return m_address; }

private:
hjk's avatar
hjk committed
210 211 212 213
    bool m_needsMarker = false;
    bool m_needsRaise = true;
    bool m_hasDebugInfo = true;
    int m_lineNumber = -1;
214 215
    QString m_fileName;
    QString m_functionName;
216
    QString m_from;
hjk's avatar
hjk committed
217
    quint64 m_address = 0;
218 219
};

220 221
enum LocationType { UnknownLocation, LocationByFile, LocationByAddress };

222 223 224
class ContextData
{
public:
225
    bool isValid() const { return type != UnknownLocation; }
226 227

public:
228
    LocationType type = UnknownLocation;
229
    QString fileName;
230 231
    int lineNumber = 0;
    quint64 address = 0;
232 233
};

hjk's avatar
hjk committed
234
class DebuggerEngine : public QObject
235 236 237 238
{
    Q_OBJECT

public:
239
    explicit DebuggerEngine();
240 241
    virtual ~DebuggerEngine();

242
    const DebuggerRunParameters &runParameters() const;
243

hjk's avatar
hjk committed
244
    virtual void setRunTool(DebuggerRunTool *runTool);
245
    DebuggerRunTool *runTool() const;
246 247 248

    void start();

249 250 251 252 253 254 255 256 257 258 259 260
    enum {
        // Remove need to qualify each use.
        NeedsTemporaryStop = DebuggerCommand::NeedsTemporaryStop,
        NeedsFullStop = DebuggerCommand::NeedsFullStop,
        Discardable = DebuggerCommand::Discardable,
        ConsoleCommand = DebuggerCommand::ConsoleCommand,
        NeedsFlush = DebuggerCommand::NeedsFlush,
        ExitRequest = DebuggerCommand::ExitRequest,
        RunRequest = DebuggerCommand::RunRequest,
        LosesChild = DebuggerCommand::LosesChild,
        RebuildBreakpointModel = DebuggerCommand::RebuildBreakpointModel,
        InUpdateLocals = DebuggerCommand::InUpdateLocals,
261
        NativeCommand = DebuggerCommand::NativeCommand,
262 263 264
        Silent = DebuggerCommand::Silent
    };

265
    virtual bool canHandleToolTip(const DebuggerToolTipContext &) const;
hjk's avatar
hjk committed
266 267 268 269
    virtual void expandItem(const QString &iname); // Called when item in tree gets expanded.
    virtual void updateItem(const QString &iname); // Called for fresh watch items.
    void updateWatchData(const QString &iname); // FIXME: Merge with above.
    virtual void selectWatchData(const QString &iname);
270

271
    virtual void prepareForRestart() {}
272

273
    virtual void watchPoint(const QPoint &pnt);
274
    virtual void runCommand(const DebuggerCommand &cmd);
hjk's avatar
hjk committed
275
    virtual void openMemoryView(const MemoryViewSetupData &data);
276 277
    virtual void fetchMemory(MemoryAgent *, quint64 addr, quint64 length);
    virtual void changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data);
278
    virtual void updateMemoryViews();
279
    virtual void openDisassemblerView(const Internal::Location &location);
280
    virtual void fetchDisassembler(Internal::DisassemblerAgent *);
281 282 283 284 285
    virtual void activateFrame(int index);

    virtual void reloadModules();
    virtual void examineModules();
    virtual void loadSymbols(const QString &moduleName);
286
    virtual void loadSymbolsForStack();
287 288
    virtual void loadAllSymbols();
    virtual void requestModuleSymbols(const QString &moduleName);
289
    virtual void requestModuleSections(const QString &moduleName);
290 291 292 293

    virtual void reloadRegisters();
    virtual void reloadSourceFiles();
    virtual void reloadFullStack();
294
    virtual void loadAdditionalQmlStack();
295
    virtual void reloadDebuggingHelpers();
hjk's avatar
hjk committed
296

hjk's avatar
hjk committed
297
    virtual void setRegisterValue(const QString &name, const QString &value);
298
    virtual void addOptionPages(QList<Core::IOptionsPage*> *) const;
299
    virtual bool hasCapability(unsigned cap) const = 0;
hjk's avatar
hjk committed
300
    virtual void debugLastCommand() {}
hjk's avatar
hjk committed
301

302
    virtual bool isSynchronous() const;
hjk's avatar
hjk committed
303 304
    virtual QString qtNamespace() const;
    void setQtNamespace(const QString &ns);
hjk's avatar
hjk committed
305

306 307
    virtual void createSnapshot();
    virtual void updateAll();
308
    virtual void updateLocals();
hjk's avatar
hjk committed
309

hjk's avatar
hjk committed
310 311
    virtual bool stateAcceptsBreakpointChanges() const { return true; }
    virtual void attemptBreakpointSynchronization();
312 313 314 315
    virtual bool acceptsBreakpoint(Breakpoint bp) const = 0;
    virtual void insertBreakpoint(Breakpoint bp);  // FIXME: make pure
    virtual void removeBreakpoint(Breakpoint bp);  // FIXME: make pure
    virtual void changeBreakpoint(Breakpoint bp);  // FIXME: make pure
hjk's avatar
hjk committed
316

317
    virtual bool acceptsDebuggerCommands() const { return true; }
hjk's avatar
hjk committed
318 319
    virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);

320
    virtual void assignValueInDebugger(WatchItem *item,
hjk's avatar
hjk committed
321
        const QString &expr, const QVariant &value);
hjk's avatar
hjk committed
322
    virtual void selectThread(Internal::ThreadId threadId) = 0;
323

324 325 326 327 328 329 330
    virtual Internal::ModulesHandler *modulesHandler() const;
    virtual Internal::RegisterHandler *registerHandler() const;
    virtual Internal::StackHandler *stackHandler() const;
    virtual Internal::ThreadsHandler *threadsHandler() const;
    virtual Internal::WatchHandler *watchHandler() const;
    virtual Internal::SourceFilesHandler *sourceFilesHandler() const;
    virtual Internal::BreakHandler *breakHandler() const;
331

332 333 334 335
    virtual QAbstractItemModel *modulesModel() const;
    virtual QAbstractItemModel *registerModel() const;
    virtual QAbstractItemModel *stackModel() const;
    virtual QAbstractItemModel *threadsModel() const;
hjk's avatar
hjk committed
336
    virtual QAbstractItemModel *watchModel() const;
337
    virtual QAbstractItemModel *sourceFilesModel() const;
338

339
    void progressPing();
340
    void handleFinished();
341
    void handleStartFailed();
342 343 344 345
    bool debuggerActionsEnabled() const;
    static bool debuggerActionsEnabled(DebuggerState state);

    DebuggerState state() const;
346
    bool isDying() const;
347

hjk's avatar
hjk committed
348
    static QString stateName(int s);
349

350
    void notifyInferiorPid(const Utils::ProcessHandle &pid);
351 352
    qint64 inferiorPid() const;
    bool isReverseDebugging() const;
353
    void handleCommand(int role, const QVariant &value);
354

355
    // Convenience
356
    Q_SLOT virtual void showMessage(const QString &msg, int channel = LogDebug,
357
        int timeout = -1) const;
Friedemann Kleint's avatar
Friedemann Kleint committed
358
    Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
359

360
    virtual void resetLocation();
361
    virtual void gotoLocation(const Internal::Location &location);
hjk's avatar
hjk committed
362
    virtual void quitDebugger(); // called when pressing the stop button
hjk's avatar
hjk committed
363 364

    void abortDebugger(); // called from the debug menu action
365

366
    void updateViews();
hjk's avatar
x  
hjk committed
367
    bool isSlaveEngine() const;
368
    bool isMasterEngine() const;
hjk's avatar
hjk committed
369
    DebuggerEngine *masterEngine() const;
370
    virtual DebuggerEngine *activeEngine() { return this; }
371
    virtual DebuggerEngine *cppEngine() { return 0; }
372

373
    virtual bool canDisplayTooltip() const;
374

375 376
    virtual void notifyInferiorIll();

377
    QString toFileInProject(const QUrl &fileUrl);
378 379
    void updateBreakpointMarker(const Breakpoint &bp);
    void removeBreakpointMarker(const Breakpoint &bp);
380

381
    QString expand(const QString &string) const;
382
    QString nativeStartupCommands() const;
383

384
protected:
385 386 387
    // The base notify*() function implementation should be sufficient
    // in most cases, but engines are free to override them to do some
    // engine specific cleanup like stopping timers etc.
388 389 390
    void notifyEngineSetupOk();
    void notifyEngineSetupFailed();
    void notifyEngineRunFailed();
391

392 393
    void notifyInferiorSetupOk();
    void notifyInferiorSetupFailed();
hjk's avatar
hjk committed
394

395 396 397
    void notifyEngineRunAndInferiorRunOk();
    void notifyEngineRunAndInferiorStopOk();
    void notifyEngineRunOkAndInferiorUnrunnable(); // Called by CoreAdapter.
hjk's avatar
hjk committed
398 399

    // Use notifyInferiorRunRequested() plus notifyInferiorRunOk() instead.
400
    // void notifyInferiorSpontaneousRun();
hjk's avatar
hjk committed
401

402 403 404
    void notifyInferiorRunRequested();
    void notifyInferiorRunOk();
    void notifyInferiorRunFailed();
hjk's avatar
hjk committed
405

406 407 408
    void notifyInferiorStopOk();
    void notifyInferiorSpontaneousStop();
    void notifyInferiorStopFailed();
hjk's avatar
hjk committed
409

410 411 412 413
    public: // FIXME: Remove, currently needed for Android.
    void notifyInferiorExited();

    protected:
414 415
    void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
                                       const QString &backendName);
hjk's avatar
hjk committed
416

417 418
    virtual void setState(DebuggerState state, bool forced = false);

419 420
    void notifyInferiorShutdownOk();
    void notifyInferiorShutdownFailed();
hjk's avatar
hjk committed
421

422 423 424
    void notifyEngineSpontaneousShutdown();
    void notifyEngineShutdownOk();
    void notifyEngineShutdownFailed();
425

426
    void notifyEngineIll();
427

hjk's avatar
hjk committed
428 429 430 431 432
    virtual void setupEngine() = 0;
    virtual void setupInferior() = 0;
    virtual void runEngine() = 0;
    virtual void shutdownInferior() = 0;
    virtual void shutdownEngine() = 0;
433
    virtual void resetInferior() {}
hjk's avatar
hjk committed
434

hjk's avatar
hjk committed
435 436
    virtual void detachDebugger();
    virtual void executeStep();
hjk's avatar
hjk committed
437
    virtual void executeStepOut();
hjk's avatar
hjk committed
438 439 440 441 442 443 444 445 446
    virtual void executeNext();
    virtual void executeStepI();
    virtual void executeNextI();
    virtual void executeReturn();

    virtual void continueInferior();
    virtual void interruptInferior();
    virtual void requestInterruptInferior();

447
    virtual void executeRunToLine(const Internal::ContextData &data);
hjk's avatar
hjk committed
448
    virtual void executeRunToFunction(const QString &functionName);
449
    virtual void executeJumpToLine(const Internal::ContextData &data);
hjk's avatar
hjk committed
450 451 452 453

    virtual void frameUp();
    virtual void frameDown();

hjk's avatar
hjk committed
454 455
    virtual void abortDebuggerProcess() {} // second attempt

456 457
    virtual void doUpdateLocals(const UpdateParameters &params);

458
    void setMasterEngine(DebuggerEngine *masterEngine);
459

460
    TerminalRunner *terminal() const;
hjk's avatar
hjk committed
461

462 463
    static QString msgStopped(const QString &reason = QString());
    static QString msgStoppedBySignal(const QString &meaning, const QString &name);
hjk's avatar
hjk committed
464 465
    static QString msgStoppedByException(const QString &description,
        const QString &threadId);
466
    static QString msgInterrupted();
467
    bool showStoppedBySignalMessageBox(const QString meaning, QString name);
468 469
    void showStoppedByExceptionMessageBox(const QString &description);

470 471 472
    bool isStateDebugging() const;
    void setStateDebugging(bool on);

473 474 475 476
    virtual void setupSlaveEngine();
    virtual void runSlaveEngine();
    virtual void shutdownSlaveEngine();

477 478 479
    virtual void slaveEngineStateChanged(DebuggerEngine *engine,
        DebuggerState state);

480
    void updateLocalsView(const GdbMi &all);
481
    void checkState(DebuggerState state, const char *file, int line);
482 483 484
    bool isNativeMixedEnabled() const;
    bool isNativeMixedActive() const;
    bool isNativeMixedActiveFrame() const;
485

hjk's avatar
hjk committed
486
private:
487
    // Wrapper engine needs access to state of its subengines.
hjk's avatar
hjk committed
488 489
    friend class QmlCppEngine;
    friend class DebuggerPluginPrivate;
hjk's avatar
hjk committed
490

hjk's avatar
hjk committed
491
    friend class DebuggerEnginePrivate;
hjk's avatar
hjk committed
492
    friend class LocationMark;
493 494 495
    DebuggerEnginePrivate *d;
};

hjk's avatar
hjk committed
496 497 498 499
class LocationMark : public TextEditor::TextMark
{
public:
    LocationMark(DebuggerEngine *engine, const QString &file, int line);
500
    void removedFromEditor() override { updateLineNumber(0); }
hjk's avatar
hjk committed
501 502

private:
503 504
    bool isDraggable() const override;
    void dragToLine(int line) override;
hjk's avatar
hjk committed
505 506 507 508

    QPointer<DebuggerEngine> m_engine;
};

hjk's avatar
hjk committed
509
} // namespace Internal
510 511
} // namespace Debugger

512
Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters)
513
Q_DECLARE_METATYPE(Debugger::Internal::ContextData)