cdbengine.h 11.5 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
Eike Ziller's avatar
Eike Ziller committed
3
4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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
Eike Ziller's avatar
Eike Ziller committed
12
13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** 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
**
Eike Ziller's avatar
Eike Ziller committed
25
26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company 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
****************************************************************************/
30
31
32
33

#ifndef DEBUGGER_CDBENGINE_H
#define DEBUGGER_CDBENGINE_H

34
#include <debugger/debuggerengine.h>
35
#include <debugger/breakhandler.h>
36

37
38
#include <projectexplorer/devicesupport/idevice.h>

39
40
41
#include <QSharedPointer>
#include <QProcess>
#include <QMap>
42
#include <QVariant>
43
#include <QTime>
44

45
46
#include <functional>

47
namespace Utils { class ConsoleProcess; }
48
namespace Debugger {
49
namespace Internal {
50

51
class DisassemblerAgent;
52
class CdbCommand;
53
struct MemoryViewCookie;
54
class ByteArrayInputStream;
55
class GdbMi;
56

hjk's avatar
hjk committed
57
class CdbEngine : public DebuggerEngine
58
59
60
61
{
    Q_OBJECT

public:
62
    typedef QSharedPointer<CdbCommand> CdbCommandPtr;
63
    typedef std::function<void(const DebuggerResponse &)> CommandHandler;
64

65
    CdbEngine(const DebuggerRunParameters &sp);
66
    ~CdbEngine();
67

68
69
    // Factory function that returns 0 if the debug engine library cannot be found.

70
71
72
73
74
75
76
77
78
79
80
81
82
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
    bool canHandleToolTip(const DebuggerToolTipContext &context) const override;

    DebuggerEngine *cppEngine() override { return this; }

    void setupEngine() override;
    void setupInferior() override;
    void runEngine() override;
    void shutdownInferior() override;
    void shutdownEngine() override;
    void abortDebugger() override;
    void detachDebugger() override;
    bool hasCapability(unsigned cap) const override;
    void watchPoint(const QPoint &) override;
    void setRegisterValue(const QByteArray &name, const QString &value) override;

    void executeStep() override;
    void executeStepOut() override;
    void executeNext() override;
    void executeStepI() override;
    void executeNextI() override;

    void continueInferior() override;
    void interruptInferior() override;

    void executeRunToLine(const ContextData &data) override;
    void executeRunToFunction(const QString &functionName) override;
    void executeJumpToLine(const ContextData &data) override;
    void assignValueInDebugger(WatchItem *w, const QString &expr, const QVariant &value) override;
    void executeDebuggerCommand(const QString &command, DebuggerLanguages languages) override;

    void activateFrame(int index) override;
    void selectThread(ThreadId threadId) override;

    bool stateAcceptsBreakpointChanges() const override;
    bool acceptsBreakpoint(Breakpoint bp) const override;
    void attemptBreakpointSynchronization() override;

    void fetchDisassembler(DisassemblerAgent *agent) override;
    void fetchMemory(MemoryAgent *, QObject *, quint64 addr, quint64 length) override;
    void changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr,
                      const QByteArray &data) override;

    void reloadModules() override;
    void loadSymbols(const QString &moduleName) override;
    void loadAllSymbols() override;
    void requestModuleSymbols(const QString &moduleName) override;

    void reloadRegisters() override;
    void reloadSourceFiles() override;
    void reloadFullStack() override;
    void loadAdditionalQmlStack() override;
David Schulz's avatar
David Schulz committed
121
    void listBreakpoints();
122

123
    static QString extensionLibraryName(bool is64Bit);
124
125
126
127
128
129

private slots:
    void readyReadStandardOut();
    void readyReadStandardError();
    void processError();
    void processFinished();
130
    void postCommand(const DebuggerCommand &cmd);
131
    void operateByInstructionTriggered(bool);
132
    void verboseLogTriggered(bool);
133

134
    void consoleStubError(const QString &);
135
136
137
    void consoleStubProcessStarted();
    void consoleStubExited();

138
139
    void createFullBacktrace();

140
141
    void handleDoInterruptInferior(const QString &errorMessage);

142
private:
143
    typedef QHash<BreakpointModelId, BreakpointResponse> PendingBreakPointMap;
144
145
146
147
148
149
150
151
    typedef QPair<QString, QString> SourcePathMapping;
    struct NormalizedSourceFileName // Struct for caching mapped/normalized source files.
    {
        NormalizedSourceFileName(const QString &fn = QString(), bool e = false) : fileName(fn), exists(e) {}

