OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / gdb / gdbengine.h
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #ifndef DEBUGGER_GDBENGINE_H
35 #define DEBUGGER_GDBENGINE_H
36
37 #include "debuggerengine.h"
38
39 #include "stackframe.h"
40 #include "watchutils.h"
41
42 #include <QtCore/QByteArray>
43 #include <QtCore/QProcess>
44 #include <QtCore/QHash>
45 #include <QtCore/QMap>
46 #include <QtCore/QMultiMap>
47 #include <QtCore/QObject>
48 #include <QtCore/QPoint>
49 #include <QtCore/QSet>
50 #include <QtCore/QTextCodec>
51 #include <QtCore/QTime>
52 #include <QtCore/QTimer>
53 #include <QtCore/QVariant>
54
55
56 namespace Debugger {
57 namespace Internal {
58
59 class AbstractGdbAdapter;
60 class AbstractGdbProcess;
61 class GdbResponse;
62 class GdbMi;
63
64 class WatchData;
65 class DisassemblerAgentCookie;
66 class DisassemblerLines;
67
68 class AttachGdbAdapter;
69 class CoreGdbAdapter;
70 class LocalPlainGdbAdapter;
71 class RemoteGdbServerAdapter;
72 class TrkGdbAdapter;
73
74 enum DebuggingHelperState
75 {
76     DebuggingHelperUninitialized,
77     DebuggingHelperLoadTried,
78     DebuggingHelperAvailable,
79     DebuggingHelperUnavailable
80 };
81
82
83 class GdbEngine : public Debugger::DebuggerEngine
84 {
85     Q_OBJECT
86
87 public:
88     explicit GdbEngine(const DebuggerStartParameters &startParameters);
89     ~GdbEngine();
90     AbstractGdbAdapter *gdbAdapter() const { return m_gdbAdapter; }
91
92 private:
93     friend class AbstractGdbAdapter;
94     friend class AbstractPlainGdbAdapter;
95     friend class AttachGdbAdapter;
96     friend class CoreGdbAdapter;
97     friend class LocalPlainGdbAdapter;
98     friend class TermGdbAdapter;
99     friend class RemoteGdbServerAdapter;
100     friend class RemotePlainGdbAdapter;
101     friend class TrkGdbAdapter;
102     friend class TcfTrkGdbAdapter;
103
104 private: ////////// General Interface //////////
105
106     virtual void setupEngine();
107     virtual void setupInferior();
108     virtual void runEngine();
109
110     virtual unsigned debuggerCapabilities() const;
111     virtual void detachDebugger();
112     virtual void shutdownEngine();
113     virtual void shutdownInferior();
114     virtual void notifyInferiorSetupFailed();
115
116     virtual void executeDebuggerCommand(const QString &command);
117     virtual QByteArray qtNamespace() const { return m_dumperHelper.qtNamespace(); }
118
119 private: ////////// General State //////////
120
121     DebuggerStartMode startMode() const;
122     Q_SLOT void reloadLocals();
123
124     bool m_registerNamesListed;
125
126 private: ////////// Gdb Process Management //////////
127
128     AbstractGdbAdapter *createAdapter();
129     bool startGdb(const QStringList &args = QStringList(),
130                   const QString &gdb = QString(),
131                   const QString &settingsIdHint = QString());
132     void handleInferiorShutdown(const GdbResponse &response);
133     void handleGdbExit(const GdbResponse &response);
134     void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
135     void handleRemoteSetupFailed(const QString &message);
136
137     void handleAdapterStarted();
138     void defaultInferiorShutdown(const char *cmd);
139     void loadPythonDumpers();
140     void pythonDumpersFailed();
141
142     // Something went wrong with the adapter *before* adapterStarted() was emitted.
143     // Make sure to clean up everything before emitting this signal.
144     void handleAdapterStartFailed(const QString &msg,
145         const QString &settingsIdHint = QString());
146
147     // This triggers the initial breakpoint synchronization and causes
148     // finishInferiorSetup() being called once done.
149     void handleInferiorPrepared();
150     // This notifies the base of a successful inferior setup.
151     void finishInferiorSetup();
152
153     // The adapter is still running just fine, but it failed to acquire a debuggee.
154     void notifyInferiorSetupFailed(const QString &msg);
155
156     void notifyAdapterShutdownOk();
157     void notifyAdapterShutdownFailed();
158
159     // Something went wrong with the adapter *after* adapterStarted() was emitted.
160     // Make sure to clean up everything before emitting this signal.
161     void handleAdapterCrashed(const QString &msg);
162
163 private slots:
164     void handleGdbFinished(int, QProcess::ExitStatus status);
165     void handleGdbError(QProcess::ProcessError error);
166     void readGdbStandardOutput();
167     void readGdbStandardError();
168     void readDebugeeOutput(const QByteArray &data);
169
170 private:
171     QTextCodec *m_outputCodec;
172     QTextCodec::ConverterState m_outputCodecState;
173
174     QByteArray m_inbuffer;
175     bool m_busy;
176
177     AbstractGdbAdapter *m_gdbAdapter;
178
179     // Name of the convenience variable containing the last
180     // known function return value.
181     QByteArray m_resultVarName;
182
183 private: ////////// Gdb Command Management //////////
184
185     public: // Otherwise the Qt flag macros are unhappy.
186     enum GdbCommandFlag {
187         NoFlags = 0,
188         // The command needs a stopped inferior.
189         NeedsStop = 1,
190         // No need to wait for the reply before continuing inferior.
191         Discardable = 2,
192         // Trigger watch model rebuild when no such commands are pending anymore.
193         RebuildWatchModel = 4,
194         WatchUpdate = Discardable | RebuildWatchModel,
195         // We can live without receiving an answer.
196         NonCriticalResponse = 8,
197         // Callback expects GdbResultRunning instead of GdbResultDone.
198         RunRequest = 16,
199         // Callback expects GdbResultExit instead of GdbResultDone.
200         ExitRequest = 32,
201         // Auto-set inferior shutdown related states.
202         LosesChild = 64,
203         // Trigger breakpoint model rebuild when no such commands are pending anymore.
204         RebuildBreakpointModel = 128,
205         // This command needs to be send immediately.
206         Immediate = 256,
207         // This is a command that needs to be wrapped into -interpreter-exec console
208         ConsoleCommand = 512
209     };
210     Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
211     private:
212
213     typedef void (GdbEngine::*GdbCommandCallback)
214         (const GdbResponse &response);
215     typedef void (AbstractGdbAdapter::*AdapterCallback)
216         (const GdbResponse &response);
217
218     struct GdbCommand
219     {
220         GdbCommand()
221             : flags(0), callback(0), adapterCallback(0), callbackName(0)
222         {}
223
224         int flags;
225         GdbCommandCallback callback;
226         AdapterCallback adapterCallback;
227         const char *callbackName;
228         QByteArray command;
229         QVariant cookie;
230         QTime postTime;
231     };
232
233     // Type and cookie are sender-internal data, opaque for the "event
234     // queue". resultNeeded == true increments m_pendingResults on
235     // send and decrements on receipt, effectively preventing
236     // watch model updates before everything is finished.
237     void flushCommand(const GdbCommand &cmd);
238     void postCommand(const QByteArray &command,
239                      GdbCommandFlags flags,
240                      GdbCommandCallback callback = 0,
241                      const char *callbackName = 0,
242                      const QVariant &cookie = QVariant());
243     void postCommand(const QByteArray &command,
244                      GdbCommandCallback callback = 0,
245                      const char *callbackName = 0,
246                      const QVariant &cookie = QVariant());
247     void postCommand(const QByteArray &command,
248                      AdapterCallback callback,
249                      const char *callbackName,
250                      const QVariant &cookie = QVariant());
251     void postCommand(const QByteArray &command,
252                      GdbCommandFlags flags,
253                      AdapterCallback callback,
254                      const char *callbackName,
255                      const QVariant &cookie = QVariant());
256     void postCommandHelper(const GdbCommand &cmd);
257     void flushQueuedCommands();
258     Q_SLOT void commandTimeout();
259     void setTokenBarrier();
260
261     QHash<int, GdbCommand> m_cookieForToken;
262     int commandTimeoutTime() const;
263     QTimer m_commandTimer;
264
265     QByteArray m_pendingConsoleStreamOutput;
266     QByteArray m_pendingLogStreamOutput;
267
268     // This contains the first token number for the current round
269     // of evaluation. Responses with older tokens are considers
270     // out of date and discarded.
271     int m_oldestAcceptableToken;
272
273     int m_pendingWatchRequests; // Watch updating commands in flight
274     int m_pendingBreakpointRequests; // Watch updating commands in flight
275
276     typedef void (GdbEngine::*CommandsDoneCallback)();
277     // This function is called after all previous responses have been received.
278     CommandsDoneCallback m_commandsDoneCallback;
279
280     QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
281     int gdbVersion() const { return m_gdbVersion; }
282
283 private: ////////// Gdb Output, State & Capability Handling //////////
284
285     void handleResponse(const QByteArray &buff);
286     void handleStopResponse(const GdbMi &data);
287     void handleResultRecord(GdbResponse *response);
288     void handleStop0(const GdbMi &data);
289     void handleStop1(const GdbResponse &response);
290     void handleStop1(const GdbMi &data);
291     Q_SLOT void handleStop2();
292     StackFrame parseStackFrame(const GdbMi &mi, int level);
293     void resetCommandQueue();
294
295     bool isSynchronous() const { return hasPython(); }
296     virtual bool hasPython() const;
297     bool supportsThreads() const;
298
299     // Gdb initialization sequence
300     void handleShowVersion(const GdbResponse &response);
301     void handleHasPython(const GdbResponse &response);
302
303     int m_gdbVersion; // 6.8.0 is 60800
304     int m_gdbBuildVersion; // MAC only?
305     bool m_isMacGdb;
306     bool m_hasPython;
307     bool m_hasInferiorThreadList;
308
309 private: ////////// Inferior Management //////////
310
311     // This should be always the last call in a function.
312     bool stateAcceptsBreakpointChanges() const;
313     bool acceptsBreakpoint(BreakpointId id) const;
314     void insertBreakpoint(BreakpointId id);
315     void removeBreakpoint(BreakpointId id);
316     void changeBreakpoint(BreakpointId id);
317
318     void executeStep();
319     void executeStepOut();
320     void executeNext();
321     void executeStepI();
322     void executeNextI();
323
324     void continueInferiorInternal();
325     void autoContinueInferior();
326     void continueInferior();
327     void interruptInferior();
328     void interruptInferiorTemporarily();
329
330     void executeRunToLine(const QString &fileName, int lineNumber);
331     void executeRunToFunction(const QString &functionName);
332     void executeJumpToLine(const QString &fileName, int lineNumber);
333     void executeReturn();
334
335     void handleExecuteContinue(const GdbResponse &response);
336     void handleExecuteStep(const GdbResponse &response);
337     void handleExecuteNext(const GdbResponse &response);
338     void handleExecuteReturn(const GdbResponse &response);
339     void handleExecuteJumpToLine(const GdbResponse &response);
340     void handleExecuteRunToLine(const GdbResponse &response);
341
342     void maybeHandleInferiorPidChanged(const QString &pid);
343     void handleInfoProc(const GdbResponse &response);
344
345     QByteArray m_entryPoint;
346
347 private: ////////// View & Data Stuff //////////
348
349     void selectThread(int index);
350     void activateFrame(int index);
351
352     //
353     // Breakpoint specific stuff
354     //
355     void handleBreakList(const GdbResponse &response);
356     void handleBreakList(const GdbMi &table);
357     void handleBreakIgnore(const GdbResponse &response);
358     void handleBreakDisable(const GdbResponse &response);
359     void handleBreakEnable(const GdbResponse &response);
360     void handleBreakInsert1(const GdbResponse &response);
361     void handleBreakInsert2(const GdbResponse &response);
362     void handleTraceInsert2(const GdbResponse &response);
363     void handleBreakCondition(const GdbResponse &response);
364     void handleBreakInfo(const GdbResponse &response);
365     void handleBreakThreadSpec(const GdbResponse &response);
366     void handleWatchInsert(const GdbResponse &response);
367     void handleInfoLine(const GdbResponse &response);
368     void extractDataFromInfoBreak(const QString &output, BreakpointId);
369     void updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt);
370     QByteArray breakpointLocation(BreakpointId id);
371     QString breakLocation(const QString &file) const;
372     void reloadBreakListInternal();
373     void attemptAdjustBreakpointLocation(BreakpointId id);
374
375     //
376     // Modules specific stuff
377     //
378     void loadSymbols(const QString &moduleName);
379     void loadAllSymbols();
380     void loadSymbolsForStack();
381     void requestModuleSymbols(const QString &moduleName);
382     void reloadModules();
383     void examineModules();
384     void reloadModulesInternal();
385     void handleModulesList(const GdbResponse &response);
386     void handleShowModuleSymbols(const GdbResponse &response);
387
388     bool m_modulesListOutdated;
389
390     //
391     // Snapshot specific stuff
392     //
393     virtual void createSnapshot();
394     void handleMakeSnapshot(const GdbResponse &response);
395
396     //
397     // Register specific stuff
398     //
399     Q_SLOT void reloadRegisters();
400     void setRegisterValue(int nr, const QString &value);
401     void handleRegisterListNames(const GdbResponse &response);
402     void handleRegisterListValues(const GdbResponse &response);
403
404     //
405     // Disassembler specific stuff
406     //
407     void fetchDisassembler(DisassemblerAgent *agent);
408     void fetchDisassemblerByAddress(const DisassemblerAgentCookie &ac,
409         bool useMixedMode);
410     void fetchDisassemblerByCli(const DisassemblerAgentCookie &ac,
411         bool useMixedMode);
412     void fetchDisassemblerByAddressCli(const DisassemblerAgentCookie &ac);
413     void handleFetchDisassemblerByCli(const GdbResponse &response);
414     void handleFetchDisassemblerByLine(const GdbResponse &response);
415     void handleFetchDisassemblerByAddress1(const GdbResponse &response);
416     void handleFetchDisassemblerByAddress0(const GdbResponse &response);
417     DisassemblerLines parseDisassembler(const GdbMi &lines);
418
419     //
420     // Source file specific stuff
421     //
422     void reloadSourceFiles();
423     void reloadSourceFilesInternal();
424     void handleQuerySources(const GdbResponse &response);
425
426     QString fullName(const QString &fileName);
427     QString cleanupFullName(const QString &fileName);
428
429     // awful hack to keep track of used files
430     QMap<QString, QString> m_shortToFullName;
431     QMap<QString, QString> m_fullToShortName;
432
433     void invalidateSourcesList();
434     bool m_sourcesListOutdated;
435     bool m_sourcesListUpdating;
436     bool m_breakListOutdated;
437
438     //
439     // Stack specific stuff
440     //
441     void updateAll();
442         void updateAllClassic();
443         void updateAllPython();
444     void handleStackListFrames(const GdbResponse &response);
445     void handleStackSelectThread(const GdbResponse &response);
446     void handleStackSelectFrame(const GdbResponse &response);
447     void handleThreadListIds(const GdbResponse &response);
448     void handleThreadInfo(const GdbResponse &response);
449     void handleThreadNames(const GdbResponse &response);
450     Q_SLOT void reloadStack(bool forceGotoLocation);
451     Q_SLOT virtual void reloadFullStack();
452     int currentFrame() const;
453
454     QList<GdbMi> m_currentFunctionArgs;
455
456     //
457     // Watch specific stuff
458     //
459     virtual void setToolTipExpression(const QPoint &mousePos,
460         TextEditor::ITextEditor *editor, int cursorPos);
461
462     virtual void assignValueInDebugger(const WatchData *data,
463         const QString &expr, const QVariant &value);
464
465     virtual void fetchMemory(MemoryAgent *agent, QObject *token,
466         quint64 addr, quint64 length);
467     void handleFetchMemory(const GdbResponse &response);
468
469     virtual void watchPoint(const QPoint &);
470     void handleWatchPoint(const GdbResponse &response);
471
472     // FIXME: BaseClass. called to improve situation for a watch item
473     void updateSubItemClassic(const WatchData &data);
474
475     void virtual updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
476     Q_SLOT void updateWatchDataHelper(const WatchData &data);
477     void rebuildWatchModel();
478     bool showToolTip();
479
480     void insertData(const WatchData &data);
481     void sendWatchParameters(const QByteArray &params0);
482     void createGdbVariableClassic(const WatchData &data);
483
484     void runDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
485     void runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
486     bool hasDebuggingHelperForType(const QByteArray &type) const;
487
488     void handleVarListChildrenClassic(const GdbResponse &response);
489     void handleVarListChildrenHelperClassic(const GdbMi &child,
490         const WatchData &parent);
491     void handleVarCreate(const GdbResponse &response);
492     void handleVarAssign(const GdbResponse &response);
493     void handleEvaluateExpressionClassic(const GdbResponse &response);
494     void handleQueryDebuggingHelperClassic(const GdbResponse &response);
495     void handleDebuggingHelperValue2Classic(const GdbResponse &response);
496     void handleDebuggingHelperValue3Classic(const GdbResponse &response);
497     void handleDebuggingHelperEditValue(const GdbResponse &response);
498     void handleDebuggingHelperSetup(const GdbResponse &response);
499     void handleDebuggingHelperVersionCheckClassic(const GdbResponse &response);
500     void handleDetach(const GdbResponse &response);
501
502     Q_SLOT void createFullBacktrace();
503     void handleCreateFullBacktrace(const GdbResponse &response);
504
505     void updateLocals(const QVariant &cookie = QVariant());
506         void updateLocalsClassic(const QVariant &cookie);
507         void updateLocalsPython(bool tryPartial, const QByteArray &varList);
508             void handleStackFramePython(const GdbResponse &response);
509
510     void handleStackListLocalsClassic(const GdbResponse &response);
511     void handleStackListLocalsPython(const GdbResponse &response);
512
513     WatchData localVariable(const GdbMi &item,
514                             const QStringList &uninitializedVariables,
515                             QMap<QByteArray, int> *seen);
516     void setLocals(const QList<GdbMi> &locals);
517     void handleStackListArgumentsClassic(const GdbResponse &response);
518
519     QSet<QByteArray> m_processedNames;
520
521     //
522     // Dumper Management
523     //
524     bool checkDebuggingHelpersClassic();
525     void setDebuggingHelperStateClassic(DebuggingHelperState);
526     void tryLoadDebuggingHelpersClassic();
527     void tryQueryDebuggingHelpersClassic();
528     Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
529
530     DebuggingHelperState m_debuggingHelperState;
531     QtDumperHelper m_dumperHelper;
532     QString m_gdb;
533
534     //
535     // Convenience Functions
536     //
537     QString errorMessage(QProcess::ProcessError error);
538     AbstractGdbProcess *gdbProc() const;
539     void showExecutionError(const QString &message);
540
541     void removeTooltip();
542     static QByteArray tooltipIName(const QString &exp);
543     QString m_toolTipExpression;
544     QPoint m_toolTipPos;
545
546     // For short-circuiting stack and thread list evaluation.
547     bool m_stackNeeded;
548     int m_currentThreadId;
549
550     // HACK:
551     StackFrame m_targetFrame;
552     QByteArray m_currentThread;
553 };
554
555 } // namespace Internal
556 } // namespace Debugger
557
558 Q_DECLARE_OPERATORS_FOR_FLAGS(Debugger::Internal::GdbEngine::GdbCommandFlags)
559
560 #endif // DEBUGGER_GDBENGINE_H