| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-01-11 16:28:15 +01:00
										 |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** No Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** This file contains pre-release code and may not be distributed. | 
					
						
							|  |  |  | ** You may use this file in accordance with the terms and conditions | 
					
						
							|  |  |  | ** contained in the Technology Preview License Agreement accompanying | 
					
						
							|  |  |  | ** this package. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							|  |  |  | ** General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ** packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							|  |  |  | ** rights.  These rights are described in the Nokia Qt LGPL Exception | 
					
						
							|  |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							|  |  |  | ** Nokia at qt-info@nokia.com. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 22:22:37 +02:00
										 |  |  | #define QT_NO_CAST_FROM_ASCII
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "gdbengine.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-10 10:14:23 +01:00
										 |  |  | #include "debuggerstartparameters.h"
 | 
					
						
							|  |  |  | #include "disassemblerlines.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-23 15:28:50 +02:00
										 |  |  | #include "attachgdbadapter.h"
 | 
					
						
							|  |  |  | #include "coregdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  | #include "localplaingdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-07 10:25:26 +02:00
										 |  |  | #include "termgdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  | #include "remotegdbserveradapter.h"
 | 
					
						
							|  |  |  | #include "remoteplaingdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-23 15:28:50 +02:00
										 |  |  | #include "trkgdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-25 15:06:30 +02:00
										 |  |  | #include "tcftrkgdbadapter.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 17:00:06 +01:00
										 |  |  | #include "debuggeractions.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "debuggerconstants.h"
 | 
					
						
							| 
									
										
										
										
											2010-12-08 12:43:11 +01:00
										 |  |  | #include "debuggercore.h"
 | 
					
						
							|  |  |  | #include "debuggerplugin.h"
 | 
					
						
							|  |  |  | #include "debuggerrunner.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-25 15:02:16 +02:00
										 |  |  | #include "debuggerstringutils.h"
 | 
					
						
							| 
									
										
										
										
											2010-12-08 12:43:11 +01:00
										 |  |  | #include "debuggertooltip.h"
 | 
					
						
							|  |  |  | #include "disassembleragent.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "gdbmi.h"
 | 
					
						
							| 
									
										
										
										
											2010-12-08 12:43:11 +01:00
										 |  |  | #include "gdboptionspage.h"
 | 
					
						
							|  |  |  | #include "memoryagent.h"
 | 
					
						
							|  |  |  | #include "watchutils.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "breakhandler.h"
 | 
					
						
							|  |  |  | #include "moduleshandler.h"
 | 
					
						
							|  |  |  | #include "registerhandler.h"
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | #include "snapshothandler.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  | #include "sourcefileshandler.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "stackhandler.h"
 | 
					
						
							| 
									
										
										
										
											2010-05-18 12:12:22 +02:00
										 |  |  | #include "threadshandler.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "watchhandler.h"
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-21 16:42:57 +01:00
										 |  |  | #ifdef Q_OS_WIN
 | 
					
						
							|  |  |  | #    include "dbgwinutils.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-09-22 16:20:08 +02:00
										 |  |  | #include "logwindow.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 17:25:28 +02:00
										 |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2010-12-08 12:43:11 +01:00
										 |  |  | #include <projectexplorer/toolchain.h>
 | 
					
						
							|  |  |  | #include <texteditor/itexteditor.h>
 | 
					
						
							|  |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-09 16:18:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | #include <QtCore/QCoreApplication>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtCore/QDebug>
 | 
					
						
							|  |  |  | #include <QtCore/QDir>
 | 
					
						
							|  |  |  | #include <QtCore/QFileInfo>
 | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  | #include <QtCore/QMetaObject>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtCore/QTime>
 | 
					
						
							|  |  |  | #include <QtCore/QTimer>
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | #include <QtCore/QTemporaryFile>
 | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  | #include <QtCore/QTextStream>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtGui/QAction>
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | #include <QtGui/QDialogButtonBox>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <QtGui/QLabel>
 | 
					
						
							|  |  |  | #include <QtGui/QMainWindow>
 | 
					
						
							|  |  |  | #include <QtGui/QMessageBox>
 | 
					
						
							| 
									
										
										
										
											2009-04-08 17:25:28 +02:00
										 |  |  | #include <QtGui/QPushButton>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-03 20:45:49 +02:00
										 |  |  | #ifdef Q_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <dlfcn.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-04-02 11:41:36 +02:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | namespace Debugger { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //#define DEBUG_PENDING  1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 16:50:28 +01:00
										 |  |  | static const char winPythonVersionC[] = "python2.5"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #if DEBUG_PENDING
 | 
					
						
							|  |  |  | #   define PENDING_DEBUG(s) qDebug() << s
 | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  | #   define PENDING_DEBUG(s)
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-10-27 17:16:46 +01:00
										 |  |  | #define PENDING_DEBUGX(s) qDebug() << s
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 11:16:54 +02:00
										 |  |  | #define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-07 16:30:42 +02:00
										 |  |  | QByteArray GdbEngine::tooltipIName(const QString &exp) | 
					
						
							| 
									
										
										
										
											2010-01-08 18:16:16 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-07 16:30:42 +02:00
										 |  |  |     return "tooltip." + exp.toLatin1().toHex(); | 
					
						
							| 
									
										
										
										
											2010-01-08 18:16:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  | static bool stateAcceptsGdbCommands(DebuggerState state) | 
					
						
							| 
									
										
										
										
											2009-09-22 09:27:19 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     switch (state) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     case EngineSetupRequested: | 
					
						
							| 
									
										
										
										
											2010-07-09 08:48:33 +02:00
										 |  |  |     case EngineSetupOk: | 
					
						
							|  |  |  |     case EngineSetupFailed: | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     case InferiorUnrunnable: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     case InferiorSetupRequested: | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  |     case InferiorSetupFailed: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     case EngineRunRequested: | 
					
						
							|  |  |  |     case InferiorRunRequested: | 
					
						
							|  |  |  |     case InferiorRunOk: | 
					
						
							|  |  |  |     case InferiorStopRequested: | 
					
						
							|  |  |  |     case InferiorStopOk: | 
					
						
							|  |  |  |     case InferiorShutdownRequested: | 
					
						
							|  |  |  |     case EngineShutdownRequested: | 
					
						
							|  |  |  |     case InferiorShutdownOk: | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     case InferiorShutdownFailed: | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     case DebuggerNotReady: | 
					
						
							|  |  |  |     case InferiorStopFailed: | 
					
						
							| 
									
										
										
										
											2011-01-14 14:25:02 +01:00
										 |  |  |     case InferiorSetupOk: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     case EngineRunFailed: | 
					
						
							| 
									
										
										
										
											2011-01-14 14:40:42 +01:00
										 |  |  |     case InferiorExitOk: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     case InferiorRunFailed: | 
					
						
							|  |  |  |     case EngineShutdownOk: | 
					
						
							|  |  |  |     case EngineShutdownFailed: | 
					
						
							|  |  |  |     case DebuggerFinished: | 
					
						
							| 
									
										
										
										
											2010-07-08 11:54:06 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-22 09:27:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | static int ¤tToken() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static int token = 0; | 
					
						
							|  |  |  |     return token; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | static QByteArray parsePlainConsoleStream(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     GdbMi output = response.data.findChild("consolestreamoutput"); | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  |     QByteArray out = output.data(); | 
					
						
							|  |  |  |     // FIXME: proper decoding needed
 | 
					
						
							|  |  |  |     if (out.endsWith("\\n")) | 
					
						
							|  |  |  |         out.chop(2); | 
					
						
							|  |  |  |     while (out.endsWith('\n') || out.endsWith(' ')) | 
					
						
							|  |  |  |         out.chop(1); | 
					
						
							|  |  |  |     int pos = out.indexOf(" = "); | 
					
						
							|  |  |  |     return out.mid(pos + 3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // GdbEngine
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 12:10:12 +01:00
										 |  |  | GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters, | 
					
						
							|  |  |  |         DebuggerEngine *masterEngine) | 
					
						
							|  |  |  |   : DebuggerEngine(startParameters, masterEngine) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     setObjectName(_("GdbEngine")); | 
					
						
							| 
									
										
										
										
											2010-07-21 11:05:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-27 12:05:03 +01:00
										 |  |  |     m_busy = false; | 
					
						
							| 
									
										
										
										
											2010-11-16 12:52:02 +01:00
										 |  |  |     m_gdbAdapter = 0; | 
					
						
							|  |  |  |     m_debuggingHelperState = DebuggingHelperUninitialized; | 
					
						
							|  |  |  |     m_gdbVersion = 100; | 
					
						
							|  |  |  |     m_gdbBuildVersion = -1; | 
					
						
							|  |  |  |     m_isMacGdb = false; | 
					
						
							|  |  |  |     m_hasPython = false; | 
					
						
							|  |  |  |     m_registerNamesListed = false; | 
					
						
							|  |  |  |     m_hasInferiorThreadList = false; | 
					
						
							|  |  |  |     m_sourcesListUpdating = false; | 
					
						
							|  |  |  |     m_oldestAcceptableToken = -1; | 
					
						
							|  |  |  |     m_outputCodec = QTextCodec::codecForLocale(); | 
					
						
							|  |  |  |     m_pendingWatchRequests = 0; | 
					
						
							|  |  |  |     m_pendingBreakpointRequests = 0; | 
					
						
							|  |  |  |     m_commandsDoneCallback = 0; | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  |     m_stackNeeded = false; | 
					
						
							| 
									
										
										
										
											2011-01-19 10:48:39 +01:00
										 |  |  |     m_preparedForQmlBreak = false; | 
					
						
							| 
									
										
										
										
											2010-11-16 12:52:02 +01:00
										 |  |  |     invalidateSourcesList(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-15 16:43:56 +02:00
										 |  |  |     m_gdbAdapter = createAdapter(); | 
					
						
							| 
									
										
										
										
											2009-10-27 12:05:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 12:52:02 +01:00
										 |  |  |     m_commandTimer.setSingleShot(true); | 
					
						
							|  |  |  |     connect(&m_commandTimer, SIGNAL(timeout()), SLOT(commandTimeout())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     connect(debuggerCore()->action(AutoDerefPointers), SIGNAL(valueChanged(QVariant)), | 
					
						
							| 
									
										
										
										
											2010-09-23 11:15:56 +02:00
										 |  |  |             SLOT(reloadLocals())); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     connect(debuggerCore()->action(SortStructMembers), SIGNAL(valueChanged(QVariant)), | 
					
						
							| 
									
										
										
										
											2010-09-23 11:15:56 +02:00
										 |  |  |             SLOT(reloadLocals())); | 
					
						
							| 
									
										
										
										
											2011-01-17 15:23:22 +01:00
										 |  |  |     connect(debuggerCore()->action(ShowStdNamespace), SIGNAL(valueChanged(QVariant)), | 
					
						
							|  |  |  |             SLOT(reloadLocals())); | 
					
						
							|  |  |  |     connect(debuggerCore()->action(ShowQtNamespace), SIGNAL(valueChanged(QVariant)), | 
					
						
							|  |  |  |             SLOT(reloadLocals())); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()), | 
					
						
							| 
									
										
										
										
											2010-09-23 11:15:56 +02:00
										 |  |  |             SLOT(createFullBacktrace())); | 
					
						
							| 
									
										
										
										
											2009-09-23 12:04:25 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-23 09:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-23 12:04:25 +02:00
										 |  |  | DebuggerStartMode GdbEngine::startMode() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-14 08:57:15 +02:00
										 |  |  |     return startParameters().startMode; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  | AbstractGdbProcess *GdbEngine::gdbProc() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_gdbAdapter->gdbProc(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | GdbEngine::~GdbEngine() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |     // Prevent sending error messages afterwards.
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     if (m_gdbAdapter) | 
					
						
							|  |  |  |         disconnect(gdbProc(), 0, this, 0); | 
					
						
							| 
									
										
										
										
											2009-10-05 14:59:39 +02:00
										 |  |  |     delete m_gdbAdapter; | 
					
						
							| 
									
										
										
										
											2009-10-26 11:55:02 +01:00
										 |  |  |     m_gdbAdapter = 0; | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  | QString GdbEngine::errorMessage(QProcess::ProcessError error) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (error) { | 
					
						
							|  |  |  |         case QProcess::FailedToStart: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("The Gdb process failed to start. Either the " | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 "invoked program '%1' is missing, or you may have insufficient " | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |                 "permissions to invoke the program.\n%2") | 
					
						
							|  |  |  |                 .arg(m_gdb, gdbProc()->errorString()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         case QProcess::Crashed: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("The Gdb process crashed some time after starting " | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 "successfully."); | 
					
						
							|  |  |  |         case QProcess::Timedout: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("The last waitFor...() function timed out. " | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 "The state of QProcess is unchanged, and you can try calling " | 
					
						
							|  |  |  |                 "waitFor...() again."); | 
					
						
							|  |  |  |         case QProcess::WriteError: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("An error occurred when attempting to write " | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 "to the Gdb process. For example, the process may not be running, " | 
					
						
							|  |  |  |                 "or it may have closed its input channel."); | 
					
						
							|  |  |  |         case QProcess::ReadError: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("An error occurred when attempting to read from " | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 "the Gdb process. For example, the process may not be running."); | 
					
						
							|  |  |  |         default: | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  |             return tr("An unknown error in the Gdb process occurred. "); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | static void dump(const char *first, const char *middle, const QString & to) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray ba(first, middle - first); | 
					
						
							| 
									
										
										
										
											2009-07-13 17:35:17 +02:00
										 |  |  |     Q_UNUSED(to) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // note that qDebug cuts off output after a certain size... (bug?)
 | 
					
						
							|  |  |  |     qDebug("\n>>>>> %s\n%s\n====\n%s\n<<<<<\n", | 
					
						
							|  |  |  |         qPrintable(currentTime()), | 
					
						
							|  |  |  |         qPrintable(QString(ba).trimmed()), | 
					
						
							|  |  |  |         qPrintable(to.trimmed())); | 
					
						
							|  |  |  |     //qDebug() << "";
 | 
					
						
							|  |  |  |     //qDebug() << qPrintable(currentTime())
 | 
					
						
							|  |  |  |     //    << " Reading response:  " << QString(ba).trimmed() << "\n";
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-21 16:42:57 +01:00
										 |  |  | // Parse "~:gdb: unknown target exception 0xc0000139 at 0x77bef04e\n"
 | 
					
						
							|  |  |  | // and return an exception message
 | 
					
						
							|  |  |  | static inline QString msgWinException(const QByteArray &data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const int exCodePos = data.indexOf("0x"); | 
					
						
							|  |  |  |     const int blankPos = exCodePos != -1 ? data.indexOf(' ', exCodePos + 1) : -1; | 
					
						
							|  |  |  |     const int addressPos = blankPos != -1 ? data.indexOf("0x", blankPos + 1) : -1; | 
					
						
							|  |  |  |     if (addressPos < 0) | 
					
						
							|  |  |  |         return GdbEngine::tr("An exception was triggered."); | 
					
						
							|  |  |  |     const unsigned exCode = data.mid(exCodePos, blankPos - exCodePos).toUInt(0, 0); | 
					
						
							|  |  |  |     const quint64 address = data.mid(addressPos).trimmed().toULongLong(0, 0); | 
					
						
							|  |  |  |     QString rc; | 
					
						
							|  |  |  |     QTextStream str(&rc); | 
					
						
							|  |  |  |     str << GdbEngine::tr("An exception was triggered: "); | 
					
						
							|  |  |  | #ifdef Q_OS_WIN
 | 
					
						
							|  |  |  |     formatWindowsException(exCode, address, 0, 0, 0, str); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     Q_UNUSED(exCode) | 
					
						
							|  |  |  |     Q_UNUSED(address) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     str << '.'; | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-15 14:47:14 +01:00
										 |  |  | void GdbEngine::readDebugeeOutput(const QByteArray &data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     QString msg = m_outputCodec->toUnicode(data.constData(), data.length(), | 
					
						
							|  |  |  |         &m_outputCodecState); | 
					
						
							|  |  |  |     showMessage(msg, AppStuff); | 
					
						
							| 
									
										
										
										
											2009-01-15 14:47:14 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  | void GdbEngine::handleResponse(const QByteArray &buff) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(QString::fromLocal8Bit(buff, buff.length()), LogOutput); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2010-08-23 14:27:24 +02:00
										 |  |  |     static QTime lastTime; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     qDebug() // << "#### start response handling #### "
 | 
					
						
							|  |  |  |         << lastTime.msecsTo(QTime::currentTime()) << "ms," | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |         << "buf:" << buff.left(1500) << "..." | 
					
						
							|  |  |  |         //<< "buf:" << buff
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         << "size:" << buff.size(); | 
					
						
							| 
									
										
										
										
											2010-08-23 14:27:24 +02:00
										 |  |  |     lastTime = QTime::currentTime(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |     //qDebug() << "buf:" << buff;
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     if (buff.isEmpty() || buff == "(gdb) ") | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     const char *from = buff.constData(); | 
					
						
							|  |  |  |     const char *to = from + buff.size(); | 
					
						
							|  |  |  |     const char *inner; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     int token = -1; | 
					
						
							|  |  |  |     // token is a sequence of numbers
 | 
					
						
							|  |  |  |     for (inner = from; inner != to; ++inner) | 
					
						
							|  |  |  |         if (*inner < '0' || *inner > '9') | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     if (from != inner) { | 
					
						
							|  |  |  |         token = QByteArray(from, inner - from).toInt(); | 
					
						
							|  |  |  |         from = inner; | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |         //qDebug() << "found token" << token;
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     // next char decides kind of response
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     const char c = *from++; | 
					
						
							|  |  |  |     //qDebug() << "CODE:" << c;
 | 
					
						
							|  |  |  |     switch (c) { | 
					
						
							|  |  |  |         case '*': | 
					
						
							|  |  |  |         case '+': | 
					
						
							|  |  |  |         case '=': { | 
					
						
							|  |  |  |             QByteArray asyncClass; | 
					
						
							|  |  |  |             for (; from != to; ++from) { | 
					
						
							|  |  |  |                 const char c = *from; | 
					
						
							|  |  |  |                 if (!isNameChar(c)) | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 asyncClass += *from; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             //qDebug() << "ASYNCCLASS" << asyncClass;
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             GdbMi result; | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             while (from != to) { | 
					
						
							|  |  |  |                 GdbMi data; | 
					
						
							| 
									
										
										
										
											2009-04-07 14:14:43 +02:00
										 |  |  |                 if (*from != ',') { | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |                     // happens on archer where we get
 | 
					
						
							|  |  |  |                     // 23^running <NL> *running,thread-id="all" <NL> (gdb)
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                     result.m_type = GdbMi::Tuple; | 
					
						
							| 
									
										
										
										
											2009-04-07 14:14:43 +02:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 ++from; // skip ','
 | 
					
						
							|  |  |  |                 data.parseResultOrValue(from, to); | 
					
						
							|  |  |  |                 if (data.isValid()) { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                     //qDebug() << "parsed result:" << data.toString();
 | 
					
						
							|  |  |  |                     result.m_children += data; | 
					
						
							|  |  |  |                     result.m_type = GdbMi::Tuple; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             if (asyncClass == "stopped") { | 
					
						
							| 
									
										
										
										
											2009-10-09 10:20:42 +02:00
										 |  |  |                 handleStopResponse(result); | 
					
						
							| 
									
										
										
										
											2009-11-09 23:21:18 +01:00
										 |  |  |                 m_pendingLogStreamOutput.clear(); | 
					
						
							|  |  |  |                 m_pendingConsoleStreamOutput.clear(); | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             } else if (asyncClass == "running") { | 
					
						
							|  |  |  |                 // Archer has 'thread-id="all"' here
 | 
					
						
							| 
									
										
										
										
											2009-04-01 15:44:34 +02:00
										 |  |  |             } else if (asyncClass == "library-loaded") { | 
					
						
							|  |  |  |                 // Archer has 'id="/usr/lib/libdrm.so.2",
 | 
					
						
							|  |  |  |                 // target-name="/usr/lib/libdrm.so.2",
 | 
					
						
							|  |  |  |                 // host-name="/usr/lib/libdrm.so.2",
 | 
					
						
							| 
									
										
										
										
											2009-04-01 16:06:49 +02:00
										 |  |  |                 // symbols-loaded="0"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2009-04-29 10:33:37 +02:00
										 |  |  |                 if (!id.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                     showStatusMessage(tr("Library %1 loaded").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2010-07-21 11:02:51 +02:00
										 |  |  |                 progressPing(); | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2009-04-07 09:40:56 +02:00
										 |  |  |             } else if (asyncClass == "library-unloaded") { | 
					
						
							|  |  |  |                 // Archer has 'id="/usr/lib/libdrm.so.2",
 | 
					
						
							|  |  |  |                 // target-name="/usr/lib/libdrm.so.2",
 | 
					
						
							|  |  |  |                 // host-name="/usr/lib/libdrm.so.2"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2010-07-21 11:02:51 +02:00
										 |  |  |                 progressPing(); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                 showStatusMessage(tr("Library %1 unloaded").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2010-03-24 13:47:28 +01:00
										 |  |  |             } else if (asyncClass == "thread-group-added") { | 
					
						
							|  |  |  |                 // 7.1-symbianelf has "{id="i1"}"
 | 
					
						
							| 
									
										
										
										
											2010-04-07 09:19:36 +02:00
										 |  |  |             } else if (asyncClass == "thread-group-created" | 
					
						
							|  |  |  |                     || asyncClass == "thread-group-started") { | 
					
						
							|  |  |  |                 // Archer had only "{id="28902"}" at some point of 6.8.x.
 | 
					
						
							| 
									
										
										
										
											2010-04-07 15:18:11 +02:00
										 |  |  |                 // *-started seems to be standard in 7.1, but in early
 | 
					
						
							|  |  |  |                 // 7.0.x, there was a *-created instead.
 | 
					
						
							| 
									
										
										
										
											2010-07-21 11:02:51 +02:00
										 |  |  |                 progressPing(); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:54:17 +02:00
										 |  |  |                 // 7.1.50 has thread-group-started,id="i1",pid="3529"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2010-04-29 18:36:18 +02:00
										 |  |  |                 showStatusMessage(tr("Thread group %1 created").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:54:17 +02:00
										 |  |  |                 int pid = id.toInt(); | 
					
						
							|  |  |  |                 if (!pid) { | 
					
						
							|  |  |  |                     id = result.findChild("pid").data(); | 
					
						
							|  |  |  |                     pid = id.toInt(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (pid) | 
					
						
							|  |  |  |                     notifyInferiorPid(pid); | 
					
						
							| 
									
										
										
										
											2009-04-01 16:06:49 +02:00
										 |  |  |             } else if (asyncClass == "thread-created") { | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |                 //"{id="1",group-id="28902"}"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                 showStatusMessage(tr("Thread %1 created").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2009-04-01 16:49:45 +02:00
										 |  |  |             } else if (asyncClass == "thread-group-exited") { | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |                 // Archer has "{id="28902"}"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                 showStatusMessage(tr("Thread group %1 exited").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2009-04-01 16:49:45 +02:00
										 |  |  |             } else if (asyncClass == "thread-exited") { | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |                 //"{id="1",group-id="28902"}"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							|  |  |  |                 QByteArray groupid = result.findChild("group-id").data(); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                 showStatusMessage(tr("Thread %1 in group %2 exited") | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |                     .arg(_(id)).arg(_(groupid)), 1000); | 
					
						
							| 
									
										
										
										
											2009-04-07 09:51:21 +02:00
										 |  |  |             } else if (asyncClass == "thread-selected") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 QByteArray id = result.findChild("id").data(); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |                 showStatusMessage(tr("Thread %1 selected").arg(_(id)), 1000); | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |                 //"{id="2"}"
 | 
					
						
							| 
									
										
										
										
											2010-03-26 08:56:36 +01:00
										 |  |  |             } else if (m_isMacGdb && asyncClass == "shlibs-updated") { | 
					
						
							|  |  |  |                 // Apple's gdb announces updated libs.
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2010-03-26 08:56:36 +01:00
										 |  |  |             } else if (m_isMacGdb && asyncClass == "shlibs-added") { | 
					
						
							|  |  |  |                 // Apple's gdb announces added libs.
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |                 // {shlib-info={num="2", name="libmathCommon.A_debug.dylib",
 | 
					
						
							|  |  |  |                 // kind="-", dyld-addr="0x7f000", reason="dyld", requested-state="Y",
 | 
					
						
							|  |  |  |                 // state="Y", path="/usr/lib/system/libmathCommon.A_debug.dylib",
 | 
					
						
							|  |  |  |                 // description="/usr/lib/system/libmathCommon.A_debug.dylib",
 | 
					
						
							|  |  |  |                 // loaded_addr="0x7f000", slide="0x7f000", prefix=""}}
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2010-03-26 16:31:47 +01:00
										 |  |  |             } else if (m_isMacGdb && asyncClass == "resolve-pending-breakpoint") { | 
					
						
							|  |  |  |                 // Apple's gdb announces resolved breakpoints.
 | 
					
						
							|  |  |  |                 // new_bp="1",pended_bp="1",new_expr="\"gdbengine.cpp\":1584",
 | 
					
						
							|  |  |  |                 // bkpt={number="1",type="breakpoint",disp="keep",enabled="y",
 | 
					
						
							|  |  |  |                 // addr="0x0000000115cc3ddf",func="foo()",file="../foo.cpp",
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:14:44 +02:00
										 |  |  |                 // line="1584",shlib="/../libFoo_debug.dylib",times="0"}
 | 
					
						
							| 
									
										
										
										
											2010-03-26 16:31:47 +01:00
										 |  |  |                 const GdbMi bkpt = result.findChild("bkpt"); | 
					
						
							|  |  |  |                 const int number = bkpt.findChild("number").data().toInt(); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |                 if (!isQmlStepBreakpoint1(number) && isQmlStepBreakpoint2(number)) { | 
					
						
							|  |  |  |                     BreakpointId id = breakHandler()->findBreakpointByNumber(number); | 
					
						
							|  |  |  |                     updateBreakpointDataFromOutput(id, bkpt); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |                 qDebug() << "IGNORED ASYNC OUTPUT" | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                     << asyncClass << result.toString(); | 
					
						
							| 
									
										
										
										
											2009-02-12 13:31:19 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-02-12 13:31:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         case '~': { | 
					
						
							| 
									
										
										
										
											2009-03-03 09:31:13 +01:00
										 |  |  |             QByteArray data = GdbMi::parseCString(from, to); | 
					
						
							|  |  |  |             m_pendingConsoleStreamOutput += data; | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Parse pid from noise.
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |             if (!inferiorPid()) { | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  |                 // Linux/Mac gdb: [New [Tt]hread 0x545 (LWP 4554)]
 | 
					
						
							|  |  |  |                 static QRegExp re1(_("New .hread 0x[0-9a-f]+ \\(LWP ([0-9]*)\\)")); | 
					
						
							|  |  |  |                 // MinGW 6.8: [New thread 2437.0x435345]
 | 
					
						
							|  |  |  |                 static QRegExp re2(_("New .hread ([0-9]+)\\.0x[0-9a-f]*")); | 
					
						
							| 
									
										
										
										
											2009-10-08 16:14:25 +02:00
										 |  |  |                 // Mac: [Switching to process 9294 local thread 0x2e03] or
 | 
					
						
							|  |  |  |                 // [Switching to process 31773]
 | 
					
						
							|  |  |  |                 static QRegExp re3(_("Switching to process ([0-9]+)")); | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  |                 QTC_ASSERT(re1.isValid() && re2.isValid(), return); | 
					
						
							|  |  |  |                 if (re1.indexIn(_(data)) != -1) | 
					
						
							|  |  |  |                     maybeHandleInferiorPidChanged(re1.cap(1)); | 
					
						
							|  |  |  |                 else if (re2.indexIn(_(data)) != -1) | 
					
						
							|  |  |  |                     maybeHandleInferiorPidChanged(re2.cap(1)); | 
					
						
							| 
									
										
										
										
											2009-09-29 14:40:23 +02:00
										 |  |  |                 else if (re3.indexIn(_(data)) != -1) | 
					
						
							|  |  |  |                     maybeHandleInferiorPidChanged(re3.cap(1)); | 
					
						
							| 
									
										
										
										
											2009-09-23 12:04:25 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Show some messages to give the impression something happens.
 | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |             if (data.startsWith("Reading symbols from ")) { | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  |                 showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))), 1000); | 
					
						
							| 
									
										
										
										
											2010-07-22 12:02:09 +02:00
										 |  |  |                 progressPing(); | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |             } else if (data.startsWith("[New ") || data.startsWith("[Thread ")) { | 
					
						
							|  |  |  |                 if (data.endsWith('\n')) | 
					
						
							|  |  |  |                     data.chop(1); | 
					
						
							| 
									
										
										
										
											2010-07-22 12:02:09 +02:00
										 |  |  |                 progressPing(); | 
					
						
							| 
									
										
										
										
											2009-09-23 12:12:36 +02:00
										 |  |  |                 showStatusMessage(_(data), 1000); | 
					
						
							| 
									
										
										
										
											2011-01-21 16:42:57 +01:00
										 |  |  |             } else if (data.startsWith("gdb: unknown target exception 0x")) { | 
					
						
							|  |  |  |                 // [Windows, most likely some DLL/Entry point not found]:
 | 
					
						
							|  |  |  |                 // "gdb: unknown target exception 0xc0000139 at 0x77bef04e"
 | 
					
						
							|  |  |  |                 // This may be fatal and cause the target to exit later
 | 
					
						
							|  |  |  |                 m_lastWinException = msgWinException(data); | 
					
						
							|  |  |  |                 showMessage(m_lastWinException, LogMisc); | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (data.startsWith("QMLBP:")) { | 
					
						
							|  |  |  |                 int pos1 = 6; | 
					
						
							|  |  |  |                 int pos2 = data.indexOf(' ', pos1); | 
					
						
							|  |  |  |                 m_qmlBreakpointNumbers[2] = data.mid(pos1, pos2 - pos1).toInt(); | 
					
						
							|  |  |  |                 //qDebug() << "FOUND QMLBP: " << m_qmlBreakpointNumbers[2];
 | 
					
						
							|  |  |  |                 //qDebug() << "CURRENT: " << m_qmlBreakpointNumbers;
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-02-12 13:31:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         case '@': { | 
					
						
							| 
									
										
										
										
											2009-10-05 17:58:25 +02:00
										 |  |  |             readDebugeeOutput(GdbMi::parseCString(from, to)); | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         case '&': { | 
					
						
							|  |  |  |             QByteArray data = GdbMi::parseCString(from, to); | 
					
						
							|  |  |  |             m_pendingLogStreamOutput += data; | 
					
						
							|  |  |  |             // On Windows, the contents seem to depend on the debugger
 | 
					
						
							|  |  |  |             // version and/or OS version used.
 | 
					
						
							|  |  |  |             if (data.startsWith("warning:")) | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |                 showMessage(_(data.mid(9)), AppStuff); // Cut "warning: "
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         case '^': { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             GdbResponse response; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             response.token = token; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             for (inner = from; inner != to; ++inner) | 
					
						
							|  |  |  |                 if (*inner < 'a' || *inner > 'z') | 
					
						
							|  |  |  |                     break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 18:22:13 +02:00
										 |  |  |             QByteArray resultClass = QByteArray::fromRawData(from, inner - from); | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             if (resultClass == "done") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultDone; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } else if (resultClass == "running") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultRunning; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } else if (resultClass == "connected") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultConnected; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } else if (resultClass == "error") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultError; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } else if (resultClass == "exit") { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultExit; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                 response.resultClass = GdbResultUnknown; | 
					
						
							| 
									
										
										
										
											2009-09-28 15:06:17 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             from = inner; | 
					
						
							|  |  |  |             if (from != to) { | 
					
						
							| 
									
										
										
										
											2009-04-07 09:51:21 +02:00
										 |  |  |                 if (*from == ',') { | 
					
						
							|  |  |  |                     ++from; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                     response.data.parseTuple_helper(from, to); | 
					
						
							|  |  |  |                     response.data.m_type = GdbMi::Tuple; | 
					
						
							|  |  |  |                     response.data.m_name = "data"; | 
					
						
							| 
									
										
										
										
											2009-04-07 09:51:21 +02:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |                     // Archer has this.
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |                     response.data.m_type = GdbMi::Tuple; | 
					
						
							|  |  |  |                     response.data.m_name = "data"; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             //qDebug() << "\nLOG STREAM:" + m_pendingLogStreamOutput;
 | 
					
						
							|  |  |  |             //qDebug() << "\nCONSOLE STREAM:" + m_pendingConsoleStreamOutput;
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             response.data.setStreamOutput("logstreamoutput", | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |                 m_pendingLogStreamOutput); | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             response.data.setStreamOutput("consolestreamoutput", | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |                 m_pendingConsoleStreamOutput); | 
					
						
							|  |  |  |             m_pendingLogStreamOutput.clear(); | 
					
						
							|  |  |  |             m_pendingConsoleStreamOutput.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  |             handleResultRecord(&response); | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         default: { | 
					
						
							|  |  |  |             qDebug() << "UNKNOWN RESPONSE TYPE" << c; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::readGdbStandardError() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     QByteArray err = gdbProc()->readAllStandardError(); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("UNEXPECTED GDB STDERR: " + err)); | 
					
						
							| 
									
										
										
										
											2009-10-30 18:18:21 +01:00
										 |  |  |     if (err == "Undefined command: \"bb\".  Try \"help\".\n") | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-03-29 16:45:34 +02:00
										 |  |  |     if (err.startsWith("BFD: reopening")) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-10-30 18:18:21 +01:00
										 |  |  |     qWarning() << "Unexpected gdb stderr:" << err; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::readGdbStandardOutput() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |     m_commandTimer.start(); // Restart timer.
 | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 22:36:36 +01:00
										 |  |  |     int newstart = 0; | 
					
						
							|  |  |  |     int scan = m_inbuffer.size(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     m_inbuffer.append(gdbProc()->readAllStandardOutput()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |     // This can trigger when a dialog starts a nested event loop.
 | 
					
						
							| 
									
										
										
										
											2009-10-27 12:05:03 +01:00
										 |  |  |     if (m_busy) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |     while (newstart < m_inbuffer.size()) { | 
					
						
							|  |  |  |         int start = newstart; | 
					
						
							| 
									
										
										
										
											2009-02-24 22:36:36 +01:00
										 |  |  |         int end = m_inbuffer.indexOf('\n', scan); | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         if (end < 0) { | 
					
						
							|  |  |  |             m_inbuffer.remove(0, start); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         newstart = end + 1; | 
					
						
							| 
									
										
										
										
											2009-02-24 22:36:36 +01:00
										 |  |  |         scan = newstart; | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         if (end == start) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #        if defined(Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         if (m_inbuffer.at(end - 1) == '\r') { | 
					
						
							|  |  |  |             --end; | 
					
						
							|  |  |  |             if (end == start) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #        endif
 | 
					
						
							| 
									
										
										
										
											2009-10-27 12:05:03 +01:00
										 |  |  |         m_busy = true; | 
					
						
							| 
									
										
										
										
											2009-02-24 20:34:30 +01:00
										 |  |  |         handleResponse(QByteArray::fromRawData(m_inbuffer.constData() + start, end - start)); | 
					
						
							| 
									
										
										
										
											2009-10-27 12:05:03 +01:00
										 |  |  |         m_busy = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-24 21:50:20 +01:00
										 |  |  |     m_inbuffer.clear(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::interruptInferior() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state(); return); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Stop requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("TRYING TO INTERRUPT INFERIOR")); | 
					
						
							| 
									
										
										
										
											2009-09-14 11:02:36 +02:00
										 |  |  |     m_gdbAdapter->interruptInferior(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  | void GdbEngine::interruptInferiorTemporarily() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     foreach (const GdbCommand &cmd, m_commandsToRunOnTemporaryBreak) { | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |         if (cmd.flags & LosesChild) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |             notifyInferiorIll(); | 
					
						
							| 
									
										
										
										
											2010-07-20 12:14:59 +02:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-20 12:14:59 +02:00
										 |  |  |     requestInterruptInferior(); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     const qint64 pid = pid0.toLongLong(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (pid == 0) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("Cannot parse PID from %1").arg(pid0)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     if (pid == inferiorPid()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     showMessage(_("FOUND PID %1").arg(pid)); | 
					
						
							|  |  |  |     notifyInferiorPid(pid); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  | void GdbEngine::postCommand(const QByteArray &command, AdapterCallback callback, | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |                             const char *callbackName, const QVariant &cookie) | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     postCommand(command, NoFlags, callback, callbackName, cookie); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  | void GdbEngine::postCommand(const QByteArray &command, GdbCommandFlags flags, | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  |                             AdapterCallback callback, | 
					
						
							|  |  |  |                             const char *callbackName, const QVariant &cookie) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     GdbCommand cmd; | 
					
						
							|  |  |  |     cmd.command = command; | 
					
						
							| 
									
										
										
										
											2009-09-22 11:31:34 +02:00
										 |  |  |     cmd.flags = flags; | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     cmd.adapterCallback = callback; | 
					
						
							|  |  |  |     cmd.callbackName = callbackName; | 
					
						
							|  |  |  |     cmd.cookie = cookie; | 
					
						
							|  |  |  |     postCommandHelper(cmd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  | void GdbEngine::postCommand(const QByteArray &command, GdbCommandCallback callback, | 
					
						
							| 
									
										
										
										
											2009-05-05 11:16:54 +02:00
										 |  |  |                             const char *callbackName, const QVariant &cookie) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-07 09:51:21 +02:00
										 |  |  |     postCommand(command, NoFlags, callback, callbackName, cookie); | 
					
						
							| 
									
										
										
										
											2009-05-05 11:16:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  | void GdbEngine::postCommand(const QByteArray &command, GdbCommandFlags flags, | 
					
						
							| 
									
										
										
										
											2009-05-05 11:16:54 +02:00
										 |  |  |                             GdbCommandCallback callback, const char *callbackName, | 
					
						
							|  |  |  |                             const QVariant &cookie) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     GdbCommand cmd; | 
					
						
							|  |  |  |     cmd.command = command; | 
					
						
							|  |  |  |     cmd.flags = flags; | 
					
						
							|  |  |  |     cmd.callback = callback; | 
					
						
							|  |  |  |     cmd.callbackName = callbackName; | 
					
						
							|  |  |  |     cmd.cookie = cookie; | 
					
						
							|  |  |  |     postCommandHelper(cmd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::postCommandHelper(const GdbCommand &cmd) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:45:08 +02:00
										 |  |  |     if (!stateAcceptsGdbCommands(state())) { | 
					
						
							| 
									
										
										
										
											2010-01-14 15:25:53 +01:00
										 |  |  |         PENDING_DEBUG(_("NO GDB PROCESS RUNNING, CMD IGNORED: " + cmd.command)); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: %1 %2") | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             .arg(_(cmd.command)).arg(state())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |     if (cmd.flags & RebuildWatchModel) { | 
					
						
							|  |  |  |         ++m_pendingWatchRequests; | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |         PENDING_DEBUG("   WATCH MODEL:" << cmd.command << "=>" << cmd.callbackName | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |                       << "INCREMENTS PENDING TO" << m_pendingWatchRequests); | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     } else if (cmd.flags & RebuildBreakpointModel) { | 
					
						
							|  |  |  |         ++m_pendingBreakpointRequests; | 
					
						
							|  |  |  |         PENDING_DEBUG("   BRWAKPOINT MODEL:" << cmd.command << "=>" << cmd.callbackName | 
					
						
							|  |  |  |                       << "INCREMENTS PENDING TO" << m_pendingBreakpointRequests); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-10-27 14:52:29 +01:00
										 |  |  |         PENDING_DEBUG("   OTHER (IN):" << cmd.command << "=>" << cmd.callbackName | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |                       << "LEAVES PENDING WATCH AT" << m_pendingWatchRequests | 
					
						
							|  |  |  |                       << "LEAVES PENDING BREAKPOINT AT" << m_pendingBreakpointRequests); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-09 14:53:45 +02:00
										 |  |  |     // FIXME: clean up logic below
 | 
					
						
							|  |  |  |     if (cmd.flags & Immediate) { | 
					
						
							|  |  |  |         // This should always be sent.
 | 
					
						
							|  |  |  |         flushCommand(cmd); | 
					
						
							|  |  |  |     } else if ((cmd.flags & NeedsStop) | 
					
						
							|  |  |  |             || !m_commandsToRunOnTemporaryBreak.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         if (state() == InferiorStopOk || state() == InferiorUnrunnable | 
					
						
							|  |  |  |             || state() == InferiorSetupRequested || state() == EngineSetupOk | 
					
						
							|  |  |  |             || state() == InferiorShutdownRequested) { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |             // Can be safely sent now.
 | 
					
						
							|  |  |  |             flushCommand(cmd); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             // Queue the commands that we cannot send at once.
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("QUEUING COMMAND " + cmd.command)); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |             m_commandsToRunOnTemporaryBreak.append(cmd); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |             if (state() == InferiorStopRequested) { | 
					
						
							|  |  |  |                 if (cmd.flags & LosesChild) { | 
					
						
							|  |  |  |                     notifyInferiorIll(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("CHILD ALREADY BEING INTERRUPTED. STILL HOPING.")); | 
					
						
							| 
									
										
										
										
											2010-04-12 14:56:19 +02:00
										 |  |  |                 // Calling shutdown() here breaks all situations where two
 | 
					
						
							|  |  |  |                 // NeedsStop commands are issued in quick succession.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |             } else if (state() == InferiorRunOk) { | 
					
						
							| 
									
										
										
										
											2010-04-29 18:36:18 +02:00
										 |  |  |                 showStatusMessage(tr("Stopping temporarily"), 1000); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |                 interruptInferiorTemporarily(); | 
					
						
							| 
									
										
										
										
											2009-11-02 14:40:54 +01:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 qDebug() << "ATTEMPTING TO QUEUE COMMAND " | 
					
						
							|  |  |  |                     << cmd.command << "IN INAPPROPRIATE STATE" << state(); | 
					
						
							| 
									
										
										
										
											2009-10-23 21:54:27 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     } else if (!cmd.command.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  |         flushCommand(cmd); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 16:40:16 +01:00
										 |  |  | void GdbEngine::flushQueuedCommands() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-29 18:36:18 +02:00
										 |  |  |     showStatusMessage(tr("Processing queued commands"), 1000); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:40:16 +01:00
										 |  |  |     while (!m_commandsToRunOnTemporaryBreak.isEmpty()) { | 
					
						
							|  |  |  |         GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst(); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("RUNNING QUEUED COMMAND " + cmd.command + ' ' | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             + cmd.callbackName)); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:40:16 +01:00
										 |  |  |         flushCommand(cmd); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | void GdbEngine::flushCommand(const GdbCommand &cmd0) | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-15 14:03:45 +02:00
										 |  |  |     if (!stateAcceptsGdbCommands(state())) { | 
					
						
							|  |  |  |         showMessage(_(cmd0.command), LogInput); | 
					
						
							|  |  |  |         showMessage(_("GDB PROCESS ACCEPTS NO CMD IN STATE %1 ").arg(state())); | 
					
						
							| 
									
										
										
										
											2009-09-15 12:16:21 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |     QTC_ASSERT(gdbProc()->state() == QProcess::Running, return;) | 
					
						
							| 
									
										
										
										
											2010-09-07 10:59:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  |     ++currentToken(); | 
					
						
							| 
									
										
										
										
											2010-07-15 14:03:45 +02:00
										 |  |  |     GdbCommand cmd = cmd0; | 
					
						
							| 
									
										
										
										
											2009-07-06 11:37:21 +02:00
										 |  |  |     cmd.postTime = QTime::currentTime(); | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  |     m_cookieForToken[currentToken()] = cmd; | 
					
						
							| 
									
										
										
										
											2010-06-28 14:53:31 +02:00
										 |  |  |     if (cmd.flags & ConsoleCommand) | 
					
						
							|  |  |  |         cmd.command = "-interpreter-exec console \"" + cmd.command + '"'; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     cmd.command = QByteArray::number(currentToken()) + cmd.command; | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_(cmd.command), LogInput); | 
					
						
							| 
									
										
										
										
											2009-09-15 12:16:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     m_gdbAdapter->write(cmd.command + "\r\n"); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-06 11:29:52 +02:00
										 |  |  |     // Start Watchdog.
 | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |     if (m_commandTimer.interval() <= 20000) | 
					
						
							|  |  |  |         m_commandTimer.setInterval(commandTimeoutTime()); | 
					
						
							| 
									
										
										
										
											2010-09-06 15:29:26 +02:00
										 |  |  |     // The process can die for external reason between the "-gdb-exit" was
 | 
					
						
							|  |  |  |     // sent and a response could be retrieved. We don't want the watchdog
 | 
					
						
							|  |  |  |     // to bark in that case since the only possible outcome is a dead
 | 
					
						
							|  |  |  |     // process anyway.
 | 
					
						
							| 
									
										
										
										
											2010-09-07 10:59:40 +02:00
										 |  |  |     if (!cmd.command.endsWith("-gdb-exit")) | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |         m_commandTimer.start(); | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     //if (cmd.flags & LosesChild)
 | 
					
						
							| 
									
										
										
										
											2010-10-27 15:39:25 +02:00
										 |  |  |     //    notifyInferiorIll();
 | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  | int GdbEngine::commandTimeoutTime() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     int time = debuggerCore()->action(GdbWatchdogTimeout)->value().toInt(); | 
					
						
							| 
									
										
										
										
											2011-01-05 09:55:01 +01:00
										 |  |  |     return 1000 * qMax(40, time); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  | void GdbEngine::commandTimeout() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<int> keys = m_cookieForToken.keys(); | 
					
						
							|  |  |  |     qSort(keys); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |     bool killIt = false; | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  |     foreach (int key, keys) { | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |         const GdbCommand &cmd = m_cookieForToken.value(key); | 
					
						
							|  |  |  |         if (!(cmd.flags & NonCriticalResponse)) | 
					
						
							|  |  |  |             killIt = true; | 
					
						
							| 
									
										
										
										
											2010-01-12 13:49:56 +01:00
										 |  |  |         QByteArray msg = QByteArray::number(key); | 
					
						
							|  |  |  |         msg += ": " + cmd.command + " => "; | 
					
						
							| 
									
										
										
										
											2010-09-08 10:32:40 +02:00
										 |  |  |         msg += cmd.callbackName ? cmd.callbackName : "<unnamed callback>"; | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_(msg)); | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |     if (killIt) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("TIMED OUT WAITING FOR GDB REPLY. COMMANDS STILL IN PROGRESS:")); | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |         int timeOut = m_commandTimer.interval(); | 
					
						
							|  |  |  |         //m_commandTimer.stop();
 | 
					
						
							| 
									
										
										
										
											2010-01-08 11:32:53 +01:00
										 |  |  |         const QString msg = tr("The gdb process has not responded " | 
					
						
							| 
									
										
										
										
											2010-01-12 15:13:36 +01:00
										 |  |  |             "to a command within %1 seconds. This could mean it is stuck " | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |             "in an endless loop or taking longer than expected to perform " | 
					
						
							| 
									
										
										
										
											2010-01-08 11:32:53 +01:00
										 |  |  |             "the operation.\nYou can choose between waiting " | 
					
						
							| 
									
										
										
										
											2010-01-12 13:51:46 +01:00
										 |  |  |             "longer or abort debugging.").arg(timeOut / 1000); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |         QMessageBox *mb = showMessageBox(QMessageBox::Critical, | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |             tr("Gdb not responding"), msg, | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |             QMessageBox::Ok | QMessageBox::Cancel); | 
					
						
							|  |  |  |         mb->button(QMessageBox::Cancel)->setText(tr("Give gdb more time")); | 
					
						
							|  |  |  |         mb->button(QMessageBox::Ok)->setText(tr("Stop debugging")); | 
					
						
							|  |  |  |         if (mb->exec() == QMessageBox::Ok) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER")); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |             // This is an undefined state, so we just pull the emergency brake.
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |             watchHandler()->endCycle(); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |             gdbProc()->kill(); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER")); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-01-12 13:49:56 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("\nNON-CRITICAL TIMEOUT\n")); | 
					
						
							| 
									
										
										
										
											2009-12-11 16:59:34 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  | void GdbEngine::handleResultRecord(GdbResponse *response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     //qDebug() << "TOKEN:" << response.token
 | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |     //    << " ACCEPTABLE:" << m_oldestAcceptableToken;
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     //qDebug() << "\nRESULT" << response.token << response.toString();
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  |     int token = response->token; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (token == -1) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-13 09:42:34 +02:00
										 |  |  |     if (!m_cookieForToken.contains(token)) { | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |         // In theory this should not happen (rather the error should be
 | 
					
						
							|  |  |  |         // reported in the "first" response to the command) in practice it
 | 
					
						
							|  |  |  |         // does. We try to handle a few situations we are aware of gracefully.
 | 
					
						
							|  |  |  |         // Ideally, this code should not be present at all.
 | 
					
						
							| 
									
										
										
										
											2011-01-21 16:42:57 +01:00
										 |  |  |         showMessage(_("COOKIE FOR TOKEN %1 ALREADY EATEN (%2). " | 
					
						
							|  |  |  |                       "TWO RESPONSES FOR ONE COMMAND?").arg(token). | 
					
						
							|  |  |  |                     arg(QString::fromAscii(stateName(state())))); | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  |         if (response->resultClass == GdbResultError) { | 
					
						
							|  |  |  |             QByteArray msg = response->data.findChild("msg").data(); | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |             if (msg == "Cannot find new threads: generic error") { | 
					
						
							|  |  |  |                 // Handle a case known to occur on Linux/gdb 6.8 when debugging moc
 | 
					
						
							|  |  |  |                 // with helpers enabled. In this case we get a second response with
 | 
					
						
							|  |  |  |                 // msg="Cannot find new threads: generic error"
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("APPLYING WORKAROUND #1")); | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |                 showMessageBox(QMessageBox::Critical, | 
					
						
							|  |  |  |                     tr("Executable failed"), QString::fromLocal8Bit(msg)); | 
					
						
							| 
									
										
										
										
											2010-04-29 18:36:18 +02:00
										 |  |  |                 showStatusMessage(tr("Process failed to start")); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 //shutdown();
 | 
					
						
							|  |  |  |                 notifyInferiorIll(); | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |             } else if (msg == "\"finish\" not meaningful in the outermost frame.") { | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |                 // Handle a case known to appear on gdb 6.4 symbianelf when
 | 
					
						
							|  |  |  |                 // the stack is cut due to access to protected memory.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 //showMessage(_("APPLYING WORKAROUND #2"));
 | 
					
						
							|  |  |  |                 notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |             } else if (msg.startsWith("Cannot find bounds of current function")) { | 
					
						
							|  |  |  |                 // Happens when running "-exec-next" in a function for which
 | 
					
						
							|  |  |  |                 // there is no debug information. Divert to "-exec-next-step"
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("APPLYING WORKAROUND #3")); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |                 executeNextI(); | 
					
						
							| 
									
										
										
										
											2009-10-29 18:31:45 +01:00
										 |  |  |             } else if (msg.startsWith("Couldn't get registers: No such process.")) { | 
					
						
							|  |  |  |                 // Happens on archer-tromey-python 6.8.50.20090910-cvs
 | 
					
						
							|  |  |  |                 // There might to be a race between a process shutting down
 | 
					
						
							|  |  |  |                 // and library load messages.
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("APPLYING WORKAROUND #4")); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2010-10-27 15:39:25 +02:00
										 |  |  |                 //notifyInferiorIll();
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |                 //showStatusMessage(tr("Executable failed: %1")
 | 
					
						
							|  |  |  |                 //    .arg(QString::fromLocal8Bit(msg)));
 | 
					
						
							|  |  |  |                 //shutdown();
 | 
					
						
							|  |  |  |                 //showMessageBox(QMessageBox::Critical,
 | 
					
						
							|  |  |  |                 //    tr("Executable failed"), QString::fromLocal8Bit(msg));
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             } else if (msg.contains("Cannot insert breakpoint")) { | 
					
						
							|  |  |  |                 // For breakpoints set by address to non-existent addresses we
 | 
					
						
							|  |  |  |                 // might get something like "6^error,msg="Warning:\nCannot insert
 | 
					
						
							|  |  |  |                 // breakpoint 3.\nError accessing memory address 0x34592327:
 | 
					
						
							|  |  |  |                 // Input/output error.\nCannot insert breakpoint 4.\nError
 | 
					
						
							|  |  |  |                 // accessing memory address 0x34592335: Input/output error.\n".
 | 
					
						
							|  |  |  |                 // This should not stop us from proceeding.
 | 
					
						
							|  |  |  |                 // Most notably, that happens after a "6^running" and "*running"
 | 
					
						
							|  |  |  |                 // We are probably sitting at _start and can't proceed as
 | 
					
						
							|  |  |  |                 // long as the breakpoints are enabled.
 | 
					
						
							|  |  |  |                 // FIXME: Should we silently disable the offending breakpoints?
 | 
					
						
							|  |  |  |                 showMessage(_("APPLYING WORKAROUND #5")); | 
					
						
							|  |  |  |                 showMessageBox(QMessageBox::Critical, | 
					
						
							|  |  |  |                     tr("Setting breakpoints failed"), QString::fromLocal8Bit(msg)); | 
					
						
							|  |  |  |                 QTC_ASSERT(state() == InferiorRunOk, /**/); | 
					
						
							|  |  |  |                 notifyInferiorSpontaneousStop(); | 
					
						
							|  |  |  |                 notifyEngineIll(); | 
					
						
							| 
									
										
										
										
											2009-10-05 08:56:02 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2011-01-21 16:42:57 +01:00
										 |  |  |                 // Windows: Some DLL or some function not found. Report
 | 
					
						
							|  |  |  |                 // the exception now in a box.
 | 
					
						
							|  |  |  |                 if (msg.startsWith("During startup program exited with")) | 
					
						
							|  |  |  |                     notifyInferiorExited(); | 
					
						
							|  |  |  |                 QString logMsg; | 
					
						
							|  |  |  |                 if (!m_lastWinException.isEmpty()) | 
					
						
							|  |  |  |                     logMsg = m_lastWinException + QLatin1Char('\n'); | 
					
						
							|  |  |  |                 logMsg += QString::fromLocal8Bit(msg); | 
					
						
							|  |  |  |                 showMessageBox(QMessageBox::Critical, tr("Executable Failed"), logMsg); | 
					
						
							|  |  |  |                 showStatusMessage(tr("Executable failed: %1").arg(logMsg)); | 
					
						
							| 
									
										
										
										
											2009-09-28 09:18:24 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-08-13 09:42:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  |     GdbCommand cmd = m_cookieForToken.take(token); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(LogTimeStamps)) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("Response time: %1: %2 s") | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             .arg(_(cmd.command)) | 
					
						
							| 
									
										
										
										
											2010-06-14 17:23:25 +02:00
										 |  |  |             .arg(cmd.postTime.msecsTo(QTime::currentTime()) / 1000.), | 
					
						
							|  |  |  |             LogTime); | 
					
						
							| 
									
										
										
										
											2009-07-06 11:37:21 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  |     if (response->token < m_oldestAcceptableToken && (cmd.flags & Discardable)) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         //showMessage(_("### SKIPPING OLD RESULT") + response.toString());
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 21:32:08 +02:00
										 |  |  |     response->cookie = cmd.cookie; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  |     bool isExpectedResult = | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |            (response->resultClass == GdbResultError) // Can always happen.
 | 
					
						
							|  |  |  |         || (response->resultClass == GdbResultRunning && (cmd.flags & RunRequest)) | 
					
						
							|  |  |  |         || (response->resultClass == GdbResultExit && (cmd.flags & ExitRequest)) | 
					
						
							|  |  |  |         || (response->resultClass == GdbResultDone); | 
					
						
							|  |  |  |         // GdbResultDone can almost "always" happen. Known examples are:
 | 
					
						
							|  |  |  |         //  (response->resultClass == GdbResultDone && cmd.command == "continue")
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |         // Happens with some incarnations of gdb 6.8 for "jump to line"
 | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |         //  (response->resultClass == GdbResultDone && cmd.command.startsWith("jump"))
 | 
					
						
							|  |  |  |         //  (response->resultClass == GdbResultDone && cmd.command.startsWith("detach"))
 | 
					
						
							|  |  |  |         // Happens when stepping finishes very quickly and issues *stopped/^done
 | 
					
						
							|  |  |  |         // instead of ^running/*stopped
 | 
					
						
							|  |  |  |         //  (response->resultClass == GdbResultDone && (cmd.flags & RunRequest));
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |     if (!isExpectedResult) { | 
					
						
							| 
									
										
										
										
											2010-04-09 12:49:21 +02:00
										 |  |  | #ifdef Q_OS_WIN
 | 
					
						
							|  |  |  |         // Ignore spurious 'running' responses to 'attach'
 | 
					
						
							| 
									
										
										
										
											2010-09-02 16:46:39 +02:00
										 |  |  |         const bool warning = !((startParameters().startMode == AttachExternal | 
					
						
							|  |  |  |                                || startParameters().useTerminal) | 
					
						
							| 
									
										
										
										
											2010-04-09 12:49:21 +02:00
										 |  |  |                                && cmd.command.startsWith("attach")); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         const bool warning = true; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         if (warning) { | 
					
						
							|  |  |  |             QByteArray rsp = GdbResponse::stringFromResultClass(response->resultClass); | 
					
						
							|  |  |  |             rsp = "UNEXPECTED RESPONSE '" + rsp + "' TO COMMAND '" + cmd.command + "'"; | 
					
						
							|  |  |  |             qWarning() << rsp << " AT " __FILE__ ":" STRINGIFY(__LINE__); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_(rsp)); | 
					
						
							| 
									
										
										
										
											2010-04-09 12:49:21 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-10-12 12:00:07 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |     if (cmd.callback) | 
					
						
							|  |  |  |         (this->*cmd.callback)(*response); | 
					
						
							|  |  |  |     else if (cmd.adapterCallback) | 
					
						
							|  |  |  |         (m_gdbAdapter->*cmd.adapterCallback)(*response); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |     if (cmd.flags & RebuildWatchModel) { | 
					
						
							|  |  |  |         --m_pendingWatchRequests; | 
					
						
							| 
									
										
										
										
											2009-10-27 14:52:29 +01:00
										 |  |  |         PENDING_DEBUG("   WATCH" << cmd.command << "=>" << cmd.callbackName | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |                       << "DECREMENTS PENDING WATCH TO" << m_pendingWatchRequests); | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |         if (m_pendingWatchRequests <= 0) { | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |             PENDING_DEBUG("\n\n ... AND TRIGGERS WATCH MODEL UPDATE\n"); | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |             rebuildWatchModel(); | 
					
						
							| 
									
										
										
										
											2009-02-13 12:34:10 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     } else if (cmd.flags & RebuildBreakpointModel) { | 
					
						
							|  |  |  |         --m_pendingBreakpointRequests; | 
					
						
							|  |  |  |         PENDING_DEBUG("   BREAKPOINT" << cmd.command << "=>" << cmd.callbackName | 
					
						
							|  |  |  |                       << "DECREMENTS PENDING TO" << m_pendingWatchRequests); | 
					
						
							|  |  |  |         if (m_pendingBreakpointRequests <= 0) { | 
					
						
							|  |  |  |             PENDING_DEBUG("\n\n ... AND TRIGGERS BREAKPOINT MODEL UPDATE\n"); | 
					
						
							|  |  |  |             attemptBreakpointSynchronization(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-10-27 14:52:29 +01:00
										 |  |  |         PENDING_DEBUG("   OTHER (OUT):" << cmd.command << "=>" << cmd.callbackName | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |                       << "LEAVES PENDING WATCH AT" << m_pendingWatchRequests | 
					
						
							|  |  |  |                       << "LEAVES PENDING BREAKPOINT AT" << m_pendingBreakpointRequests); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-07 12:18:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-02 14:40:54 +01:00
										 |  |  |     // Commands were queued, but we were in RunningRequested state, so the interrupt
 | 
					
						
							|  |  |  |     // was postponed.
 | 
					
						
							|  |  |  |     // This is done after the command callbacks so the running-requesting commands
 | 
					
						
							|  |  |  |     // can assert on the right state.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() == InferiorRunOk && !m_commandsToRunOnTemporaryBreak.isEmpty()) | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |         interruptInferiorTemporarily(); | 
					
						
							| 
									
										
										
										
											2009-11-02 14:40:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-15 12:16:21 +02:00
										 |  |  |     // Continue only if there are no commands wire anymore, so this will
 | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     // be fully synchronous.
 | 
					
						
							| 
									
										
										
										
											2009-05-07 12:18:45 +02:00
										 |  |  |     // This is somewhat inefficient, as it makes the last command synchronous.
 | 
					
						
							|  |  |  |     // An optimization would be requesting the continue immediately when the
 | 
					
						
							|  |  |  |     // event loop is entered, and let individual commands have a flag to suppress
 | 
					
						
							|  |  |  |     // that behavior.
 | 
					
						
							| 
									
										
										
										
											2009-10-08 12:38:01 +02:00
										 |  |  |     if (m_commandsDoneCallback && m_cookieForToken.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("ALL COMMANDS DONE; INVOKING CALLBACK")); | 
					
						
							| 
									
										
										
										
											2009-10-08 12:38:01 +02:00
										 |  |  |         CommandsDoneCallback cont = m_commandsDoneCallback; | 
					
						
							|  |  |  |         m_commandsDoneCallback = 0; | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |         (this->*cont)(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         PENDING_DEBUG("MISSING TOKENS: " << m_cookieForToken.keys()); | 
					
						
							| 
									
										
										
										
											2009-05-07 12:18:45 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-03 14:56:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_cookieForToken.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |         m_commandTimer.stop(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::executeDebuggerCommand(const QString &command) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     if (state() == DebuggerNotReady) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("GDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + command); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-11 15:53:08 +02:00
										 |  |  |     m_gdbAdapter->write(command.toLatin1() + "\r\n"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-29 11:40:40 +02:00
										 |  |  | // Called from CoreAdapter and AttachAdapter
 | 
					
						
							| 
									
										
										
										
											2009-09-23 15:28:50 +02:00
										 |  |  | void GdbEngine::updateAll() | 
					
						
							| 
									
										
										
										
											2009-03-02 15:14:12 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |     if (hasPython()) | 
					
						
							|  |  |  |         updateAllPython(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         updateAllClassic(); | 
					
						
							| 
									
										
										
										
											2009-09-30 12:27:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleQuerySources(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |     m_sourcesListUpdating = false; | 
					
						
							|  |  |  |     m_sourcesListOutdated = false; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  |         QMap<QString, QString> oldShortToFull = m_shortToFullName; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         m_shortToFullName.clear(); | 
					
						
							|  |  |  |         m_fullToShortName.clear(); | 
					
						
							|  |  |  |         // "^done,files=[{file="../../../../bin/gdbmacros/gdbmacros.cpp",
 | 
					
						
							|  |  |  |         // fullname="/data5/dev/ide/main/bin/gdbmacros/gdbmacros.cpp"},
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |         GdbMi files = response.data.findChild("files"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         foreach (const GdbMi &item, files.children()) { | 
					
						
							|  |  |  |             GdbMi fullName = item.findChild("fullname"); | 
					
						
							| 
									
										
										
										
											2010-03-05 18:24:32 +01:00
										 |  |  |             GdbMi fileName = item.findChild("file"); | 
					
						
							|  |  |  |             QString file = QString::fromLocal8Bit(fileName.data()); | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |             if (fullName.isValid()) { | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  |                 QString full = cleanupFullName(QString::fromLocal8Bit(fullName.data())); | 
					
						
							| 
									
										
										
										
											2010-03-05 18:24:32 +01:00
										 |  |  |                 m_shortToFullName[file] = full; | 
					
						
							|  |  |  |                 m_fullToShortName[full] = file; | 
					
						
							|  |  |  |             } else if (fileName.isValid()) { | 
					
						
							|  |  |  |                 m_shortToFullName[file] = tr("<unknown>"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  |         if (m_shortToFullName != oldShortToFull) | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |             sourceFilesHandler()->setSourceFiles(m_shortToFullName); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  | void GdbEngine::handleExecuteJumpToLine(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultRunning) { | 
					
						
							| 
									
										
										
										
											2010-08-16 15:52:38 +02:00
										 |  |  |         notifyInferiorRunOk(); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  |         // All is fine. Waiting for the temporary breakpoint to be hit.
 | 
					
						
							|  |  |  |     } else if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // This happens on old gdb. Trigger the effect of a '*stopped'.
 | 
					
						
							|  |  |  |         showStatusMessage(tr("Jumped. Stopped")); | 
					
						
							| 
									
										
										
										
											2010-07-12 15:39:22 +02:00
										 |  |  |         notifyInferiorSpontaneousStop(); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  |         handleStop1(response); | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  | void GdbEngine::handleExecuteRunToLine(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultRunning) { | 
					
						
							| 
									
										
										
										
											2010-08-16 15:52:38 +02:00
										 |  |  |         notifyInferiorRunOk(); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |         // All is fine. Waiting for the temporary breakpoint to be hit.
 | 
					
						
							|  |  |  |     } else if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // This happens on old gdb. Trigger the effect of a '*stopped'.
 | 
					
						
							|  |  |  |         // >&"continue\n"
 | 
					
						
							|  |  |  |         // >~"Continuing.\n"
 | 
					
						
							|  |  |  |         //>~"testArray () at ../simple/app.cpp:241\n"
 | 
					
						
							|  |  |  |         //>~"241\t    s[1] = \"b\";\n"
 | 
					
						
							|  |  |  |         //>122^done
 | 
					
						
							| 
									
										
										
										
											2010-12-16 19:06:33 +01:00
										 |  |  |         gotoLocation(m_targetFrame); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |         showStatusMessage(tr("Target line hit. Stopped")); | 
					
						
							| 
									
										
										
										
											2010-07-12 15:39:22 +02:00
										 |  |  |         notifyInferiorSpontaneousStop(); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |         handleStop1(response); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  | static bool isExitedReason(const QByteArray &reason) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     return reason == "exited-normally"   // inferior exited normally
 | 
					
						
							|  |  |  |         || reason == "exited-signalled"  // inferior exited because of a signal
 | 
					
						
							|  |  |  |         //|| reason == "signal-received" // inferior received signal
 | 
					
						
							|  |  |  |         || reason == "exited";           // inferior exited
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  | void GdbEngine::handleAqcuiredInferior() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-25 17:19:42 +02:00
										 |  |  |     // Reverse debugging. FIXME: Should only be used when available.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     //if (debuggerCore()->boolSetting(EnableReverseDebugging))
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //    postCommand("target response");
 | 
					
						
							| 
									
										
										
										
											2009-05-25 17:19:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 16:39:17 +02:00
										 |  |  |     tryLoadDebuggingHelpers(); | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #    ifndef Q_OS_MAC
 | 
					
						
							| 
									
										
										
										
											2009-04-07 16:39:17 +02:00
										 |  |  |     // intentionally after tryLoadDebuggingHelpers(),
 | 
					
						
							| 
									
										
										
										
											2010-01-11 10:22:55 +01:00
										 |  |  |     // otherwise we'd interrupt solib loading.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(AllPluginBreakpoints)) { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set auto-solib-add on"); | 
					
						
							|  |  |  |         postCommand("set stop-on-solib-events 0"); | 
					
						
							|  |  |  |         postCommand("sharedlibrary .*"); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     } else if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set auto-solib-add on"); | 
					
						
							|  |  |  |         postCommand("set stop-on-solib-events 1"); | 
					
						
							|  |  |  |         postCommand("sharedlibrary " | 
					
						
							| 
									
										
										
										
											2009-03-19 10:54:27 +01:00
										 |  |  |           + theDebuggerStringSetting(SelectedPluginBreakpointsPattern)); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     } else if (debuggerCore()->boolSetting(NoPluginBreakpoints)) { | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  |         // should be like that already
 | 
					
						
							| 
									
										
										
										
											2010-01-20 17:35:21 +01:00
										 |  |  |         postCommand("set auto-solib-add off"); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set stop-on-solib-events 0"); | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #    endif
 | 
					
						
							| 
									
										
										
										
											2009-03-03 09:31:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 10:08:17 +02:00
										 |  |  |     // It's nicer to see a bit of the world we live in.
 | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  |     reloadModulesInternal(); | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-02-18 15:27:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 15:47:54 +02:00
										 |  |  | #ifdef Q_OS_UNIX
 | 
					
						
							|  |  |  | # define STOP_SIGNAL "SIGINT"
 | 
					
						
							|  |  |  | # define CROSS_STOP_SIGNAL "SIGTRAP"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define STOP_SIGNAL "SIGTRAP"
 | 
					
						
							|  |  |  | # define CROSS_STOP_SIGNAL "SIGINT"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-09 10:20:42 +02:00
										 |  |  | void GdbEngine::handleStopResponse(const GdbMi &data) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-30 17:40:29 +01:00
										 |  |  |     // This is gdb 7+'s initial *stopped in response to attach.
 | 
					
						
							|  |  |  |     // For consistency, we just discard it.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() == InferiorSetupRequested) | 
					
						
							| 
									
										
										
										
											2009-10-30 17:40:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-13 08:41:27 +02:00
										 |  |  |     if (isDying()) { | 
					
						
							|  |  |  |         notifyInferiorStopOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     const QByteArray reason = data.findChild("reason").data(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 16:25:48 +01:00
										 |  |  |     if (isExitedReason(reason)) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         //   // The user triggered a stop, but meanwhile the app simply exited ...
 | 
					
						
							|  |  |  |         //    QTC_ASSERT(state() == InferiorStopRequested
 | 
					
						
							|  |  |  |         //            /*|| state() == InferiorStopRequested_Kill*/,
 | 
					
						
							|  |  |  |         //               qDebug() << state());
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |         QString msg; | 
					
						
							| 
									
										
										
										
											2009-02-17 16:25:48 +01:00
										 |  |  |         if (reason == "exited") { | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |             msg = tr("Application exited with exit code %1") | 
					
						
							| 
									
										
										
										
											2009-04-30 22:22:37 +02:00
										 |  |  |                 .arg(_(data.findChild("exit-code").toString())); | 
					
						
							|  |  |  |         } else if (reason == "exited-signalled" || reason == "signal-received") { | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |             msg = tr("Application exited after receiving signal %1") | 
					
						
							| 
									
										
										
										
											2009-04-30 22:22:37 +02:00
										 |  |  |                 .arg(_(data.findChild("signal-name").toString())); | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |             msg = tr("Application exited normally"); | 
					
						
							| 
									
										
										
										
											2009-02-17 16:25:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-14 11:02:36 +02:00
										 |  |  |         showStatusMessage(msg); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorExited(); | 
					
						
							| 
									
										
										
										
											2009-02-17 16:25:48 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-18 12:30:56 +01:00
										 |  |  |     const int bkptno = data.findChild("bkptno").data().toInt(); | 
					
						
							|  |  |  |     const GdbMi frame = data.findChild("frame"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  |     const int lineNumber = frame.findChild("line").data().toInt(); | 
					
						
							|  |  |  |     QString fullName = QString::fromUtf8(frame.findChild("fullname").data()); | 
					
						
							| 
									
										
										
										
											2011-01-19 10:48:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  |     if (fullName.isEmpty()) | 
					
						
							|  |  |  |         fullName = QString::fromUtf8(frame.findChild("file").data()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     if (bkptno && frame.isValid() | 
					
						
							|  |  |  |             && !isQmlStepBreakpoint1(bkptno) | 
					
						
							|  |  |  |             && !isQmlStepBreakpoint2(bkptno)) { | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  |         // Use opportunity to update the breakpoint marker position.
 | 
					
						
							| 
									
										
										
										
											2010-11-18 15:47:50 +01:00
										 |  |  |         BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |         //qDebug() << " PROBLEM: " << m_qmlBreakpointNumbers << bkptno
 | 
					
						
							|  |  |  |         //    << isQmlStepBreakpoint1(bkptno)
 | 
					
						
							|  |  |  |         //    << isQmlStepBreakpoint2(bkptno)
 | 
					
						
							| 
									
										
										
										
											2010-11-18 15:47:50 +01:00
										 |  |  |         BreakpointId id = handler->findBreakpointByNumber(bkptno); | 
					
						
							|  |  |  |         const BreakpointResponse &response = handler->response(id); | 
					
						
							|  |  |  |         QString fileName = response.fileName; | 
					
						
							|  |  |  |         if (fileName.isEmpty()) | 
					
						
							|  |  |  |             fileName = handler->fileName(id); | 
					
						
							|  |  |  |         if (fileName.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  |             fileName = fullName; | 
					
						
							|  |  |  |         if (!fileName.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-18 12:30:56 +01:00
										 |  |  |             handler->setMarkerFileAndLine(id, fileName, lineNumber); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     //qDebug() << "BP " << bkptno << data.toString();
 | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  |     // Quickly set the location marker.
 | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |     if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction) | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |             && QFileInfo(fullName).exists() | 
					
						
							|  |  |  |             && !isQmlStepBreakpoint1(bkptno) | 
					
						
							|  |  |  |             && !isQmlStepBreakpoint2(bkptno)) | 
					
						
							| 
									
										
										
										
											2010-12-16 19:06:33 +01:00
										 |  |  |         gotoLocation(Location(fullName, lineNumber)); | 
					
						
							| 
									
										
										
										
											2010-11-23 15:54:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-16 18:28:15 +01:00
										 |  |  |     if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()) | 
					
						
							| 
									
										
										
										
											2010-07-13 08:41:27 +02:00
										 |  |  |         notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2009-11-02 16:40:16 +01:00
										 |  |  |         flushQueuedCommands(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         if (state() == InferiorStopOk) { | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |             QTC_ASSERT(m_commandsDoneCallback == 0, /**/); | 
					
						
							|  |  |  |             m_commandsDoneCallback = &GdbEngine::autoContinueInferior; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |             QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()) | 
					
						
							| 
									
										
										
										
											2009-02-16 18:28:15 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() == InferiorRunOk) { | 
					
						
							| 
									
										
										
										
											2009-10-09 10:54:03 +02:00
										 |  |  |         // Stop triggered by a breakpoint or otherwise not directly
 | 
					
						
							|  |  |  |         // initiated by the user.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorSpontaneousStop(); | 
					
						
							|  |  |  |     } else if (state() == InferiorRunRequested) { | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |         // Stop triggered by something like "-exec-step\n"
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         // "&"Cannot access memory at address 0xbfffedd4\n"
 | 
					
						
							|  |  |  |         // In this case a proper response 94^error,msg="" will follow and
 | 
					
						
							|  |  |  |         // be handled in the result handler.
 | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |         // -- or --
 | 
					
						
							|  |  |  |         // *stopped arriving earlier than ^done response to an -exec-step
 | 
					
						
							|  |  |  |         notifyInferiorRunOk(); | 
					
						
							|  |  |  |         notifyInferiorSpontaneousStop(); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     } else if (state() == InferiorStopOk && isQmlStepBreakpoint2(bkptno)) { | 
					
						
							|  |  |  |         // That's expected.
 | 
					
						
							| 
									
										
										
										
											2009-10-09 10:54:03 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); | 
					
						
							|  |  |  |         notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2009-10-09 10:54:03 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |     // FIXME: Replace the #ifdef by the "target" architecture.
 | 
					
						
							|  |  |  | #ifdef Q_OS_LINUX
 | 
					
						
							|  |  |  |     if (!m_entryPoint.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-12-17 12:02:23 +01:00
										 |  |  |         // This is needed as long as we support stock gdb 6.8.
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |         if (frame.findChild("addr").data() == m_entryPoint) { | 
					
						
							|  |  |  |             // There are two expected reasons for getting here:
 | 
					
						
							| 
									
										
										
										
											2010-12-17 12:02:23 +01:00
										 |  |  |             // 1) For some reason, attaching to a stopped process causes *two*
 | 
					
						
							|  |  |  |             // SIGSTOPs
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |             //    when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
 | 
					
						
							|  |  |  |             //    Interestingly enough, on MacOSX no signal is delivered at all.
 | 
					
						
							|  |  |  |             // 2) The explicit tbreak at the entry point we set to query the PID.
 | 
					
						
							| 
									
										
										
										
											2010-12-17 12:02:23 +01:00
										 |  |  |             //    Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports
 | 
					
						
							|  |  |  |             //    everything.
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |             // The case of the user really setting a breakpoint at _start is simply
 | 
					
						
							|  |  |  |             // unsupported.
 | 
					
						
							|  |  |  |             if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8.
 | 
					
						
							|  |  |  |                 postCommand("info proc", CB(handleInfoProc)); | 
					
						
							|  |  |  |             continueInferiorInternal(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // We are past the initial stop(s). No need to waste time on further checks.
 | 
					
						
							|  |  |  |         m_entryPoint.clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     //qDebug() << "STOP: " << m_qmlBreakpointNumbers;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isQmlStepBreakpoint1(bkptno)) | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |     handleStop0(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleStop0(const GdbMi &data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #if 0 // See http://vladimir_prus.blogspot.com/2007/12/debugger-stories-pending-breakpoints.html
 | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |     // Due to LD_PRELOADing the dumpers, these events can occur even before
 | 
					
						
							|  |  |  |     // reaching the entry point. So handle it before the entry point hacks below.
 | 
					
						
							|  |  |  |     if (reason.isEmpty() && m_gdbVersion < 70000 && !m_isMacGdb) { | 
					
						
							|  |  |  |         // On Linux it reports "Stopped due to shared library event\n", but
 | 
					
						
							|  |  |  |         // on Windows it simply forgets about it. Thus, we identify the response
 | 
					
						
							|  |  |  |         // based on it having no frame information.
 | 
					
						
							|  |  |  |         if (!data.findChild("frame").isValid()) { | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |             invalidateSourcesList(); | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |             // Each stop causes a roundtrip and button flicker, so prevent
 | 
					
						
							|  |  |  |             // a flood of useless stops. Will be automatically re-enabled.
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             postCommand("set stop-on-solib-events 0"); | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |             // The related code (handleAqcuiredInferior()) is disabled as well.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             if (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) { | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |                 QString dataStr = _(data.toString()); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("SHARED LIBRARY EVENT: ") + dataStr); | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |                 QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("PATTERN: ") + pat); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |                 postCommand("sharedlibrary " + pat.toLocal8Bit()); | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |                 showStatusMessage(tr("Loading %1...").arg(dataStr)); | 
					
						
							| 
									
										
										
										
											2009-10-30 17:16:56 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |             continueInferiorInternal(); | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-10-23 22:17:15 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-10-23 22:17:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-23 12:31:47 +01:00
										 |  |  |     const GdbMi frame = data.findChild("frame"); | 
					
						
							|  |  |  |     const QByteArray reason = data.findChild("reason").data(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-19 12:00:01 +02:00
										 |  |  |     // This was seen on XP after removing a breakpoint while running
 | 
					
						
							| 
									
										
										
										
											2009-06-19 12:04:21 +02:00
										 |  |  |     //  >945*stopped,reason="signal-received",signal-name="SIGTRAP",
 | 
					
						
							| 
									
										
										
										
											2009-02-13 16:55:24 +01:00
										 |  |  |     //  signal-meaning="Trace/breakpoint trap",thread-id="2",
 | 
					
						
							|  |  |  |     //  frame={addr="0x7c91120f",func="ntdll!DbgUiConnectToDbg",
 | 
					
						
							|  |  |  |     //  args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
 | 
					
						
							| 
									
										
										
										
											2009-12-18 16:25:59 +01:00
										 |  |  |     // also seen on gdb 6.8-symbianelf without qXfer:libraries:read+;
 | 
					
						
							|  |  |  |     // FIXME: remote.c parses "loaded" reply. It should be turning
 | 
					
						
							|  |  |  |     // that into a TARGET_WAITKIND_LOADED. Does it?
 | 
					
						
							|  |  |  |     // The bandaid here has the problem that it breaks for 'next' over a
 | 
					
						
							|  |  |  |     // statement that indirectly loads shared libraries
 | 
					
						
							| 
									
										
										
										
											2010-01-06 14:16:35 +01:00
										 |  |  |     // 6.1.2010: Breaks interrupting inferiors, disabled:
 | 
					
						
							|  |  |  |     // if (reason == "signal-received"
 | 
					
						
							|  |  |  |     //      && data.findChild("signal-name").data() == "SIGTRAP") {
 | 
					
						
							|  |  |  |     //    continueInferiorInternal();
 | 
					
						
							|  |  |  |     //    return;
 | 
					
						
							|  |  |  |     // }
 | 
					
						
							| 
									
										
										
										
											2009-02-13 16:55:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |     // Jump over well-known frames.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     static int stepCounter = 0; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(SkipKnownFrames)) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (reason == "end-stepping-range" || reason == "function-finished") { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             //showMessage(frame.toString());
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |             QString funcName = _(frame.findChild("func").data()); | 
					
						
							|  |  |  |             QString fileName = QString::fromLocal8Bit(frame.findChild("file").data()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             if (isLeavableFunction(funcName, fileName)) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 //showMessage(_("LEAVING ") + funcName);
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 ++stepCounter; | 
					
						
							| 
									
										
										
										
											2010-11-08 15:41:44 +01:00
										 |  |  |                 executeStepOut(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (isSkippableFunction(funcName, fileName)) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 //showMessage(_("SKIPPING ") + funcName);
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 ++stepCounter; | 
					
						
							| 
									
										
										
										
											2010-11-08 15:41:44 +01:00
										 |  |  |                 executeStep(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             //if (stepCounter)
 | 
					
						
							|  |  |  |             //    qDebug() << "STEPCOUNTER:" << stepCounter;
 | 
					
						
							|  |  |  |             stepCounter = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-19 12:00:01 +02:00
										 |  |  |     // Show return value if possible, usually with reason "function-finished".
 | 
					
						
							|  |  |  |     // *stopped,reason="function-finished",frame={addr="0x080556da",
 | 
					
						
							|  |  |  |     // func="testReturnValue",args=[],file="/../app.cpp",
 | 
					
						
							|  |  |  |     // fullname="/../app.cpp",line="1611"},gdb-result-var="$1",
 | 
					
						
							|  |  |  |     // return-value="{d = 0x808d998}",thread-id="1",stopped-threads="all",
 | 
					
						
							|  |  |  |     // core="1"
 | 
					
						
							|  |  |  |     GdbMi resultVar = data.findChild("gdb-result-var"); | 
					
						
							|  |  |  |     if (resultVar.isValid()) | 
					
						
							|  |  |  |         m_resultVarName = resultVar.data(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         m_resultVarName.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-03 14:06:21 +01:00
										 |  |  |     bool initHelpers = m_debuggingHelperState == DebuggingHelperUninitialized | 
					
						
							|  |  |  |                        || m_debuggingHelperState == DebuggingHelperLoadTried; | 
					
						
							| 
									
										
										
										
											2009-10-23 22:52:16 +02:00
										 |  |  |     // Don't load helpers on stops triggered by signals unless it's
 | 
					
						
							|  |  |  |     // an intentional trap.
 | 
					
						
							| 
									
										
										
										
											2009-11-13 14:15:08 +01:00
										 |  |  |     if (initHelpers | 
					
						
							|  |  |  |             && m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperLoadedByGdbPreload | 
					
						
							| 
									
										
										
										
											2009-11-16 11:35:47 +01:00
										 |  |  |             && reason == "signal-received") { | 
					
						
							| 
									
										
										
										
											2009-10-26 13:51:56 +01:00
										 |  |  |         QByteArray name = data.findChild("signal-name").data(); | 
					
						
							|  |  |  |         if (name != STOP_SIGNAL | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |             && (startParameters().startMode != AttachToRemote | 
					
						
							| 
									
										
										
										
											2009-10-26 13:51:56 +01:00
										 |  |  |                 || name != CROSS_STOP_SIGNAL)) | 
					
						
							| 
									
										
										
										
											2009-10-13 14:54:23 +02:00
										 |  |  |             initHelpers = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     if (isSynchronous()) | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  |         initHelpers = false; | 
					
						
							| 
									
										
										
										
											2009-10-23 22:52:16 +02:00
										 |  |  |     if (initHelpers) { | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |         tryLoadDebuggingHelpersClassic(); | 
					
						
							| 
									
										
										
										
											2009-10-23 22:52:16 +02:00
										 |  |  |         QVariant var = QVariant::fromValue<GdbMi>(data); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("p 4", CB(handleStop1), var);  // dummy
 | 
					
						
							| 
									
										
										
										
											2009-10-23 22:52:16 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         handleStop1(data); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-27 15:31:22 +01:00
										 |  |  |     // Dumper loading is sequenced, as otherwise the display functions
 | 
					
						
							|  |  |  |     // will start requesting data without knowing that dumpers are available.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleStop1(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-09 10:59:56 +02:00
										 |  |  |     handleStop1(response.cookie.value<GdbMi>()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleStop1(const GdbMi &data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-13 08:41:27 +02:00
										 |  |  |     if (isDying()) { | 
					
						
							|  |  |  |         qDebug() << "HANDLING STOP WHILE DYING"; | 
					
						
							|  |  |  |         notifyInferiorStopOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-13 10:31:03 +01:00
										 |  |  |     QByteArray reason = data.findChild("reason").data(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-02 16:46:39 +02:00
										 |  |  | #ifdef Q_OS_WIN
 | 
					
						
							|  |  |  |     if (startParameters().useTerminal && reason == "signal-received" | 
					
						
							|  |  |  |         && data.findChild("signal-name").data() == "SIGTRAP") { | 
					
						
							|  |  |  |         // Command line start up trap
 | 
					
						
							|  |  |  |         showMessage(_("INTERNAL CONTINUE"), LogMisc); | 
					
						
							| 
									
										
										
										
											2010-01-13 10:31:03 +01:00
										 |  |  |         continueInferiorInternal(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-02 16:46:39 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-01-13 10:31:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     // This is for display only.
 | 
					
						
							| 
									
										
										
										
											2009-10-22 15:46:49 +02:00
										 |  |  |     if (m_modulesListOutdated) | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |         reloadModulesInternal(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_breakListOutdated) { | 
					
						
							|  |  |  |         reloadBreakListInternal(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Older gdb versions do not produce "library loaded" messages
 | 
					
						
							|  |  |  |         // so the breakpoint update is not triggered.
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |         if (m_gdbVersion < 70000 && !m_isMacGdb && breakHandler()->size() > 0) | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |             reloadBreakListInternal(); | 
					
						
							| 
									
										
										
										
											2010-02-05 15:23:09 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |     if (reason == "watchpoint-trigger") { | 
					
						
							|  |  |  |         // *stopped,reason="watchpoint-trigger",wpt={number="2",exp="*0xbfffed40"},
 | 
					
						
							|  |  |  |         // value={old="1",new="0"},frame={addr="0x00451e1b",
 | 
					
						
							|  |  |  |         // func="QScopedPointer",args=[{name="this",value="0xbfffed40"},
 | 
					
						
							|  |  |  |         // {name="p",value="0x0"}],file="x.h",fullname="/home/.../x.h",line="95"},
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:14:44 +02:00
										 |  |  |         // thread-id="1",stopped-threads="all",core="2"
 | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |         GdbMi wpt = data.findChild("wpt"); | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |         const int bpNumber = wpt.findChild("number").data().toInt(); | 
					
						
							|  |  |  |         const BreakpointId id = breakHandler()->findBreakpointByNumber(bpNumber); | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |         const quint64 bpAddress = wpt.findChild("exp").data().mid(1).toULongLong(0, 0); | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |         showStatusMessage(msgWatchpointTriggered(id, bpNumber, bpAddress)); | 
					
						
							| 
									
										
										
										
											2010-11-23 16:14:19 +01:00
										 |  |  |     } else if (reason == "breakpoint-hit") { | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |         GdbMi gNumber = data.findChild("bkptno"); // 'number' or 'bkptno'?
 | 
					
						
							|  |  |  |         if (!gNumber.isValid()) | 
					
						
							|  |  |  |             gNumber = data.findChild("number"); | 
					
						
							|  |  |  |         const int bpNumber = gNumber.data().toInt(); | 
					
						
							|  |  |  |         const QByteArray threadId = data.findChild("thread-id").data(); | 
					
						
							|  |  |  |         const BreakpointId id = breakHandler()->findBreakpointByNumber(bpNumber); | 
					
						
							| 
									
										
										
										
											2010-12-01 11:27:31 +01:00
										 |  |  |         showStatusMessage(msgBreakpointTriggered(id, bpNumber, _(threadId))); | 
					
						
							| 
									
										
										
										
											2010-12-20 16:28:26 +01:00
										 |  |  |         m_currentThread = threadId; | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |         QString reasontr = msgStopped(_(reason)); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |         if (reason == "signal-received" | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             && debuggerCore()->boolSetting(UseMessageBoxForSignals)) { | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |             QByteArray name = data.findChild("signal-name").data(); | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |             QByteArray meaning = data.findChild("signal-meaning").data(); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:47:54 +02:00
										 |  |  |             // Ignore these as they are showing up regularly when
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |             // stopping debugging.
 | 
					
						
							| 
									
										
										
										
											2010-11-26 14:35:36 +01:00
										 |  |  |             if (name == STOP_SIGNAL) { | 
					
						
							|  |  |  |                 showMessage(_(STOP_SIGNAL " CONSIDERED HARMLESS. CONTINUING.")); | 
					
						
							|  |  |  |             } else if (startParameters().startMode == AttachToRemote | 
					
						
							|  |  |  |                     && name == CROSS_STOP_SIGNAL) { | 
					
						
							|  |  |  |                 showMessage(_(CROSS_STOP_SIGNAL " CONSIDERED HARMLESS. CONTINUING.")); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 showMessage(_("HANDLING SIGNAL" + name)); | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |                 showStoppedBySignalMessageBox(_(meaning), _(name)); | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |                 if (!name.isEmpty() && !meaning.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |                     reasontr = msgStoppedBySignal(_(meaning), _(name)); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (reason.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-17 17:16:34 +01:00
										 |  |  |             showStatusMessage(msgStopped()); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |             showStatusMessage(reasontr); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  |     // Let the event loop run before deciding whether to update the stack.
 | 
					
						
							|  |  |  |     m_stackNeeded = true; // setTokenBarrier() might reset this.
 | 
					
						
							|  |  |  |     m_currentThreadId = data.findChild("thread-id").data().toInt(); | 
					
						
							|  |  |  |     QTimer::singleShot(0, this, SLOT(handleStop2())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleStop2() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // We are already continuing.
 | 
					
						
							|  |  |  |     if (!m_stackNeeded) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |     reloadStack(false); // Will trigger register reload.
 | 
					
						
							| 
									
										
										
										
											2009-09-23 13:59:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (supportsThreads()) { | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |         if (m_gdbAdapter->isTrkAdapter()) { | 
					
						
							| 
									
										
										
										
											2010-02-08 12:39:25 +01:00
										 |  |  |             m_gdbAdapter->trkReloadThreads(); | 
					
						
							| 
									
										
										
										
											2010-05-19 14:24:00 +02:00
										 |  |  |         } else if (m_isMacGdb) { | 
					
						
							| 
									
										
										
										
											2010-09-15 14:16:03 +02:00
										 |  |  |             postCommand("-thread-list-ids", Discardable, | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  |                 CB(handleThreadListIds), m_currentThreadId); | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             // This is only available in gdb 7.1+.
 | 
					
						
							| 
									
										
										
										
											2010-09-15 14:16:03 +02:00
										 |  |  |             postCommand("-thread-info", Discardable, | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  |                 CB(handleThreadInfo), m_currentThreadId); | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-23 13:59:55 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 22:11:56 +01:00
										 |  |  | void GdbEngine::handleInfoProc(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         static QRegExp re(_("\\bprocess ([0-9]+)\n")); | 
					
						
							|  |  |  |         QTC_ASSERT(re.isValid(), return); | 
					
						
							|  |  |  |         if (re.indexIn(_(response.data.findChild("consolestreamoutput").data())) != -1) | 
					
						
							|  |  |  |             maybeHandleInferiorPidChanged(re.cap(1)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleShowVersion(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("PARSING VERSION: " + response.toString())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         m_gdbVersion = 100; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:06:23 +01:00
										 |  |  |         m_gdbBuildVersion = -1; | 
					
						
							| 
									
										
										
										
											2009-10-22 11:08:06 +02:00
										 |  |  |         m_isMacGdb = false; | 
					
						
							| 
									
										
										
										
											2010-01-21 16:34:59 +01:00
										 |  |  |         GdbMi version = response.data.findChild("consolestreamoutput"); | 
					
						
							|  |  |  |         QString msg = QString::fromLocal8Bit(version.data()); | 
					
						
							| 
									
										
										
										
											2010-05-27 15:41:52 +02:00
										 |  |  |         extractGdbVersion(msg, | 
					
						
							|  |  |  |               &m_gdbVersion, &m_gdbBuildVersion, &m_isMacGdb); | 
					
						
							|  |  |  |         if (m_gdbVersion > 60500 && m_gdbVersion < 200000) | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("SUPPORTED GDB VERSION ") + msg); | 
					
						
							| 
									
										
										
										
											2010-05-27 15:41:52 +02:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("UNSUPPORTED GDB VERSION ") + msg); | 
					
						
							| 
									
										
										
										
											2010-01-21 16:34:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("USING GDB VERSION: %1, BUILD: %2%3").arg(m_gdbVersion) | 
					
						
							| 
									
										
										
										
											2010-01-21 16:34:59 +01:00
										 |  |  |             .arg(m_gdbBuildVersion).arg(_(m_isMacGdb ? " (APPLE)" : ""))); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  | void GdbEngine::handleHasPython(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-10-14 09:41:14 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |         m_hasPython = true; | 
					
						
							| 
									
										
										
										
											2010-06-25 09:07:14 +02:00
										 |  |  |         GdbMi contents = response.data.findChild("consolestreamoutput"); | 
					
						
							|  |  |  |         GdbMi data; | 
					
						
							|  |  |  |         data.fromStringMultiple(contents.data()); | 
					
						
							|  |  |  |         const GdbMi dumpers = data.findChild("dumpers"); | 
					
						
							|  |  |  |         foreach (const GdbMi &dumper, dumpers.children()) { | 
					
						
							| 
									
										
										
										
											2010-09-01 19:02:56 +02:00
										 |  |  |             QByteArray type = dumper.findChild("type").data(); | 
					
						
							| 
									
										
										
										
											2010-06-25 09:07:14 +02:00
										 |  |  |             QStringList formats(tr("Raw structure")); | 
					
						
							| 
									
										
										
										
											2010-06-25 09:53:23 +02:00
										 |  |  |             QString reported = _(dumper.findChild("formats").data()); | 
					
						
							|  |  |  |             formats.append(reported.split(_(","), QString::SkipEmptyParts)); | 
					
						
							| 
									
										
										
										
											2010-06-25 09:07:14 +02:00
										 |  |  |             watchHandler()->addTypeFormats(type, formats); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-09-14 12:57:24 +02:00
										 |  |  |         const GdbMi hasInferiorThreadList = data.findChild("hasInferiorThreadList"); | 
					
						
							|  |  |  |         m_hasInferiorThreadList = (hasInferiorThreadList.data().toInt() != 0); | 
					
						
							| 
									
										
										
										
											2009-10-14 09:41:14 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-09-23 14:58:45 +02:00
										 |  |  |         pythonDumpersFailed(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::pythonDumpersFailed() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_hasPython = false; | 
					
						
							|  |  |  |     if (m_gdbAdapter->dumperHandling() | 
					
						
							|  |  |  |                 == AbstractGdbAdapter::DumperLoadedByGdbPreload | 
					
						
							|  |  |  |             && checkDebuggingHelpersClassic()) { | 
					
						
							| 
									
										
										
										
											2010-11-04 18:19:33 +01:00
										 |  |  | #ifdef Q_OS_MAC
 | 
					
						
							|  |  |  |         const char * const LD_PRELOAD_ENV_VAR = "DYLD_INSERT_LIBRARIES"; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD"; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-09-23 14:58:45 +02:00
										 |  |  |         QByteArray cmd = "set environment "; | 
					
						
							| 
									
										
										
										
											2010-11-04 18:19:33 +01:00
										 |  |  |         cmd += LD_PRELOAD_ENV_VAR; | 
					
						
							| 
									
										
										
										
											2010-09-23 14:58:45 +02:00
										 |  |  |         cmd += ' '; | 
					
						
							|  |  |  |         cmd += startParameters().startMode == StartRemoteGdb | 
					
						
							|  |  |  |            ? startParameters().remoteDumperLib | 
					
						
							|  |  |  |            : qtDumperLibraryName().toLocal8Bit(); | 
					
						
							|  |  |  |         postCommand(cmd); | 
					
						
							|  |  |  |         m_debuggingHelperState = DebuggingHelperLoadTried; | 
					
						
							| 
									
										
										
										
											2009-10-14 09:41:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  | void GdbEngine::showExecutionError(const QString &message) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     showMessageBox(QMessageBox::Critical, tr("Execution Error"), | 
					
						
							|  |  |  |        tr("Cannot continue debugged process:\n") + message); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::handleExecuteContinue(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-07-21 14:37:31 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2009-07-21 14:37:31 +02:00
										 |  |  |     if (response.resultClass == GdbResultRunning) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorRunOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |     if (msg.startsWith("Cannot find bounds of current function") | 
					
						
							|  |  |  |         || msg.startsWith("\"finish\" not meaningful in the outermost frame")) { | 
					
						
							|  |  |  |         notifyInferiorRunFailed(); | 
					
						
							|  |  |  |         if (isDying()) | 
					
						
							| 
									
										
										
										
											2009-11-02 16:59:57 +01:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         if (!m_commandsToRunOnTemporaryBreak.isEmpty()) | 
					
						
							|  |  |  |             flushQueuedCommands(); | 
					
						
							|  |  |  |         QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							|  |  |  |         showStatusMessage(tr("Stopped."), 5000); | 
					
						
							|  |  |  |         reloadStack(true); | 
					
						
							|  |  |  |         //showStatusMessage(tr("No debug information available. "
 | 
					
						
							|  |  |  |         //  "Leaving function..."));
 | 
					
						
							|  |  |  |         //executeStepOut();
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         showExecutionError(QString::fromLocal8Bit(msg)); | 
					
						
							|  |  |  |         notifyInferiorIll(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString GdbEngine::fullName(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (fileName.isEmpty()) | 
					
						
							|  |  |  |         return QString(); | 
					
						
							| 
									
										
										
										
											2010-01-29 15:47:51 +01:00
										 |  |  |     //QTC_ASSERT(!m_sourcesListOutdated, /* */)
 | 
					
						
							| 
									
										
										
										
											2009-10-22 22:54:30 +02:00
										 |  |  |     QTC_ASSERT(!m_sourcesListUpdating, /* */) | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  |     return m_shortToFullName.value(fileName, QString()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  | QString GdbEngine::cleanupFullName(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-09 15:27:21 +02:00
										 |  |  |     QString cleanFilePath = fileName; | 
					
						
							|  |  |  | #ifdef Q_OS_WIN
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  |     QTC_ASSERT(!fileName.isEmpty(), return QString()) | 
					
						
							| 
									
										
										
										
											2009-10-29 17:49:37 +01:00
										 |  |  |     // Gdb on windows often delivers "fullnames" which
 | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |     // (a) have no drive letter and (b) are not normalized.
 | 
					
						
							| 
									
										
										
										
											2009-10-29 17:49:37 +01:00
										 |  |  |     QFileInfo fi(fileName); | 
					
						
							| 
									
										
										
										
											2010-08-09 15:27:21 +02:00
										 |  |  |     if (fi.isReadable()) | 
					
						
							|  |  |  |         cleanFilePath = QDir::cleanPath(fi.absoluteFilePath()); | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-08-09 15:27:21 +02:00
										 |  |  |     if (startMode() == StartRemoteGdb) { | 
					
						
							|  |  |  |         cleanFilePath.replace(0, startParameters().remoteMountPoint.length(), | 
					
						
							|  |  |  |             startParameters().localMountDir); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return cleanFilePath; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  | void GdbEngine::shutdownInferior() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); | 
					
						
							|  |  |  |     m_commandsToRunOnTemporaryBreak.clear(); | 
					
						
							|  |  |  |     m_gdbAdapter->shutdownInferior(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::defaultInferiorShutdown(const char *cmd) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); | 
					
						
							|  |  |  |     postCommand(cmd, NeedsStop | LosesChild, CB(handleInferiorShutdown)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleInferiorShutdown(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         notifyInferiorShutdownOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QByteArray ba = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |     if (ba.contains(": No such file or directory.")) { | 
					
						
							|  |  |  |         // This happens when someone removed the binary behind our back.
 | 
					
						
							|  |  |  |         // It is not really an error from a user's point of view.
 | 
					
						
							|  |  |  |         showMessage(_("NOTE: " + ba)); | 
					
						
							|  |  |  |         notifyInferiorShutdownOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     showMessageBox(QMessageBox::Critical, | 
					
						
							|  |  |  |         tr("Failed to shut down application"), | 
					
						
							|  |  |  |         AbstractGdbAdapter::msgInferiorStopFailed(QString::fromLocal8Bit(ba))); | 
					
						
							|  |  |  |     notifyInferiorShutdownFailed(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::shutdownEngine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_gdbAdapter->shutdownAdapter(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::notifyAdapterShutdownFailed() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     showMessage(_("ADAPTER SHUTDOWN FAILED")); | 
					
						
							|  |  |  |     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); | 
					
						
							|  |  |  |     notifyEngineShutdownFailed(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::notifyAdapterShutdownOk() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-07-02 12:20:26 +02:00
										 |  |  |     showMessage(_("INITIATE GDBENGINE SHUTDOWN IN STATE %1, PROC: %2") | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         .arg(lastGoodState()).arg(gdbProc()->state())); | 
					
						
							|  |  |  |     m_commandsDoneCallback = 0; | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |     switch (gdbProc()->state()) { | 
					
						
							|  |  |  |     case QProcess::Running: | 
					
						
							| 
									
										
										
										
											2010-09-07 10:59:40 +02:00
										 |  |  |         postCommand("-gdb-exit", GdbEngine::ExitRequest, CB(handleGdbExit)); | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |     case QProcess::NotRunning: | 
					
						
							|  |  |  |         // Cannot find executable.
 | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |         notifyEngineShutdownOk(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case QProcess::Starting: | 
					
						
							| 
									
										
										
										
											2010-09-07 10:59:40 +02:00
										 |  |  |         showMessage(_("GDB NOT REALLY RUNNING; KILLING IT")); | 
					
						
							|  |  |  |         gdbProc()->kill(); | 
					
						
							|  |  |  |         notifyEngineShutdownFailed(); | 
					
						
							| 
									
										
										
										
											2010-09-29 10:32:41 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2010-09-07 10:59:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleGdbExit(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultExit) { | 
					
						
							|  |  |  |         showMessage(_("GDB CLAIMS EXIT; WAITING")); | 
					
						
							|  |  |  |         // Don't set state here, this will be handled in handleGdbFinished()
 | 
					
						
							|  |  |  |         //notifyEngineShutdownOk();
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         QString msg = m_gdbAdapter->msgGdbStopFailed( | 
					
						
							|  |  |  |             QString::fromLocal8Bit(response.data.findChild("msg").data())); | 
					
						
							|  |  |  |         qDebug() << (_("GDB WON'T EXIT (%1); KILLING IT").arg(msg)); | 
					
						
							|  |  |  |         showMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg)); | 
					
						
							|  |  |  |         gdbProc()->kill(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-07 15:20:44 +02:00
										 |  |  | void GdbEngine::detachDebugger() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							|  |  |  |     QTC_ASSERT(startMode() != AttachCore, qDebug() << startMode()); | 
					
						
							| 
									
										
										
										
											2010-07-12 15:39:22 +02:00
										 |  |  |     postCommand("detach", GdbEngine::ExitRequest, CB(handleDetach)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleDetach(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_UNUSED(response); | 
					
						
							|  |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorExited(); | 
					
						
							| 
									
										
										
										
											2010-07-02 12:20:26 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | int GdbEngine::currentFrame() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     return stackHandler()->currentIndex(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | QString msgNoBinaryForToolChain(int tc) | 
					
						
							| 
									
										
										
										
											2010-04-09 08:43:26 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     using namespace ProjectExplorer; | 
					
						
							|  |  |  |     return GdbEngine::tr("There is no gdb binary available for '%1'") | 
					
						
							|  |  |  |         .arg(ToolChain::toolChainName(ToolChainType(tc))); | 
					
						
							| 
									
										
										
										
											2009-10-08 17:23:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 13:17:54 +02:00
										 |  |  | AbstractGdbAdapter *GdbEngine::createAdapter() | 
					
						
							| 
									
										
										
										
											2009-09-29 13:49:35 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     const DebuggerStartParameters &sp = startParameters(); | 
					
						
							| 
									
										
										
										
											2010-06-14 13:17:54 +02:00
										 |  |  |     switch (sp.toolChainType) { | 
					
						
							| 
									
										
										
										
											2011-01-07 15:47:22 +01:00
										 |  |  |     case ProjectExplorer::ToolChain_WINSCW: // S60
 | 
					
						
							|  |  |  |     case ProjectExplorer::ToolChain_GCCE: | 
					
						
							|  |  |  |     case ProjectExplorer::ToolChain_RVCT2_ARMV5: | 
					
						
							|  |  |  |     case ProjectExplorer::ToolChain_RVCT2_ARMV6: | 
					
						
							|  |  |  |     case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: | 
					
						
							|  |  |  |     case ProjectExplorer::ToolChain_GCCE_GNUPOC: | 
					
						
							|  |  |  |         // FIXME: 1 of 3 testing hacks.
 | 
					
						
							|  |  |  |         if (sp.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) | 
					
						
							|  |  |  |             return new TcfTrkGdbAdapter(this); | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |             return new TrkGdbAdapter(this); | 
					
						
							| 
									
										
										
										
											2011-01-07 15:47:22 +01:00
										 |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-09-29 13:49:35 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 13:17:54 +02:00
										 |  |  |     switch (sp.startMode) { | 
					
						
							| 
									
										
										
										
											2011-01-07 15:47:22 +01:00
										 |  |  |     case AttachCore: | 
					
						
							|  |  |  |         return new CoreGdbAdapter(this); | 
					
						
							|  |  |  |     case AttachToRemote: | 
					
						
							|  |  |  |         return new RemoteGdbServerAdapter(this, sp.toolChainType); | 
					
						
							|  |  |  |     case StartRemoteGdb: | 
					
						
							|  |  |  |         return new RemotePlainGdbAdapter(this); | 
					
						
							|  |  |  |     case AttachExternal: | 
					
						
							|  |  |  |         return new AttachGdbAdapter(this); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         if (sp.useTerminal) | 
					
						
							|  |  |  |             return new TermGdbAdapter(this); | 
					
						
							|  |  |  |         return new LocalPlainGdbAdapter(this); | 
					
						
							| 
									
										
										
										
											2009-09-29 13:49:35 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  | void GdbEngine::setupEngine() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized, /**/); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 12:41:26 +02:00
										 |  |  |     if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         connect(debuggerCore()->action(UseDebuggingHelpers), | 
					
						
							|  |  |  |             SIGNAL(valueChanged(QVariant)), | 
					
						
							|  |  |  |             SLOT(setUseDebuggingHelpers(QVariant))); | 
					
						
							| 
									
										
										
										
											2010-07-08 12:41:26 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-24 10:08:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == EngineSetupRequested, /**/); | 
					
						
							| 
									
										
										
										
											2009-09-23 10:14:53 +02:00
										 |  |  |     m_gdbAdapter->startAdapter(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-05 10:23:55 +01:00
										 |  |  | unsigned GdbEngine::debuggerCapabilities() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-13 15:57:34 +02:00
										 |  |  |     unsigned caps = ReverseSteppingCapability | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |         | AutoDerefPointersCapability | 
					
						
							|  |  |  |         | DisassemblerCapability | 
					
						
							|  |  |  |         | RegisterCapability | 
					
						
							|  |  |  |         | ShowMemoryCapability | 
					
						
							|  |  |  |         | JumpToLineCapability | 
					
						
							|  |  |  |         | ReloadModuleCapability | 
					
						
							|  |  |  |         | ReloadModuleSymbolsCapability | 
					
						
							|  |  |  |         | BreakOnThrowAndCatchCapability | 
					
						
							| 
									
										
										
										
											2010-06-15 11:14:44 +02:00
										 |  |  |         | ReturnFromFunctionCapability | 
					
						
							| 
									
										
										
										
											2010-04-16 16:36:00 +02:00
										 |  |  |         | CreateFullBacktraceCapability | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |         | WatchpointCapability | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |         | AddWatcherCapability | 
					
						
							|  |  |  |         | ShowModuleSymbolsCapability; | 
					
						
							| 
									
										
										
										
											2010-07-13 15:57:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (startParameters().startMode == AttachCore) | 
					
						
							|  |  |  |         return caps; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return caps | SnapshotCapability; | 
					
						
							| 
									
										
										
										
											2010-02-05 10:23:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-08 13:47:56 +02:00
										 |  |  | void GdbEngine::continueInferiorInternal() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-20 12:14:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							|  |  |  |     notifyInferiorRunRequested(); | 
					
						
							|  |  |  |     showStatusMessage(tr("Running requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |     postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-08 13:47:56 +02:00
										 |  |  | void GdbEngine::autoContinueInferior() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-30 08:59:22 +01:00
										 |  |  |     resetLocation(); | 
					
						
							| 
									
										
										
										
											2009-10-08 13:47:56 +02:00
										 |  |  |     continueInferiorInternal(); | 
					
						
							|  |  |  |     showStatusMessage(tr("Continuing after temporary stop..."), 1000); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::continueInferior() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2009-10-20 14:08:59 +02:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2009-10-08 13:47:56 +02:00
										 |  |  |     continueInferiorInternal(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeStep() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Step requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0) | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |         postCommand("sal step,0x" + QByteArray::number(stackHandler()->topAddress(), 16)); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     if (isReverseDebugging()) | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |         postCommand("reverse-step", RunRequest, CB(handleExecuteStep)); | 
					
						
							| 
									
										
										
										
											2009-05-25 17:19:42 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |         postCommand("-exec-step", RunRequest, CB(handleExecuteStep)); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::handleExecuteStep(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // Step was finishing too quick, and a '*stopped' messages should
 | 
					
						
							|  |  |  |         // have preceeded it, so just ignore this result.
 | 
					
						
							|  |  |  |         QTC_ASSERT(state() == InferiorStopOk, /**/); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     if (response.resultClass == GdbResultRunning) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorRunOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |     if (msg.startsWith("Cannot find bounds of current function")) { | 
					
						
							|  |  |  |         notifyInferiorRunFailed(); | 
					
						
							|  |  |  |         if (isDying()) | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         if (!m_commandsToRunOnTemporaryBreak.isEmpty()) | 
					
						
							|  |  |  |             flushQueuedCommands(); | 
					
						
							|  |  |  |         executeStepI(); // Fall back to instruction-wise stepping.
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         showExecutionError(QString::fromLocal8Bit(msg)); | 
					
						
							|  |  |  |         notifyInferiorIll(); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeStepI() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Step by instruction requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     if (isReverseDebugging()) | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |         postCommand("reverse-stepi", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2009-05-25 17:19:42 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |         postCommand("-exec-step-instruction", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeStepOut() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-06-01 14:35:51 +02:00
										 |  |  |     postCommand("-stack-select-frame 0"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Finish function requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |     postCommand("-exec-finish", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeNext() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Step next requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0) | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |         postCommand("sal next,0x" + QByteArray::number(stackHandler()->topAddress(), 16)); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     if (isReverseDebugging()) | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |         postCommand("reverse-next", RunRequest, CB(handleExecuteNext)); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |         postCommand("-exec-next", RunRequest, CB(handleExecuteNext)); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::handleExecuteNext(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-12 11:52:11 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // Step was finishing too quick, and a '*stopped' messages should
 | 
					
						
							|  |  |  |         // have preceeded it, so just ignore this result.
 | 
					
						
							|  |  |  |         QTC_ASSERT(state() == InferiorStopOk, /**/); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     if (response.resultClass == GdbResultRunning) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorRunOk(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							|  |  |  |     QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |     if (msg.startsWith("Cannot find bounds of current function")) { | 
					
						
							|  |  |  |         if (!m_commandsToRunOnTemporaryBreak.isEmpty()) | 
					
						
							|  |  |  |             flushQueuedCommands(); | 
					
						
							|  |  |  |         notifyInferiorRunFailed(); | 
					
						
							|  |  |  |         if (!isDying()) | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |             executeNextI(); // Fall back to instruction-wise stepping.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         showMessageBox(QMessageBox::Critical, tr("Execution Error"), | 
					
						
							|  |  |  |            tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); | 
					
						
							|  |  |  |         notifyInferiorIll(); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeNextI() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Step next instruction requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     if (isReverseDebugging()) | 
					
						
							| 
									
										
										
										
											2010-03-11 11:07:16 +01:00
										 |  |  |         postCommand("reverse-nexti", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2009-05-25 17:19:42 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |         postCommand("-exec-next-instruction", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeRunToLine(const QString &fileName, int lineNumber) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage(tr("Run to line %1 requested...").arg(lineNumber), 5000); | 
					
						
							| 
									
										
										
										
											2010-03-29 15:58:52 +02:00
										 |  |  | #if 1
 | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |     m_targetFrame.file = fileName; | 
					
						
							|  |  |  |     m_targetFrame.line = lineNumber; | 
					
						
							| 
									
										
										
										
											2010-03-29 15:58:52 +02:00
										 |  |  |     QByteArray loc = '"' + breakLocation(fileName).toLocal8Bit() + '"' + ':' | 
					
						
							|  |  |  |         + QByteArray::number(lineNumber); | 
					
						
							|  |  |  |     postCommand("tbreak " + loc); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:39:41 +02:00
										 |  |  |     postCommand("continue", RunRequest, CB(handleExecuteRunToLine)); | 
					
						
							| 
									
										
										
										
											2010-03-29 15:58:52 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     // Seems to jump to unpredicatable places. Observed in the manual
 | 
					
						
							|  |  |  |     // tests in the Foo::Foo() constructor with both gdb 6.8 and 7.1.
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     QByteArray args = '"' + breakLocation(fileName).toLocal8Bit() + '"' + ':' | 
					
						
							|  |  |  |         + QByteArray::number(lineNumber); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |     postCommand("-exec-until " + args, RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2010-03-29 15:58:52 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeRunToFunction(const QString &functionName) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("-break-insert -t " + functionName.toLatin1()); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000); | 
					
						
							| 
									
										
										
										
											2009-10-20 14:08:59 +02:00
										 |  |  |     continueInferiorInternal(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeJumpToLine(const QString &fileName, int lineNumber) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     StackFrame frame; | 
					
						
							|  |  |  |     frame.file = fileName; | 
					
						
							|  |  |  |     frame.line = lineNumber; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #if 1
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     QByteArray loc = '"' + breakLocation(fileName).toLocal8Bit() + '"' + ':' | 
					
						
							|  |  |  |         + QByteArray::number(lineNumber); | 
					
						
							|  |  |  |     postCommand("tbreak " + loc); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2010-06-30 14:18:47 +02:00
										 |  |  |     postCommand("jump " + loc, RunRequest, CB(handleExecuteJumpToLine)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // will produce something like
 | 
					
						
							| 
									
										
										
										
											2009-10-22 22:54:30 +02:00
										 |  |  |     //  &"jump \"/home/apoenitz/dev/work/test1/test1.cpp\":242"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     //  ~"Continuing at 0x4058f3."
 | 
					
						
							|  |  |  |     //  ~"run1 (argc=1, argv=0x7fffbf1f5538) at test1.cpp:242"
 | 
					
						
							|  |  |  |     //  ~"242\t x *= 2;"
 | 
					
						
							|  |  |  |     //  23^done"
 | 
					
						
							| 
									
										
										
										
											2010-12-16 19:06:33 +01:00
										 |  |  |     gotoLocation(frame); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     //setBreakpoint();
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //postCommand("jump " + loc);
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-12-16 19:06:33 +01:00
										 |  |  |     gotoLocation(frame); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     setBreakpoint(fileName, lineNumber); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("jump " + loc, RunRequest); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::executeReturn() | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorStopOk, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  |     showStatusMessage(tr("Immediate return from function requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  |     postCommand("-exec-finish", RunRequest, CB(handleExecuteReturn)); | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 16:17:40 +01:00
										 |  |  | void GdbEngine::handleExecuteReturn(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyInferiorStopOk(); | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  |         updateAll(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyInferiorRunFailed(); | 
					
						
							| 
									
										
										
										
											2010-02-15 16:02:41 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |     \fn void GdbEngine::setTokenBarrier() | 
					
						
							| 
									
										
										
										
											2009-02-18 13:50:55 +01:00
										 |  |  |     \brief Discard the results of all pending watch-updating commands. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 10:28:31 +01:00
										 |  |  |     This method is called at the beginning of all step/next/finish etc. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     debugger functions. | 
					
						
							| 
									
										
										
										
											2009-02-18 13:50:55 +01:00
										 |  |  |     If non-watch-updating commands with call-backs are still in the pipe, | 
					
						
							|  |  |  |     it will complain. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::setTokenBarrier() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 18:30:22 +02:00
										 |  |  |     foreach (const GdbCommand &cookie, m_cookieForToken) { | 
					
						
							|  |  |  |         QTC_ASSERT(!cookie.callback || (cookie.flags & Discardable), | 
					
						
							| 
									
										
										
										
											2010-03-10 17:39:08 +01:00
										 |  |  |             qDebug() << "CMD:" << cookie.command | 
					
						
							|  |  |  |                 << " FLAGS:" << cookie.flags | 
					
						
							|  |  |  |                 << " CALLBACK:" << cookie.callbackName; | 
					
						
							| 
									
										
										
										
											2009-04-14 12:14:01 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-04 10:11:42 +01:00
										 |  |  |     PENDING_DEBUG("\n--- token barrier ---\n"); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("--- token barrier ---"), LogMiscInput); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(LogTimeStamps)) | 
					
						
							| 
									
										
										
										
											2010-09-22 16:20:08 +02:00
										 |  |  |         showMessage(LogWindow::logTimeStamp(), LogMiscInput); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     m_oldestAcceptableToken = currentToken(); | 
					
						
							| 
									
										
										
										
											2010-12-17 13:07:17 +01:00
										 |  |  |     m_stackNeeded = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Breakpoint specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  | void GdbEngine::updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |     QTC_ASSERT(bkpt.isValid(), return); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |     BreakpointResponse response = breakHandler()->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |     response.multiple = false; | 
					
						
							|  |  |  |     response.enabled = true; | 
					
						
							| 
									
										
										
										
											2010-11-18 14:57:00 +01:00
										 |  |  |     response.pending = false; | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |     response.condition.clear(); | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |     QByteArray file, fullName; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     foreach (const GdbMi &child, bkpt.children()) { | 
					
						
							|  |  |  |         if (child.hasName("number")) { | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |             response.number = child.data().toInt(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("func")) { | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |             response.functionName = _(child.data()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("addr")) { | 
					
						
							|  |  |  |             // <MULTIPLE> happens in constructors. In this case there are
 | 
					
						
							|  |  |  |             // _two_ fields named "addr" in the response. On Linux that is...
 | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  |             if (child.data().startsWith("0x")) { | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |                 response.address = child.data().mid(2).toULongLong(0, 16); | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2010-11-16 11:55:48 +01:00
										 |  |  |                 response.extra = child.data(); | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  |                 if (child.data() == "<MULTIPLE>") | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |                     response.multiple = true; | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("file")) { | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |             file = child.data(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("fullname")) { | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |             fullName = child.data(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("line")) { | 
					
						
							| 
									
										
										
										
											2011-01-05 19:30:24 +01:00
										 |  |  |             // The line numbers here are the uncorrected ones. So don't
 | 
					
						
							|  |  |  |             // change it if we know better already.
 | 
					
						
							|  |  |  |             if (response.correctedLineNumber == 0) | 
					
						
							|  |  |  |                 response.lineNumber = child.data().toInt(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else if (child.hasName("cond")) { | 
					
						
							|  |  |  |             // gdb 6.3 likes to "rewrite" conditions. Just accept that fact.
 | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |             response.condition = child.data(); | 
					
						
							| 
									
										
										
										
											2009-06-10 10:30:48 +02:00
										 |  |  |         } else if (child.hasName("enabled")) { | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |             response.enabled = (child.data() == "y"); | 
					
						
							| 
									
										
										
										
											2009-10-01 12:06:15 +02:00
										 |  |  |         } else if (child.hasName("pending")) { | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |             // Any content here would be interesting only if we did accept
 | 
					
						
							|  |  |  |             // spontaneously appearing breakpoints (user using gdb commands).
 | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |             response.pending = true; | 
					
						
							| 
									
										
										
										
											2009-10-01 12:06:15 +02:00
										 |  |  |         } else if (child.hasName("at")) { | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |             // Happens with gdb 6.4 symbianelf.
 | 
					
						
							| 
									
										
										
										
											2009-10-01 12:06:15 +02:00
										 |  |  |             QByteArray ba = child.data(); | 
					
						
							|  |  |  |             if (ba.startsWith('<') && ba.endsWith('>')) | 
					
						
							|  |  |  |                 ba = ba.mid(1, ba.size() - 2); | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |             response.functionName = _(ba); | 
					
						
							| 
									
										
										
										
											2010-04-29 18:36:18 +02:00
										 |  |  |         } else if (child.hasName("thread")) { | 
					
						
							| 
									
										
										
										
											2010-11-30 13:39:01 +01:00
										 |  |  |             response.threadSpec = child.data().toInt(); | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |         } else if (child.hasName("type")) { | 
					
						
							| 
									
										
										
										
											2010-12-16 17:58:43 +01:00
										 |  |  |             // "breakpoint", "hw breakpoint", "tracepoint"
 | 
					
						
							|  |  |  |             if (child.data().contains("tracepoint")) | 
					
						
							|  |  |  |                 response.tracepoint = true; | 
					
						
							|  |  |  |             else if (!child.data().contains("reakpoint")) | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |                 response.type = Watchpoint; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |         // This field is not present.  Contents needs to be parsed from
 | 
					
						
							|  |  |  |         // the plain "ignore" response.
 | 
					
						
							|  |  |  |         //else if (child.hasName("ignore"))
 | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |         //    response.ignoreCount = child.data();
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |     QString name; | 
					
						
							|  |  |  |     if (!fullName.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  |         name = cleanupFullName(QFile::decodeName(fullName)); | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |         response.fileName = name; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         //if (data->markerFileName().isEmpty())
 | 
					
						
							|  |  |  |         //    data->setMarkerFileName(name);
 | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         name = QFile::decodeName(file); | 
					
						
							| 
									
										
										
										
											2010-02-01 17:49:11 +01:00
										 |  |  |         // Use fullName() once we have a mapping which is more complete than
 | 
					
						
							|  |  |  |         // gdb's own. No point in assigning markerFileName for now.
 | 
					
						
							| 
									
										
										
										
											2009-10-23 18:45:01 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-01 17:49:11 +01:00
										 |  |  |     if (!name.isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |         response.fileName = name; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     breakHandler()->setResponse(id, response); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-22 22:54:30 +02:00
										 |  |  | QString GdbEngine::breakLocation(const QString &file) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     //QTC_ASSERT(!m_breakListOutdated, /* */)
 | 
					
						
							| 
									
										
										
										
											2009-10-22 22:54:30 +02:00
										 |  |  |     QString where = m_fullToShortName.value(file); | 
					
						
							|  |  |  |     if (where.isEmpty()) | 
					
						
							|  |  |  |         return QFileInfo(file).fileName(); | 
					
						
							|  |  |  |     return where; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | static QByteArray addressSpec(quint64 address) | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     return "*0x" + QByteArray::number(address, 16); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | QByteArray GdbEngine::breakpointLocation(BreakpointId id) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     const BreakpointParameters &data = handler->breakpointData(id); | 
					
						
							|  |  |  |     QTC_ASSERT(data.type != UnknownType, return QByteArray()); | 
					
						
							| 
									
										
										
										
											2010-11-16 10:23:20 +01:00
										 |  |  |     // FIXME: Non-GCC-runtime
 | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (data.type == BreakpointAtThrow) | 
					
						
							| 
									
										
										
										
											2010-11-16 10:23:20 +01:00
										 |  |  |         return "__cxa_throw"; | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (data.type == BreakpointAtCatch) | 
					
						
							| 
									
										
										
										
											2010-11-16 10:23:20 +01:00
										 |  |  |         return "__cxa_begin_catch"; | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (data.type == BreakpointAtMain) | 
					
						
							| 
									
										
										
										
											2010-11-16 10:23:20 +01:00
										 |  |  | #ifdef Q_OS_WIN
 | 
					
						
							| 
									
										
										
										
											2010-11-25 14:33:13 +01:00
										 |  |  |         // FIXME: Should be target specific.
 | 
					
						
							| 
									
										
										
										
											2010-11-16 10:23:20 +01:00
										 |  |  |         return "qMain"; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         return "main"; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-11-25 14:33:13 +01:00
										 |  |  |     if (data.type == BreakpointByFunction) | 
					
						
							|  |  |  |         return data.functionName.toUtf8(); | 
					
						
							|  |  |  |     if (data.type == BreakpointByAddress) | 
					
						
							|  |  |  |         return addressSpec(data.address); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     const QString fileName = data.useFullPath | 
					
						
							| 
									
										
										
										
											2010-11-16 12:17:00 +01:00
										 |  |  |         ? data.fileName : breakLocation(data.fileName); | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |     // The argument is simply a C-quoted version of the argument to the
 | 
					
						
							|  |  |  |     // non-MI "break" command, including the "original" quoting it wants.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     return "\"\\\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\\\":" | 
					
						
							| 
									
										
										
										
											2010-11-25 14:33:13 +01:00
										 |  |  |         + QByteArray::number(data.lineNumber) + '"'; | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  | void GdbEngine::handleWatchInsert(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     const int id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // "Hardware watchpoint 2: *0xbfffed40\n"
 | 
					
						
							|  |  |  |         QByteArray ba = response.data.findChild("consolestreamoutput").data(); | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |         if (ba.startsWith("Hardware watchpoint ") | 
					
						
							|  |  |  |                 || ba.startsWith("Watchpoint ")) { | 
					
						
							|  |  |  |             const int end = ba.indexOf(':'); | 
					
						
							|  |  |  |             const int begin = ba.lastIndexOf(' ', end) + 1; | 
					
						
							|  |  |  |             const QByteArray address = ba.mid(end + 3).trimmed(); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |             BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |             BreakpointResponse response = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |             response.number = ba.mid(begin, end - begin).toInt(); | 
					
						
							|  |  |  |             response.address = address.toULongLong(0, 0); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |             handler->setResponse(id, response); | 
					
						
							|  |  |  |             QTC_ASSERT(!handler->needsChange(id), /**/); | 
					
						
							|  |  |  |             handler->notifyBreakpointInsertOk(id); | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-11-26 12:30:05 +01:00
										 |  |  |             showMessage(_("CANNOT PARSE WATCHPOINT FROM " + ba)); | 
					
						
							| 
									
										
										
										
											2010-05-07 15:16:31 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-18 13:38:58 +01:00
										 |  |  | void GdbEngine::attemptAdjustBreakpointLocation(BreakpointId id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!debuggerCore()->boolSetting(AdjustBreakpointLocations)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     BreakpointResponse response = breakHandler()->response(id); | 
					
						
							|  |  |  |     if (response.address == 0 || response.correctedLineNumber != 0) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     // Prevent endless loop.
 | 
					
						
							|  |  |  |     response.correctedLineNumber = -1; | 
					
						
							|  |  |  |     breakHandler()->setResponse(id, response); | 
					
						
							|  |  |  |     postCommand("info line *0x" + QByteArray::number(response.address, 16), | 
					
						
							|  |  |  |         NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |         CB(handleInfoLine), id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  | void GdbEngine::handleBreakInsert1(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-16 17:58:43 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2010-11-25 14:33:13 +01:00
										 |  |  |     BreakpointId id(response.cookie.toInt()); | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // Interesting only on Mac?
 | 
					
						
							|  |  |  |         GdbMi bkpt = response.data.findChild("bkpt"); | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |         updateBreakpointDataFromOutput(id, bkpt); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         if (handler->needsChange(id)) { | 
					
						
							|  |  |  |             handler->notifyBreakpointChangeAfterInsertNeeded(id); | 
					
						
							|  |  |  |             changeBreakpoint(id); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             handler->notifyBreakpointInsertOk(id); | 
					
						
							|  |  |  |             attemptAdjustBreakpointLocation(id); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-12-16 17:58:43 +01:00
										 |  |  |     } else if (response.data.findChild("msg").data().contains("Unknown option")) { | 
					
						
							|  |  |  |         // Older version of gdb don't know the -a option to set tracepoints
 | 
					
						
							|  |  |  |         // ^error,msg="mi_cmd_break_insert: Unknown option ``a''"
 | 
					
						
							|  |  |  |         const QString fileName = handler->fileName(id); | 
					
						
							|  |  |  |         const int lineNumber = handler->lineNumber(id); | 
					
						
							|  |  |  |         QByteArray cmd = "trace " | 
					
						
							|  |  |  |             "\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\":" | 
					
						
							|  |  |  |             + QByteArray::number(lineNumber); | 
					
						
							|  |  |  |         postCommand(cmd, NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleTraceInsert2), id); | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // Some versions of gdb like "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)"
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:14:44 +02:00
										 |  |  |         // know how to do pending breakpoints using CLI but not MI. So try
 | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |         // again with MI.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         QByteArray cmd = "break " + breakpointLocation(id); | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |         postCommand(cmd, NeedsStop | RebuildBreakpointModel, | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             CB(handleBreakInsert2), id); | 
					
						
							| 
									
										
										
										
											2010-03-04 15:42:09 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleBreakInsert2(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultError) { | 
					
						
							|  |  |  |         if (m_gdbVersion < 60800 && !m_isMacGdb) { | 
					
						
							|  |  |  |             // This gdb version doesn't "do" pending breakpoints.
 | 
					
						
							|  |  |  |             // Not much we can do about it except implementing the
 | 
					
						
							|  |  |  |             // logic on top of shared library events, and that's not
 | 
					
						
							|  |  |  |             // worth the effort.
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             QTC_ASSERT(false, /**/); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-16 17:58:43 +01:00
										 |  |  | void GdbEngine::handleTraceInsert2(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) | 
					
						
							|  |  |  |         reloadBreakListInternal(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  | void GdbEngine::reloadBreakListInternal() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     postCommand("-break-list", | 
					
						
							|  |  |  |         NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |         CB(handleBreakList)); | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-27 15:36:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  | void GdbEngine::handleBreakList(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // 45^done,BreakpointTable={nr_rows="2",nr_cols="6",hdr=[
 | 
					
						
							|  |  |  |     // {width="3",alignment="-1",col_name="number",colhdr="Num"}, ...
 | 
					
						
							|  |  |  |     // body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",
 | 
					
						
							|  |  |  |     //  addr="0x000000000040109e",func="main",file="app.cpp",
 | 
					
						
							|  |  |  |     //  fullname="/home/apoenitz/dev/work/plugintest/app/app.cpp",
 | 
					
						
							|  |  |  |     //  line="11",times="1"},
 | 
					
						
							|  |  |  |     //  bkpt={number="2",type="breakpoint",disp="keep",enabled="y",
 | 
					
						
							|  |  |  |     //  addr="<PENDING>",pending="plugin.cpp:7",times="0"}] ... }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         GdbMi table = response.data.findChild("BreakpointTable"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (table.isValid()) | 
					
						
							|  |  |  |             handleBreakList(table); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleBreakList(const GdbMi &table) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |     const GdbMi body = table.findChild("body"); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QList<GdbMi> bkpts; | 
					
						
							|  |  |  |     if (body.isValid()) { | 
					
						
							|  |  |  |         // Non-Mac
 | 
					
						
							|  |  |  |         bkpts = body.children(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Mac
 | 
					
						
							|  |  |  |         bkpts = table.children(); | 
					
						
							| 
									
										
										
										
											2009-10-02 13:24:41 +02:00
										 |  |  |         // Remove the 'hdr' and artificial items.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         for (int i = bkpts.size(); --i >= 0; ) { | 
					
						
							|  |  |  |             int num = bkpts.at(i).findChild("number").data().toInt(); | 
					
						
							| 
									
										
										
										
											2009-10-02 13:24:41 +02:00
										 |  |  |             if (num <= 0) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 bkpts.removeAt(i); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |     foreach (const GdbMi &bkpt, bkpts) { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         BreakpointResponse needle; | 
					
						
							| 
									
										
										
										
											2010-12-01 11:43:48 +01:00
										 |  |  |         needle.number = bkpt.findChild("number").data().toInt(); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |         if (isQmlStepBreakpoint2(needle.number)) | 
					
						
							| 
									
										
										
										
											2011-01-19 10:48:39 +01:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         BreakpointId id = breakHandler()->findSimilarBreakpoint(needle); | 
					
						
							|  |  |  |         if (id != BreakpointId(-1)) { | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |             updateBreakpointDataFromOutput(id, bkpt); | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             qDebug() << "  NOTHING SUITABLE FOUND"; | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("CANNOT FIND BP: " + bkpt.toString())); | 
					
						
							| 
									
										
										
										
											2010-05-10 12:34:52 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |     m_breakListOutdated = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-25 13:33:38 +01:00
										 |  |  | void GdbEngine::handleBreakDisable(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     QTC_ASSERT(response.resultClass == GdbResultDone, /**/) | 
					
						
							| 
									
										
										
										
											2010-11-18 16:07:42 +01:00
										 |  |  |     const BreakpointId id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     // This should only be the requested state.
 | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     QTC_ASSERT(!handler->isEnabled(id), /* Prevent later recursion */); | 
					
						
							|  |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-18 16:07:42 +01:00
										 |  |  |     br.enabled = false; | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     handler->setResponse(id, br); | 
					
						
							|  |  |  |     changeBreakpoint(id); // Maybe there's more to do.
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleBreakEnable(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(response.resultClass == GdbResultDone, /**/) | 
					
						
							|  |  |  |     const BreakpointId id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2010-11-15 16:58:23 +01:00
										 |  |  |     // This should only be the requested state.
 | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     QTC_ASSERT(handler->isEnabled(id), /* Prevent later recursion */); | 
					
						
							|  |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-18 16:07:42 +01:00
										 |  |  |     br.enabled = true; | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     handler->setResponse(id, br); | 
					
						
							|  |  |  |     changeBreakpoint(id); // Maybe there's more to do.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleBreakThreadSpec(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(response.resultClass == GdbResultDone, /**/) | 
					
						
							|  |  |  |     const BreakpointId id = response.cookie.toInt(); | 
					
						
							|  |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							|  |  |  |     br.threadSpec = handler->threadSpec(id); | 
					
						
							|  |  |  |     handler->setResponse(id, br); | 
					
						
							| 
									
										
										
										
											2010-11-30 13:39:01 +01:00
										 |  |  |     handler->notifyBreakpointNeedsReinsertion(id); | 
					
						
							|  |  |  |     insertBreakpoint(id); | 
					
						
							| 
									
										
										
										
											2010-03-25 13:33:38 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleBreakIgnore(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // gdb 6.8:
 | 
					
						
							|  |  |  |     // ignore 2 0:
 | 
					
						
							|  |  |  |     // ~"Will stop next time breakpoint 2 is reached.\n"
 | 
					
						
							|  |  |  |     // 28^done
 | 
					
						
							|  |  |  |     // ignore 2 12:
 | 
					
						
							|  |  |  |     // &"ignore 2 12\n"
 | 
					
						
							|  |  |  |     // ~"Will ignore next 12 crossings of breakpoint 2.\n"
 | 
					
						
							|  |  |  |     // 29^done
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |     // gdb 6.3 does not produce any console output
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     QTC_ASSERT(response.resultClass == GdbResultDone, /**/) | 
					
						
							|  |  |  |     QString msg = _(response.data.findChild("consolestreamoutput").data()); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     BreakpointId id = response.cookie.toInt(); | 
					
						
							|  |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     //if (msg.contains(__("Will stop next time breakpoint")))
 | 
					
						
							| 
									
										
										
										
											2010-11-18 16:07:42 +01:00
										 |  |  |     //    response.ignoreCount = _("0");
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     //else if (msg.contains(__("Will ignore next")))
 | 
					
						
							| 
									
										
										
										
											2010-11-18 16:07:42 +01:00
										 |  |  |     //    response.ignoreCount = data->ignoreCount;
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     // FIXME: this assumes it is doing the right thing...
 | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     br.ignoreCount = handler->ignoreCount(id); | 
					
						
							|  |  |  |     handler->setResponse(id, br); | 
					
						
							|  |  |  |     changeBreakpoint(id); // Maybe there's more to do.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleBreakCondition(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     // Can happen at invalid condition strings.
 | 
					
						
							|  |  |  |     //QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     const BreakpointId id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     // We just assume it was successful. Otherwise we had to parse
 | 
					
						
							|  |  |  |     // the output stream data.
 | 
					
						
							|  |  |  |     // The following happens on Mac:
 | 
					
						
							|  |  |  |     //   QByteArray msg = response.data.findChild("msg").data();
 | 
					
						
							|  |  |  |     //   if (1 || msg.startsWith("Error parsing breakpoint condition. "
 | 
					
						
							|  |  |  |     //            " Will try again when we hit the breakpoint.")) {
 | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							|  |  |  |     br.condition = handler->condition(id); | 
					
						
							|  |  |  |     handler->setResponse(id, br); | 
					
						
							|  |  |  |     changeBreakpoint(id); // Maybe there's more to do.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     //qDebug() << output;
 | 
					
						
							|  |  |  |     if (output.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     // "Num     Type           Disp Enb Address            What
 | 
					
						
							|  |  |  |     // 4       breakpoint     keep y   <MULTIPLE>         0x00000000004066ad
 | 
					
						
							|  |  |  |     // 4.1                         y     0x00000000004066ad in CTorTester
 | 
					
						
							|  |  |  |     //  at /data5/dev/ide/main/tests/manual/gdbdebugger/simple/app.cpp:124
 | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  |     // - or -
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // everything on a single line on Windows for constructors of classes
 | 
					
						
							|  |  |  |     // within namespaces.
 | 
					
						
							|  |  |  |     // Sometimes the path is relative too.
 | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-16 12:52:29 +02:00
										 |  |  |     // 2    breakpoint     keep y   <MULTIPLE> 0x0040168e
 | 
					
						
							|  |  |  |     // 2.1    y     0x0040168e in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
 | 
					
						
							|  |  |  |     // 2.2    y     0x00401792 in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-16 13:54:34 +02:00
										 |  |  |     // tested in ../../../tests/auto/debugger/
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     QRegExp re(_("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)")); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     re.setMinimal(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     BreakpointResponse response; | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |     response.fileName = _("<MULTIPLE>"); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString requestedFileName = breakHandler()->fileName(id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (re.indexIn(output) != -1) { | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |         response.address = re.cap(1).toULongLong(0, 16); | 
					
						
							|  |  |  |         response.functionName = re.cap(2).trimmed(); | 
					
						
							|  |  |  |         response.lineNumber = re.cap(4).toInt(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         QString full = fullName(re.cap(3)); | 
					
						
							| 
									
										
										
										
											2009-04-16 13:54:34 +02:00
										 |  |  |         if (full.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-01-11 10:22:55 +01:00
										 |  |  |             // FIXME: This happens without UsePreciseBreakpoints regularly.
 | 
					
						
							| 
									
										
										
										
											2009-12-10 13:53:29 +01:00
										 |  |  |             // We need to revive that "fill full name mapping bit by bit"
 | 
					
						
							|  |  |  |             // approach of 1.2.x
 | 
					
						
							|  |  |  |             //qDebug() << "NO FULL NAME KNOWN FOR" << re.cap(3);
 | 
					
						
							| 
									
										
										
										
											2009-10-28 11:59:57 +01:00
										 |  |  |             full = cleanupFullName(re.cap(3)); | 
					
						
							|  |  |  |             if (full.isEmpty()) { | 
					
						
							|  |  |  |                 qDebug() << "FILE IS NOT RESOLVABLE" << re.cap(3); | 
					
						
							|  |  |  |                 full = re.cap(3); // FIXME: wrong, but prevents recursion
 | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-04-16 13:54:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-04 12:30:51 +01:00
										 |  |  |         // The variable full could still contain, say "foo.cpp" when we asked
 | 
					
						
							|  |  |  |         // for "/full/path/to/foo.cpp". In this case, using the requested
 | 
					
						
							|  |  |  |         // instead of the acknowledged name makes sense as it will allow setting
 | 
					
						
							|  |  |  |         // the marker in more cases.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         if (requestedFileName.endsWith(full)) | 
					
						
							|  |  |  |             full = requestedFileName; | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |         response.fileName = full; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         qDebug() << "COULD NOT MATCH " << re.pattern() << " AND " << output; | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |         response.number = -1; // <unavailable>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     breakHandler()->setResponse(id, response); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleBreakInfo(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         // Old-style output for multiple breakpoints, presumably in a
 | 
					
						
							| 
									
										
										
										
											2010-02-01 17:49:11 +01:00
										 |  |  |         // constructor.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         const BreakpointId id(response.cookie.toInt()); | 
					
						
							|  |  |  |         const QString str = QString::fromLocal8Bit( | 
					
						
							|  |  |  |             response.data.findChild("consolestreamoutput").data()); | 
					
						
							|  |  |  |         extractDataFromInfoBreak(str, id); | 
					
						
							| 
									
										
										
										
											2010-03-26 10:29:19 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleInfoLine(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         // Old-style output: "Line 1102 of \"simple/app.cpp\" starts
 | 
					
						
							|  |  |  |         // at address 0x80526aa <_Z10...+131> and ends at 0x80526b5
 | 
					
						
							|  |  |  |         // <_Z10testQStackv+142>.\n"
 | 
					
						
							|  |  |  |         QByteArray ba = response.data.findChild("consolestreamoutput").data(); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         const BreakpointId id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-03-26 10:29:19 +01:00
										 |  |  |         const int pos = ba.indexOf(' ', 5); | 
					
						
							|  |  |  |         if (ba.startsWith("Line ") && pos != -1) { | 
					
						
							| 
									
										
										
										
											2010-09-21 14:26:45 +02:00
										 |  |  |             const int line = ba.mid(5, pos - 5).toInt(); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             BreakpointResponse br = breakHandler()->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |             br.lineNumber = line; | 
					
						
							| 
									
										
										
										
											2011-01-05 19:30:24 +01:00
										 |  |  |             br.correctedLineNumber = line; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |             breakHandler()->setResponse(id, br); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | bool GdbEngine::stateAcceptsBreakpointChanges() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (state()) { | 
					
						
							|  |  |  |     case InferiorSetupRequested: | 
					
						
							|  |  |  |     case InferiorRunRequested: | 
					
						
							|  |  |  |     case InferiorRunOk: | 
					
						
							|  |  |  |     case InferiorStopRequested: | 
					
						
							|  |  |  |     case InferiorStopOk: | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GdbEngine::acceptsBreakpoint(BreakpointId id) const | 
					
						
							| 
									
										
										
										
											2010-10-05 11:01:14 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-26 13:06:03 +01:00
										 |  |  |     return DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id)); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::insertBreakpoint(BreakpointId id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Set up fallback in case of pending breakpoints which aren't handled
 | 
					
						
							|  |  |  |     // by the MI interface.
 | 
					
						
							|  |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |     QTC_ASSERT(handler->state(id) == BreakpointInsertRequested, /**/); | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |     handler->notifyBreakpointInsertProceeding(id); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (handler->type(id) == Watchpoint) { | 
					
						
							|  |  |  |         postCommand("watch " + addressSpec(handler->address(id)), | 
					
						
							|  |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleWatchInsert), id); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QByteArray cmd; | 
					
						
							| 
									
										
										
										
											2010-12-16 17:58:43 +01:00
										 |  |  |     if (handler->isTracepoint(id)) { | 
					
						
							|  |  |  |         cmd = "-break-insert -a -f "; | 
					
						
							|  |  |  |     } else if (m_isMacGdb) { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         cmd = "-break-insert -l -1 -f "; | 
					
						
							|  |  |  |     } else if (m_gdbAdapter->isTrkAdapter()) { | 
					
						
							|  |  |  |         cmd = "-break-insert -h -f "; | 
					
						
							|  |  |  |     } else if (m_gdbVersion >= 70000) { | 
					
						
							| 
									
										
										
										
											2010-11-30 13:39:01 +01:00
										 |  |  |         int spec = handler->threadSpec(id); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         cmd = "-break-insert "; | 
					
						
							| 
									
										
										
										
											2010-12-14 13:00:02 +01:00
										 |  |  |         if (spec >= 0) | 
					
						
							| 
									
										
										
										
											2010-11-30 13:39:01 +01:00
										 |  |  |             cmd += "-p " + QByteArray::number(spec); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         cmd += " -f "; | 
					
						
							|  |  |  |     } else if (m_gdbVersion >= 60800) { | 
					
						
							|  |  |  |         // Probably some earlier version would work as well.
 | 
					
						
							|  |  |  |         cmd = "-break-insert -f "; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         cmd = "-break-insert "; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     //if (!data->condition.isEmpty())
 | 
					
						
							|  |  |  |     //    cmd += "-c " + data->condition + ' ';
 | 
					
						
							|  |  |  |     cmd += breakpointLocation(id); | 
					
						
							|  |  |  |     postCommand(cmd, NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |         CB(handleBreakInsert1), id); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  | void GdbEngine::changeBreakpoint(BreakpointId id) | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-18 16:16:23 +01:00
										 |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |     const BreakpointParameters &data = handler->breakpointData(id); | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     QTC_ASSERT(data.type != UnknownType, return); | 
					
						
							| 
									
										
										
										
											2010-11-18 16:16:23 +01:00
										 |  |  |     const BreakpointResponse &response = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |     QTC_ASSERT(response.number > 0, return); | 
					
						
							|  |  |  |     const QByteArray bpnr = QByteArray::number(response.number); | 
					
						
							| 
									
										
										
										
											2010-11-18 16:16:23 +01:00
										 |  |  |     QTC_ASSERT(response.number > 0, return); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     const BreakpointState state = handler->state(id); | 
					
						
							|  |  |  |     if (state == BreakpointChangeRequested) | 
					
						
							| 
									
										
										
										
											2010-11-18 16:16:23 +01:00
										 |  |  |         handler->notifyBreakpointChangeProceeding(id); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     const BreakpointState state2 = handler->state(id); | 
					
						
							|  |  |  |     QTC_ASSERT(state2 == BreakpointChangeProceeding, qDebug() << state2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-30 13:39:01 +01:00
										 |  |  |     if (data.threadSpec != response.threadSpec) { | 
					
						
							|  |  |  |         // The only way to change this seems to be to re-set the bp completely.
 | 
					
						
							|  |  |  |         postCommand("-break-delete " + bpnr, | 
					
						
							|  |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleBreakThreadSpec), id); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     if (!data.conditionsMatch(response.condition)) { | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |         postCommand("condition " + bpnr + ' '  + data.condition, | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleBreakCondition), id); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (data.ignoreCount != response.ignoreCount) { | 
					
						
							|  |  |  |         postCommand("ignore " + bpnr + ' ' + QByteArray::number(data.ignoreCount), | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleBreakIgnore), id); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (!data.enabled && response.enabled) { | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |         postCommand("-break-disable " + bpnr, | 
					
						
							|  |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleBreakDisable), id); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-16 11:06:09 +01:00
										 |  |  |     if (data.enabled && !response.enabled) { | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |         postCommand("-break-enable " + bpnr, | 
					
						
							|  |  |  |             NeedsStop | RebuildBreakpointModel, | 
					
						
							|  |  |  |             CB(handleBreakEnable), id); | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-11-15 16:22:51 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-30 12:47:53 +01:00
										 |  |  |     handler->notifyBreakpointChangeOk(id); | 
					
						
							| 
									
										
										
										
											2010-11-18 13:38:58 +01:00
										 |  |  |     attemptAdjustBreakpointLocation(id); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::removeBreakpoint(BreakpointId id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BreakHandler *handler = breakHandler(); | 
					
						
							|  |  |  |     QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/); | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |     handler->notifyBreakpointRemoveProceeding(id); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     BreakpointResponse br = handler->response(id); | 
					
						
							| 
									
										
										
										
											2010-11-25 14:33:13 +01:00
										 |  |  |     showMessage(_("DELETING BP %1 IN %2").arg(br.number) | 
					
						
							|  |  |  |         .arg(handler->fileName(id))); | 
					
						
							| 
									
										
										
										
											2010-11-15 17:04:29 +01:00
										 |  |  |     postCommand("-break-delete " + QByteArray::number(br.number), | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         NeedsStop | RebuildBreakpointModel); | 
					
						
							|  |  |  |     // Pretend it succeeds without waiting for response. Feels better.
 | 
					
						
							| 
									
										
										
										
											2010-11-16 13:52:21 +01:00
										 |  |  |     // FIXME: Really?
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     handler->notifyBreakpointRemoveOk(id); | 
					
						
							| 
									
										
										
										
											2010-10-05 11:01:14 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Modules specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::loadSymbols(const QString &moduleName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // FIXME: gdb does not understand quoted names here (tested with 6.8)
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("sharedlibrary " + dotEscape(moduleName.toLocal8Bit())); | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  |     reloadModulesInternal(); | 
					
						
							| 
									
										
										
										
											2010-12-21 12:41:34 +01:00
										 |  |  |     reloadStack(true); | 
					
						
							|  |  |  |     updateLocals(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::loadAllSymbols() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("sharedlibrary .*"); | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  |     reloadModulesInternal(); | 
					
						
							| 
									
										
										
										
											2010-12-21 12:41:34 +01:00
										 |  |  |     reloadStack(true); | 
					
						
							|  |  |  |     updateLocals(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-21 13:34:59 +01:00
										 |  |  | void GdbEngine::loadSymbolsForStack() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool needUpdate = false; | 
					
						
							|  |  |  |     const Modules &modules = modulesHandler()->modules(); | 
					
						
							|  |  |  |     foreach (const StackFrame &frame, stackHandler()->frames()) { | 
					
						
							|  |  |  |         if (frame.function == _("??")) { | 
					
						
							| 
									
										
										
										
											2010-12-21 14:41:17 +01:00
										 |  |  |             //qDebug() << "LOAD FOR " << frame.address;
 | 
					
						
							| 
									
										
										
										
											2010-12-21 13:34:59 +01:00
										 |  |  |             foreach (const Module &module, modules) { | 
					
						
							|  |  |  |                 if (module.startAddress <= frame.address | 
					
						
							|  |  |  |                         && frame.address < module.endAddress) { | 
					
						
							|  |  |  |                     postCommand("sharedlibrary " | 
					
						
							|  |  |  |                         + dotEscape(module.moduleName.toLocal8Bit())); | 
					
						
							|  |  |  |                     needUpdate = true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (needUpdate) { | 
					
						
							|  |  |  |         reloadModulesInternal(); | 
					
						
							|  |  |  |         reloadStack(true); | 
					
						
							|  |  |  |         updateLocals(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-03 19:12:52 +02:00
										 |  |  | void GdbEngine::requestModuleSymbols(const QString &moduleName) | 
					
						
							| 
									
										
										
										
											2009-04-15 12:01:58 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |     QTemporaryFile tf(QDir::tempPath() + _("/gdbsymbols")); | 
					
						
							|  |  |  |     if (!tf.open()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     QString fileName = tf.fileName(); | 
					
						
							|  |  |  |     tf.close(); | 
					
						
							|  |  |  |     postCommand("maint print msymbols " + fileName.toLocal8Bit() | 
					
						
							|  |  |  |             + " " + moduleName.toLocal8Bit(), | 
					
						
							|  |  |  |         NeedsStop, CB(handleShowModuleSymbols), | 
					
						
							|  |  |  |         QVariant(moduleName + QLatin1Char('@') +  fileName)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleShowModuleSymbols(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QString cookie = response.cookie.toString(); | 
					
						
							|  |  |  |     const QString moduleName = cookie.section(QLatin1Char('@'), 0, 0); | 
					
						
							|  |  |  |     const QString fileName = cookie.section(QLatin1Char('@'), 1, 1); | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         Symbols rc; | 
					
						
							|  |  |  |         QFile file(fileName); | 
					
						
							|  |  |  |         file.open(QIODevice::ReadOnly); | 
					
						
							| 
									
										
										
										
											2010-12-16 11:25:28 +01:00
										 |  |  |         // Object file /opt/dev/qt/lib/libQtNetworkMyns.so.4:
 | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |         // [ 0] A 0x16bd64 _DYNAMIC  moc_qudpsocket.cpp
 | 
					
						
							| 
									
										
										
										
											2010-12-16 11:25:28 +01:00
										 |  |  |         // [12] S 0xe94680 _ZN4myns5QFileC1Ev section .plt  myns::QFile::QFile()
 | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |         foreach (const QByteArray &line, file.readAll().split('\n')) { | 
					
						
							|  |  |  |             if (line.isEmpty()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2010-11-26 13:06:03 +01:00
										 |  |  |             if (line.at(0) != '[') | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             int posCode = line.indexOf(']') + 2; | 
					
						
							|  |  |  |             int posAddress = line.indexOf("0x", posCode); | 
					
						
							|  |  |  |             if (posAddress == -1) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             int posName = line.indexOf(" ", posAddress); | 
					
						
							|  |  |  |             int lenAddress = posName - posAddress - 1; | 
					
						
							|  |  |  |             int posSection = line.indexOf(" section "); | 
					
						
							|  |  |  |             int lenName = 0; | 
					
						
							|  |  |  |             int lenSection = 0; | 
					
						
							|  |  |  |             int posDemangled = 0; | 
					
						
							|  |  |  |             if (posSection == -1) { | 
					
						
							|  |  |  |                 lenName = line.size() - posName; | 
					
						
							|  |  |  |                 posDemangled = posName; | 
					
						
							| 
									
										
										
										
											2009-04-15 12:01:58 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |                 lenName = posSection - posName; | 
					
						
							|  |  |  |                 posSection += 10; | 
					
						
							|  |  |  |                 posDemangled = line.indexOf(' ', posSection + 1); | 
					
						
							|  |  |  |                 if (posDemangled == -1) { | 
					
						
							|  |  |  |                     lenSection = line.size() - posSection; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     lenSection = posDemangled - posSection; | 
					
						
							|  |  |  |                     posDemangled += 1; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2009-04-15 12:01:58 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |             int lenDemangled = 0; | 
					
						
							|  |  |  |             if (posDemangled != -1) | 
					
						
							|  |  |  |                 lenDemangled = line.size() - posDemangled; | 
					
						
							|  |  |  |             Symbol symbol; | 
					
						
							|  |  |  |             symbol.state = _(line.mid(posCode, 1)); | 
					
						
							|  |  |  |             symbol.address = _(line.mid(posAddress, lenAddress)); | 
					
						
							|  |  |  |             symbol.name = _(line.mid(posName, lenName)); | 
					
						
							|  |  |  |             symbol.section = _(line.mid(posSection, lenSection)); | 
					
						
							|  |  |  |             symbol.demangled = _(line.mid(posDemangled, lenDemangled)); | 
					
						
							|  |  |  |             rc.push_back(symbol); | 
					
						
							| 
									
										
										
										
											2009-04-15 12:01:58 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |         file.close(); | 
					
						
							|  |  |  |         file.remove(); | 
					
						
							|  |  |  |         debuggerCore()->showModuleSymbols(moduleName, rc); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         showMessageBox(QMessageBox::Critical, tr("Cannot Read Symbols"), | 
					
						
							|  |  |  |             tr("Cannot read symbols for module \"%1\".").arg(fileName)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-15 12:01:58 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void GdbEngine::reloadModules() | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() == InferiorRunOk || state() == InferiorStopOk) | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  |         reloadModulesInternal(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::reloadModulesInternal() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-22 15:46:49 +02:00
										 |  |  |     m_modulesListOutdated = false; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("info shared", NeedsStop, CB(handleModulesList)); | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |     if (m_gdbVersion < 70000 && !m_isMacGdb) | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set stop-on-solib-events 1"); | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleModulesList(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-26 09:58:34 +01:00
										 |  |  |     Modules modules; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2009-10-02 13:24:41 +02:00
										 |  |  |         // That's console-based output, likely Linux or Windows,
 | 
					
						
							|  |  |  |         // but we can avoid the #ifdef here.
 | 
					
						
							| 
									
										
										
										
											2010-09-15 14:17:02 +02:00
										 |  |  |         QString data = QString::fromLocal8Bit( | 
					
						
							|  |  |  |             response.data.findChild("consolestreamoutput").data()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         QTextStream ts(&data, QIODevice::ReadOnly); | 
					
						
							|  |  |  |         while (!ts.atEnd()) { | 
					
						
							|  |  |  |             QString line = ts.readLine(); | 
					
						
							|  |  |  |             Module module; | 
					
						
							|  |  |  |             QString symbolsRead; | 
					
						
							|  |  |  |             QTextStream ts(&line, QIODevice::ReadOnly); | 
					
						
							| 
									
										
										
										
											2009-10-23 15:46:39 +02:00
										 |  |  |             if (line.startsWith(__("0x"))) { | 
					
						
							|  |  |  |                 ts >> module.startAddress >> module.endAddress >> symbolsRead; | 
					
						
							|  |  |  |                 module.moduleName = ts.readLine().trimmed(); | 
					
						
							| 
									
										
										
										
											2010-07-22 16:15:50 +02:00
										 |  |  |                 module.symbolsRead = | 
					
						
							|  |  |  |                     (symbolsRead == __("Yes") ? Module::ReadOk : Module::ReadFailed); | 
					
						
							| 
									
										
										
										
											2009-10-23 15:46:39 +02:00
										 |  |  |                 modules.append(module); | 
					
						
							|  |  |  |             } else if (line.trimmed().startsWith(__("No"))) { | 
					
						
							|  |  |  |                 // gdb 6.4 symbianelf
 | 
					
						
							|  |  |  |                 ts >> symbolsRead; | 
					
						
							|  |  |  |                 QTC_ASSERT(symbolsRead == __("No"), continue); | 
					
						
							| 
									
										
										
										
											2011-01-06 09:34:45 +01:00
										 |  |  |                 module.startAddress = 0; | 
					
						
							|  |  |  |                 module.endAddress = 0; | 
					
						
							| 
									
										
										
										
											2009-10-23 15:46:39 +02:00
										 |  |  |                 module.moduleName = ts.readLine().trimmed(); | 
					
						
							|  |  |  |                 modules.append(module); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-12 12:00:53 +01:00
										 |  |  |         if (modules.isEmpty()) { | 
					
						
							|  |  |  |             // Mac has^done,shlib-info={num="1",name="dyld",kind="-",
 | 
					
						
							|  |  |  |             // dyld-addr="0x8fe00000",reason="dyld",requested-state="Y",
 | 
					
						
							|  |  |  |             // state="Y",path="/usr/lib/dyld",description="/usr/lib/dyld",
 | 
					
						
							|  |  |  |             // loaded_addr="0x8fe00000",slide="0x0",prefix="__dyld_"},
 | 
					
						
							|  |  |  |             // shlib-info={...}...
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |             foreach (const GdbMi &item, response.data.children()) { | 
					
						
							| 
									
										
										
										
											2009-03-12 12:00:53 +01:00
										 |  |  |                 Module module; | 
					
						
							| 
									
										
										
										
											2010-12-21 13:34:59 +01:00
										 |  |  |                 module.moduleName = | 
					
						
							|  |  |  |                     QString::fromLocal8Bit(item.findChild("path").data()); | 
					
						
							| 
									
										
										
										
											2010-07-22 16:15:50 +02:00
										 |  |  |                 module.symbolsRead = (item.findChild("state").data() == "Y") | 
					
						
							|  |  |  |                         ? Module::ReadOk : Module::ReadFailed; | 
					
						
							| 
									
										
										
										
											2010-12-21 13:34:59 +01:00
										 |  |  |                 module.startAddress = | 
					
						
							|  |  |  |                     item.findChild("loaded_addr").data().toULongLong(0, 0); | 
					
						
							|  |  |  |                 module.endAddress = 0; // FIXME: End address not easily available.
 | 
					
						
							| 
									
										
										
										
											2009-03-12 12:00:53 +01:00
										 |  |  |                 modules.append(module); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     modulesHandler()->setModules(modules); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-22 16:53:01 +02:00
										 |  |  | void GdbEngine::examineModules() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (Module module, modulesHandler()->modules()) { | 
					
						
							|  |  |  |         if (module.symbolsType == Module::UnknownType) { | 
					
						
							|  |  |  |             QProcess proc; | 
					
						
							|  |  |  |             qDebug() << _("objdump -h \"%1\"").arg(module.moduleName); | 
					
						
							|  |  |  |             proc.start(_("objdump -h \"%1\"").arg(module.moduleName)); | 
					
						
							|  |  |  |             if (!proc.waitForStarted()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             if (!proc.waitForFinished()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             QByteArray ba = proc.readAllStandardOutput(); | 
					
						
							|  |  |  |             if (ba.contains(".gdb_index")) | 
					
						
							|  |  |  |                 module.symbolsType = Module::FastSymbols; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 module.symbolsType = Module::PlainSymbols; | 
					
						
							|  |  |  |             modulesHandler()->updateModule(module.moduleName, module); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Source files specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  | void GdbEngine::invalidateSourcesList() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_modulesListOutdated = true; | 
					
						
							|  |  |  |     m_sourcesListOutdated = true; | 
					
						
							|  |  |  |     m_breakListOutdated = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  | void GdbEngine::reloadSourceFiles() | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if ((state() == InferiorRunOk || state() == InferiorStopOk) | 
					
						
							| 
									
										
										
										
											2009-10-28 22:08:58 +01:00
										 |  |  |         && !m_sourcesListUpdating) | 
					
						
							|  |  |  |         reloadSourceFilesInternal(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::reloadSourceFilesInternal() | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |     QTC_ASSERT(!m_sourcesListUpdating, /**/); | 
					
						
							| 
									
										
										
										
											2009-10-22 22:54:30 +02:00
										 |  |  |     m_sourcesListUpdating = true; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("-file-list-exec-source-files", NeedsStop, CB(handleQuerySources)); | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2009-11-10 12:40:23 +01:00
										 |  |  |     if (m_gdbVersion < 70000 && !m_isMacGdb) | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set stop-on-solib-events 1"); | 
					
						
							| 
									
										
										
										
											2009-11-12 14:49:54 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-02-17 14:08:49 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Stack specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  | void GdbEngine::selectThread(int index) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     threadsHandler()->setCurrentThread(index); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     Threads threads = threadsHandler()->threads(); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     QTC_ASSERT(index < threads.size(), return); | 
					
						
							| 
									
										
										
										
											2010-06-30 17:14:57 +02:00
										 |  |  |     const int id = threads.at(index).id; | 
					
						
							| 
									
										
										
										
											2010-11-23 15:43:05 +01:00
										 |  |  |     showStatusMessage(tr("Retrieving data for stack view thread 0x%1...") | 
					
						
							|  |  |  |         .arg(id, 0, 16), 10000); | 
					
						
							|  |  |  |     postCommand("-thread-select " + QByteArray::number(id), Discardable, | 
					
						
							| 
									
										
										
										
											2010-09-15 14:16:03 +02:00
										 |  |  |         CB(handleStackSelectThread)); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleStackSelectThread(const GdbResponse &) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/); | 
					
						
							| 
									
										
										
										
											2009-09-14 11:02:36 +02:00
										 |  |  |     showStatusMessage(tr("Retrieving data for stack view..."), 3000); | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |     reloadStack(true); // Will reload registers.
 | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |     updateLocals(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  | void GdbEngine::reloadFullStack() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-14 15:25:53 +01:00
										 |  |  |     PENDING_DEBUG("RELOAD FULL STACK"); | 
					
						
							| 
									
										
										
										
											2010-09-15 14:16:03 +02:00
										 |  |  |     postCommand("-stack-list-frames", Discardable, CB(handleStackListFrames), | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         QVariant::fromValue<StackCookie>(StackCookie(true, true))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::reloadStack(bool forceGotoLocation) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-14 15:25:53 +01:00
										 |  |  |     PENDING_DEBUG("RELOAD STACK"); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     QByteArray cmd = "-stack-list-frames"; | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     int stackDepth = debuggerCore()->action(MaximalStackDepth)->value().toInt(); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     if (stackDepth && !m_gdbAdapter->isTrkAdapter()) | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         cmd += " 0 " + QByteArray::number(stackDepth); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     // FIXME: gdb 6.4 symbianelf likes to be asked twice. The first time it
 | 
					
						
							|  |  |  |     // returns with "^error,msg="Previous frame identical to this frame
 | 
					
						
							|  |  |  |     // (corrupt stack?)". Might be related to the fact that we can't
 | 
					
						
							|  |  |  |     // access the memory belonging to the lower frames. But as we know
 | 
					
						
							|  |  |  |     // this sometimes happens, ask the second time immediately instead
 | 
					
						
							|  |  |  |     // of waiting for the first request to fail.
 | 
					
						
							| 
									
										
										
										
											2010-01-14 15:25:53 +01:00
										 |  |  |     // FIXME: Seems to work with 6.8.
 | 
					
						
							| 
									
										
										
										
											2010-01-15 11:35:33 +01:00
										 |  |  |     if (m_gdbAdapter->isTrkAdapter() && m_gdbVersion < 6.8) | 
					
						
							| 
									
										
										
										
											2010-03-10 17:39:08 +01:00
										 |  |  |         postCommand(cmd); | 
					
						
							| 
									
										
										
										
											2010-09-15 14:16:03 +02:00
										 |  |  |     postCommand(cmd, Discardable, CB(handleStackListFrames), | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         QVariant::fromValue<StackCookie>(StackCookie(false, forceGotoLocation))); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  | StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //qDebug() << "HANDLING FRAME:" << frameMi.toString();
 | 
					
						
							|  |  |  |     StackFrame frame; | 
					
						
							|  |  |  |     frame.level = level; | 
					
						
							| 
									
										
										
										
											2009-10-29 17:50:53 +01:00
										 |  |  |     GdbMi fullName = frameMi.findChild("fullname"); | 
					
						
							|  |  |  |     if (fullName.isValid()) | 
					
						
							|  |  |  |         frame.file = cleanupFullName(QFile::decodeName(fullName.data())); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         frame.file = QFile::decodeName(frameMi.findChild("file").data()); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |     frame.function = _(frameMi.findChild("func").data()); | 
					
						
							|  |  |  |     frame.from = _(frameMi.findChild("from").data()); | 
					
						
							|  |  |  |     frame.line = frameMi.findChild("line").data().toInt(); | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |     frame.address = frameMi.findChild("addr").data().toULongLong(0, 16); | 
					
						
							| 
									
										
										
										
											2010-12-01 15:57:13 +01:00
										 |  |  |     frame.usable = QFileInfo(frame.file).isReadable(); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |     return frame; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleStackListFrames(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-22 11:08:06 +02:00
										 |  |  |     bool handleIt = (m_isMacGdb || response.resultClass == GdbResultDone); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     if (!handleIt) { | 
					
						
							|  |  |  |         // That always happens on symbian gdb with
 | 
					
						
							|  |  |  |         // ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
 | 
					
						
							|  |  |  |         // logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
 | 
					
						
							|  |  |  |         //qDebug() << "LISTING STACK FAILED: " << response.toString();
 | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |         reloadRegisters(); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     StackCookie cookie = response.cookie.value<StackCookie>(); | 
					
						
							|  |  |  |     QList<StackFrame> stackFrames; | 
					
						
							| 
									
										
										
										
											2009-09-14 09:46:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     GdbMi stack = response.data.findChild("stack"); | 
					
						
							|  |  |  |     if (!stack.isValid()) { | 
					
						
							|  |  |  |         qDebug() << "FIXME: stack:" << stack.toString(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-14 09:46:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     int targetFrame = -1; | 
					
						
							| 
									
										
										
										
											2009-09-14 09:46:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     int n = stack.childCount(); | 
					
						
							|  |  |  |     for (int i = 0; i != n; ++i) { | 
					
						
							|  |  |  |         stackFrames.append(parseStackFrame(stack.childAt(i), i)); | 
					
						
							|  |  |  |         const StackFrame &frame = stackFrames.back(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #        if defined(Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         const bool isBogus = | 
					
						
							|  |  |  |             // Assume this is wrong and points to some strange stl_algobase
 | 
					
						
							|  |  |  |             // implementation. Happens on Karsten's XP system with Gdb 5.50
 | 
					
						
							|  |  |  |             (frame.file.endsWith(__("/bits/stl_algobase.h")) && frame.line == 150) | 
					
						
							|  |  |  |             // Also wrong. Happens on Vista with Gdb 5.50
 | 
					
						
							|  |  |  |                || (frame.function == __("operator new") && frame.line == 151); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Immediately leave bogus frames.
 | 
					
						
							|  |  |  |         if (targetFrame == -1 && isBogus) { | 
					
						
							| 
									
										
										
										
											2009-10-20 20:47:47 +02:00
										 |  |  |             setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |             notifyInferiorRunRequested(); | 
					
						
							| 
									
										
										
										
											2010-03-10 16:51:06 +01:00
										 |  |  |             postCommand("-exec-finish", RunRequest, CB(handleExecuteContinue)); | 
					
						
							| 
									
										
										
										
											2009-10-20 20:47:47 +02:00
										 |  |  |             showStatusMessage(tr("Jumping out of bogus frame..."), 1000); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-09-14 09:46:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #        endif
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Initialize top frame to the first valid frame.
 | 
					
						
							| 
									
										
										
										
											2009-10-30 15:07:17 +01:00
										 |  |  |         const bool isValid = frame.isUsable() && !frame.function.isEmpty(); | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         if (isValid && targetFrame == -1) | 
					
						
							|  |  |  |             targetFrame = i; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |     bool canExpand = !cookie.isFull | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         && (n >= debuggerCore()->action(MaximalStackDepth)->value().toInt()); | 
					
						
							|  |  |  |     debuggerCore()->action(ExpandStack)->setEnabled(canExpand); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     stackHandler()->setFrames(stackFrames, canExpand); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     // We can't jump to any file if we don't have any frames.
 | 
					
						
							|  |  |  |     if (stackFrames.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     // targetFrame contains the top most frame for which we have source
 | 
					
						
							|  |  |  |     // information. That's typically the frame we'd like to jump to, with
 | 
					
						
							|  |  |  |     // a few exceptions:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Always jump to frame #0 when stepping by instruction.
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(OperateByInstruction)) | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |         targetFrame = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If there is no frame with source, jump to frame #0.
 | 
					
						
							|  |  |  |     if (targetFrame == -1) | 
					
						
							|  |  |  |         targetFrame = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     stackHandler()->setCurrentIndex(targetFrame); | 
					
						
							| 
									
										
										
										
											2010-11-19 08:50:53 +01:00
										 |  |  |     activateFrame(targetFrame); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::activateFrame(int frameIndex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() != InferiorStopOk && state() != InferiorUnrunnable) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     StackHandler *handler = stackHandler(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     if (frameIndex == handler->stackSize()) { | 
					
						
							| 
									
										
										
										
											2009-04-06 17:27:15 +02:00
										 |  |  |         reloadFullStack(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-02 12:31:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     QTC_ASSERT(frameIndex < handler->stackSize(), return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-22 17:12:02 +01:00
										 |  |  |     // Assuming the command always succeeds this saves a roundtrip.
 | 
					
						
							|  |  |  |     // Otherwise the lines below would need to get triggered
 | 
					
						
							|  |  |  |     // after a response to this -stack-select-frame here.
 | 
					
						
							|  |  |  |     handler->setCurrentIndex(frameIndex); | 
					
						
							| 
									
										
										
										
											2010-12-20 16:28:26 +01:00
										 |  |  |     QByteArray cmd = "-stack-select-frame"; | 
					
						
							|  |  |  |     //if (!m_currentThread.isEmpty())
 | 
					
						
							|  |  |  |     //    cmd += " --thread " + m_currentThread;
 | 
					
						
							|  |  |  |     cmd += ' '; | 
					
						
							|  |  |  |     cmd += QByteArray::number(frameIndex); | 
					
						
							|  |  |  |     postCommand(cmd, Discardable, CB(handleStackSelectFrame)); | 
					
						
							| 
									
										
										
										
											2010-12-16 19:06:33 +01:00
										 |  |  |     gotoLocation(stackHandler()->currentFrame()); | 
					
						
							| 
									
										
										
										
											2010-11-22 17:12:02 +01:00
										 |  |  |     updateLocals(); | 
					
						
							|  |  |  |     reloadRegisters(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-10 17:39:08 +01:00
										 |  |  | void GdbEngine::handleStackSelectFrame(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_UNUSED(response); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  | void GdbEngine::handleThreadInfo(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-22 14:12:53 +01:00
										 |  |  |     const int id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-11-08 17:15:33 +01:00
										 |  |  |         int currentThreadId; | 
					
						
							| 
									
										
										
										
											2010-11-22 14:12:53 +01:00
										 |  |  |         const Threads threads = | 
					
						
							|  |  |  |             ThreadsHandler::parseGdbmiThreads(response.data, ¤tThreadId); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |         threadsHandler()->setThreads(threads); | 
					
						
							| 
									
										
										
										
											2010-07-02 10:58:47 +02:00
										 |  |  |         threadsHandler()->setCurrentThreadId(currentThreadId); | 
					
						
							| 
									
										
										
										
											2010-10-27 14:21:33 +02:00
										 |  |  |         updateViews(); // Adjust Threads combobox.
 | 
					
						
							| 
									
										
										
										
											2010-12-20 17:39:51 +01:00
										 |  |  |         if (m_hasInferiorThreadList && debuggerCore()->boolSetting(ShowThreadNames)) { | 
					
						
							| 
									
										
										
										
											2010-10-27 14:21:33 +02:00
										 |  |  |             postCommand("threadnames " + | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |                 debuggerCore()->action(MaximalStackDepth)->value().toByteArray(), | 
					
						
							| 
									
										
										
										
											2010-11-22 14:12:53 +01:00
										 |  |  |                 Discardable, CB(handleThreadNames), id); | 
					
						
							| 
									
										
										
										
											2010-10-27 14:21:33 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // Fall back for older versions: Try to get at least a list
 | 
					
						
							|  |  |  |         // of running threads.
 | 
					
						
							| 
									
										
										
										
											2010-11-22 14:12:53 +01:00
										 |  |  |         postCommand("-thread-list-ids", Discardable, CB(handleThreadListIds), id); | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleThreadListIds(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-02 10:58:47 +02:00
										 |  |  |     const int id = response.cookie.toInt(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // "72^done,{thread-ids={thread-id="2",thread-id="1"},number-of-threads="2"}
 | 
					
						
							| 
									
										
										
										
											2010-05-17 17:38:31 +02:00
										 |  |  |     // In gdb 7.1+ additionally: current-thread-id="1"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     const QList<GdbMi> items = response.data.findChild("thread-ids").children(); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     Threads threads; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     for (int index = 0, n = items.size(); index != n; ++index) { | 
					
						
							|  |  |  |         ThreadData thread; | 
					
						
							|  |  |  |         thread.id = items.at(index).data().toInt(); | 
					
						
							|  |  |  |         threads.append(thread); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     threadsHandler()->setThreads(threads); | 
					
						
							| 
									
										
										
										
											2010-07-02 10:58:47 +02:00
										 |  |  |     threadsHandler()->setCurrentThreadId(id); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 12:37:30 +02:00
										 |  |  | void GdbEngine::handleThreadNames(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         GdbMi contents = response.data.findChild("consolestreamoutput"); | 
					
						
							|  |  |  |         GdbMi names; | 
					
						
							|  |  |  |         names.fromString(contents.data()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Threads threads = threadsHandler()->threads(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (const GdbMi &name, names.children()) { | 
					
						
							|  |  |  |             int id = name.findChild("id").data().toInt(); | 
					
						
							|  |  |  |             for (int index = 0, n = threads.size(); index != n; ++index) { | 
					
						
							|  |  |  |                 ThreadData & thread = threads[index]; | 
					
						
							| 
									
										
										
										
											2010-10-15 10:56:39 +02:00
										 |  |  |                 if (thread.id == (quint64)id) { | 
					
						
							| 
									
										
										
										
											2010-10-27 14:21:33 +02:00
										 |  |  |                     thread.name = decodeData(name.findChild("value").data(), | 
					
						
							|  |  |  |                         name.findChild("valueencoded").data().toInt()); | 
					
						
							| 
									
										
										
										
											2010-09-13 12:37:30 +02:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         threadsHandler()->setThreads(threads); | 
					
						
							| 
									
										
										
										
											2010-10-27 14:21:33 +02:00
										 |  |  |         updateViews(); | 
					
						
							| 
									
										
										
										
											2010-09-13 12:37:30 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Snapshot specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-21 09:42:33 +02:00
										 |  |  | void GdbEngine::createSnapshot() | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QString fileName; | 
					
						
							|  |  |  |     QTemporaryFile tf(QDir::tempPath() + _("/gdbsnapshot")); | 
					
						
							|  |  |  |     if (tf.open()) { | 
					
						
							|  |  |  |         fileName = tf.fileName(); | 
					
						
							|  |  |  |         tf.close(); | 
					
						
							|  |  |  |         postCommand("gcore " + fileName.toLocal8Bit(), | 
					
						
							|  |  |  |             NeedsStop, CB(handleMakeSnapshot), fileName); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         showMessageBox(QMessageBox::Critical, tr("Snapshot Creation Error"), | 
					
						
							|  |  |  |             tr("Cannot create snapshot file.")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleMakeSnapshot(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-07-13 15:57:34 +02:00
										 |  |  |         DebuggerStartParameters sp = startParameters(); | 
					
						
							|  |  |  |         sp.startMode = AttachCore; | 
					
						
							|  |  |  |         sp.coreFile = response.cookie.toString(); | 
					
						
							|  |  |  |         //snapshot.setDate(QDateTime::currentDateTime());
 | 
					
						
							|  |  |  |         StackFrames frames = stackHandler()->frames(); | 
					
						
							|  |  |  |         QString function = _("<unknown>"); | 
					
						
							|  |  |  |         if (!frames.isEmpty()) { | 
					
						
							|  |  |  |             const StackFrame &frame = frames.at(0); | 
					
						
							|  |  |  |             function = frame.function + _(":") + QString::number(frame.line); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         sp.displayName = function + _(": ") + QDateTime::currentDateTime().toString(); | 
					
						
							| 
									
										
										
										
											2010-09-07 14:19:44 +02:00
										 |  |  |         sp.isSnapshot = true; | 
					
						
							| 
									
										
										
										
											2010-07-13 15:57:34 +02:00
										 |  |  |         DebuggerRunControl *rc = DebuggerPlugin::createDebugger(sp); | 
					
						
							|  |  |  |         DebuggerPlugin::startDebugger(rc); | 
					
						
							| 
									
										
										
										
											2010-02-02 17:25:14 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |         showMessageBox(QMessageBox::Critical, tr("Snapshot Creation Error"), | 
					
						
							|  |  |  |             tr("Cannot create snapshot:\n") + QString::fromLocal8Bit(msg)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Register specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::reloadRegisters() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 15:03:51 +01:00
										 |  |  |     if (!debuggerCore()->isDockVisible(_(Constants::DOCKWIDGET_REGISTER))) | 
					
						
							| 
									
										
										
										
											2010-06-28 09:10:20 +02:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() != InferiorStopOk && state() != InferiorUnrunnable) | 
					
						
							| 
									
										
										
										
											2009-11-30 16:45:15 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-10-30 16:42:33 +01:00
										 |  |  |     if (!m_registerNamesListed) { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("-data-list-register-names", CB(handleRegisterListNames)); | 
					
						
							| 
									
										
										
										
											2009-10-30 16:42:33 +01:00
										 |  |  |         m_registerNamesListed = true; | 
					
						
							| 
									
										
										
										
											2010-02-10 11:37:57 +01:00
										 |  |  |         // FIXME: Maybe better completely re-do this logic in TRK adapter.
 | 
					
						
							|  |  |  |         if (m_gdbAdapter->isTrkAdapter()) | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-10-30 16:42:33 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-22 11:31:34 +02:00
										 |  |  |     if (m_gdbAdapter->isTrkAdapter()) { | 
					
						
							| 
									
										
										
										
											2010-02-04 11:36:49 +01:00
										 |  |  |         m_gdbAdapter->trkReloadRegisters(); | 
					
						
							| 
									
										
										
										
											2009-09-15 15:32:49 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("-data-list-register-values x", | 
					
						
							| 
									
										
										
										
											2009-09-15 15:32:49 +02:00
										 |  |  |                     Discardable, CB(handleRegisterListValues)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | void GdbEngine::setRegisterValue(int nr, const QString &value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     Register reg = registerHandler()->registers().at(nr); | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     //qDebug() << "NOT IMPLEMENTED: CHANGE REGISTER " << nr << reg.name << ":"
 | 
					
						
							|  |  |  |     //    << value;
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("-var-delete \"R@\""); | 
					
						
							|  |  |  |     postCommand("-var-create \"R@\" * $" + reg.name); | 
					
						
							|  |  |  |     postCommand("-var-assign \"R@\" " + value.toLatin1()); | 
					
						
							|  |  |  |     postCommand("-var-delete \"R@\""); | 
					
						
							|  |  |  |     //postCommand("-data-list-register-values d",
 | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     //            Discardable, CB(handleRegisterListValues));
 | 
					
						
							|  |  |  |     reloadRegisters(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleRegisterListNames(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-30 16:42:33 +01:00
										 |  |  |     if (response.resultClass != GdbResultDone) { | 
					
						
							|  |  |  |         m_registerNamesListed = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-10-30 16:42:33 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-10 11:37:57 +01:00
										 |  |  |     Registers registers; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     foreach (const GdbMi &item, response.data.findChild("register-names").children()) | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         registers.append(Register(item.data())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     registerHandler()->setRegisters(registers); | 
					
						
							| 
									
										
										
										
											2010-02-10 11:37:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_gdbAdapter->isTrkAdapter()) | 
					
						
							|  |  |  |         m_gdbAdapter->trkReloadRegisters(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleRegisterListValues(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass != GdbResultDone) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     Registers registers = registerHandler()->registers(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 24^done,register-values=[{number="0",value="0xf423f"},...]
 | 
					
						
							| 
									
										
										
										
											2010-03-22 17:49:56 +01:00
										 |  |  |     const GdbMi values = response.data.findChild("register-values"); | 
					
						
							|  |  |  |     foreach (const GdbMi &item, values.children()) { | 
					
						
							|  |  |  |         const int index = item.findChild("number").data().toInt(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (index < registers.size()) { | 
					
						
							|  |  |  |             Register ® = registers[index]; | 
					
						
							| 
									
										
										
										
											2010-03-22 17:49:56 +01:00
										 |  |  |             GdbMi val = item.findChild("value"); | 
					
						
							|  |  |  |             QByteArray ba; | 
					
						
							|  |  |  |             bool handled = false; | 
					
						
							|  |  |  |             if (val.data().startsWith("{")) { | 
					
						
							|  |  |  |                 int pos1 = val.data().indexOf("v2_int32"); | 
					
						
							|  |  |  |                 if (pos1 == -1) | 
					
						
							|  |  |  |                     pos1 = val.data().indexOf("v4_int32"); | 
					
						
							|  |  |  |                 if (pos1 != -1) { | 
					
						
							|  |  |  |                     // FIXME: This block wastes cycles.
 | 
					
						
							|  |  |  |                     pos1 = val.data().indexOf("{", pos1 + 1) + 1; | 
					
						
							|  |  |  |                     int pos2 = val.data().indexOf("}", pos1); | 
					
						
							|  |  |  |                     QByteArray ba2 = val.data().mid(pos1, pos2 - pos1); | 
					
						
							|  |  |  |                     foreach (QByteArray ba3, ba2.split(',')) { | 
					
						
							|  |  |  |                         ba3 = ba3.trimmed(); | 
					
						
							|  |  |  |                         QTC_ASSERT(ba3.size() >= 3, continue); | 
					
						
							|  |  |  |                         QTC_ASSERT(ba3.size() <= 10, continue); | 
					
						
							|  |  |  |                         ba.prepend(QByteArray(10 - ba3.size(), '0')); | 
					
						
							|  |  |  |                         ba.prepend(ba3.mid(2)); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     ba.prepend("0x"); | 
					
						
							|  |  |  |                     handled = true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-09-01 13:56:51 +02:00
										 |  |  |             reg.value = _(handled ? ba : val.data()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-01 13:56:51 +02:00
										 |  |  |     registerHandler()->setAndMarkRegisters(registers); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Thread specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GdbEngine::supportsThreads() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-24 14:11:47 +02:00
										 |  |  |     // FSF gdb 6.3 crashes happily on -thread-list-ids. So don't use it.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     // The test below is a semi-random pick, 6.8 works fine
 | 
					
						
							| 
									
										
										
										
											2009-10-22 11:08:06 +02:00
										 |  |  |     return m_isMacGdb || m_gdbVersion > 60500; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Tooltip specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  | bool GdbEngine::showToolTip() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-22 17:06:08 +01:00
										 |  |  |     const QByteArray iname = tooltipIName(m_toolTipExpression); | 
					
						
							| 
									
										
										
										
											2010-06-29 10:58:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)) { | 
					
						
							| 
									
										
										
										
											2010-06-29 10:58:09 +02:00
										 |  |  |         watchHandler()->removeData(iname); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-22 17:06:08 +01:00
										 |  |  |     const QModelIndex index = watchHandler()->itemIndex(iname); | 
					
						
							|  |  |  |     if (!index.isValid()) { | 
					
						
							| 
									
										
										
										
											2010-06-29 10:58:09 +02:00
										 |  |  |         watchHandler()->removeData(iname); | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |         hideDebuggerToolTip(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-29 13:38:02 +01:00
										 |  |  |     showDebuggerToolTip(m_toolTipPos, index); | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::setToolTipExpression(const QPoint &mousePos, | 
					
						
							|  |  |  |     TextEditor::ITextEditor *editor, int cursorPos) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     if (state() != InferiorStopOk || !isCppEditor(editor)) { | 
					
						
							| 
									
										
										
										
											2010-11-29 13:38:02 +01:00
										 |  |  |         //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
 | 
					
						
							|  |  |  |         // " OR NOT A CPPEDITOR";
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |     m_toolTipPos = mousePos; | 
					
						
							|  |  |  |     int line, column; | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     QString exp = cppExpressionAt(editor, cursorPos, &line, &column); | 
					
						
							| 
									
										
										
										
											2010-09-02 18:32:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Extract the first identifier, everything else is considered
 | 
					
						
							|  |  |  |     // too dangerous.
 | 
					
						
							|  |  |  |     int pos1 = 0, pos2 = exp.size(); | 
					
						
							|  |  |  |     bool inId = false; | 
					
						
							|  |  |  |     for (int i = 0; i != exp.size(); ++i) { | 
					
						
							|  |  |  |         const QChar c = exp.at(i); | 
					
						
							|  |  |  |         const bool isIdChar = c.isLetterOrNumber() || c.unicode() == '_'; | 
					
						
							|  |  |  |         if (inId && !isIdChar) { | 
					
						
							|  |  |  |             pos2 = i; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!inId && isIdChar) { | 
					
						
							|  |  |  |             inId = true; | 
					
						
							|  |  |  |             pos1 = i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     exp = exp.mid(pos1, pos2 - pos1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-07 16:30:42 +02:00
										 |  |  |     if (!exp.isEmpty() && exp == m_toolTipExpression) { | 
					
						
							|  |  |  |         showToolTip(); | 
					
						
							| 
									
										
										
										
											2010-01-08 18:16:16 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-07-07 16:30:42 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-01-08 18:16:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     m_toolTipExpression = exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // FIXME: enable caching
 | 
					
						
							|  |  |  |     //if (showToolTip())
 | 
					
						
							|  |  |  |     //    return;
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (exp.isEmpty() || exp.startsWith(_c('#')))  { | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |         //QToolTip::hideText();
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!hasLetterOrNumber(exp)) { | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |         //QToolTip::showText(m_toolTipPos,
 | 
					
						
							|  |  |  |         //    tr("'%1' contains no identifier").arg(exp));
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (isKeyWord(exp)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (exp.startsWith(_c('"')) && exp.endsWith(_c('"')))  { | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |         //QToolTip::showText(m_toolTipPos, tr("String literal %1").arg(exp));
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (exp.startsWith(__("++")) || exp.startsWith(__("--"))) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         exp = exp.mid(2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (exp.endsWith(__("++")) || exp.endsWith(__("--"))) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         exp = exp.mid(2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (exp.startsWith(_c('<')) || exp.startsWith(_c('['))) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hasSideEffects(exp)) { | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |         //QToolTip::showText(m_toolTipPos,
 | 
					
						
							|  |  |  |         //    tr("Cowardly refusing to evaluate expression '%1' "
 | 
					
						
							|  |  |  |         //       "with potential side effects").arg(exp));
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Gdb crashes when creating a variable object with the name
 | 
					
						
							|  |  |  |     // of the type of 'this'
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |     for (int i = 0; i != m_currentLocals.childCount(); ++i) { | 
					
						
							|  |  |  |         if (m_currentLocals.childAt(i).exp == "this") { | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |             qDebug() << "THIS IN ROW" << i; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             if (m_currentLocals.childAt(i).type.startsWith(exp)) { | 
					
						
							|  |  |  |                 QToolTip::showText(m_toolTipPos, | 
					
						
							| 
									
										
										
										
											2009-04-08 12:11:30 +02:00
										 |  |  |                     tr("%1: type of current 'this'").arg(exp)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 qDebug() << " TOOLTIP CRASH SUPPRESSED"; | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     if (isSynchronous()) { | 
					
						
							| 
									
										
										
										
											2010-01-08 18:16:16 +01:00
										 |  |  |         updateLocals(QVariant()); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     WatchData toolTip; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     toolTip.exp = exp.toLatin1(); | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     toolTip.name = exp; | 
					
						
							| 
									
										
										
										
											2010-07-07 16:30:42 +02:00
										 |  |  |     toolTip.iname = tooltipIName(exp); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     watchHandler()->removeData(toolTip.iname); | 
					
						
							|  |  |  |     watchHandler()->insertData(toolTip); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Watch specific stuff
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-23 11:15:56 +02:00
										 |  |  | void GdbEngine::reloadLocals() | 
					
						
							| 
									
										
										
										
											2009-10-06 10:54:08 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     setTokenBarrier(); | 
					
						
							|  |  |  |     updateLocals(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 17:36:09 +02:00
										 |  |  | bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (!debuggerCore()->boolSetting(UseDebuggingHelpers)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-03-03 17:27:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-03 14:06:21 +01:00
										 |  |  |     if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) { | 
					
						
							| 
									
										
										
										
											2010-11-29 13:52:43 +01:00
										 |  |  |         // Inferior calls are not possible in gdb when looking at core files.
 | 
					
						
							| 
									
										
										
										
											2010-09-01 17:36:09 +02:00
										 |  |  |         return type == "QString" || type.endsWith("::QString") | 
					
						
							|  |  |  |             || type == "QStringList" || type.endsWith("::QStringList"); | 
					
						
							| 
									
										
										
										
											2009-03-03 17:27:25 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 16:39:17 +02:00
										 |  |  |     if (m_debuggingHelperState != DebuggingHelperAvailable) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2008-12-18 10:11:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-29 13:52:43 +01:00
										 |  |  |     // Simple types.
 | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |     return m_dumperHelper.type(type) != QtDumperHelper::UnknownType; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 08:32:12 +02:00
										 |  |  | void GdbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) | 
					
						
							| 
									
										
										
										
											2009-08-28 17:31:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     if (isSynchronous()) { | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  |         // This should only be called for fresh expanded items, not for
 | 
					
						
							|  |  |  |         // items that had their children retrieved earlier.
 | 
					
						
							| 
									
										
										
										
											2009-10-20 16:02:35 +02:00
										 |  |  |         //qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
 | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |         WatchData data1 = data; | 
					
						
							|  |  |  |         data1.setAllUnneeded(); | 
					
						
							|  |  |  |         insertData(data1); | 
					
						
							|  |  |  |         rebuildModel(); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         if (data.iname.endsWith(".")) | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Avoid endless loops created by faulty dumpers.
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         QByteArray processedName = "1-" + data.iname; | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  |         //qDebug() << "PROCESSED NAMES: " << processedName << m_processedNames;
 | 
					
						
							|  |  |  |         if (m_processedNames.contains(processedName)) { | 
					
						
							|  |  |  |             WatchData data1 = data; | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |             showMessage(_("<Breaking endless loop for " + data.iname + '>'), | 
					
						
							|  |  |  |                 LogMiscInput); | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  |             data1.setAllUnneeded(); | 
					
						
							|  |  |  |             data1.setValue(_("<unavailable>")); | 
					
						
							|  |  |  |             data1.setHasChildren(false); | 
					
						
							|  |  |  |             insertData(data1); | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         m_processedNames.insert(processedName); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 08:32:12 +02:00
										 |  |  |         // FIXME: Is this sufficient when "external" changes are
 | 
					
						
							|  |  |  |         // triggered e.g. by manually entered command in the gdb console?
 | 
					
						
							|  |  |  |         //qDebug() << "TRY PARTIAL: " << flags.tryIncremental
 | 
					
						
							|  |  |  |         //        << hasPython()
 | 
					
						
							|  |  |  |         //        << (m_pendingWatchRequests == 0)
 | 
					
						
							|  |  |  |         //        << (m_pendingBreakpointRequests == 0);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool tryPartial = flags.tryIncremental | 
					
						
							|  |  |  |                 && hasPython() | 
					
						
							|  |  |  |                 && m_pendingWatchRequests == 0 | 
					
						
							|  |  |  |                 && m_pendingBreakpointRequests == 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (tryPartial) | 
					
						
							|  |  |  |             updateLocalsPython(true, data.iname); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             updateLocals(); | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Bump requests to avoid model rebuilding during the nested
 | 
					
						
							|  |  |  |         // updateWatchModel runs.
 | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |         ++m_pendingWatchRequests; | 
					
						
							|  |  |  |         PENDING_DEBUG("UPDATE WATCH BUMPS PENDING UP TO " << m_pendingWatchRequests); | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  | #if 1
 | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  |         QMetaObject::invokeMethod(this, "updateWatchDataHelper", | 
					
						
							|  |  |  |             Qt::QueuedConnection, Q_ARG(WatchData, data)); | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  |         updateWatchDataHelper(data); | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-08-28 17:31:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  | void GdbEngine::updateWatchDataHelper(const WatchData &data) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-17 16:00:03 +02:00
										 |  |  |     //m_pendingRequests = 0;
 | 
					
						
							|  |  |  |     PENDING_DEBUG("UPDATE WATCH DATA"); | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #    if DEBUG_PENDING
 | 
					
						
							| 
									
										
										
										
											2009-06-17 16:00:03 +02:00
										 |  |  |     //qDebug() << "##############################################";
 | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  |     qDebug() << "UPDATE MODEL, FOUND INCOMPLETE:"; | 
					
						
							| 
									
										
										
										
											2009-06-17 16:00:03 +02:00
										 |  |  |     //qDebug() << data.toString();
 | 
					
						
							| 
									
										
										
										
											2010-06-10 13:12:12 +02:00
										 |  |  | #    endif
 | 
					
						
							| 
									
										
										
										
											2009-06-17 16:00:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |     updateSubItemClassic(data); | 
					
						
							| 
									
										
										
										
											2009-06-17 16:00:03 +02:00
										 |  |  |     //PENDING_DEBUG("INTERNAL TRIGGERING UPDATE WATCH MODEL");
 | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |     --m_pendingWatchRequests; | 
					
						
							|  |  |  |     PENDING_DEBUG("UPDATE WATCH DONE BUMPS PENDING DOWN TO " << m_pendingWatchRequests); | 
					
						
							|  |  |  |     if (m_pendingWatchRequests <= 0) | 
					
						
							|  |  |  |         rebuildWatchModel(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  | void GdbEngine::rebuildWatchModel() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  |     static int count = 0; | 
					
						
							|  |  |  |     ++count; | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     if (!isSynchronous()) | 
					
						
							| 
									
										
										
										
											2009-10-27 16:36:23 +01:00
										 |  |  |         m_processedNames.clear(); | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  |     PENDING_DEBUG("REBUILDING MODEL" << count); | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     if (debuggerCore()->boolSetting(LogTimeStamps)) | 
					
						
							| 
									
										
										
										
											2010-09-22 16:20:08 +02:00
										 |  |  |         showMessage(LogWindow::logTimeStamp(), LogMiscInput); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput); | 
					
						
							| 
									
										
										
										
											2010-03-23 14:49:02 +01:00
										 |  |  |     showStatusMessage(tr("Finished retrieving data"), 400); | 
					
						
							| 
									
										
										
										
											2010-06-15 11:42:49 +02:00
										 |  |  |     watchHandler()->endCycle(); | 
					
						
							| 
									
										
										
										
											2009-06-24 12:31:09 +02:00
										 |  |  |     showToolTip(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  | static QByteArray arrayFillCommand(const char *array, const QByteArray ¶ms) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-11 13:41:31 +10:00
										 |  |  |     QString buf; | 
					
						
							|  |  |  |     buf.sprintf("set {char[%d]} &%s = {", params.size(), array); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QByteArray encoded; | 
					
						
							| 
									
										
										
										
											2010-06-11 13:41:31 +10:00
										 |  |  |     encoded.append(buf.toLocal8Bit()); | 
					
						
							| 
									
										
										
										
											2009-07-06 17:36:50 +02:00
										 |  |  |     const int size = params.size(); | 
					
						
							|  |  |  |     for (int i = 0; i != size; ++i) { | 
					
						
							| 
									
										
										
										
											2010-06-11 13:41:31 +10:00
										 |  |  |         buf.sprintf("%d,", int(params[i])); | 
					
						
							|  |  |  |         encoded.append(buf.toLocal8Bit()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     encoded[encoded.size() - 1] = '}'; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     return encoded; | 
					
						
							| 
									
										
										
										
											2009-07-06 17:36:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::sendWatchParameters(const QByteArray ¶ms0) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray params = params0; | 
					
						
							|  |  |  |     params.append('\0'); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     const QByteArray inBufferCmd = arrayFillCommand("qDumpInBuffer", params); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-02 15:44:03 +02:00
										 |  |  |     params.replace('\0','!'); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(QString::fromUtf8(params), LogMiscInput); | 
					
						
							| 
									
										
										
										
											2009-06-02 15:44:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-06 17:36:50 +02:00
										 |  |  |     params.clear(); | 
					
						
							|  |  |  |     params.append('\0'); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     const QByteArray outBufferCmd = arrayFillCommand("qDumpOutBuffer", params); | 
					
						
							| 
									
										
										
										
											2009-07-06 17:36:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     postCommand(inBufferCmd); | 
					
						
							|  |  |  |     postCommand(outBufferCmd); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleVarAssign(const GdbResponse &) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-05 12:00:47 +02:00
										 |  |  |     // Everything might have changed, force re-evaluation.
 | 
					
						
							| 
									
										
										
										
											2009-02-18 13:50:55 +01:00
										 |  |  |     setTokenBarrier(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     updateLocals(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleVarCreate(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     WatchData data = response.cookie.value<WatchData>(); | 
					
						
							| 
									
										
										
										
											2010-03-11 18:55:52 +01:00
										 |  |  |     // Happens e.g. when we already issued a var-evaluate command.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (!data.isValid()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |     //qDebug() << "HANDLE VARIABLE CREATION:" << data.toString();
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         data.variable = data.iname; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |         setWatchDataType(data, response.data.findChild("type")); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |         if (watchHandler()->isExpandedIName(data.iname) | 
					
						
							| 
									
										
										
										
											2009-11-04 17:44:11 +01:00
										 |  |  |                 && !response.data.findChild("children").isValid()) | 
					
						
							|  |  |  |             data.setChildrenNeeded(); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             data.setChildrenUnneeded(); | 
					
						
							|  |  |  |         setWatchDataChildCount(data, response.data.findChild("numchild")); | 
					
						
							|  |  |  |         insertData(data); | 
					
						
							| 
									
										
										
										
											2009-10-12 12:00:07 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |         data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (data.isWatcher()) { | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |             data.value = WatchData::msgNotInScope(); | 
					
						
							| 
									
										
										
										
											2010-09-01 17:36:09 +02:00
										 |  |  |             data.type = " "; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             data.setAllUnneeded(); | 
					
						
							| 
									
										
										
										
											2009-06-22 11:35:08 +02:00
										 |  |  |             data.setHasChildren(false); | 
					
						
							| 
									
										
										
										
											2009-08-31 09:14:04 +02:00
										 |  |  |             data.valueEnabled = false; | 
					
						
							|  |  |  |             data.valueEditable = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             insertData(data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2009-10-12 12:00:07 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |         QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data()); | 
					
						
							| 
									
										
										
										
											2009-09-14 11:02:36 +02:00
										 |  |  |         showStatusMessage(tr("Custom dumper setup: %1").arg(msg), 10000); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  | void GdbEngine::updateLocals(const QVariant &cookie) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-02 18:02:30 +01:00
										 |  |  |     m_pendingWatchRequests = 0; | 
					
						
							| 
									
										
										
										
											2010-03-03 18:08:18 +01:00
										 |  |  |     m_pendingBreakpointRequests = 0; | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |     if (hasPython()) | 
					
						
							| 
									
										
										
										
											2010-09-13 08:32:12 +02:00
										 |  |  |         updateLocalsPython(false, QByteArray()); | 
					
						
							| 
									
										
										
										
											2010-01-29 22:49:55 +01:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |         updateLocalsClassic(cookie); | 
					
						
							| 
									
										
										
										
											2010-12-13 18:17:31 +01:00
										 |  |  |     updateMemoryViews(); | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-03 16:51:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 18:55:52 +01:00
										 |  |  | // Parse a local variable from GdbMi.
 | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  | WatchData GdbEngine::localVariable(const GdbMi &item, | 
					
						
							|  |  |  |                                    const QStringList &uninitializedVariables, | 
					
						
							|  |  |  |                                    QMap<QByteArray, int> *seen) | 
					
						
							| 
									
										
										
										
											2009-02-16 18:56:20 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |     // Local variables of inlined code are reported as
 | 
					
						
							|  |  |  |     // 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
 | 
					
						
							| 
									
										
										
										
											2009-10-20 16:02:35 +02:00
										 |  |  |     // numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."}}
 | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |     // We do not want these at all. Current hypotheses is that those
 | 
					
						
							|  |  |  |     // "spurious" locals have _two_ "exp" field. Try to filter them:
 | 
					
						
							| 
									
										
										
										
											2009-10-22 11:08:06 +02:00
										 |  |  |     QByteArray name; | 
					
						
							|  |  |  |     if (m_isMacGdb) { | 
					
						
							|  |  |  |         int numExps = 0; | 
					
						
							|  |  |  |         foreach (const GdbMi &child, item.children()) | 
					
						
							|  |  |  |             numExps += int(child.name() == "exp"); | 
					
						
							|  |  |  |         if (numExps > 1) | 
					
						
							|  |  |  |             return WatchData(); | 
					
						
							|  |  |  |         name = item.findChild("exp").data(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         name = item.findChild("name").data(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |     const QMap<QByteArray, int>::iterator it  = seen->find(name); | 
					
						
							|  |  |  |     if (it != seen->end()) { | 
					
						
							|  |  |  |         const int n = it.value(); | 
					
						
							|  |  |  |         ++(it.value()); | 
					
						
							|  |  |  |         WatchData data; | 
					
						
							|  |  |  |         QString nam = _(name); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         data.iname = "local." + name + QByteArray::number(n + 1); | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         data.name = WatchData::shadowedName(nam, n); | 
					
						
							|  |  |  |         if (uninitializedVariables.contains(data.name)) { | 
					
						
							|  |  |  |             data.setError(WatchData::msgNotInScope()); | 
					
						
							|  |  |  |             return data; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-09-10 10:51:43 +02:00
										 |  |  |         setWatchDataValue(data, item); | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |         //: Type of local variable or parameter shadowed by another
 | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         //: variable of the same name in a nested block.
 | 
					
						
							| 
									
										
										
										
											2010-09-01 17:36:09 +02:00
										 |  |  |         data.setType(GdbEngine::tr("<shadowed>").toUtf8()); | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         data.setHasChildren(false); | 
					
						
							|  |  |  |         return data; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     seen->insert(name, 1); | 
					
						
							|  |  |  |     WatchData data; | 
					
						
							|  |  |  |     QString nam = _(name); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     data.iname = "local." + name; | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |     data.name = nam; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     data.exp = name; | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |     setWatchDataType(data, item.findChild("type")); | 
					
						
							|  |  |  |     if (uninitializedVariables.contains(data.name)) { | 
					
						
							|  |  |  |         data.setError(WatchData::msgNotInScope()); | 
					
						
							|  |  |  |         return data; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-08-30 07:52:41 +02:00
										 |  |  |     if (isSynchronous()) { | 
					
						
							| 
									
										
										
										
											2010-04-08 14:38:42 +02:00
										 |  |  |         setWatchDataValue(data, item); | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         // We know that the complete list of children is
 | 
					
						
							|  |  |  |         // somewhere in the response.
 | 
					
						
							|  |  |  |         data.setChildrenUnneeded(); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-03-11 18:55:52 +01:00
										 |  |  |         // Set value only directly if it is simple enough, otherwise
 | 
					
						
							|  |  |  |         // pass through the insertData() machinery.
 | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         if (isIntOrFloatType(data.type) || isPointerType(data.type)) | 
					
						
							| 
									
										
										
										
											2010-04-08 14:38:42 +02:00
										 |  |  |             setWatchDataValue(data, item); | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         if (isSymbianIntType(data.type)) { | 
					
						
							| 
									
										
										
										
											2010-04-08 14:38:42 +02:00
										 |  |  |             setWatchDataValue(data, item); | 
					
						
							| 
									
										
										
										
											2009-06-22 11:35:08 +02:00
										 |  |  |             data.setHasChildren(false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-15 12:15:25 +02:00
										 |  |  |     if (!watchHandler()->isExpandedIName(data.iname)) | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         data.setChildrenUnneeded(); | 
					
						
							| 
									
										
										
										
											2010-03-11 18:55:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     GdbMi t = item.findChild("numchild"); | 
					
						
							|  |  |  |     if (t.isValid()) | 
					
						
							|  |  |  |         data.setHasChildren(t.data().toInt() > 0); | 
					
						
							|  |  |  |     else if (isPointerType(data.type) || data.name == __("this")) | 
					
						
							| 
									
										
										
										
											2009-10-16 16:26:28 +02:00
										 |  |  |         data.setHasChildren(true); | 
					
						
							|  |  |  |     return data; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::insertData(const WatchData &data0) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-01 18:01:23 +02:00
										 |  |  |     PENDING_DEBUG("INSERT DATA" << data0.toString()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     WatchData data = data0; | 
					
						
							| 
									
										
										
										
											2009-04-30 15:21:37 +02:00
										 |  |  |     if (data.value.startsWith(__("mi_cmd_var_create:"))) { | 
					
						
							| 
									
										
										
										
											2009-05-06 20:55:21 +02:00
										 |  |  |         qDebug() << "BOGUS VALUE:" << data.toString(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     watchHandler()->insertData(data); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  | void GdbEngine::assignValueInDebugger(const WatchData *, | 
					
						
							|  |  |  |     const QString &expression, const QVariant &value) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("-var-delete assign"); | 
					
						
							|  |  |  |     postCommand("-var-create assign * " + expression.toLatin1()); | 
					
						
							| 
									
										
										
										
											2010-09-23 13:22:08 +02:00
										 |  |  |     postCommand("-var-assign assign " + GdbMi::escapeCString(value.toString().toLatin1()), | 
					
						
							| 
									
										
										
										
											2010-02-11 13:21:38 +01:00
										 |  |  |         Discardable, CB(handleVarAssign)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  | void GdbEngine::watchPoint(const QPoint &pnt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     QByteArray x = QByteArray::number(pnt.x()); | 
					
						
							|  |  |  |     QByteArray y = QByteArray::number(pnt.y()); | 
					
						
							| 
									
										
										
										
											2011-01-17 15:11:11 +01:00
										 |  |  |     postCommand("print '" + qtNamespace() + "QApplication::widgetAt'(" | 
					
						
							|  |  |  |             + x + ',' + y + ')', | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  |         NeedsStop, CB(handleWatchPoint)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleWatchPoint(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  |         // "$5 = (void *) 0xbfa7ebfc\n"
 | 
					
						
							| 
									
										
										
										
											2011-01-17 15:11:11 +01:00
										 |  |  |         const QByteArray ba = parsePlainConsoleStream(response); | 
					
						
							|  |  |  |         //qDebug() << "BA: " << ba;
 | 
					
						
							| 
									
										
										
										
											2011-01-17 12:27:49 +01:00
										 |  |  |         const int posWidget = ba.indexOf("QWidget"); | 
					
						
							|  |  |  |         const int pos0x = ba.indexOf("0x", posWidget + 7); | 
					
						
							| 
									
										
										
										
											2011-01-17 16:33:31 +01:00
										 |  |  |         if (posWidget == -1 || pos0x == -1) { | 
					
						
							| 
									
										
										
										
											2011-01-17 15:11:11 +01:00
										 |  |  |             showStatusMessage(tr("Cannot read widget data: %1").arg(_(ba))); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             const QByteArray addr = ba.mid(pos0x); | 
					
						
							| 
									
										
										
										
											2011-01-17 16:33:31 +01:00
										 |  |  |             if (addr.toULongLong(0, 0)) { // Non-null pointer
 | 
					
						
							|  |  |  |                 const QByteArray ns = qtNamespace(); | 
					
						
							|  |  |  |                 const QByteArray type = ns.isEmpty() ? "QWidget*" : ("'" + ns + "QWidget'*"); | 
					
						
							|  |  |  |                 const QString exp = _("(*(struct %1)%2)").arg(_(type)).arg(_(addr)); | 
					
						
							|  |  |  |                 // qDebug() << posNs << posWidget << pos0x << addr << ns << type;
 | 
					
						
							|  |  |  |                 watchHandler()->watchExpression(exp); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 showStatusMessage(tr("Could not find a widget.")); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-01-17 15:11:11 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-07-01 12:49:41 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct MemoryAgentCookie | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |     MemoryAgentCookie() : agent(0), token(0), address(0) {} | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  |     MemoryAgentCookie(MemoryAgent *agent_, QObject *token_, quint64 address_) | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |         : agent(agent_), token(token_), address(address_) | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     {} | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  |     QPointer<MemoryAgent> agent; | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |     QPointer<QObject> token; | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     quint64 address; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  | void GdbEngine::fetchMemory(MemoryAgent *agent, QObject *token, quint64 addr, | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |                             quint64 length) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     //qDebug() << "GDB MEMORY FETCH" << agent << addr << length;
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("-data-read-memory " + QByteArray::number(addr) + " x 1 1 " | 
					
						
							|  |  |  |             + QByteArray::number(length), | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |         NeedsStop, CB(handleFetchMemory), | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |         QVariant::fromValue(MemoryAgentCookie(agent, token, addr))); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleFetchMemory(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     // ^done,addr="0x08910c88",nr-bytes="16",total-bytes="16",
 | 
					
						
							|  |  |  |     // next-row="0x08910c98",prev-row="0x08910c78",next-page="0x08910c98",
 | 
					
						
							|  |  |  |     // prev-page="0x08910c78",memory=[{addr="0x08910c88",
 | 
					
						
							|  |  |  |     // data=["1","0","0","0","5","0","0","0","0","0","0","0","0","0","0","0"]}]
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     MemoryAgentCookie ac = response.cookie.value<MemoryAgentCookie>(); | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  |     QByteArray ba; | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     GdbMi memory = response.data.findChild("memory"); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     QTC_ASSERT(memory.children().size() <= 1, return); | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     if (memory.children().isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  |     GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
 | 
					
						
							|  |  |  |     GdbMi data = memory0.findChild("data"); | 
					
						
							|  |  |  |     foreach (const GdbMi &child, data.children()) { | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |         bool ok = true; | 
					
						
							| 
									
										
										
										
											2009-10-05 17:37:15 +02:00
										 |  |  |         unsigned char c = '?'; | 
					
						
							|  |  |  |         c = child.data().toUInt(&ok, 0); | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  |         QTC_ASSERT(ok, return); | 
					
						
							|  |  |  |         ba.append(c); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-17 17:33:42 +01:00
										 |  |  |     ac.agent->addLazyData(ac.token, ac.address, ba); | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | class DisassemblerAgentCookie | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | public: | 
					
						
							|  |  |  |     DisassemblerAgentCookie() : agent(0), attempts(0) {} | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  |     DisassemblerAgentCookie(DisassemblerAgent *agent_) | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |         : agent(agent_), attempts(0) | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     {} | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  |     QPointer<DisassemblerAgent> agent; | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     int attempts; | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  | // FIXME: add agent->frame() accessor and use that
 | 
					
						
							| 
									
										
										
										
											2010-12-14 12:29:32 +01:00
										 |  |  | void GdbEngine::fetchDisassembler(DisassemblerAgent *agent) | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     fetchDisassemblerByCli(agent, agent->isMixed()); | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     if (agent->isMixed()) { | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |         // Disassemble full function:
 | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |         const StackFrame &frame = agent->frame(); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         QByteArray cmd = "-data-disassemble" | 
					
						
							|  |  |  |             " -f " + frame.file.toLocal8Bit() + | 
					
						
							| 
									
										
										
										
											2010-01-06 12:17:34 +01:00
										 |  |  |             " -l " + QByteArray::number(frame.line) + " -n -1 -- 1"; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand(cmd, Discardable, CB(handleFetchDisassemblerByLine), | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |             QVariant::fromValue(DisassemblerAgentCookie(agent))); | 
					
						
							| 
									
										
										
										
											2010-02-01 16:14:57 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         fetchDisassemblerByAddress(agent, true); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | void GdbEngine::fetchDisassemblerByAddress(const DisassemblerAgentCookie &ac0, | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     bool useMixedMode) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     DisassemblerAgentCookie ac = ac0; | 
					
						
							|  |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |     const quint64 address = ac.agent->address(); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     QByteArray start = QByteArray::number(address - 20, 16); | 
					
						
							|  |  |  |     QByteArray end = QByteArray::number(address + 100, 16); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     // -data-disassemble [ -s start-addr -e end-addr ]
 | 
					
						
							|  |  |  |     //  | [ -f filename -l linenum [ -n lines ] ] -- mode
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     ++ac.attempts; | 
					
						
							| 
									
										
										
										
											2010-01-29 21:33:57 +01:00
										 |  |  |     if (useMixedMode) | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("-data-disassemble -s 0x" + start + " -e 0x" + end + " -- 1", | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |             Discardable, CB(handleFetchDisassemblerByAddress1), | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             QVariant::fromValue(ac)); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("-data-disassemble -s 0x" + start + " -e 0x" + end + " -- 0", | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |             Discardable, CB(handleFetchDisassemblerByAddress0), | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             QVariant::fromValue(ac)); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | void GdbEngine::fetchDisassemblerByCli(const DisassemblerAgentCookie &ac0, | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     bool useMixedMode) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     DisassemblerAgentCookie ac = ac0; | 
					
						
							|  |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |     const quint64 address = ac.agent->address(); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     QByteArray cmd = "disassemble "; | 
					
						
							|  |  |  |     if (useMixedMode && m_gdbVersion >= 60850) | 
					
						
							|  |  |  |         cmd += "/m "; | 
					
						
							|  |  |  |     cmd += " 0x"; | 
					
						
							|  |  |  |     cmd += QByteArray::number(address, 16); | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     ++ac.attempts; | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     postCommand(cmd, Discardable, CB(handleFetchDisassemblerByCli), | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |         QVariant::fromValue(ac)); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  | void GdbEngine::fetchDisassemblerByAddressCli(const DisassemblerAgentCookie &ac0) | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     DisassemblerAgentCookie ac = ac0; | 
					
						
							|  |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2010-09-21 15:12:33 +02:00
										 |  |  |     const quint64 address = ac.agent->address(); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     QByteArray start = QByteArray::number(address - 20, 16); | 
					
						
							|  |  |  |     QByteArray end = QByteArray::number(address + 100, 16); | 
					
						
							| 
									
										
										
										
											2010-04-29 12:07:24 +02:00
										 |  |  |     // There have been changes to the syntax sometime between 7.0 and 7.1.
 | 
					
						
							|  |  |  |     // As it is unclear how a given incarnation of gdb behaves without
 | 
					
						
							|  |  |  |     // actually calling the command, try both.
 | 
					
						
							|  |  |  |     const char sep = (ac.attempts % 2) ? ',' : ' '; | 
					
						
							|  |  |  |     QByteArray cmd = "disassemble 0x" + start + sep + "0x" + end; | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |     ++ac.attempts; | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |     postCommand(cmd, Discardable, CB(handleFetchDisassemblerByCli), | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |         QVariant::fromValue(ac)); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  | static DisassemblerLine parseLine(const GdbMi &line) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |     DisassemblerLine dl; | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     QByteArray address = line.findChild("address").data(); | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |     dl.address = address.toULongLong(); | 
					
						
							|  |  |  |     dl.data = _(line.findChild("inst").data()); | 
					
						
							|  |  |  |     return dl; | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  | DisassemblerLines GdbEngine::parseDisassembler(const GdbMi &lines) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     // ^done,data={asm_insns=[src_and_asm_line={line="1243",file=".../app.cpp",
 | 
					
						
							|  |  |  |     // line_asm_insn=[{address="0x08054857",func-name="main",offset="27",
 | 
					
						
							|  |  |  |     // inst="call 0x80545b0 <_Z13testQFileInfov>"}]},
 | 
					
						
							|  |  |  |     // src_and_asm_line={line="1244",file=".../app.cpp",
 | 
					
						
							|  |  |  |     // line_asm_insn=[{address="0x0805485c",func-name="main",offset="32",
 | 
					
						
							|  |  |  |     //inst="call 0x804cba1 <_Z11testObject1v>"}]}]}
 | 
					
						
							|  |  |  |     // - or -
 | 
					
						
							|  |  |  |     // ^done,asm_insns=[
 | 
					
						
							|  |  |  |     // {address="0x0805acf8",func-name="...",offset="25",inst="and $0xe8,%al"},
 | 
					
						
							|  |  |  |     // {address="0x0805acfa",func-name="...",offset="27",inst="pop %esp"},
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |     QStringList fileContents; | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     bool fileLoaded = false; | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |     DisassemblerLines result; | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // FIXME: Performance?
 | 
					
						
							|  |  |  |     foreach (const GdbMi &child, lines.children()) { | 
					
						
							|  |  |  |         if (child.hasName("src_and_asm_line")) { | 
					
						
							| 
									
										
										
										
											2010-11-19 09:14:08 +01:00
										 |  |  |             // Mixed mode.
 | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |             if (!fileLoaded) { | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |                 QString fileName = QFile::decodeName(child.findChild("file").data()); | 
					
						
							| 
									
										
										
										
											2009-12-09 11:13:20 +01:00
										 |  |  |                 fileName = cleanupFullName(fileName); | 
					
						
							|  |  |  |                 QFile file(fileName); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |                 file.open(QIODevice::ReadOnly); | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                 QTextStream ts(&file); | 
					
						
							|  |  |  |                 fileContents = ts.readAll().split(QLatin1Char('\n')); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |                 fileLoaded = true; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-10-22 20:04:59 +02:00
										 |  |  |             int line = child.findChild("line").data().toInt(); | 
					
						
							| 
									
										
										
										
											2010-02-04 15:01:42 +01:00
										 |  |  |             if (line >= 1 && line <= fileContents.size()) | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                 result.appendComment(fileContents.at(line - 1)); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |             GdbMi insn = child.findChild("line_asm_insn"); | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             foreach (const GdbMi &item, insn.children()) | 
					
						
							|  |  |  |                 result.appendLine(parseLine(item)); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-11-19 09:14:08 +01:00
										 |  |  |             // The non-mixed version.
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             result.appendLine(parseLine(child)); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2009-08-12 10:51:25 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     DisassemblerAgentCookie ac = response.cookie.value<DisassemblerAgentCookie>(); | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         GdbMi lines = response.data.findChild("asm_insns"); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |         if (lines.children().isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             fetchDisassemblerByAddress(ac, true); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |         else if (lines.children().size() == 1 | 
					
						
							|  |  |  |                     && lines.childAt(0).findChild("line").data() == "0") | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             fetchDisassemblerByAddress(ac, true); | 
					
						
							| 
									
										
										
										
											2010-02-01 13:59:30 +01:00
										 |  |  |         else { | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             DisassemblerLines dlines = parseDisassembler(lines); | 
					
						
							|  |  |  |             if (dlines.coversAddress(ac.agent->address())) { | 
					
						
							| 
									
										
										
										
											2010-02-01 13:59:30 +01:00
										 |  |  |                 // All is well.
 | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                 ac.agent->setContents(dlines); | 
					
						
							| 
									
										
										
										
											2010-02-01 13:59:30 +01:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 // Can happen e.g. for initializer list on symbian/rvct where
 | 
					
						
							|  |  |  |                 // we get a file name and line number but where the 'fully
 | 
					
						
							| 
									
										
										
										
											2010-02-04 13:04:13 +01:00
										 |  |  |                 // disassembled function' does not cover the code in the
 | 
					
						
							| 
									
										
										
										
											2010-02-01 13:59:30 +01:00
										 |  |  |                 // initializer list. Fall back needed:
 | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |                 //fetchDisassemblerByAddress(ac.agent, true);
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |                 fetchDisassemblerByCli(ac, true); | 
					
						
							| 
									
										
										
										
											2010-02-01 13:59:30 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-10-12 12:00:07 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-09-28 15:44:57 +02:00
										 |  |  |         // 536^error,msg="mi_cmd_disassemble: Invalid line number"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |         QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							| 
									
										
										
										
											2010-02-04 13:04:13 +01:00
										 |  |  |         if (msg == "mi_cmd_disassemble: Invalid line number" | 
					
						
							| 
									
										
										
										
											2010-02-01 16:30:11 +01:00
										 |  |  |                 || msg.startsWith("Cannot access memory at address")) | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             fetchDisassemblerByAddress(ac, true); | 
					
						
							| 
									
										
										
										
											2009-09-28 15:44:57 +02:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |             showStatusMessage(tr("Disassembler failed: %1") | 
					
						
							|  |  |  |                 .arg(QString::fromLocal8Bit(msg)), 5000); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     DisassemblerAgentCookie ac = response.cookie.value<DisassemblerAgentCookie>(); | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         GdbMi lines = response.data.findChild("asm_insns"); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |         if (lines.children().isEmpty()) | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |             fetchDisassemblerByAddress(ac, false); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |         else { | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             DisassemblerLines dlines = parseDisassembler(lines); | 
					
						
							|  |  |  |             if (dlines.coversAddress(ac.agent->address())) { | 
					
						
							|  |  |  |                 ac.agent->setContents(dlines); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |                 showMessage(_("FALL BACK TO NON-MIXED")); | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |                 fetchDisassemblerByAddress(ac, false); | 
					
						
							| 
									
										
										
										
											2009-10-02 11:45:19 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-09-28 15:44:57 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // 26^error,msg="Cannot access memory at address 0x801ca308"
 | 
					
						
							|  |  |  |         QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |         showStatusMessage(tr("Disassembler failed: %1") | 
					
						
							|  |  |  |             .arg(QString::fromLocal8Bit(msg)), 5000); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  | void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     DisassemblerAgentCookie ac = response.cookie.value<DisassemblerAgentCookie>(); | 
					
						
							| 
									
										
										
										
											2009-08-18 11:34:26 +02:00
										 |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 11:16:00 +02:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							|  |  |  |         GdbMi lines = response.data.findChild("asm_insns"); | 
					
						
							| 
									
										
										
										
											2009-08-18 11:34:26 +02:00
										 |  |  |         ac.agent->setContents(parseDisassembler(lines)); | 
					
						
							| 
									
										
										
										
											2009-09-28 15:44:57 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |         showStatusMessage(tr("Disassembler failed: %1") | 
					
						
							|  |  |  |             .arg(QString::fromLocal8Bit(msg)), 5000); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DisassemblerAgentCookie ac = response.cookie.value<DisassemblerAgentCookie>(); | 
					
						
							|  |  |  |     QTC_ASSERT(ac.agent, return); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |         // Apple's gdb produces MI output even for CLI commands.
 | 
					
						
							| 
									
										
										
										
											2010-06-28 14:53:31 +02:00
										 |  |  |         // FIXME: Check whether wrapping this into -interpreter-exec console
 | 
					
						
							|  |  |  |         // (i.e. usgind the 'ConsoleCommand' GdbCommandFlag makes a
 | 
					
						
							|  |  |  |         // difference.
 | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |         GdbMi lines = response.data.findChild("asm_insns"); | 
					
						
							|  |  |  |         if (lines.isValid()) { | 
					
						
							|  |  |  |             ac.agent->setContents(parseDisassembler(lines)); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             const QString someSpace = _("        "); | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |             // First line is something like
 | 
					
						
							|  |  |  |             // "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
 | 
					
						
							|  |  |  |             GdbMi output = response.data.findChild("consolestreamoutput"); | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             DisassemblerLines dlines; | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |             QByteArray lastFunction; | 
					
						
							| 
									
										
										
										
											2010-11-19 09:14:08 +01:00
										 |  |  |             foreach (const QByteArray &line0, output.data().split('\n')) { | 
					
						
							|  |  |  |                 QByteArray line = line0.trimmed(); | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |                 if (line.startsWith("=> ")) | 
					
						
							|  |  |  |                     line = line.mid(3); | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |                 if (line.isEmpty()) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |                 if (line.startsWith("Current language:")) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |                 if (line.startsWith("Dump of assembler")) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |                 if (line.startsWith("The current source")) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-11-19 09:14:08 +01:00
										 |  |  |                 if (line.startsWith("End of assembler")) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |                 if (line.startsWith("0x")) { | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |                     int pos1 = line.indexOf('<') + 1; | 
					
						
							|  |  |  |                     int pos2 = line.indexOf('+', pos1); | 
					
						
							|  |  |  |                     int pos3 = line.indexOf('>', pos1); | 
					
						
							|  |  |  |                     if (pos1 < pos2 && pos2 < pos3) { | 
					
						
							|  |  |  |                         QByteArray function = line.mid(pos1, pos2 - pos1); | 
					
						
							|  |  |  |                         if (function != lastFunction) { | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                             dlines.appendComment(QString()); | 
					
						
							|  |  |  |                             dlines.appendComment(_("Function: ") + _(function)); | 
					
						
							| 
									
										
										
										
											2010-11-24 11:44:43 +01:00
										 |  |  |                             lastFunction = function; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         line.replace(pos1, pos2 - pos1, ""); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                     dlines.appendLine(DisassemblerLine(_(line))); | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |                 dlines.appendComment(someSpace + _(line)); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-11-24 15:55:09 +01:00
										 |  |  |             if (dlines.size()) | 
					
						
							|  |  |  |                 ac.agent->setContents(dlines); | 
					
						
							| 
									
										
										
										
											2010-04-07 14:37:42 +02:00
										 |  |  |             else | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |                 fetchDisassemblerByAddressCli(ac); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         QByteArray msg = response.data.findChild("msg").data(); | 
					
						
							|  |  |  |         //76^error,msg="No function contains program counter for selected..."
 | 
					
						
							|  |  |  |         //76^error,msg="No function contains specified address."
 | 
					
						
							|  |  |  |         //>568^error,msg="Line number 0 out of range;
 | 
					
						
							| 
									
										
										
										
											2010-04-12 12:01:40 +02:00
										 |  |  |         if (ac.attempts < 4 // Try once more.
 | 
					
						
							|  |  |  |               && (msg.startsWith("No function ") || msg.startsWith("Line number "))) | 
					
						
							|  |  |  |             fetchDisassemblerByAddressCli(ac); | 
					
						
							| 
									
										
										
										
											2010-02-09 15:02:55 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |             showStatusMessage(tr("Disassembler failed: %1") | 
					
						
							|  |  |  |                 .arg(QString::fromLocal8Bit(msg)), 5000); | 
					
						
							| 
									
										
										
										
											2009-08-14 13:04:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | //
 | 
					
						
							|  |  |  | // Starting up & shutting down
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-26 11:55:02 +01:00
										 |  |  | bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QString &settingsIdHint) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     gdbProc()->disconnect(); // From any previous runs
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     m_gdb = QString::fromLocal8Bit(qgetenv("QTC_DEBUGGER_PATH")); | 
					
						
							| 
									
										
										
										
											2010-09-17 13:44:35 +02:00
										 |  |  |     if (m_gdb.isEmpty() && startParameters().startMode != StartRemoteGdb) | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |         m_gdb = debuggerCore()->gdbBinaryForToolChain(startParameters().toolChainType); | 
					
						
							| 
									
										
										
										
											2010-04-08 16:55:25 +02:00
										 |  |  |     if (m_gdb.isEmpty()) | 
					
						
							|  |  |  |         m_gdb = gdb; | 
					
						
							|  |  |  |     if (m_gdb.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |         handleAdapterStartFailed( | 
					
						
							|  |  |  |             msgNoBinaryForToolChain(startParameters().toolChainType), | 
					
						
							|  |  |  |             GdbOptionsPage::settingsId()); | 
					
						
							| 
									
										
										
										
											2010-04-08 16:55:25 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     QStringList gdbArgs; | 
					
						
							|  |  |  |     gdbArgs << _("-i"); | 
					
						
							|  |  |  |     gdbArgs << _("mi"); | 
					
						
							| 
									
										
										
										
											2010-12-21 11:52:21 +01:00
										 |  |  |     if (!debuggerCore()->boolSetting(LoadGdbInit)) | 
					
						
							|  |  |  |         gdbArgs << _("-n"); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     gdbArgs += args; | 
					
						
							| 
									
										
										
										
											2010-12-02 17:43:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-03 16:50:28 +01:00
										 |  |  | #ifdef Q_OS_WIN
 | 
					
						
							| 
									
										
										
										
											2010-03-10 15:51:31 +01:00
										 |  |  |     // Set python path. By convention, python is located below gdb executable.
 | 
					
						
							| 
									
										
										
										
											2010-04-01 11:18:02 +02:00
										 |  |  |     // Extend the environment set on the process in startAdapter().
 | 
					
						
							| 
									
										
										
										
											2010-04-08 16:55:25 +02:00
										 |  |  |     const QFileInfo fi(m_gdb); | 
					
						
							| 
									
										
										
										
											2010-12-02 17:43:14 +01:00
										 |  |  |     if (!fi.isAbsolute()) { | 
					
						
							|  |  |  |         showMessage(_("GDB %1 DOES NOT HAVE ABSOLUTE LOCATION.").arg(m_gdb)); | 
					
						
							|  |  |  |         const QString msg = tr("The gdb location must be given as an " | 
					
						
							|  |  |  |             "absolute path in the debugger settings."); | 
					
						
							|  |  |  |         handleAdapterStartFailed(msg, settingsIdHint); | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2010-02-03 16:50:28 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-02 17:43:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     const QString winPythonVersion = _(winPythonVersionC); | 
					
						
							| 
									
										
										
										
											2010-12-02 17:43:14 +01:00
										 |  |  |     const QDir dir = fi.absoluteDir(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QProcessEnvironment environment = gdbProc()->processEnvironment(); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     const QString pythonPathVariable = _("PYTHONPATH"); | 
					
						
							| 
									
										
										
										
											2010-12-16 12:10:56 +01:00
										 |  |  |     QString pythonPath; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 15:31:40 +01:00
										 |  |  |     const QString environmentPythonPath = environment.value(pythonPathVariable); | 
					
						
							| 
									
										
										
										
											2010-12-16 12:10:56 +01:00
										 |  |  |     if (dir.exists(winPythonVersion)) { | 
					
						
							|  |  |  |         pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(winPythonVersion)); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     } else if (dir.exists(_("lib"))) { | 
					
						
							|  |  |  |         // Needed for our gdb 7.2 packages
 | 
					
						
							|  |  |  |         pythonPath = QDir::toNativeSeparators(dir.absoluteFilePath(_("lib"))); | 
					
						
							| 
									
										
										
										
											2010-12-02 17:43:14 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2011-01-12 15:31:40 +01:00
										 |  |  |         pythonPath = environmentPythonPath; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (pythonPath.isEmpty()) { | 
					
						
							|  |  |  |         const QString nativeGdb = QDir::toNativeSeparators(m_gdb); | 
					
						
							|  |  |  |         showMessage(_("GDB %1 CANNOT FIND THE PYTHON INSTALLATION.").arg(nativeGdb)); | 
					
						
							|  |  |  |         showStatusMessage(_("%1 cannot find python").arg(nativeGdb)); | 
					
						
							|  |  |  |         const QString msg = tr("The gdb installed at %1 cannot " | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |            "find a valid python installation in its %2 subdirectory.\n" | 
					
						
							|  |  |  |            "You may set the PYTHONPATH to your installation.") | 
					
						
							| 
									
										
										
										
											2011-01-12 15:31:40 +01:00
										 |  |  |                 .arg(nativeGdb).arg(winPythonVersion); | 
					
						
							|  |  |  |         handleAdapterStartFailed(msg, settingsIdHint); | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2010-03-22 14:06:19 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-12-16 12:10:56 +01:00
										 |  |  |     showMessage(_("Python path: %1").arg(pythonPath), LogMisc); | 
					
						
							| 
									
										
										
										
											2011-01-12 15:31:40 +01:00
										 |  |  |     // Apply to process
 | 
					
						
							|  |  |  |     if (pythonPath != environmentPythonPath) { | 
					
						
							|  |  |  |         environment.insert(pythonPathVariable, pythonPath); | 
					
						
							|  |  |  |         gdbProc()->setProcessEnvironment(environment); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-02-03 16:50:28 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     connect(gdbProc(), SIGNAL(error(QProcess::ProcessError)), | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         SLOT(handleGdbError(QProcess::ProcessError))); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     connect(gdbProc(), SIGNAL(finished(int, QProcess::ExitStatus)), | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         SLOT(handleGdbFinished(int, QProcess::ExitStatus))); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     connect(gdbProc(), SIGNAL(readyReadStandardOutput()), | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         SLOT(readGdbStandardOutput())); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     connect(gdbProc(), SIGNAL(readyReadStandardError()), | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         SLOT(readGdbStandardError())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-21 11:52:21 +01:00
										 |  |  |     showMessage(_("STARTING ") + m_gdb + _(" ") + gdbArgs.join(_(" "))); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     gdbProc()->start(m_gdb, gdbArgs); | 
					
						
							| 
									
										
										
										
											2010-03-10 15:51:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     if (!gdbProc()->waitForStarted()) { | 
					
						
							| 
									
										
										
										
											2010-09-06 14:26:19 +02:00
										 |  |  |         const QString msg = errorMessage(QProcess::FailedToStart); | 
					
						
							| 
									
										
										
										
											2010-03-10 15:51:31 +01:00
										 |  |  |         handleAdapterStartFailed(msg, settingsIdHint); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("GDB STARTED, INITIALIZING IT")); | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("show version", CB(handleShowVersion)); | 
					
						
							| 
									
										
										
										
											2009-11-25 15:43:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //postCommand("-enable-timings");
 | 
					
						
							| 
									
										
										
										
											2010-12-21 11:54:15 +01:00
										 |  |  |     //postCommand("set print static-members off"); // Seemingly doesn't work.
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //postCommand("set debug infrun 1");
 | 
					
						
							|  |  |  |     //postCommand("define hook-stop\n-thread-list-ids\n-stack-list-frames\nend");
 | 
					
						
							|  |  |  |     //postCommand("define hook-stop\nprint 4\nend");
 | 
					
						
							|  |  |  |     //postCommand("define hookpost-stop\nprint 5\nend");
 | 
					
						
							|  |  |  |     //postCommand("define hook-call\nprint 6\nend");
 | 
					
						
							|  |  |  |     //postCommand("define hookpost-call\nprint 7\nend");
 | 
					
						
							|  |  |  |     //postCommand("set print object on"); // works with CLI, but not MI
 | 
					
						
							|  |  |  |     //postCommand("set step-mode on");  // we can't work with that yes
 | 
					
						
							|  |  |  |     //postCommand("set exec-done-display on");
 | 
					
						
							|  |  |  |     //postCommand("set print pretty on");
 | 
					
						
							|  |  |  |     //postCommand("set confirm off");
 | 
					
						
							|  |  |  |     //postCommand("set pagination off");
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:06:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // The following does not work with 6.3.50-20050815 (Apple version gdb-1344)
 | 
					
						
							|  |  |  |     // (Mac OS 10.6), but does so for gdb-966 (10.5):
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //postCommand("set print inferior-events 1");
 | 
					
						
							| 
									
										
										
										
											2009-10-05 12:06:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("set breakpoint pending on"); | 
					
						
							|  |  |  |     postCommand("set print elements 10000"); | 
					
						
							| 
									
										
										
										
											2010-01-12 13:49:56 +01:00
										 |  |  |     // Produces a few messages during symtab loading
 | 
					
						
							|  |  |  |     //postCommand("set verbose on");
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     //postCommand("set substitute-path /var/tmp/qt-x11-src-4.5.0 "
 | 
					
						
							|  |  |  |     //    "/home/sandbox/qtsdk-2009.01/qt");
 | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // one of the following is needed to prevent crashes in gdb on code like:
 | 
					
						
							|  |  |  |     //  template <class T> T foo() { return T(0); }
 | 
					
						
							|  |  |  |     //  int main() { return foo<int>(); }
 | 
					
						
							|  |  |  |     //  (gdb) call 'int foo<int>'()
 | 
					
						
							|  |  |  |     //  /build/buildd/gdb-6.8/gdb/valops.c:2069: internal-error:
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("set overload-resolution off"); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     //postCommand(_("set demangle-style none"));
 | 
					
						
							|  |  |  |     // From the docs:
 | 
					
						
							|  |  |  |     //  Stop means reenter debugger if this signal happens (implies print).
 | 
					
						
							|  |  |  |     //  Print means print a message if this signal happens.
 | 
					
						
							|  |  |  |     //  Pass means let program see this signal;
 | 
					
						
							|  |  |  |     //  otherwise program doesn't know.
 | 
					
						
							|  |  |  |     //  Pass and Stop may be combined.
 | 
					
						
							| 
									
										
										
										
											2010-01-11 10:22:55 +01:00
										 |  |  |     // We need "print" as otherwise we will get no feedback whatsoever
 | 
					
						
							|  |  |  |     // when Custom DebuggingHelper crash (which happen regularly when accessing
 | 
					
						
							|  |  |  |     // uninitialized variables).
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("handle SIGSEGV nopass stop print"); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // This is useful to kill the inferior whenever gdb dies.
 | 
					
						
							|  |  |  |     //postCommand(_("handle SIGTERM pass nostop print"));
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |     postCommand("set unwindonsignal on"); | 
					
						
							|  |  |  |     //postCommand("pwd");
 | 
					
						
							|  |  |  |     postCommand("set width 0"); | 
					
						
							|  |  |  |     postCommand("set height 0"); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-14 10:44:36 +02:00
										 |  |  |     if (false && m_isMacGdb) { | 
					
						
							|  |  |  |         // FIXME: m_isMacGdb is only known after handleShowVersion!
 | 
					
						
							|  |  |  |         // also, setting load-rules seems to be only possible after 'file'
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("-gdb-set inferior-auto-start-cfm off"); | 
					
						
							|  |  |  |         postCommand("-gdb-set sharedLibrary load-rules " | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |             "dyld \".*libSystem.*\" all " | 
					
						
							|  |  |  |             "dyld \".*libauto.*\" all " | 
					
						
							|  |  |  |             "dyld \".*AppKit.*\" all " | 
					
						
							|  |  |  |             "dyld \".*PBGDBIntrospectionSupport.*\" all " | 
					
						
							|  |  |  |             "dyld \".*Foundation.*\" all " | 
					
						
							|  |  |  |             "dyld \".*CFDataFormatters.*\" all " | 
					
						
							|  |  |  |             "dyld \".*libobjc.*\" all " | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             "dyld \".*CarbonDataFormatters.*\" all"); | 
					
						
							| 
									
										
										
										
											2010-09-23 14:58:45 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2010-10-14 10:44:36 +02:00
										 |  |  |         // Work around http://bugreports.qt.nokia.com/browse/QTCREATORBUG-2004
 | 
					
						
							|  |  |  |         postCommand("maintenance set internal-warning quit no", ConsoleCommand); | 
					
						
							|  |  |  |         postCommand("maintenance set internal-error quit no", ConsoleCommand); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-23 17:18:22 +02:00
										 |  |  |         // We know that we don't have Python on Mac.
 | 
					
						
							| 
									
										
										
										
											2010-09-23 14:58:45 +02:00
										 |  |  |         loadPythonDumpers(); | 
					
						
							| 
									
										
										
										
											2009-10-22 11:08:06 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-10 16:33:11 +01:00
										 |  |  |     QString scriptFileName = debuggerCore()->stringSetting(GdbScriptFile); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |     if (!scriptFileName.isEmpty()) { | 
					
						
							|  |  |  |         if (QFileInfo(scriptFileName).isReadable()) { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |             postCommand("source " + scriptFileName.toLocal8Bit()); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-09-23 09:54:21 +02:00
										 |  |  |             showMessageBox(QMessageBox::Warning, | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  |             tr("Cannot find debugger initialization script"), | 
					
						
							|  |  |  |             tr("The debugger settings point to a script file at '%1' " | 
					
						
							|  |  |  |                "which is not accessible. If a script file is not needed, " | 
					
						
							|  |  |  |                "consider clearing that entry to avoid this warning. " | 
					
						
							|  |  |  |               ).arg(scriptFileName)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-02 18:16:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-15 13:23:44 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::loadPythonDumpers() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QByteArray dumperSourcePath = | 
					
						
							|  |  |  |         Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/"; | 
					
						
							| 
									
										
										
										
											2010-03-02 12:27:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 14:53:31 +02:00
										 |  |  |     postCommand("python execfile('" + dumperSourcePath + "dumper.py')", | 
					
						
							|  |  |  |         ConsoleCommand|NonCriticalResponse); | 
					
						
							|  |  |  |     postCommand("python execfile('" + dumperSourcePath + "gdbmacros.py')", | 
					
						
							|  |  |  |         ConsoleCommand|NonCriticalResponse); | 
					
						
							|  |  |  |     postCommand("bbsetup", | 
					
						
							| 
									
										
										
										
											2010-07-15 11:37:06 +02:00
										 |  |  |         ConsoleCommand, CB(handleHasPython)); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-13 09:53:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | void GdbEngine::handleGdbError(QProcess::ProcessError error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-06 14:26:19 +02:00
										 |  |  |     const QString msg = errorMessage(error); | 
					
						
							|  |  |  |     showMessage(_("HANDLE GDB ERROR: ") + msg); | 
					
						
							| 
									
										
										
										
											2010-10-30 21:54:23 +02:00
										 |  |  |     // Show a message box for asynchronously reported issues.
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     switch (error) { | 
					
						
							| 
									
										
										
										
											2010-09-06 14:26:19 +02:00
										 |  |  |     case QProcess::FailedToStart: | 
					
						
							|  |  |  |         // This should be handled by the code trying to start the process.
 | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     case QProcess::Crashed: | 
					
						
							| 
									
										
										
										
											2010-09-06 14:26:19 +02:00
										 |  |  |         // This will get a processExited() as well.
 | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     case QProcess::ReadError: | 
					
						
							|  |  |  |     case QProcess::WriteError: | 
					
						
							|  |  |  |     case QProcess::Timedout: | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         //gdbProc()->kill();
 | 
					
						
							| 
									
										
										
										
											2010-10-27 15:39:25 +02:00
										 |  |  |         //notifyEngineIll();
 | 
					
						
							| 
									
										
										
										
											2010-09-06 14:26:19 +02:00
										 |  |  |         showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"), msg); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |     if (m_commandTimer.isActive()) | 
					
						
							|  |  |  |         m_commandTimer.stop(); | 
					
						
							| 
									
										
										
										
											2010-11-16 12:38:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code)); | 
					
						
							| 
									
										
										
										
											2010-11-18 17:32:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 12:38:50 +01:00
										 |  |  |     switch (state()) { | 
					
						
							|  |  |  |     case EngineShutdownRequested: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         notifyEngineShutdownOk(); | 
					
						
							| 
									
										
										
										
											2010-11-16 12:38:50 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case InferiorRunOk: | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |         // This could either be a real gdb crash or a quickly exited inferior
 | 
					
						
							|  |  |  |         // in the terminal adapter. In this case the stub proc will die soon,
 | 
					
						
							|  |  |  |         // too, so there's no need to act here.
 | 
					
						
							|  |  |  |         showMessage(_("The gdb process exited somewhat unexpectedly.")); | 
					
						
							|  |  |  |         notifyEngineSpontaneousShutdown(); | 
					
						
							| 
									
										
										
										
											2010-11-16 12:38:50 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         notifyEngineIll(); // Initiate shutdown sequence
 | 
					
						
							|  |  |  |         const QString msg = type == QProcess::CrashExit ? | 
					
						
							|  |  |  |                     tr("The gdb process crashed.") : | 
					
						
							|  |  |  |                     tr("The gdb process exited unexpectedly (code %1)").arg(code); | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |         showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"), msg); | 
					
						
							| 
									
										
										
										
											2010-11-16 12:38:50 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-11-16 12:52:02 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  | void GdbEngine::handleAdapterStartFailed(const QString &msg, | 
					
						
							|  |  |  |     const QString &settingsIdHint) | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("ADAPTER START FAILED")); | 
					
						
							| 
									
										
										
										
											2010-02-25 16:05:45 +01:00
										 |  |  |     if (!msg.isEmpty()) { | 
					
						
							|  |  |  |         const QString title = tr("Adapter start failed"); | 
					
						
							|  |  |  |         if (settingsIdHint.isEmpty()) { | 
					
						
							|  |  |  |             Core::ICore::instance()->showWarningWithOptions(title, msg); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             Core::ICore::instance()->showWarningWithOptions(title, msg, QString(), | 
					
						
							| 
									
										
										
										
											2010-03-10 10:32:58 +01:00
										 |  |  |                 _(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint); | 
					
						
							| 
									
										
										
										
											2010-02-25 16:05:45 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-10-26 11:55:02 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     notifyEngineSetupFailed(); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | void GdbEngine::handleAdapterStarted() | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("ADAPTER SUCCESSFULLY STARTED")); | 
					
						
							| 
									
										
										
										
											2010-07-09 08:48:33 +02:00
										 |  |  |     notifyEngineSetupOk(); | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  | void GdbEngine::setupInferior() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); | 
					
						
							|  |  |  |     showStatusMessage(tr("Setting up inferior...")); | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  |     m_gdbAdapter->setupInferior(); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 09:46:39 +02:00
										 |  |  | void GdbEngine::notifyInferiorSetupFailed() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // FIXME: that's not enough to stop gdb from getting confused
 | 
					
						
							|  |  |  |     // by a timeout of the adapter.
 | 
					
						
							|  |  |  |     //resetCommandQueue();
 | 
					
						
							|  |  |  |     DebuggerEngine::notifyInferiorSetupFailed(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 19:04:01 +02:00
										 |  |  | void GdbEngine::handleInferiorPrepared() | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     const QByteArray qtInstallPath = startParameters().qtInstallPath.toLocal8Bit(); | 
					
						
							| 
									
										
										
										
											2009-11-09 16:25:24 +01:00
										 |  |  |     if (!qtInstallPath.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         QByteArray qtBuildPath; | 
					
						
							| 
									
										
										
										
											2009-11-19 19:43:18 +01:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         qtBuildPath = "C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.6/qt"; | 
					
						
							|  |  |  |         postCommand("set substitute-path " + qtBuildPath + ' ' + qtInstallPath); | 
					
						
							|  |  |  |         qtBuildPath = "C:/iwmake/build_mingw_opensource"; | 
					
						
							|  |  |  |         postCommand("set substitute-path " + qtBuildPath + ' ' + qtInstallPath); | 
					
						
							| 
									
										
										
										
											2009-11-19 19:43:18 +01:00
										 |  |  | #elif defined(Q_OS_UNIX) && !defined (Q_OS_MAC)
 | 
					
						
							| 
									
										
										
										
											2010-02-04 15:09:05 +01:00
										 |  |  |         qtBuildPath = "/var/tmp/qt-src"; | 
					
						
							| 
									
										
										
										
											2010-01-05 16:51:55 +01:00
										 |  |  |         postCommand("set substitute-path " + qtBuildPath + ' ' + qtInstallPath); | 
					
						
							| 
									
										
										
										
											2009-11-19 19:43:18 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-11-09 16:25:24 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-21 14:41:17 +01:00
										 |  |  |     // Initial attempt to set breakpoints.
 | 
					
						
							|  |  |  |     if (startParameters().startMode != AttachCore) { | 
					
						
							|  |  |  |         showStatusMessage(tr("Setting breakpoints...")); | 
					
						
							|  |  |  |         showMessage(tr("Setting breakpoints...")); | 
					
						
							|  |  |  |         attemptBreakpointSynchronization(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-13 09:53:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     if (m_cookieForToken.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  |         finishInferiorSetup(); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         QTC_ASSERT(m_commandsDoneCallback == 0, /**/); | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  |         m_commandsDoneCallback = &GdbEngine::finishInferiorSetup; | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-24 10:08:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  | void GdbEngine::finishInferiorSetup() | 
					
						
							| 
									
										
										
										
											2009-09-24 10:08:17 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); | 
					
						
							| 
									
										
										
										
											2010-07-08 18:10:50 +02:00
										 |  |  |     notifyInferiorSetupOk(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::runEngine() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); | 
					
						
							|  |  |  |     m_gdbAdapter->runEngine(); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  | void GdbEngine::notifyInferiorSetupFailed(const QString &msg) | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-23 16:56:42 +01:00
										 |  |  |     showStatusMessage(tr("Failed to start application: ") + msg); | 
					
						
							| 
									
										
										
										
											2010-07-09 08:48:33 +02:00
										 |  |  |     if (state() == EngineSetupFailed) { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |         showMessage(_("INFERIOR START FAILED, BUT ADAPTER DIED ALREADY")); | 
					
						
							| 
									
										
										
										
											2009-10-29 11:20:21 +01:00
										 |  |  |         return; // Adapter crashed meanwhile, so this notification is meaningless.
 | 
					
						
							| 
									
										
										
										
											2010-03-10 15:51:31 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("INFERIOR START FAILED")); | 
					
						
							| 
									
										
										
										
											2010-03-23 16:56:42 +01:00
										 |  |  |     showMessageBox(QMessageBox::Critical, tr("Failed to start application"), msg); | 
					
						
							| 
									
										
										
										
											2010-07-09 17:07:59 +02:00
										 |  |  |     DebuggerEngine::notifyInferiorSetupFailed(); | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 11:06:51 +02:00
										 |  |  | void GdbEngine::handleAdapterCrashed(const QString &msg) | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-14 18:19:02 +02:00
										 |  |  |     showMessage(_("ADAPTER CRASHED")); | 
					
						
							| 
									
										
										
										
											2009-09-21 11:09:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     // The adapter is expected to have cleaned up after itself when we get here,
 | 
					
						
							|  |  |  |     // so the effect is about the same as AdapterStartFailed => use it.
 | 
					
						
							|  |  |  |     // Don't bother with state transitions - this can happen in any state and
 | 
					
						
							|  |  |  |     // the end result is always the same, so it makes little sense to find a
 | 
					
						
							|  |  |  |     // "path" which does not assert.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 08:48:33 +02:00
										 |  |  |     notifyEngineSetupFailed(); | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     // No point in being friendly here ...
 | 
					
						
							| 
									
										
										
										
											2010-05-05 12:49:08 +02:00
										 |  |  |     gdbProc()->kill(); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-07 10:25:26 +02:00
										 |  |  |     if (!msg.isEmpty()) | 
					
						
							|  |  |  |         showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); | 
					
						
							| 
									
										
										
										
											2009-09-21 17:35:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  | void GdbEngine::setUseDebuggingHelpers(const QVariant &) | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     setTokenBarrier(); | 
					
						
							|  |  |  |     updateLocals(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GdbEngine::hasPython() const | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-01-20 15:38:01 +01:00
										 |  |  |     return m_hasPython; | 
					
						
							| 
									
										
										
										
											2009-10-12 14:50:27 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-24 10:08:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-29 18:44:02 +02:00
										 |  |  | void GdbEngine::createFullBacktrace() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-28 14:53:31 +02:00
										 |  |  |     postCommand("thread apply all bt full", | 
					
						
							|  |  |  |         NeedsStop|ConsoleCommand, CB(handleCreateFullBacktrace)); | 
					
						
							| 
									
										
										
										
											2010-03-29 18:44:02 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleCreateFullBacktrace(const GdbResponse &response) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2010-11-10 11:39:01 +01:00
										 |  |  |         debuggerCore()->openTextEditor(_("Backtrace $"), | 
					
						
							| 
									
										
										
										
											2010-03-29 18:44:02 +02:00
										 |  |  |             _(response.data.findChild("consolestreamoutput").data())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 09:46:39 +02:00
										 |  |  | void GdbEngine::resetCommandQueue() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-11-16 12:42:57 +01:00
										 |  |  |     m_commandTimer.stop(); | 
					
						
							| 
									
										
										
										
											2010-08-11 09:46:39 +02:00
										 |  |  |     if (!m_cookieForToken.isEmpty()) { | 
					
						
							|  |  |  |         QString msg; | 
					
						
							|  |  |  |         QTextStream ts(&msg); | 
					
						
							|  |  |  |         ts << "RESETING COMMAND QUEUE. LEFT OVER TOKENS: "; | 
					
						
							|  |  |  |         foreach (const GdbCommand &cookie, m_cookieForToken) | 
					
						
							|  |  |  |             ts << "CMD:" << cookie.command << cookie.callbackName; | 
					
						
							|  |  |  |         m_cookieForToken.clear(); | 
					
						
							|  |  |  |         showMessage(msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-03-29 18:44:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-15 19:02:12 +02:00
										 |  |  | void GdbEngine::removeTooltip() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_toolTipExpression.clear(); | 
					
						
							|  |  |  |     m_toolTipPos = QPoint(); | 
					
						
							|  |  |  |     DebuggerEngine::removeTooltip(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-10 12:41:44 +01:00
										 |  |  | void GdbEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_gdbAdapter->handleRemoteSetupDone(gdbServerPort, qmlPort); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GdbEngine::handleRemoteSetupFailed(const QString &message) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_gdbAdapter->handleRemoteSetupFailed(message); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  | bool GdbEngine::setupQmlStep(bool on) | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(isSlaveEngine(), return false); | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |     m_qmlBreakpointNumbers.clear(); | 
					
						
							|  |  |  |     //qDebug() << "CLEAR: " << m_qmlBreakpointNumbers;
 | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |     postCommand("tbreak '" + qtNamespace() + "QScript::FunctionWrapper::proxyCall'\n" | 
					
						
							|  |  |  |         "commands\n" | 
					
						
							|  |  |  |         "set $d=(void*)((FunctionWrapper*)callee)->data->function\n" | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |         "tbreak *$d\nprintf \"QMLBP:%d \\n\",$bpnum\ncontinue\nend", | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |         NeedsStop, CB(handleSetQmlStepBreakpoint)); | 
					
						
							| 
									
										
										
										
											2011-01-19 10:48:39 +01:00
										 |  |  |     m_preparedForQmlBreak = on; | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  | void GdbEngine::handleSetQmlStepBreakpoint(const GdbResponse &response) | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |     //QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
 | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  |     if (response.resultClass == GdbResultDone) { | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |         // "{logstreamoutput="tbreak 'myns::QScript::FunctionWrapper::proxyCall'\n"
 | 
					
						
							|  |  |  |         //,consolestreamoutput="Temporary breakpoint 1 at 0xf166e7:
 | 
					
						
							|  |  |  |         // file bridge/qscriptfunction.cpp, line 75.\n"}
 | 
					
						
							|  |  |  |         QByteArray ba = parsePlainConsoleStream(response); | 
					
						
							|  |  |  |         const int pos2 = ba.indexOf(" at 0x"); | 
					
						
							|  |  |  |         const int pos1 = ba.lastIndexOf(" ", pos2 - 1) + 1; | 
					
						
							|  |  |  |         QByteArray mid = ba.mid(pos1, pos2 - pos1); | 
					
						
							|  |  |  |         const int bpnr = mid.toInt(); | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |         m_qmlBreakpointNumbers[1] = bpnr; | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  |         //qDebug() << "SET: " << m_qmlBreakpointNumbers;
 | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     QTC_ASSERT(masterEngine(), return); | 
					
						
							| 
									
										
										
										
											2011-01-19 14:34:25 +01:00
										 |  |  |     masterEngine()->readyToExecuteQmlStep(); | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-24 13:37:07 +01:00
										 |  |  | bool GdbEngine::isQmlStepBreakpoint1(int bpnr) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //qDebug() << "CHECK 1: " << m_qmlBreakpointNumbers[1] << bpnr;
 | 
					
						
							|  |  |  |     return bpnr && m_qmlBreakpointNumbers[1] == bpnr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GdbEngine::isQmlStepBreakpoint2(int bpnr) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     //qDebug() << "CHECK 2: " << m_qmlBreakpointNumbers[2] << bpnr;
 | 
					
						
							|  |  |  |     return bpnr && m_qmlBreakpointNumbers[2] == bpnr; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-01-14 17:08:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-23 09:54:21 +02:00
										 |  |  | //
 | 
					
						
							|  |  |  | // Factory
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 12:10:12 +01:00
										 |  |  | DebuggerEngine *createGdbEngine(const DebuggerStartParameters &startParameters, | 
					
						
							|  |  |  |     DebuggerEngine *masterEngine) | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-01-12 12:10:12 +01:00
										 |  |  |     return new GdbEngine(startParameters, masterEngine); | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void addGdbOptionPages(QList<Core::IOptionsPage *> *opts) | 
					
						
							| 
									
										
										
										
											2009-09-23 09:54:21 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-16 11:08:54 +02:00
										 |  |  |     opts->push_back(new GdbOptionsPage()); | 
					
						
							| 
									
										
										
										
											2009-09-11 15:37:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 08:34:48 +02:00
										 |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace Debugger
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-16 11:25:28 +01:00
										 |  |  | Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie) | 
					
						
							|  |  |  | Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie) | 
					
						
							|  |  |  | Q_DECLARE_METATYPE(Debugger::Internal::GdbMi) |