        QString fileName;
        bool exists;
    };
152

153
154
155
156
    enum SpecialStopMode
    {
        NoSpecialStop,
        SpecialStopSynchronizeBreakpoints,
157
158
        SpecialStopGetWidgetAt,
        CustomSpecialStop // Associated with m_specialStopData, handleCustomSpecialStop()
159
    };
160
161
    enum ParseStackResultFlags // Flags returned by parseStackTrace
    {
162
        ParseStackStepInto = 1, // Need to execute a step, hit on a call frame in "Step into"
163
164
        ParseStackStepOut = 2, // Need to step out, hit on a frame without debug information
        ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode
165
    };
166
167
168
169
170
    enum CommandFlags {
        NoCallBack = 0,
        BuiltinCommand,
        ExtensionCommand,
    };
171

172
    bool startConsole(const DebuggerRunParameters &sp, QString *errorMessage);
173
    void init();
174
    unsigned examineStopReason(const GdbMi &stopReason, QString *message,
175
176
177
                               QString *exceptionBoxMessage,
                               bool conditionalBreakPointTriggered = false);
    void processStop(const GdbMi &stopReason, bool conditionalBreakPointTriggered = false);
178
    bool commandsPending() const;
179
180
    void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message);
    bool doSetupEngine(QString *errorMessage);
181
    bool launchCDB(const DebuggerRunParameters &sp, QString *errorMessage);
182
183
184
    void handleSessionAccessible(unsigned long cdbExState);
    void handleSessionInaccessible(unsigned long cdbExState);
    void handleSessionIdle(const QByteArray &message);
185
    void doInterruptInferior(SpecialStopMode sm);
186
    void doInterruptInferiorCustomSpecialStop(const QVariant &v);
187
188
189
    void doContinueInferior();
    inline void parseOutputLine(QByteArray line);
    inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
190
    bool canInterruptInferior() const;
191
    void syncOperateByInstruction(bool operateByInstruction);
192
    void syncVerboseLog(bool verboseLog);
193
    void postWidgetAtCommand();
194
    void handleCustomSpecialStop(const QVariant &v);
195
    void postFetchMemory(const MemoryViewCookie &c);
196
    inline void postDisassemblerCommand(quint64 address, DisassemblerAgent *agent);
197
    void postDisassemblerCommand(quint64 address, quint64 endAddress,
198
                                 DisassemblerAgent *agent);
199
    void postResolveSymbol(const QString &module, const QString &function,
200
                           DisassemblerAgent *agent);
201
    // Builtin commands
202
203
204
205
206
207
    void handleStackTrace(const DebuggerResponse &);
    void handleRegisters(const DebuggerResponse &);
    void handleDisassembler(const DebuggerResponse &, DisassemblerAgent *agent);
    void handleJumpToLineAddressResolution(const DebuggerResponse &response, const ContextData &context);
    void handleExpression(const DebuggerResponse &command, BreakpointModelId id, const GdbMi &stopReason);
    void handleResolveSymbol(const DebuggerResponse &command, const QString &symbol, DisassemblerAgent *agent);
208
    void handleResolveSymbolHelper(const QList<quint64> &addresses, DisassemblerAgent *agent);
209
210
211
212
    void handleBreakInsert(const DebuggerResponse &response, const BreakpointModelId &bpId);
    void handleCheckWow64(const DebuggerResponse &response, const GdbMi &stack);
    void ensureUsing32BitStackInWow64(const DebuggerResponse &response, const GdbMi &stack);
    void handleSwitchWow64Stack(const DebuggerResponse &response);
213
    void jumpToAddress(quint64 address);
214
    void handleCreateFullBackTrace(const DebuggerResponse &response);
215

216
    // Extension commands
217
218
219
220
221
222
223
224
225
226
    void handleThreads(const DebuggerResponse &response);
    void handlePid(const DebuggerResponse &response);
    void handleLocals(const DebuggerResponse &response, bool partialUpdate);
    void handleExpandLocals(const DebuggerResponse &response);
    void handleRegistersExt(const DebuggerResponse &response);
    void handleModules(const DebuggerResponse &response);
    void handleMemory(const DebuggerResponse &response, const MemoryViewCookie &memViewCookie);
    void handleWidgetAt(const DebuggerResponse &response);
    void handleBreakPoints(const DebuggerResponse &response);
    void handleAdditionalQmlStack(const DebuggerResponse &response);
227
    NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
228
    void doUpdateLocals(const UpdateParameters &params) override;
229
    void updateAll() override;
230
    int elapsedLogTime() const;
231
    unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
232
    void mergeStartParametersSourcePathMap();
233
234
235
236

    const QByteArray m_tokenPrefix;

    QProcess m_process;
237
238
    QScopedPointer<Utils::ConsoleProcess> m_consoleStub;
    DebuggerStartMode m_effectiveStartMode;
239
    QByteArray m_outputBuffer;
240
    //! Debugger accessible (expecting commands)
241
242
    bool m_accessible;
    SpecialStopMode m_specialStopMode;
243
    ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
244
    int m_nextCommandToken;
245
    QHash<int, DebuggerCommand> m_commandForToken;
246
247
    QByteArray m_currentBuiltinResponse;
    int m_currentBuiltinResponseToken;
248
    QMap<QString, NormalizedSourceFileName> m_normalizedFileCache;
249
250
    const QByteArray m_extensionCommandPrefixBA; //!< Library name used as prefix
    bool m_operateByInstructionPending; //!< Creator operate by instruction action changed.
251
    bool m_operateByInstruction;
252
253
    bool m_verboseLogPending; //!< Creator verbose log action changed.
    bool m_verboseLog;
254
    bool m_hasDebuggee;
255
256
257
258
259
260
    enum Wow64State {
        wow64Uninitialized,
        noWow64Stack,
        wow64Stack32Bit,
        wow64Stack64Bit
    } m_wow64State;
261
262
    QTime m_logTime;
    mutable int m_elapsedLogTime;
263
    QByteArray m_extensionMessageBuffer;
264
    bool m_sourceStepInto;
265
266
    int m_watchPointX;
    int m_watchPointY;
267
    PendingBreakPointMap m_pendingBreakpointMap;
268
269
    PendingBreakPointMap m_insertSubBreakpointMap;
    PendingBreakPointMap m_pendingSubBreakpointMap;
270
    bool m_autoBreakPointCorrection;
271
    QHash<QString, QString> m_fileNameModuleHash;
272
    QMultiHash<QString, quint64> m_symbolAddressCache;
273
    bool m_ignoreCdbOutput;
274
    QVariantList m_customSpecialStopData;
275
    QList<SourcePathMapping> m_sourcePathMappings;
276
    QScopedPointer<GdbMi> m_coreStopReason;
277
278
};

279
} // namespace Internal
280
281
282
} // namespace Debugger

#endif // DEBUGGER_CDBENGINE_H