| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Licensees holding valid Qt Commercial licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the Qt Commercial License Agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Nokia. | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +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.
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** If you are unsure which license is appropriate for your use, please | 
					
						
							| 
									
										
										
										
											2009-08-14 09:30:56 +02:00
										 |  |  | ** contact the sales department at http://qt.nokia.com/contact.
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | #include "cdbdebugengine.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | #include "cdbdebugengine_p.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | #include "cdbstacktracecontext.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  | #include "cdbstackframecontext.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  | #include "cdbsymbolgroupcontext.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  | #include "cdbbreakpoint.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | #include "cdbmodules.h"
 | 
					
						
							|  |  |  | #include "cdbassembler.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  | #include "cdboptionspage.h"
 | 
					
						
							|  |  |  | #include "cdboptions.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  | #include "cdbexceptionutils.h"
 | 
					
						
							| 
									
										
										
										
											2009-08-17 16:03:27 +02:00
										 |  |  | #include "debuggeragents.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | #include "debuggeractions.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | #include "debuggermanager.h"
 | 
					
						
							|  |  |  | #include "breakhandler.h"
 | 
					
						
							|  |  |  | #include "stackhandler.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  | #include "watchhandler.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | #include "registerhandler.h"
 | 
					
						
							|  |  |  | #include "moduleshandler.h"
 | 
					
						
							| 
									
										
										
										
											2009-03-25 17:33:49 +01:00
										 |  |  | #include "watchutils.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-17 11:16:23 +01:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | #include <utils/winutils.h>
 | 
					
						
							| 
									
										
										
										
											2009-03-03 17:11:27 +01:00
										 |  |  | #include <utils/consoleprocess.h>
 | 
					
						
							| 
									
										
										
										
											2009-09-25 15:10:19 +02:00
										 |  |  | #include <utils/fancymainwindow.h>
 | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  | #include <texteditor/itexteditor.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-17 11:16:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | #include <QtCore/QDebug>
 | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  | #include <QtCore/QTimer>
 | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | #include <QtCore/QTimerEvent>
 | 
					
						
							|  |  |  | #include <QtCore/QFileInfo>
 | 
					
						
							|  |  |  | #include <QtCore/QDir>
 | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | #include <QtCore/QLibrary>
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | #include <QtCore/QCoreApplication>
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  | #include <QtGui/QMessageBox>
 | 
					
						
							|  |  |  | #include <QtGui/QMainWindow>
 | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  | #include <QtGui/QApplication>
 | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  | #include <QtGui/QToolTip>
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define DBGHELP_TRANSLATE_TCHAR
 | 
					
						
							| 
									
										
										
										
											2009-02-20 14:56:36 +01:00
										 |  |  | #include <inc/Dbghelp.h>
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  | static const char *dbgHelpDllC = "dbghelp"; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | static const char *dbgEngineDllC = "dbgeng"; | 
					
						
							|  |  |  | static const char *debugCreateFuncC = "DebugCreate"; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | static const char *localSymbolRootC = "local"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Debugger { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  | typedef QList<WatchData> WatchList; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | // ----- Message helpers
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | QString msgDebugEngineComResult(HRESULT hr) | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (hr) { | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  |         case S_OK: | 
					
						
							|  |  |  |         return QLatin1String("S_OK"); | 
					
						
							|  |  |  |         case S_FALSE: | 
					
						
							|  |  |  |         return QLatin1String("S_FALSE"); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         case E_FAIL: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |         case E_INVALIDARG: | 
					
						
							|  |  |  |         return QLatin1String("E_INVALIDARG"); | 
					
						
							|  |  |  |         case E_NOINTERFACE: | 
					
						
							|  |  |  |         return QLatin1String("E_NOINTERFACE"); | 
					
						
							|  |  |  |         case E_OUTOFMEMORY: | 
					
						
							|  |  |  |         return QLatin1String("E_OUTOFMEMORY"); | 
					
						
							|  |  |  |         case E_UNEXPECTED: | 
					
						
							|  |  |  |         return QLatin1String("E_UNEXPECTED"); | 
					
						
							|  |  |  |         case E_NOTIMPL: | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         return QLatin1String("E_NOTIMPL"); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) | 
					
						
							|  |  |  |         return QLatin1String("ERROR_ACCESS_DENIED");; | 
					
						
							|  |  |  |     if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT)) | 
					
						
							|  |  |  |         return QLatin1String("STATUS_CONTROL_C_EXIT"); | 
					
						
							| 
									
										
										
										
											2009-10-05 11:06:05 +02:00
										 |  |  |     return QLatin1String("E_FAIL ") + Utils::winErrorMessage(HRESULT_CODE(hr)); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | static QString msgStackIndexOutOfRange(int idx, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return QString::fromLatin1("Frame index %1 out of range (%2).").arg(idx).arg(size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | QString msgComFailed(const char *func, HRESULT hr) | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(func), msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  | QString msgDebuggerCommandFailed(const QString &command, HRESULT hr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return QString::fromLatin1("Unable to execute '%1': %2").arg(command, msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | static const char *msgNoStackTraceC = "Internal error: no stack trace present."; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  | static inline QString msgLibLoadFailed(const QString &lib, const QString &why) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return CdbDebugEngine::tr("Unable to load the debugger engine library '%1': %2"). | 
					
						
							|  |  |  |             arg(lib, why); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  | // Format function failure message. Pass in Q_FUNC_INFO
 | 
					
						
							|  |  |  | static QString msgFunctionFailed(const char *func, const QString &why) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Strip a "cdecl_ int namespace1::class::foo(int bar)" as
 | 
					
						
							|  |  |  |     // returned by Q_FUNC_INFO down to "foo"
 | 
					
						
							|  |  |  |     QString function = QLatin1String(func); | 
					
						
							|  |  |  |     const int firstParentPos = function.indexOf(QLatin1Char('(')); | 
					
						
							|  |  |  |     if (firstParentPos != -1) | 
					
						
							|  |  |  |         function.truncate(firstParentPos); | 
					
						
							|  |  |  |     const int classSepPos = function.lastIndexOf(QLatin1String("::")); | 
					
						
							|  |  |  |     if (classSepPos != -1) | 
					
						
							|  |  |  |         function.remove(0, classSepPos + 2); | 
					
						
							|  |  |  |    //: Function call failed
 | 
					
						
							|  |  |  |    return CdbDebugEngine::tr("The function \"%1()\" failed: %2").arg(function, why); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | // ----- Engine helpers
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  | static inline ULONG getInterruptTimeOutSecs(CIDebugControl *ctl) | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     ULONG rc = 0; | 
					
						
							|  |  |  |     ctl->GetInterruptTimeout(&rc); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  | bool getExecutionStatus(CIDebugControl *ctl, | 
					
						
							|  |  |  |                         ULONG *executionStatus, | 
					
						
							|  |  |  |                         QString *errorMessage /* = 0 */) | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const HRESULT hr = ctl->GetExecutionStatus(executionStatus); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  |         if (errorMessage) | 
					
						
							|  |  |  |             *errorMessage = msgComFailed("GetExecutionStatus", hr); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  | const char *executionStatusString(ULONG executionStatus) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (executionStatus) { | 
					
						
							|  |  |  |     case DEBUG_STATUS_NO_CHANGE: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_NO_CHANGE"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_GO: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_GO"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_GO_HANDLED: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_GO_HANDLED"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_GO_NOT_HANDLED: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_GO_NOT_HANDLED"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_STEP_OVER: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_STEP_OVER"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_STEP_INTO: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_STEP_INTO"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_BREAK: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_BREAK"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_NO_DEBUGGEE: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_NO_DEBUGGEE"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_STEP_BRANCH: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_STEP_BRANCH"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_IGNORE_EVENT: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_IGNORE_EVENT"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_RESTART_REQUESTED: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_RESTART_REQUESTED"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_REVERSE_GO: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_REVERSE_GO"; | 
					
						
							|  |  |  |           case DEBUG_STATUS_REVERSE_STEP_BRANCH: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_REVERSE_STEP_BRANCH"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_REVERSE_STEP_OVER: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_REVERSE_STEP_OVER"; | 
					
						
							|  |  |  |     case DEBUG_STATUS_REVERSE_STEP_INTO: | 
					
						
							|  |  |  |         return "DEBUG_STATUS_REVERSE_STEP_INTO"; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return "<Unknown execution status>"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Debug convenience
 | 
					
						
							|  |  |  | const char *executionStatusString(CIDebugControl *ctl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ULONG executionStatus; | 
					
						
							|  |  |  |     if (getExecutionStatus(ctl, &executionStatus)) | 
					
						
							|  |  |  |         return executionStatusString(executionStatus); | 
					
						
							|  |  |  |     return "<failed>"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | // --------- DebuggerEngineLibrary
 | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | DebuggerEngineLibrary::DebuggerEngineLibrary() : | 
					
						
							|  |  |  |     m_debugCreate(0) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  | // Build a lib name as "Path\x.dll"
 | 
					
						
							|  |  |  | static inline QString libPath(const QString &libName, const QString &path = QString()) | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  |     QString rc = path; | 
					
						
							|  |  |  |     if (!rc.isEmpty()) | 
					
						
							|  |  |  |         rc += QDir::separator(); | 
					
						
							|  |  |  |     rc += libName; | 
					
						
							|  |  |  |     rc += QLatin1String(".dll"); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  | bool DebuggerEngineLibrary::init(const QString &path, | 
					
						
							|  |  |  |                                  QString *dbgEngDLL, | 
					
						
							|  |  |  |                                  QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     // Load the dependent help lib first
 | 
					
						
							|  |  |  |     const QString helpLibPath = libPath(QLatin1String(dbgHelpDllC), path); | 
					
						
							|  |  |  |     QLibrary helpLib(helpLibPath, 0); | 
					
						
							|  |  |  |     if (!helpLib.isLoaded() && !helpLib.load()) { | 
					
						
							|  |  |  |         *errorMessage = msgLibLoadFailed(helpLibPath, helpLib.errorString()); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Load dbgeng lib
 | 
					
						
							|  |  |  |     const QString engineLibPath = libPath(QLatin1String(dbgEngineDllC), path); | 
					
						
							|  |  |  |     QLibrary lib(engineLibPath, 0); | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     if (!lib.isLoaded() && !lib.load()) { | 
					
						
							| 
									
										
										
										
											2009-04-17 10:13:41 +02:00
										 |  |  |         *errorMessage = msgLibLoadFailed(engineLibPath, lib.errorString()); | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  |     *dbgEngDLL = engineLibPath; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     // Locate symbols
 | 
					
						
							|  |  |  |     void *createFunc = lib.resolve(debugCreateFuncC); | 
					
						
							|  |  |  |     if (!createFunc) { | 
					
						
							|  |  |  |         *errorMessage = CdbDebugEngine::tr("Unable to resolve '%1' in the debugger engine library '%2'"). | 
					
						
							|  |  |  |                         arg(QLatin1String(debugCreateFuncC), QLatin1String(dbgEngineDllC)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_debugCreate = static_cast<DebugCreateFunction>(createFunc); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  | // ----- SyntaxSetter
 | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  | SyntaxSetter::SyntaxSetter(CIDebugControl *ctl, ULONG desiredSyntax) : | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  |     m_desiredSyntax(desiredSyntax), | 
					
						
							|  |  |  |     m_ctl(ctl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_ctl->GetExpressionSyntax(&m_oldSyntax); | 
					
						
							|  |  |  |     if (m_oldSyntax != m_desiredSyntax) | 
					
						
							|  |  |  |         m_ctl->SetExpressionSyntax(m_desiredSyntax); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SyntaxSetter::~SyntaxSetter() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_oldSyntax != m_desiredSyntax) | 
					
						
							|  |  |  |         m_ctl->SetExpressionSyntax(m_oldSyntax); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  | // CdbComInterfaces
 | 
					
						
							|  |  |  | CdbComInterfaces::CdbComInterfaces() : | 
					
						
							|  |  |  |     debugClient(0), | 
					
						
							|  |  |  |     debugControl(0), | 
					
						
							|  |  |  |     debugSystemObjects(0), | 
					
						
							|  |  |  |     debugSymbols(0), | 
					
						
							|  |  |  |     debugRegisters(0), | 
					
						
							|  |  |  |     debugDataSpaces(0) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | // --- CdbDebugEnginePrivate
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  | CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager, | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |                                              const QSharedPointer<CdbOptions> &options, | 
					
						
							|  |  |  |                                              CdbDebugEngine* engine) : | 
					
						
							|  |  |  |     m_options(options), | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     m_hDebuggeeProcess(0), | 
					
						
							|  |  |  |     m_hDebuggeeThread(0), | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     m_breakEventMode(BreakEventHandle), | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     m_dumper(new CdbDumperHelper(manager, &m_cif)), | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     m_currentThreadId(-1), | 
					
						
							|  |  |  |     m_eventThreadId(-1), | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_interruptArticifialThreadId(-1), | 
					
						
							| 
									
										
										
										
											2009-10-15 15:04:11 +02:00
										 |  |  |     m_ignoreInitialBreakPoint(false), | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_interrupted(false),     | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     m_watchTimer(-1), | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  |     m_debugEventCallBack(engine), | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     m_engine(engine), | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     m_currentStackTrace(0), | 
					
						
							| 
									
										
										
										
											2009-03-27 17:19:39 +01:00
										 |  |  |     m_firstActivatedFrame(true), | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_inferiorStartupComplete(false), | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |     m_mode(AttachCore) | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::init(QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-27 15:32:46 +02:00
										 |  |  |     enum {  bufLen = 10240 }; | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     // Load the DLL
 | 
					
						
							|  |  |  |     DebuggerEngineLibrary lib; | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  |     if (!lib.init(m_options->path, &m_dbengDLL, errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     // Initialize the COM interfaces
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     HRESULT hr; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     hr = lib.debugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_cif.debugClient)); | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugClient5 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     m_cif.debugClient->SetOutputCallbacksWide(&m_debugOutputCallBack); | 
					
						
							|  |  |  |     m_cif.debugClient->SetEventCallbacksWide(&m_debugEventCallBack); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     hr = lib.debugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_cif.debugControl)); | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugControl4 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |     setCodeLevel(); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     hr = lib.debugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_cif.debugSystemObjects)); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugSystemObjects4 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     hr = lib.debugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_cif.debugSymbols)); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugSymbols3 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 15:32:46 +02:00
										 |  |  |     WCHAR buf[bufLen]; | 
					
						
							|  |  |  |     hr = m_cif.debugSymbols->GetImagePathWide(buf, bufLen, 0); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = msgComFailed("GetImagePathWide", hr); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_baseImagePath = QString::fromUtf16(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     hr = lib.debugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_cif.debugRegisters)); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugRegisters2 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     hr = lib.debugCreate( __uuidof(IDebugDataSpaces4), reinterpret_cast<void**>(&m_cif.debugDataSpaces)); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Creation of IDebugDataSpaces4 failed: %1").arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     if (debugCDB) | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |         qDebug() << QString::fromLatin1("CDB Initialization succeeded, interrupt time out %1s.").arg(getInterruptTimeOutSecs(m_cif.debugControl)); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 16:01:28 +02:00
										 |  |  | IDebuggerEngine *CdbDebugEngine::create(Debugger::DebuggerManager *manager, | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |                                         const QSharedPointer<CdbOptions> &options, | 
					
						
							|  |  |  |                                         QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     CdbDebugEngine *rc = new CdbDebugEngine(manager, options); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     if (rc->m_d->init(errorMessage)) { | 
					
						
							|  |  |  |         rc->syncDebuggerPaths(); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |         return rc; | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     delete rc; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  | // Adapt code level setting to the setting of the action.
 | 
					
						
							|  |  |  | static inline const char *codeLevelName(ULONG level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return level == DEBUG_LEVEL_ASSEMBLY ? "assembly" : "source"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::setCodeLevel() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-29 16:03:30 +02:00
										 |  |  |     const ULONG codeLevel = theDebuggerBoolSetting(OperateByInstruction) ? | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |                             DEBUG_LEVEL_ASSEMBLY : DEBUG_LEVEL_SOURCE; | 
					
						
							|  |  |  |     ULONG currentCodeLevel = DEBUG_LEVEL_ASSEMBLY; | 
					
						
							|  |  |  |     HRESULT hr = m_cif.debugControl->GetCodeLevel(¤tCodeLevel); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         m_engine->warning(QString::fromLatin1("Cannot determine code level: %1").arg(msgComFailed("GetCodeLevel", hr))); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << "\nSetting code level to " << codeLevelName(codeLevel) << " (was" << codeLevelName(currentCodeLevel) << ')'; | 
					
						
							| 
									
										
										
										
											2009-08-27 14:12:42 +02:00
										 |  |  |     if (currentCodeLevel == codeLevel) | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     hr = m_cif.debugControl->SetCodeLevel(codeLevel); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         m_engine->warning(QString::fromLatin1("Cannot set code level: %1").arg(msgComFailed("SetCodeLevel", hr))); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | CdbDebugEnginePrivate::~CdbDebugEnginePrivate() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     cleanStackTrace(); | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (m_cif.debugClient) | 
					
						
							|  |  |  |         m_cif.debugClient->Release(); | 
					
						
							|  |  |  |     if (m_cif.debugControl) | 
					
						
							|  |  |  |         m_cif.debugControl->Release(); | 
					
						
							|  |  |  |     if (m_cif.debugSystemObjects) | 
					
						
							|  |  |  |         m_cif.debugSystemObjects->Release(); | 
					
						
							|  |  |  |     if (m_cif.debugSymbols) | 
					
						
							|  |  |  |         m_cif.debugSymbols->Release(); | 
					
						
							|  |  |  |     if (m_cif.debugRegisters) | 
					
						
							|  |  |  |         m_cif.debugRegisters->Release(); | 
					
						
							|  |  |  |     if (m_cif.debugDataSpaces) | 
					
						
							|  |  |  |         m_cif.debugDataSpaces->Release(); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  | DebuggerManager *CdbDebugEnginePrivate::manager() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_engine->manager(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | void CdbDebugEnginePrivate::clearForRun() | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     m_breakEventMode = BreakEventHandle; | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_eventThreadId = m_interruptArticifialThreadId = -1; | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |     m_interrupted = false; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     cleanStackTrace(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEnginePrivate::cleanStackTrace() | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     if (m_currentStackTrace) { | 
					
						
							|  |  |  |         delete m_currentStackTrace; | 
					
						
							|  |  |  |         m_currentStackTrace = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     m_firstActivatedFrame = false; | 
					
						
							|  |  |  |     m_editorToolTipCache.clear(); | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  | CdbDebugEngine::CdbDebugEngine(DebuggerManager *manager, const QSharedPointer<CdbOptions> &options) : | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     IDebuggerEngine(manager), | 
					
						
							|  |  |  |     m_d(new CdbDebugEnginePrivate(manager, options, this)) | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-05 11:06:05 +02:00
										 |  |  |     m_d->m_consoleStubProc.setMode(Utils::ConsoleProcess::Suspend); | 
					
						
							| 
									
										
										
										
											2009-09-29 14:09:13 +02:00
										 |  |  |     connect(&m_d->m_consoleStubProc, SIGNAL(processError(QString)), | 
					
						
							|  |  |  |             this, SLOT(slotConsoleStubError(QString))); | 
					
						
							|  |  |  |     connect(&m_d->m_consoleStubProc, SIGNAL(processStarted()), | 
					
						
							|  |  |  |             this, SLOT(slotConsoleStubStarted())); | 
					
						
							|  |  |  |     connect(&m_d->m_consoleStubProc, SIGNAL(wrapperStopped()), | 
					
						
							|  |  |  |             this, SLOT(slotConsoleStubTerminated())); | 
					
						
							| 
									
										
										
										
											2009-06-19 12:47:23 +02:00
										 |  |  |     connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggerOutput(int,QString)), | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             manager, SLOT(showDebuggerOutput(int,QString))); | 
					
						
							| 
									
										
										
										
											2009-06-19 12:47:23 +02:00
										 |  |  |     connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggerInputPrompt(int,QString)), | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             manager, SLOT(showDebuggerInput(int,QString))); | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |     connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggeeOutput(QString)), | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             manager, SLOT(showApplicationOutput(QString))); | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |     connect(&m_d->m_debugOutputCallBack, SIGNAL(debuggeeInputPrompt(QString)), | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             manager, SLOT(showApplicationOutput(QString))); | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CdbDebugEngine::~CdbDebugEngine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete m_d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  | void CdbDebugEngine::setState(DebuggerState state, const char *func, int line) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << "setState(" << state << ") at " << func << ':' << line; | 
					
						
							|  |  |  |     IDebuggerEngine::setState(state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::startWatchTimer() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  |     if (m_d->m_watchTimer == -1) | 
					
						
							|  |  |  |         m_d->m_watchTimer = startTimer(0); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::killWatchTimer() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  |     if (m_d->m_watchTimer != -1) { | 
					
						
							|  |  |  |         killTimer(m_d->m_watchTimer); | 
					
						
							|  |  |  |         m_d->m_watchTimer = -1; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::shutdown() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     exitDebugger(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  | QString CdbDebugEngine::editorToolTip(const QString &exp, const QString &function) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |     // Figure the editor tooltip. Ask the frame context of the
 | 
					
						
							|  |  |  |     // function if it is a local variable it knows. If that is not
 | 
					
						
							|  |  |  |     // the case, try to evaluate via debugger
 | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     QString rc; | 
					
						
							|  |  |  |     // Find the frame of the function if there is any
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |     CdbStackFrameContext *frame = 0; | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |     if (m_d->m_currentStackTrace &&  !function.isEmpty()) { | 
					
						
							|  |  |  |         const int frameIndex = m_d->m_currentStackTrace->indexOf(function); | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         if (frameIndex != -1) | 
					
						
							|  |  |  |             frame = m_d->m_currentStackTrace->frameContextAt(frameIndex, &errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |     if (frame && frame->editorToolTip(QLatin1String("local.") + exp, &rc, &errorMessage)) | 
					
						
							|  |  |  |         return rc; | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |     // No function/symbol context found, try to evaluate in current context.
 | 
					
						
							|  |  |  |     // Do not append type as this will mostly be 'long long' for integers, etc.
 | 
					
						
							|  |  |  |     QString type; | 
					
						
							|  |  |  |     if (!evaluateExpression(exp, &rc, &type, &errorMessage)) | 
					
						
							|  |  |  |         return QString(); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     typedef CdbDebugEnginePrivate::EditorToolTipCache EditorToolTipCache; | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  |     if (debugCDB) | 
					
						
							| 
									
										
										
										
											2009-05-14 14:29:37 +02:00
										 |  |  |         qDebug() << Q_FUNC_INFO << '\n' << cursorPos; | 
					
						
							|  |  |  |     // Need a stopped debuggee and a cpp file
 | 
					
						
							|  |  |  |     if (!m_d->m_hDebuggeeProcess || m_d->isDebuggeeRunning()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (!isCppEditor(editor)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     // Determine expression and function
 | 
					
						
							|  |  |  |     QString toolTip; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         int line; | 
					
						
							|  |  |  |         int column; | 
					
						
							|  |  |  |         QString function; | 
					
						
							|  |  |  |         const QString exp = cppExpressionAt(editor, cursorPos, &line, &column, &function); | 
					
						
							|  |  |  |         if (function.isEmpty() || exp.isEmpty()) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         // Check cache (key containing function) or try to figure out expression
 | 
					
						
							|  |  |  |         QString cacheKey = function; | 
					
						
							|  |  |  |         cacheKey += QLatin1Char('@'); | 
					
						
							|  |  |  |         cacheKey += exp; | 
					
						
							|  |  |  |         const EditorToolTipCache::const_iterator cit = m_d->m_editorToolTipCache.constFind(cacheKey); | 
					
						
							|  |  |  |         if (cit != m_d->m_editorToolTipCache.constEnd()) { | 
					
						
							|  |  |  |             toolTip = cit.value(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             toolTip = editorToolTip(exp, function); | 
					
						
							|  |  |  |             if (!toolTip.isEmpty()) | 
					
						
							|  |  |  |                 m_d->m_editorToolTipCache.insert(cacheKey, toolTip); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  |     // Display
 | 
					
						
							|  |  |  |     QToolTip::hideText(); | 
					
						
							|  |  |  |     if (!toolTip.isEmpty()) | 
					
						
							|  |  |  |         QToolTip::showText(mousePos, toolTip); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | void CdbDebugEnginePrivate::clearDisplay() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->threadsHandler()->removeAll(); | 
					
						
							|  |  |  |     manager()->modulesHandler()->removeAll(); | 
					
						
							|  |  |  |     manager()->registerHandler()->removeAll(); | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  | void CdbDebugEnginePrivate::checkVersion() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static bool versionNotChecked = true; | 
					
						
							|  |  |  |     // Check for version 6.11 (extended expression syntax)
 | 
					
						
							|  |  |  |     if (versionNotChecked) { | 
					
						
							|  |  |  |         versionNotChecked = false; | 
					
						
							|  |  |  |         // Get engine DLL version
 | 
					
						
							|  |  |  |         QString errorMessage; | 
					
						
							|  |  |  |         const QString version = Utils::winGetDLLVersion(Utils::WinDLLProductVersion, m_dbengDLL, &errorMessage); | 
					
						
							|  |  |  |         if (version.isEmpty()) { | 
					
						
							|  |  |  |             qWarning("%s\n", qPrintable(errorMessage)); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Compare
 | 
					
						
							|  |  |  |         const double minVersion = 6.11; | 
					
						
							|  |  |  |         manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Version: %1").arg(version)); | 
					
						
							|  |  |  |         if (version.toDouble() <  minVersion) { | 
					
						
							|  |  |  |             const QString msg = CdbDebugEngine::tr( | 
					
						
							|  |  |  |                     "<html>The installed version of the <i>Debugging Tools for Windows</i> (%1) " | 
					
						
							|  |  |  |                     "is rather old. Upgrading to version %2 is recommended " | 
					
						
							|  |  |  |                     "for the proper display of Qt's data types.</html>").arg(version).arg(minVersion); | 
					
						
							|  |  |  |             Core::ICore::instance()->showWarningWithOptions(CdbDebugEngine::tr("Debugger"), msg, QString(), | 
					
						
							|  |  |  |                                                             QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY), | 
					
						
							|  |  |  |                                                             CdbOptionsPage::settingsId()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-10 13:09:42 +02:00
										 |  |  | void CdbDebugEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp) | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "startDebugger" << *sp; | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     setState(AdapterStarting, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-10-09 17:33:24 +02:00
										 |  |  |     m_d->checkVersion(); | 
					
						
							| 
									
										
										
										
											2009-06-19 11:07:38 +02:00
										 |  |  |     if (m_d->m_hDebuggeeProcess) { | 
					
						
							|  |  |  |         warning(QLatin1String("Internal error: Attempt to start debugger while another process is being debugged.")); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         setState(AdapterStartFailed, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-09-10 13:09:42 +02:00
										 |  |  |         emit startFailed(); | 
					
						
							| 
									
										
										
										
											2009-06-19 11:07:38 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  |     m_d->clearDisplay(); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_d->m_inferiorStartupComplete = false; | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     setState(AdapterStarted, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-17 16:29:51 +02:00
										 |  |  |     const DebuggerStartMode mode = sp->startMode; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     // Figure out dumper. @TODO: same in gdb...
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     const QString dumperLibName = QDir::toNativeSeparators(manager()->qtDumperLibraryName()); | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |     bool dumperEnabled = mode != AttachCore | 
					
						
							|  |  |  |                          && mode != AttachCrashedExternal | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |                          && manager()->qtDumperLibraryEnabled(); | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (dumperEnabled) { | 
					
						
							|  |  |  |         const QFileInfo fi(dumperLibName); | 
					
						
							|  |  |  |         if (!fi.isFile()) { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             const QStringList &locations = manager()->qtDumperLibraryLocations(); | 
					
						
							| 
									
										
										
										
											2009-07-15 17:41:45 +02:00
										 |  |  |             const QString loc = locations.join(QLatin1String(", ")); | 
					
						
							|  |  |  |             const QString msg = tr("The dumper library was not found at %1.").arg(loc); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |             manager()->showQtDumperLibraryWarning(msg); | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |             dumperEnabled = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |     m_d->m_dumper->reset(dumperLibName, dumperEnabled); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     setState(InferiorStarting, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->showStatusMessage("Starting Debugger", -1); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     bool rc = false; | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |     bool needWatchTimer = false; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     m_d->clearForRun(); | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |     m_d->setCodeLevel(); | 
					
						
							| 
									
										
										
										
											2009-10-15 15:04:11 +02:00
										 |  |  |     m_d->m_ignoreInitialBreakPoint = false; | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |     switch (mode) { | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     case AttachExternal: | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |     case AttachCrashedExternal: | 
					
						
							|  |  |  |         rc = startAttachDebugger(sp->attachPID, mode, &errorMessage); | 
					
						
							|  |  |  |         needWatchTimer = true; // Fetch away module load, etc. even if crashed
 | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case StartInternal: | 
					
						
							|  |  |  |     case StartExternal: | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         if (sp->useTerminal) { | 
					
						
							| 
									
										
										
										
											2009-10-15 15:04:11 +02:00
										 |  |  |             // Attaching to console processes triggers an initial breakpoint, which we do not want
 | 
					
						
							|  |  |  |             m_d->m_ignoreInitialBreakPoint = true; | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |             // Launch console stub and wait for its startup
 | 
					
						
							|  |  |  |             m_d->m_consoleStubProc.stop(); // We leave the console open, so recycle it now.
 | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |             m_d->m_consoleStubProc.setWorkingDirectory(sp->workingDir); | 
					
						
							|  |  |  |             m_d->m_consoleStubProc.setEnvironment(sp->environment); | 
					
						
							|  |  |  |             rc = m_d->m_consoleStubProc.start(sp->executable, sp->processArgs); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |             if (!rc) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |                 errorMessage = tr("The console stub process was unable to start '%1'.").arg(sp->executable); | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |             // continues in slotConsoleStubStarted()...
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |             needWatchTimer = true; | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |             rc = startDebuggerWithExecutable(mode, &errorMessage); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case AttachCore: | 
					
						
							| 
									
										
										
										
											2009-05-07 15:34:52 +02:00
										 |  |  |         errorMessage = tr("Attaching to core files is not supported!"); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (rc) { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         manager()->showStatusMessage(tr("Debugger running"), -1); | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |         if (needWatchTimer) | 
					
						
							|  |  |  |             startWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |             emit startSuccessful(); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         setState(InferiorStartFailed, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-09-10 13:09:42 +02:00
										 |  |  |         emit startFailed(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  | bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |     // Need to attrach invasively, otherwise, no notification signals
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     // for for CreateProcess/ExitProcess occur.
 | 
					
						
							| 
									
										
										
										
											2009-10-19 14:04:11 +02:00
										 |  |  |     // Initial breakpoint occur:
 | 
					
						
							|  |  |  |     // 1) Desired: When attaching to a crashed process
 | 
					
						
							|  |  |  |     // 2) Undesired: When starting up a console process, in conjunction
 | 
					
						
							|  |  |  |     //    with the 32bit Wow-engine
 | 
					
						
							|  |  |  |     //  As of version 6.11, the flag only affects 1). 2) Still needs to be suppressed
 | 
					
						
							|  |  |  |     // by lookup at the state of the application (startup trap). However,
 | 
					
						
							|  |  |  |     // there is no startup trap when attaching to a process that has been
 | 
					
						
							|  |  |  |     // running for a while. (see notifyException).
 | 
					
						
							|  |  |  |     ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS; | 
					
						
							|  |  |  |     if (manager()->startParameters()->startMode != AttachCrashedExternal) | 
					
						
							|  |  |  |         flags |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK; | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |     const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |         qDebug() << "Attaching to " << pid << " using flags" << flags << " returns " << hr << executionStatusString(m_d->m_cif.debugControl); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-05-07 15:34:52 +02:00
										 |  |  |         *errorMessage = tr("Attaching to a process failed for process id %1: %2").arg(pid).arg(msgDebugEngineComResult(hr)); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |         m_d->m_mode = sm; | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  | bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     showStatusMessage("Starting Debugger", -1); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     DEBUG_CREATE_PROCESS_OPTIONS dbgopts; | 
					
						
							|  |  |  |     memset(&dbgopts, 0, sizeof(dbgopts)); | 
					
						
							|  |  |  |     dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     const QSharedPointer<DebuggerStartParameters> sp = manager()->startParameters(); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     const QString filename(sp->executable); | 
					
						
							| 
									
										
										
										
											2009-07-27 15:32:46 +02:00
										 |  |  |     // Set image path
 | 
					
						
							|  |  |  |     const QFileInfo fi(filename); | 
					
						
							|  |  |  |     QString imagePath = QDir::toNativeSeparators(fi.absolutePath()); | 
					
						
							|  |  |  |     if (!m_d->m_baseImagePath.isEmpty()) { | 
					
						
							|  |  |  |         imagePath += QLatin1Char(';'); | 
					
						
							|  |  |  |         imagePath += m_d->m_baseImagePath; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-07-28 09:10:12 +02:00
										 |  |  |     HRESULT hr = m_d->m_cif.debugSymbols->SetImagePathWide(reinterpret_cast<PCWSTR>(imagePath.utf16())); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = tr("Unable to set the image path to %1: %2").arg(imagePath, msgComFailed("SetImagePathWide", hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							| 
									
										
										
										
											2009-07-27 15:32:46 +02:00
										 |  |  |         qDebug() << Q_FUNC_INFO <<'\n' << filename << imagePath; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 15:32:46 +02:00
										 |  |  |     ULONG symbolOptions = SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS; | 
					
						
							|  |  |  |     if (m_d->m_options->verboseSymbolLoading) | 
					
						
							|  |  |  |         symbolOptions |= SYMOPT_DEBUG; | 
					
						
							|  |  |  |     m_d->m_cif.debugSymbols->SetSymbolOptions(symbolOptions); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-05 11:06:05 +02:00
										 |  |  |     const QString cmd = Utils::AbstractProcess::createWinCommandline(filename, sp->processArgs); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << "Starting " << cmd; | 
					
						
							|  |  |  |     PCWSTR env = 0; | 
					
						
							|  |  |  |     QByteArray envData; | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     if (!sp->environment.empty()) { | 
					
						
							| 
									
										
										
										
											2009-10-05 11:06:05 +02:00
										 |  |  |         envData = Utils::AbstractProcess::createWinEnvironment(Utils::AbstractProcess::fixWinEnvironment(sp->environment)); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |         env = reinterpret_cast<PCWSTR>(envData.data()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-07-28 09:10:12 +02:00
										 |  |  |     // The working directory cannot be empty.
 | 
					
						
							|  |  |  |     PCWSTR workingDirC = 0; | 
					
						
							|  |  |  |     const QString workingDir = sp->workingDir.isEmpty() ? QString() : QDir::toNativeSeparators(sp->workingDir); | 
					
						
							|  |  |  |     if (!workingDir.isEmpty()) | 
					
						
							|  |  |  |         workingDirC = workingDir.utf16(); | 
					
						
							|  |  |  |     hr = m_d->m_cif.debugClient->CreateProcess2Wide(NULL, | 
					
						
							|  |  |  |                                                     reinterpret_cast<PWSTR>(const_cast<ushort *>(cmd.utf16())), | 
					
						
							|  |  |  |                                                     &dbgopts, sizeof(dbgopts), | 
					
						
							|  |  |  |                                                     workingDirC, env); | 
					
						
							| 
									
										
										
										
											2009-03-04 16:00:43 +01:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-05-07 15:34:52 +02:00
										 |  |  |         *errorMessage = tr("Unable to create a process '%1': %2").arg(cmd, msgDebugEngineComResult(hr)); | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         m_d->m_mode = sm; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  | void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle) | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  | {    | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  |     setDebuggeeHandles(reinterpret_cast<HANDLE>(processHandle), reinterpret_cast<HANDLE>(initialThreadHandle)); | 
					
						
							|  |  |  |     ULONG currentThreadId; | 
					
						
							|  |  |  |     if (SUCCEEDED(m_cif.debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, ¤tThreadId))) { | 
					
						
							|  |  |  |         m_currentThreadId = currentThreadId; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_currentThreadId = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |     // Clear any saved breakpoints and set initial breakpoints
 | 
					
						
							|  |  |  |     m_engine->executeDebuggerCommand(QLatin1String("bc")); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (manager()->breakHandler()->hasPendingBreakpoints()) { | 
					
						
							|  |  |  |         if (debugCDBExecution) | 
					
						
							|  |  |  |             qDebug() << "processCreatedAttached: Syncing breakpoints"; | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         m_engine->attemptBreakpointSynchronization(); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |     // Attaching to crashed: This handshake (signalling an event) is required for
 | 
					
						
							|  |  |  |     // the exception to be delivered to the debugger
 | 
					
						
							|  |  |  |     if (m_mode == AttachCrashedExternal) { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |         const QString crashParameter = manager()->startParameters()->crashParameter; | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |         if (!crashParameter.isEmpty()) { | 
					
						
							|  |  |  |             ULONG64 evtNr = crashParameter.toULongLong(); | 
					
						
							|  |  |  |             const HRESULT hr = m_cif.debugControl->SetNotifyEventHandle(evtNr); | 
					
						
							|  |  |  |             if (FAILED(hr)) | 
					
						
							|  |  |  |                 m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(msgComFailed("SetNotifyEventHandle", hr))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "<processCreatedAttached" << executionStatusString(m_cif.debugControl); | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-25 13:42:47 +01:00
										 |  |  | void CdbDebugEngine::processTerminated(unsigned long exitCode) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     manager()->showDebuggerOutput(LogMisc, tr("The process exited with exit code %1.").arg(exitCode)); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:38:27 +02:00
										 |  |  |     if (state() != InferiorStopping) | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |         setState(InferiorStopping, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     setState(InferiorStopped, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-03-25 13:42:47 +01:00
										 |  |  |     m_d->setDebuggeeHandles(0, 0); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     m_d->clearForRun(); | 
					
						
							|  |  |  |     setState(InferiorShutDown, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     // Avoid calls from event handler.
 | 
					
						
							|  |  |  |     QTimer::singleShot(0, manager(), SLOT(exitDebugger())); | 
					
						
							| 
									
										
										
										
											2009-03-25 13:42:47 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  | bool CdbDebugEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     // Process must be stopped in order to terminate
 | 
					
						
							|  |  |  |     m_engine->setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__); // pretend it is shutdown
 | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  |     const bool wasRunning = isDebuggeeRunning(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     if (wasRunning) { | 
					
						
							|  |  |  |         interruptInterferiorProcess(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  |         QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     bool success = false; | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  |     switch (action) { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     case DetachInferior: {             | 
					
						
							|  |  |  |             const HRESULT hr = m_cif.debugClient->DetachCurrentProcess(); | 
					
						
							|  |  |  |             if (SUCCEEDED(hr)) { | 
					
						
							|  |  |  |                 success = true; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 *errorMessage += msgComFailed("DetachCurrentProcess", hr); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     case TerminateInferior: { | 
					
						
							|  |  |  |             do { | 
					
						
							|  |  |  |                 // The exit process event handler will not be called.
 | 
					
						
							|  |  |  |                 HRESULT hr = m_cif.debugClient->TerminateCurrentProcess(); | 
					
						
							|  |  |  |                 if (FAILED(hr)) { | 
					
						
							|  |  |  |                     *errorMessage += msgComFailed("TerminateCurrentProcess", hr); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (wasRunning) { | 
					
						
							|  |  |  |                     success = true; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 hr = m_cif.debugClient->TerminateProcesses(); | 
					
						
							|  |  |  |                 if (SUCCEEDED(hr)) { | 
					
						
							|  |  |  |                     success = true; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     *errorMessage += msgComFailed("TerminateProcesses", hr); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } while (false); | 
					
						
							|  |  |  |             QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     // Perform cleanup even when failed..no point clinging to the process
 | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  |     setDebuggeeHandles(0, 0); | 
					
						
							|  |  |  |     m_engine->killWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     m_engine->setState(success ? InferiorShutDown : InferiorShutdownFailed, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     return success; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-15 16:30:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  | // End debugging. Note that this can invoked via user action
 | 
					
						
							|  |  |  | // or the processTerminated() event handler, in which case it
 | 
					
						
							|  |  |  | // must not kill the process again.
 | 
					
						
							|  |  |  | void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << em; | 
					
						
							| 
									
										
										
										
											2009-06-15 16:30:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     const DebuggerState oldState = m_engine->state(); | 
					
						
							|  |  |  |     if (oldState == DebuggerNotReady || m_mode == AttachCore) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     // Do we need to stop the process?
 | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     if (oldState != InferiorShutDown && m_hDebuggeeProcess) { | 
					
						
							|  |  |  |         EndInferiorAction action; | 
					
						
							|  |  |  |         switch (em) { | 
					
						
							|  |  |  |         case EndDebuggingAuto: | 
					
						
							|  |  |  |             action = (m_mode == AttachExternal || m_mode == AttachCrashedExternal) ? | 
					
						
							|  |  |  |                      DetachInferior : TerminateInferior; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case EndDebuggingDetach: | 
					
						
							|  |  |  |             action = DetachInferior; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case EndDebuggingTerminate: | 
					
						
							|  |  |  |             action = TerminateInferior; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (debugCDB) | 
					
						
							|  |  |  |             qDebug() << Q_FUNC_INFO << action; | 
					
						
							|  |  |  |         // Need a stopped debuggee to act
 | 
					
						
							|  |  |  |         if (!endInferior(action, &errorMessage)) { | 
					
						
							|  |  |  |             errorMessage = QString::fromLatin1("Unable to detach from/end the debuggee: %1").arg(errorMessage); | 
					
						
							|  |  |  |             manager()->showDebuggerOutput(LogError, errorMessage); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         errorMessage.clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Clean up resources (open files, etc.)
 | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     clearForRun(); | 
					
						
							|  |  |  |     const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE); | 
					
						
							| 
									
										
										
										
											2009-10-20 11:02:16 +02:00
										 |  |  |     m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     if (!SUCCEEDED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr)); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         manager()->showDebuggerOutput(LogError, errorMessage); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-11 16:54:35 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::exitDebugger() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_d->endDebugging(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::detachDebugger() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_d->endDebugging(CdbDebugEnginePrivate::EndDebuggingDetach); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  | CdbStackFrameContext *CdbDebugEnginePrivate::getStackFrameContext(int frameIndex, QString *errorMessage) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_currentStackTrace) { | 
					
						
							|  |  |  |         *errorMessage = QLatin1String(msgNoStackTraceC); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (CdbStackFrameContext *sg = m_currentStackTrace->frameContextAt(frameIndex, errorMessage)) | 
					
						
							|  |  |  |         return sg; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::evaluateWatcher(WatchData *wd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDBWatchHandling) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << wd->exp; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     QString value; | 
					
						
							|  |  |  |     QString type; | 
					
						
							|  |  |  |     if (evaluateExpression(wd->exp, &value, &type, &errorMessage)) { | 
					
						
							|  |  |  |         wd->setValue(value); | 
					
						
							|  |  |  |         wd->setType(type); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         wd->setValue(errorMessage); | 
					
						
							|  |  |  |         wd->setTypeUnneeded(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     wd->setHasChildren(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::updateWatchData(const WatchData &incomplete) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Watch item was edited while running
 | 
					
						
							|  |  |  |     if (m_d->isDebuggeeRunning()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (debugCDBWatchHandling) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << "\n    " << incomplete.toString(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     WatchHandler *watchHandler = manager()->watchHandler(); | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |     if (incomplete.iname.startsWith(QLatin1String("watch."))) { | 
					
						
							|  |  |  |         WatchData watchData = incomplete; | 
					
						
							|  |  |  |         evaluateWatcher(&watchData); | 
					
						
							|  |  |  |         watchHandler->insertData(watchData); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     const int frameIndex = manager()->stackHandler()->currentIndex(); | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool success = false; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         CdbStackFrameContext *sg = m_d->m_currentStackTrace->frameContextAt(frameIndex, &errorMessage); | 
					
						
							|  |  |  |         if (!sg) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (!sg->completeData(incomplete, watchHandler, &errorMessage)) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         success = true; | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  |     if (!success) | 
					
						
							|  |  |  |         warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-08-12 11:21:44 +02:00
										 |  |  |     if (debugCDBWatchHandling > 1) | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         qDebug() << *manager()->watchHandler()->model(LocalsWatch); | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  | // Continue inferior with a debugger command, such as "p", "pt"
 | 
					
						
							|  |  |  | // or its thread variations
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::executeContinueCommand(const QString &command) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << command; | 
					
						
							|  |  |  |     clearForRun(); | 
					
						
							|  |  |  |     setCodeLevel(); // Step by instruction
 | 
					
						
							|  |  |  |     m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Continuing with '%1'...").arg(command)); | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     const bool success = CdbDebugEnginePrivate::executeDebuggerCommand(m_cif.debugControl, command, &errorMessage); | 
					
						
							|  |  |  |     if (success) { | 
					
						
							|  |  |  |         m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |         m_engine->startWatchTimer(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |         m_engine->warning(CdbDebugEngine::tr("Unable to continue: %1").arg(errorMessage)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  | static inline QString msgStepFailed(unsigned long executionStatus, int threadId, const QString &why) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (executionStatus ==  DEBUG_STATUS_STEP_OVER) | 
					
						
							|  |  |  |         return QString::fromLatin1("Thread %1: Unable to step over: %2").arg(threadId).arg(why); | 
					
						
							|  |  |  |     return QString::fromLatin1("Thread %1: Unable to step into: %2").arg(threadId).arg(why); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  | // Step out has to be done via executing 'gu'. TODO: Remove once it is
 | 
					
						
							|  |  |  | // accessible via normal API for SetExecutionStatus().
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { CdbExtendedExecutionStatusStepOut = 7452347 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Step with  DEBUG_STATUS_STEP_OVER ('p'-command),
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  | // DEBUG_STATUS_STEP_INTO ('t'-trace-command) or
 | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  | // CdbExtendedExecutionStatusStepOut ("gu"-command)
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  | // its reverse equivalents in the case of single threads.
 | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  | bool CdbDebugEngine::step(unsigned long executionStatus) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << ">step" << executionStatus << "curr " << m_d->m_currentThreadId << " evt " << m_d->m_eventThreadId; | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     // State of reverse stepping as of 10/2009 (Debugging tools 6.11@404):
 | 
					
						
							|  |  |  |     // The constants exist, but invoking the calls leads to E_NOINTERFACE.
 | 
					
						
							|  |  |  |     // Also there is no CDB command for it.
 | 
					
						
							|  |  |  |     if (executionStatus == DEBUG_STATUS_REVERSE_STEP_OVER || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO) { | 
					
						
							|  |  |  |         warning(tr("Reverse stepping is not implemented.")); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     // Do not step the artifical thread created to interrupt the debuggee.
 | 
					
						
							|  |  |  |     if (m_d->m_interrupted && m_d->m_currentThreadId == m_d->m_interruptArticifialThreadId) { | 
					
						
							|  |  |  |         warning(tr("Thread %1 cannot be stepped.").arg(m_d->m_currentThreadId)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     // SetExecutionStatus() continues the thread that triggered the
 | 
					
						
							|  |  |  |     // stop event (~# p). This can be confusing if the user is looking
 | 
					
						
							|  |  |  |     // at the stack trace of another thread and wants to step that one. If that
 | 
					
						
							|  |  |  |     // is the case, explicitly tell it to step the current thread using a command.
 | 
					
						
							|  |  |  |     const int triggeringEventThread = m_d->m_eventThreadId; | 
					
						
							|  |  |  |     const bool sameThread = triggeringEventThread == -1 | 
					
						
							|  |  |  |                             || m_d->m_currentThreadId == triggeringEventThread | 
					
						
							|  |  |  |                             || manager()->threadsHandler()->threads().size() == 1; | 
					
						
							|  |  |  |     m_d->clearForRun(); // clears thread ids
 | 
					
						
							|  |  |  |     m_d->setCodeLevel(); // Step by instruction or source line
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     bool success = false; | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  |     if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |         const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(executionStatus); | 
					
						
							|  |  |  |         success = SUCCEEDED(hr); | 
					
						
							|  |  |  |         if (!success) | 
					
						
							|  |  |  |             warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgComFailed("SetExecutionStatus", hr))); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Need to use a command to explicitly specify the current thread
 | 
					
						
							|  |  |  |         QString command; | 
					
						
							|  |  |  |         QTextStream str(&command); | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  |         str << '~' << m_d->m_currentThreadId << ' '; | 
					
						
							|  |  |  |         switch (executionStatus) { | 
					
						
							|  |  |  |         case DEBUG_STATUS_STEP_OVER: | 
					
						
							|  |  |  |             str << 'p'; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case DEBUG_STATUS_STEP_INTO: | 
					
						
							|  |  |  |             str << 't';             | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case CdbExtendedExecutionStatusStepOut: | 
					
						
							|  |  |  |             str << "gu"; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |         manager()->showDebuggerOutput(tr("Stepping %1").arg(command)); | 
					
						
							|  |  |  |         const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, command.toLatin1().constData(), DEBUG_EXECUTE_ECHO); | 
					
						
							|  |  |  |         success = SUCCEEDED(hr); | 
					
						
							|  |  |  |         if (!success) | 
					
						
							|  |  |  |             warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgDebuggerCommandFailed(command, hr))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (success) { | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |         // Oddity: Step into will first break at the calling function. Ignore
 | 
					
						
							|  |  |  |         if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO) | 
					
						
							|  |  |  |             m_d->m_breakEventMode = CdbDebugEnginePrivate::BreakEventIgnoreOnce; | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |         startWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         setState(InferiorRunning, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         setState(InferiorStopped, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "<step samethread" << sameThread << "succeeded" << success; | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     return success; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::stepExec() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     step(manager()->isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_INTO : DEBUG_STATUS_STEP_INTO); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::nextExec() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     step(manager()->isReverseDebugging() ? DEBUG_STATUS_REVERSE_STEP_OVER : DEBUG_STATUS_STEP_OVER); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::stepIExec() | 
					
						
							|  |  |  | {       | 
					
						
							|  |  |  |     stepExec(); // Step into by instruction (figured out by step)
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::nextIExec() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     nextExec(); // Step over by instruction (figured out by step)
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::stepOutExec() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-10 10:40:24 +01:00
										 |  |  |     if (!manager()->isReverseDebugging()) | 
					
						
							|  |  |  |         step(CdbExtendedExecutionStatusStepOut); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::continueInferior() | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |     QString errorMessage;     | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     if  (!m_d->continueInferior(&errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Continue process without notifications
 | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  | bool CdbDebugEnginePrivate::continueInferiorProcess(QString *errorMessagePtr /* = 0 */) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "continueInferiorProcess"; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     const HRESULT hr = m_cif.debugControl->SetExecutionStatus(DEBUG_STATUS_GO); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  |         const QString errorMessage = msgComFailed("SetExecutionStatus", hr); | 
					
						
							|  |  |  |         if (errorMessagePtr) { | 
					
						
							|  |  |  |             *errorMessagePtr = errorMessage; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |             m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return  true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | // Continue process with notifications
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::continueInferior(QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     // Check state: Are we running?
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     ULONG executionStatus; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (!getExecutionStatus(m_cif.debugControl, &executionStatus, errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << "\n    ex=" << executionStatus; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (executionStatus == DEBUG_STATUS_GO) { | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         m_engine->warning(QLatin1String("continueInferior() called while debuggee is running.")); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     // Request continue
 | 
					
						
							|  |  |  |     m_engine->setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     bool success = false; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         clearForRun(); | 
					
						
							|  |  |  |         setCodeLevel(); | 
					
						
							|  |  |  |         m_engine->killWatchTimer(); | 
					
						
							|  |  |  |         manager()->resetLocation(); | 
					
						
							|  |  |  |         manager()->showStatusMessage(CdbDebugEngine::tr("Running requested..."), 5000); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         if (!continueInferiorProcess(errorMessage)) | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         m_engine->startWatchTimer(); | 
					
						
							|  |  |  |         success = true; | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  |     if (success) { | 
					
						
							|  |  |  |         m_engine->setState(InferiorRunning, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); // No RunningRequestFailed?
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     // Interrupt the interferior process without notifications
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) { | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         ULONG executionStatus; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |         getExecutionStatus(m_cif.debugControl, &executionStatus, errorMessage); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |         qDebug() << "interruptInterferiorProcess  ex=" << executionStatus; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |     if (DebugBreakProcess(m_hDebuggeeProcess)) { | 
					
						
							|  |  |  |         m_interrupted = true; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-10-05 11:06:05 +02:00
										 |  |  |         *errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError())); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     const HRESULT hr = m_cif.debugControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE|DEBUG_INTERRUPT_EXIT); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Unable to interrupt debuggee after %1s: %2"). | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |                         arg(getInterruptTimeOutSecs(m_cif.debugControl)).arg(msgComFailed("SetInterrupt", hr)); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     m_interrupted = true; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | void CdbDebugEngine::interruptInferior() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_d->m_hDebuggeeProcess || !m_d->isDebuggeeRunning()) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |     setState(InferiorStopping, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |     if (!m_d->interruptInterferiorProcess(&errorMessage)) { | 
					
						
							|  |  |  |         setState(InferiorStopFailed, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  |     manager()->showDebuggerOutput(LogMisc, tr("Running up to %1:%2...").arg(fileName).arg(lineNumber)); | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     CDBBreakPoint tempBreakPoint; | 
					
						
							|  |  |  |     tempBreakPoint.fileName = fileName; | 
					
						
							|  |  |  |     tempBreakPoint.lineNumber = lineNumber; | 
					
						
							|  |  |  |     tempBreakPoint.oneShot = true; | 
					
						
							|  |  |  |     const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage) | 
					
						
							|  |  |  |                     && m_d->continueInferior(&errorMessage); | 
					
						
							|  |  |  |     if (!ok) | 
					
						
							|  |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::runToFunctionExec(const QString &functionName) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  |     manager()->showDebuggerOutput(LogMisc, tr("Running up to function '%1()'...").arg(functionName)); | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     CDBBreakPoint tempBreakPoint; | 
					
						
							|  |  |  |     tempBreakPoint.funcName = functionName; | 
					
						
							|  |  |  |     tempBreakPoint.oneShot = true; | 
					
						
							|  |  |  |     const bool ok = tempBreakPoint.add(m_d->m_cif.debugControl, &errorMessage) | 
					
						
							|  |  |  |                     && m_d->continueInferior(&errorMessage); | 
					
						
							|  |  |  |     if (!ok) | 
					
						
							|  |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  | void CdbDebugEngine::jumpToLineExec(const QString & /* fileName */, int /*lineNumber*/) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  |     warning(tr("Jump to line is not implemented")); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << expr << value; | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     const int frameIndex = manager()->stackHandler()->currentIndex(); | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |     bool success = false; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         QString newValue; | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         CdbStackFrameContext *sg = m_d->getStackFrameContext(frameIndex, &errorMessage); | 
					
						
							|  |  |  |         if (!sg) | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         if (!sg->assignValue(expr, value, &newValue, &errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-07-10 14:36:28 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         // Update view
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         WatchHandler *watchHandler = manager()->watchHandler(); | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         if (WatchData *fwd = watchHandler->findItem(expr)) { | 
					
						
							|  |  |  |             fwd->setValue(newValue); | 
					
						
							|  |  |  |             watchHandler->insertData(*fwd); | 
					
						
							|  |  |  |             watchHandler->updateWatchers(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |         success = true; | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  |     if (!success) { | 
					
						
							|  |  |  |         const QString msg = tr("Unable to assign the value '%1' to '%2': %3").arg(value, expr, errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(msg); | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | void CdbDebugEngine::executeDebuggerCommand(const QString &command) | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_d->m_cif.debugControl, command, &errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  | bool CdbDebugEnginePrivate::executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     // output to all clients, else we do not see anything
 | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |     const HRESULT hr = ctrl->ExecuteWide(DEBUG_OUTCTL_ALL_CLIENTS, reinterpret_cast<PCWSTR>(command.utf16()), 0); | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << "executeDebuggerCommand" << command << SUCCEEDED(hr); | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Unable to execute '%1': %2"). | 
					
						
							|  |  |  |                         arg(command, msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEngine::evaluateExpression(const QString &expression, | 
					
						
							|  |  |  |                                         QString *value, | 
					
						
							|  |  |  |                                         QString *type, | 
					
						
							|  |  |  |                                         QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     DEBUG_VALUE debugValue; | 
					
						
							|  |  |  |     if (!m_d->evaluateExpression(m_d->m_cif.debugControl, expression, &debugValue, errorMessage)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     *value = CdbSymbolGroupContext::debugValueToString(debugValue, m_d->m_cif.debugControl, type); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::evaluateExpression(CIDebugControl *ctrl, | 
					
						
							|  |  |  |                                                const QString &expression, | 
					
						
							|  |  |  |                                                DEBUG_VALUE *debugValue, | 
					
						
							|  |  |  |                                                QString *errorMessage) | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (debugCDB > 1) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << expression; | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     memset(debugValue, 0, sizeof(DEBUG_VALUE)); | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  |     // Original syntax must be restored, else setting breakpoints will fail.
 | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |     SyntaxSetter syntaxSetter(ctrl, DEBUG_EXPR_CPLUSPLUS); | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  |     ULONG errorPosition = 0; | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |     const HRESULT hr = ctrl->EvaluateWide(reinterpret_cast<PCWSTR>(expression.utf16()), | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |                                           DEBUG_VALUE_INVALID, debugValue, | 
					
						
							|  |  |  |                                           &errorPosition); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2009-04-07 17:07:11 +02:00
										 |  |  |         if (HRESULT_CODE(hr) == 517) { | 
					
						
							|  |  |  |             *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Expression out of scope."). | 
					
						
							|  |  |  |                             arg(expression); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             *errorMessage = QString::fromLatin1("Unable to evaluate '%1': Error at %2: %3"). | 
					
						
							|  |  |  |                             arg(expression).arg(errorPosition).arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::activateFrame(int frameIndex) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << frameIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     if (state() != InferiorStopped) { | 
					
						
							| 
									
										
										
										
											2009-03-25 13:42:47 +01:00
										 |  |  |         qWarning("WARNING %s: invoked while debuggee is running\n", Q_FUNC_INFO); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-03-25 13:42:47 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     bool success = false; | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  |     StackHandler *stackHandler = manager()->stackHandler(); | 
					
						
							|  |  |  |     do {         | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         WatchHandler *watchHandler = manager()->watchHandler(); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         const int oldIndex = stackHandler->currentIndex(); | 
					
						
							|  |  |  |         if (frameIndex >= stackHandler->stackSize()) { | 
					
						
							|  |  |  |             errorMessage = msgStackIndexOutOfRange(frameIndex, stackHandler->stackSize()); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |         if (oldIndex != frameIndex) | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |             stackHandler->setCurrentIndex(frameIndex); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         const StackFrame &frame = stackHandler->currentFrame(); | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |         if (!frame.isUsable()) { | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |             // Clean out model
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |             watchHandler->beginCycle(); | 
					
						
							|  |  |  |             watchHandler->endCycle(); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |             errorMessage = QString::fromLatin1("%1: file %2 unusable."). | 
					
						
							|  |  |  |                            arg(QLatin1String(Q_FUNC_INFO), frame.file); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |         manager()->gotoLocation(frame, true); | 
					
						
							| 
									
										
										
										
											2009-06-18 10:34:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) { | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  |             watchHandler->beginCycle(); | 
					
						
							|  |  |  |             if (CdbStackFrameContext *sgc = m_d->getStackFrameContext(frameIndex, &errorMessage)) | 
					
						
							|  |  |  |                 success = sgc->populateModelInitially(watchHandler, &errorMessage); | 
					
						
							|  |  |  |             watchHandler->endCycle(); | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             success = true; | 
					
						
							| 
									
										
										
										
											2009-06-18 10:34:53 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     } while (false); | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  |     if (!success) { | 
					
						
							| 
									
										
										
										
											2009-09-30 17:13:52 +02:00
										 |  |  |         const QString msg = QString::fromLatin1("Internal error: activateFrame() failed for frame #%1 of %2, thread %3: %4"). | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  |                             arg(frameIndex).arg(stackHandler->stackSize()).arg(m_d->m_currentThreadId).arg(errorMessage); | 
					
						
							|  |  |  |         warning(msg); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-27 17:19:39 +01:00
										 |  |  |     m_d->m_firstActivatedFrame = false; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::selectThread(int index) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << index; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     //reset location arrow
 | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     manager()->resetLocation(); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     ThreadsHandler *threadsHandler = manager()->threadsHandler(); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     threadsHandler->setCurrentThread(index); | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |     const int newThreadId = threadsHandler->threads().at(index).id; | 
					
						
							|  |  |  |     if (newThreadId != m_d->m_currentThreadId) { | 
					
						
							|  |  |  |         m_d->m_currentThreadId = threadsHandler->threads().at(index).id; | 
					
						
							|  |  |  |         m_d->updateStackTrace(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::attemptBreakpointSynchronization() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-30 15:50:56 +02:00
										 |  |  |     if (!m_d->m_hDebuggeeProcess) // Sometimes called from the breakpoint Window
 | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     if (!m_d->attemptBreakpointSynchronization(&errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  | bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_hDebuggeeProcess) { | 
					
						
							|  |  |  |         *errorMessage = QLatin1String("attemptBreakpointSynchronization() called while debugger is not running"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // This is called from
 | 
					
						
							|  |  |  |     // 1) CreateProcessEvent with the halted engine
 | 
					
						
							|  |  |  |     // 2) from the break handler, potentially while the debuggee is running
 | 
					
						
							|  |  |  |     // If the debuggee is running (for which the execution status is
 | 
					
						
							|  |  |  |     // no reliable indicator), we temporarily halt and have ourselves
 | 
					
						
							|  |  |  |     // called again from the debug event handler.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ULONG dummy; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     const bool wasRunning = !CDBBreakPoint::getBreakPointCount(m_cif.debugControl, &dummy); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << "\n  Running=" << wasRunning; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (wasRunning) { | 
					
						
							|  |  |  |         const HandleBreakEventMode oldMode = m_breakEventMode; | 
					
						
							|  |  |  |         m_breakEventMode = BreakEventSyncBreakPoints; | 
					
						
							|  |  |  |         if (!interruptInterferiorProcess(errorMessage)) { | 
					
						
							|  |  |  |             m_breakEventMode = oldMode; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-30 15:50:56 +02:00
										 |  |  |     QStringList warnings; | 
					
						
							|  |  |  |     const bool ok = CDBBreakPoint::synchronizeBreakPoints(m_cif.debugControl, | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |                                                  m_cif.debugSymbols, | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |                                                  manager()->breakHandler(), | 
					
						
							| 
									
										
										
										
											2009-06-30 15:50:56 +02:00
										 |  |  |                                                  errorMessage, &warnings); | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |     if (const int warningsCount = warnings.size()) | 
					
						
							| 
									
										
										
										
											2009-06-30 15:50:56 +02:00
										 |  |  |         for (int w = 0; w < warningsCount; w++) | 
					
						
							|  |  |  |             m_engine->warning(warnings.at(w)); | 
					
						
							|  |  |  |     return ok; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-17 13:34:15 +02:00
										 |  |  | void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent, | 
					
						
							| 
									
										
										
										
											2009-08-17 16:03:27 +02:00
										 |  |  |                                        const StackFrame & frame) | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |     enum { ContextLines = 40 }; | 
					
						
							| 
									
										
										
										
											2009-08-17 16:03:27 +02:00
										 |  |  |     bool ok = false; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         // get address       
 | 
					
						
							|  |  |  |         QString address; | 
					
						
							|  |  |  |         if (!frame.file.isEmpty()) | 
					
						
							|  |  |  |             address = frame.address; | 
					
						
							|  |  |  |         if (address.isEmpty()) | 
					
						
							|  |  |  |             address = agent->address(); | 
					
						
							|  |  |  |         if (debugCDB) | 
					
						
							|  |  |  |             qDebug() << "fetchDisassembler" << address << " Agent: " << agent->address() | 
					
						
							|  |  |  |             << " Frame" << frame.file << frame.line << frame.address; | 
					
						
							|  |  |  |         if (address.isEmpty()) { // Clear window
 | 
					
						
							|  |  |  |             agent->setContents(QString()); | 
					
						
							|  |  |  |             ok = true; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (address.startsWith(QLatin1String("0x"))) | 
					
						
							|  |  |  |             address.remove(0, 2); | 
					
						
							|  |  |  |         const int addressFieldWith = address.size(); // For the Marker
 | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-17 16:03:27 +02:00
										 |  |  |         const ULONG64 offset = address.toULongLong(&ok, 16); | 
					
						
							|  |  |  |         if (!ok) { | 
					
						
							|  |  |  |             errorMessage = QString::fromLatin1("Internal error: Invalid address for disassembly: '%1'.").arg(agent->address()); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         QString disassembly; | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |         QApplication::setOverrideCursor(Qt::WaitCursor); | 
					
						
							| 
									
										
										
										
											2009-08-18 09:59:15 +02:00
										 |  |  |         ok = dissassemble(m_d->m_cif.debugClient, m_d->m_cif.debugControl, offset, | 
					
						
							|  |  |  |                           ContextLines, ContextLines, addressFieldWith, QTextStream(&disassembly), &errorMessage); | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |         QApplication::restoreOverrideCursor(); | 
					
						
							| 
									
										
										
										
											2009-08-17 16:03:27 +02:00
										 |  |  |         if (!ok) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         agent->setContents(disassembly); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!ok) { | 
					
						
							|  |  |  |         agent->setContents(QString()); | 
					
						
							|  |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-04-14 15:04:19 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-19 14:41:51 +02:00
										 |  |  | void CdbDebugEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_d->m_hDebuggeeProcess && !length) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     ULONG received; | 
					
						
							|  |  |  |     QByteArray data(length, '\0'); | 
					
						
							|  |  |  |     const HRESULT hr = m_d->m_cif.debugDataSpaces->ReadVirtual(addr, data.data(), length, &received); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         warning(tr("Unable to retrieve %1 bytes of memory at 0x%2: %3"). | 
					
						
							|  |  |  |                 arg(length).arg(addr, 0, 16).arg(msgComFailed("ReadVirtual", hr))); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (received < length) | 
					
						
							|  |  |  |         data.truncate(received); | 
					
						
							|  |  |  |     agent->addLazyData(addr, data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::reloadModules() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::loadSymbols(const QString &moduleName) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << moduleName; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::loadAllSymbols() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 12:04:27 +02:00
										 |  |  | QList<Symbol> CdbDebugEngine::moduleSymbols(const QString &moduleName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<Symbol> rc; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     bool success = false; | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         if (m_d->isDebuggeeRunning()) { | 
					
						
							|  |  |  |             errorMessage = tr("Cannot retrieve symbols while the debuggee is running."); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |         if (!getModuleSymbols(m_d->m_cif.debugSymbols, moduleName, &rc, &errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-04-15 12:04:27 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |         success = true; | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  |     if (!success) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-04-15 12:04:27 +02:00
										 |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::reloadRegisters() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-30 16:45:15 +01:00
										 |  |  |     if (state() != InferiorStopped) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-08-13 16:16:19 +02:00
										 |  |  |     const int intBase = 10; | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << intBase; | 
					
						
							|  |  |  |     QList<Register> registers; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (!getRegisters(m_d->m_cif.debugControl, m_d->m_cif.debugRegisters, ®isters, &errorMessage, intBase)) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(msgFunctionFailed("reloadRegisters" , errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->registerHandler()->setRegisters(registers); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 13:07:38 +01:00
										 |  |  | void CdbDebugEngine::timerEvent(QTimerEvent* te) | 
					
						
							| 
									
										
										
										
											2009-03-03 17:11:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-21 12:30:12 +02:00
										 |  |  |     // Fetch away the debug events and notify if debuggee
 | 
					
						
							|  |  |  |     // stops. Note that IDebugEventCallback does not
 | 
					
						
							|  |  |  |     // cover all cases of a debuggee stopping execution
 | 
					
						
							|  |  |  |     // (such as step over,etc).
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  |     if (te->timerId() != m_d->m_watchTimer) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     const HRESULT hr = m_d->m_cif.debugControl->WaitForEvent(0, 1); | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         if (debugCDB > 1 || hr != S_FALSE) | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |             qDebug() << Q_FUNC_INFO << "WaitForEvent" << state() << msgDebugEngineComResult(hr); | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     switch (hr) { | 
					
						
							|  |  |  |         case S_OK: | 
					
						
							|  |  |  |             killWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  |             m_d->handleDebugEvent(); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |             break; | 
					
						
							|  |  |  |         case S_FALSE: | 
					
						
							|  |  |  |         case E_PENDING: | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  |         case E_FAIL: | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |         case E_UNEXPECTED: // Occurs on ExitProcess.
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |             killWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  | void CdbDebugEngine::slotConsoleStubStarted() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const qint64 appPid = m_d->m_consoleStubProc.applicationPID(); | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << appPid; | 
					
						
							|  |  |  |     // Attach to console process
 | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-05-26 16:27:24 +02:00
										 |  |  |     if (startAttachDebugger(appPid, AttachExternal, &errorMessage)) { | 
					
						
							| 
									
										
										
										
											2009-05-06 14:26:20 +02:00
										 |  |  |         startWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         manager()->notifyInferiorPidChanged(appPid); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |         QMessageBox::critical(manager()->mainWindow(), tr("Debugger Error"), errorMessage); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::slotConsoleStubError(const QString &msg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 08:35:31 +02:00
										 |  |  |     QMessageBox::critical(manager()->mainWindow(), tr("Debugger Error"), msg); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:54:35 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::slotConsoleStubTerminated() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     exitDebugger(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  | void CdbDebugEngine::warning(const QString &w) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->showDebuggerOutput(LogWarning, w); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     qWarning("%s\n", qPrintable(w)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  | void CdbDebugEnginePrivate::notifyException(long code, bool fatal) | 
					
						
							| 
									
										
										
										
											2009-05-05 09:52:24 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "notifyException code" << code << " fatal=" << fatal; | 
					
						
							|  |  |  |     // Suppress the initial breakpoint that occurs when
 | 
					
						
							| 
									
										
										
										
											2009-10-15 15:04:11 +02:00
										 |  |  |     // attaching to a console (If a breakpoint is encountered before startup
 | 
					
						
							|  |  |  |     // is complete, see startAttachDebugger()).
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     switch (code) { | 
					
						
							|  |  |  |     case winExceptionStartupCompleteTrap: | 
					
						
							|  |  |  |         m_inferiorStartupComplete = true; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case EXCEPTION_BREAKPOINT: | 
					
						
							| 
									
										
										
										
											2009-10-15 15:04:11 +02:00
										 |  |  |         if (m_ignoreInitialBreakPoint && !m_inferiorStartupComplete && m_breakEventMode == BreakEventHandle) { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |             manager()->showDebuggerOutput(LogMisc, CdbDebugEngine::tr("Ignoring initial breakpoint...")); | 
					
						
							|  |  |  |             m_breakEventMode = BreakEventIgnoreOnce; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-05 09:52:24 +02:00
										 |  |  |     // Cannot go over crash point to execute calls.
 | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (fatal) | 
					
						
							|  |  |  |         m_dumper->disable(); | 
					
						
							| 
									
										
										
										
											2009-05-05 09:52:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  | static int threadIndexById(const ThreadsHandler *threadsHandler, int id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QList<ThreadData> threads = threadsHandler->threads(); | 
					
						
							|  |  |  |     const int count = threads.count(); | 
					
						
							|  |  |  |     for (int i = 0; i < count; i++) | 
					
						
							|  |  |  |         if (threads.at(i).id == id) | 
					
						
							|  |  |  |             return i; | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-20 17:07:00 +01:00
										 |  |  | void CdbDebugEnginePrivate::handleDebugEvent() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							|  |  |  |         qDebug() << "handleDebugEvent mode " << m_breakEventMode | 
					
						
							|  |  |  |                 << executionStatusString(m_cif.debugControl) << " interrupt" << m_interrupted | 
					
						
							|  |  |  |                 << " startupcomplete" << m_inferiorStartupComplete; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     // restore mode and do special handling
 | 
					
						
							|  |  |  |     const HandleBreakEventMode mode = m_breakEventMode; | 
					
						
							|  |  |  |     m_breakEventMode = BreakEventHandle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (mode) { | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |     case BreakEventHandle: { | 
					
						
							| 
									
										
										
										
											2009-09-30 11:44:04 +02:00
										 |  |  |         // If this is triggered by breakpoint/crash: Set state to stopping
 | 
					
						
							|  |  |  |         // to avoid warnings as opposed to interrupt inferior
 | 
					
						
							|  |  |  |         if (m_engine->state() != InferiorStopping) | 
					
						
							|  |  |  |             m_engine->setState(InferiorStopping, Q_FUNC_INFO, __LINE__); | 
					
						
							|  |  |  |         m_engine->setState(InferiorStopped, Q_FUNC_INFO, __LINE__); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |         m_eventThreadId = updateThreadList(); | 
					
						
							|  |  |  |         m_interruptArticifialThreadId = m_interrupted ? m_eventThreadId : -1; | 
					
						
							|  |  |  |         // Get thread to stop and its index. If avoidable, do not use
 | 
					
						
							|  |  |  |         // the artifical thread that is created when interrupting,
 | 
					
						
							|  |  |  |         // use the oldest thread 0 instead.
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         ThreadsHandler *threadsHandler = manager()->threadsHandler(); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |         m_currentThreadId = m_interrupted ? 0 : m_eventThreadId; | 
					
						
							|  |  |  |         int currentThreadIndex = -1; | 
					
						
							|  |  |  |         m_currentThreadId = -1; | 
					
						
							|  |  |  |         if (m_interrupted) { | 
					
						
							|  |  |  |             m_currentThreadId = 0; | 
					
						
							|  |  |  |             currentThreadIndex = threadIndexById(threadsHandler, m_currentThreadId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!m_interrupted || currentThreadIndex == -1) { | 
					
						
							|  |  |  |             m_currentThreadId = m_eventThreadId; | 
					
						
							|  |  |  |             currentThreadIndex = threadIndexById(threadsHandler, m_currentThreadId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const QString msg = m_interrupted ? | 
					
						
							|  |  |  |                             CdbDebugEngine::tr("Interrupted in thread %1, current thread: %2").arg(m_interruptArticifialThreadId).arg(m_currentThreadId) : | 
					
						
							|  |  |  |                             CdbDebugEngine::tr("Stopped, current thread: %1").arg(m_currentThreadId); | 
					
						
							|  |  |  |         manager()->showDebuggerOutput(LogMisc, msg); | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |         const int threadIndex = threadIndexById(threadsHandler, m_currentThreadId); | 
					
						
							|  |  |  |         if (threadIndex != -1) | 
					
						
							|  |  |  |             threadsHandler->setCurrentThread(threadIndex); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         updateStackTrace(); | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-22 17:28:26 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     case BreakEventIgnoreOnce: | 
					
						
							|  |  |  |         m_engine->startWatchTimer(); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |         m_interrupted = false; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case BreakEventSyncBreakPoints: { | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |             m_interrupted = false; | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |             // Temp stop to sync breakpoints
 | 
					
						
							|  |  |  |             QString errorMessage; | 
					
						
							|  |  |  |             attemptBreakpointSynchronization(&errorMessage); | 
					
						
							|  |  |  |             m_engine->startWatchTimer(); | 
					
						
							|  |  |  |             continueInferiorProcess(&errorMessage); | 
					
						
							|  |  |  |             if (!errorMessage.isEmpty()) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |                 m_engine->warning(QString::fromLatin1("In handleDebugEvent: %1").arg(errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-04-08 16:37:41 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  | void CdbDebugEnginePrivate::setDebuggeeHandles(HANDLE hDebuggeeProcess,  HANDLE hDebuggeeThread) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << hDebuggeeProcess << hDebuggeeThread; | 
					
						
							|  |  |  |     m_hDebuggeeProcess = hDebuggeeProcess; | 
					
						
							|  |  |  |     m_hDebuggeeThread = hDebuggeeThread; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  | // Set thread in CDB engine
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::setCDBThreadId(unsigned long threadId, QString *errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ULONG currentThreadId; | 
					
						
							|  |  |  |     HRESULT hr = m_cif.debugSystemObjects->GetCurrentThreadId(¤tThreadId); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = msgComFailed("GetCurrentThreadId", hr); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (currentThreadId == threadId) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     hr = m_cif.debugSystemObjects->SetCurrentThreadId(threadId); | 
					
						
							|  |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         *errorMessage = QString::fromLatin1("Failed to change to from thread %1 to %2: SetCurrentThreadId() failed: %3"). | 
					
						
							|  |  |  |                         arg(currentThreadId).arg(threadId).arg(msgDebugEngineComResult(hr)); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const QString msg = CdbDebugEngine::tr("Changing threads: %1 -> %2").arg(currentThreadId).arg(threadId); | 
					
						
							|  |  |  |     m_engine->showStatusMessage(msg, 500);     | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  | ULONG CdbDebugEnginePrivate::updateThreadList() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							| 
									
										
										
										
											2009-03-05 17:30:29 +01:00
										 |  |  |         qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  |     QList<ThreadData> threads; | 
					
						
							| 
									
										
										
										
											2009-10-05 17:20:38 +02:00
										 |  |  |     ULONG currentThreadId; | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |     // When interrupting, an artifical thread with a breakpoint is created.
 | 
					
						
							| 
									
										
										
										
											2009-10-05 17:20:38 +02:00
										 |  |  |     if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage)) | 
					
						
							|  |  |  |         m_engine->warning(errorMessage); | 
					
						
							|  |  |  |     manager()->threadsHandler()->setThreads(threads); | 
					
						
							| 
									
										
										
										
											2009-07-24 16:05:46 +02:00
										 |  |  |     return currentThreadId; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  | // Figure out the thread to run the dumpers in (see notes on.
 | 
					
						
							|  |  |  | // CdbDumperHelper). Avoid the artifical threads created by interrupt
 | 
					
						
							|  |  |  | // and threads that are in waitFor().
 | 
					
						
							|  |  |  | // A stricter version could only use the thread if it is the event
 | 
					
						
							|  |  |  | // thread of a step or breakpoint hit (see CdbDebugEnginePrivate::m_interrupted).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline unsigned long dumperThreadId(const QList<StackFrame> &frames, | 
					
						
							|  |  |  |                                            unsigned long currentThread) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (frames.empty()) | 
					
						
							|  |  |  |         return CdbDumperHelper::InvalidDumperCallThread; | 
					
						
							|  |  |  |     if (frames.at(0).function == QLatin1String(CdbStackTraceContext::winFuncDebugBreakPoint)) | 
					
						
							|  |  |  |         return CdbDumperHelper::InvalidDumperCallThread; | 
					
						
							|  |  |  |     const int waitCheckDepth = qMin(frames.size(), 5); | 
					
						
							|  |  |  |     static const QString waitForPrefix = QLatin1String(CdbStackTraceContext::winFuncWaitForPrefix); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     static const QString msgWaitForPrefix = QLatin1String(CdbStackTraceContext::winFuncMsgWaitForPrefix); | 
					
						
							|  |  |  |     for (int f = 0; f < waitCheckDepth; f++) { | 
					
						
							|  |  |  |         const QString &function = frames.at(f).function; | 
					
						
							|  |  |  |         if (function.startsWith(waitForPrefix) || function.startsWith(msgWaitForPrefix)) | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |             return CdbDumperHelper::InvalidDumperCallThread; | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |     return currentThread; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  | void CdbDebugEnginePrivate::updateStackTrace() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     // Create a new context
 | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     cleanStackTrace(); | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  |     m_engine->reloadRegisters(); | 
					
						
							| 
									
										
										
										
											2009-09-29 17:33:51 +02:00
										 |  |  |     if (!setCDBThreadId(m_currentThreadId, &errorMessage)) { | 
					
						
							|  |  |  |         m_engine->warning(errorMessage); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     m_currentStackTrace = | 
					
						
							| 
									
										
										
										
											2009-04-29 14:15:09 +02:00
										 |  |  |             CdbStackTraceContext::create(m_dumper, m_currentThreadId, &errorMessage); | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     if (!m_currentStackTrace) { | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  |     // Disassembling slows things down a bit. Assembler is still available via menu.
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |     m_engine->reloadDisassembler(); // requires stack trace
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-03-26 16:49:28 +01:00
										 |  |  |     const QList<StackFrame> stackFrames = m_currentStackTrace->frames(); | 
					
						
							|  |  |  |     // find the first usable frame and select it
 | 
					
						
							|  |  |  |     int current = -1; | 
					
						
							|  |  |  |     const int count = stackFrames.count(); | 
					
						
							|  |  |  |     for (int i=0; i < count; ++i) | 
					
						
							|  |  |  |         if (stackFrames.at(i).isUsable()) { | 
					
						
							|  |  |  |             current = i; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-10-01 14:41:30 +02:00
										 |  |  |     // Visibly warn the users about missing top frames/all frames, as they otherwise
 | 
					
						
							|  |  |  |     // might think stepping is broken.    
 | 
					
						
							|  |  |  |     if (!stackFrames.at(0).isUsable()) { | 
					
						
							|  |  |  |         const QString topFunction = count ? stackFrames.at(0).function : QString(); | 
					
						
							|  |  |  |         const QString msg = current >= 0 ? | 
					
						
							|  |  |  |                             CdbDebugEngine::tr("Thread %1: Missing debug information for top stack frame (%2).").arg(m_currentThreadId).arg(topFunction) : | 
					
						
							|  |  |  |                             CdbDebugEngine::tr("Thread %1: No debug information available (%2).").arg(m_currentThreadId).arg(topFunction); | 
					
						
							|  |  |  |         m_engine->warning(msg); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |     // Set up dumper with a thread (or invalid)
 | 
					
						
							|  |  |  |     const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     if (debugCDBExecution) | 
					
						
							| 
									
										
										
										
											2009-10-06 15:50:48 +02:00
										 |  |  |         qDebug() << "updateStackTrace() current: " << m_currentThreadId << " dumper=" << dumperThread; | 
					
						
							|  |  |  |     m_dumper->setDumperCallThread(dumperThread); | 
					
						
							|  |  |  |     // Display frames
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->stackHandler()->setFrames(stackFrames); | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |     m_firstActivatedFrame = true; | 
					
						
							| 
									
										
										
										
											2009-03-06 17:10:23 +01:00
										 |  |  |     if (current >= 0) { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |         manager()->stackHandler()->setCurrentIndex(current); | 
					
						
							| 
									
										
										
										
											2009-04-03 16:42:02 +02:00
										 |  |  |         m_engine->activateFrame(current); | 
					
						
							| 
									
										
										
										
											2009-10-13 14:16:50 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // Clean out variables
 | 
					
						
							|  |  |  |         manager()->watchHandler()->beginCycle(); | 
					
						
							|  |  |  |         manager()->watchHandler()->endCycle(); | 
					
						
							| 
									
										
										
										
											2009-04-15 10:05:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->watchHandler()->updateWatchers(); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  | void CdbDebugEnginePrivate::updateModules() | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-09 16:51:13 +02:00
										 |  |  |     QList<Module> modules; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     if (!getModuleList(m_cif.debugSymbols, &modules, &errorMessage)) | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:31:35 +02:00
										 |  |  |     manager()->modulesHandler()->setModules(modules); | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-13 09:11:07 +02:00
										 |  |  | static const char *dumperPrefixC = "dumper"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  | void CdbDebugEnginePrivate::handleModuleLoad(const QString &name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugCDB>2) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << "\n    " << name; | 
					
						
							| 
									
										
										
										
											2009-05-05 09:52:24 +02:00
										 |  |  |     m_dumper->moduleLoadHook(name, m_hDebuggeeProcess); | 
					
						
							| 
									
										
										
										
											2009-04-20 16:40:50 +02:00
										 |  |  |     updateModules(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT2 pBP) | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-20 14:56:36 +01:00
										 |  |  |     Q_UNUSED(pBP) | 
					
						
							| 
									
										
										
										
											2009-02-23 14:46:46 +01:00
										 |  |  |     if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO; | 
					
						
							| 
									
										
										
										
											2009-02-09 11:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-20 14:56:36 +01:00
										 |  |  | void CdbDebugEngine::reloadSourceFiles() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  | QStringList CdbDebugEnginePrivate::sourcePaths() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     WCHAR wszBuf[MAX_PATH]; | 
					
						
							|  |  |  |     if (SUCCEEDED(m_cif.debugSymbols->GetSourcePathWide(wszBuf, MAX_PATH, 0))) | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |         return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';')); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     return QStringList(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CdbDebugEngine::syncDebuggerPaths() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |      if (debugCDB) | 
					
						
							|  |  |  |         qDebug() << Q_FUNC_INFO << m_d->m_options->symbolPaths << m_d->m_options->sourcePaths; | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							|  |  |  |     if (!m_d->setSourcePaths(m_d->m_options->sourcePaths, &errorMessage) | 
					
						
							|  |  |  |         || !m_d->setSymbolPaths(m_d->m_options->symbolPaths, &errorMessage)) { | 
					
						
							|  |  |  |         errorMessage = QString::fromLatin1("Unable to set the debugger paths: %1").arg(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         warning(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline QString pathString(const QStringList &s) | 
					
						
							|  |  |  | {  return s.join(QString(QLatin1Char(';')));  } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::setSourcePaths(const QStringList &s, QString *errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |     const HRESULT hr = m_cif.debugSymbols->SetSourcePathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16())); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         if (errorMessage) | 
					
						
							|  |  |  |             *errorMessage = msgComFailed("SetSourcePathWide", hr); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QStringList CdbDebugEnginePrivate::symbolPaths() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     WCHAR wszBuf[MAX_PATH]; | 
					
						
							|  |  |  |     if (SUCCEEDED(m_cif.debugSymbols->GetSymbolPathWide(wszBuf, MAX_PATH, 0))) | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |         return QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)).split(QLatin1Char(';')); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     return QStringList(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CdbDebugEnginePrivate::setSymbolPaths(const QStringList &s, QString *errorMessage) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-30 23:03:43 +09:00
										 |  |  |     const HRESULT hr = m_cif.debugSymbols->SetSymbolPathWide(reinterpret_cast<PCWSTR>(pathString(s).utf16())); | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     if (FAILED(hr)) { | 
					
						
							|  |  |  |         if (errorMessage) | 
					
						
							|  |  |  |             *errorMessage = msgComFailed("SetSymbolPathWide", hr); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | // Accessed by DebuggerManager
 | 
					
						
							| 
									
										
										
										
											2009-09-23 10:45:32 +02:00
										 |  |  | IDebuggerEngine *createWinEngine(DebuggerManager *parent, | 
					
						
							|  |  |  |                                  bool cmdLineEnabled, | 
					
						
							|  |  |  |                                  QList<Core::IOptionsPage*> *opts) | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     // Create options page
 | 
					
						
							| 
									
										
										
										
											2009-09-23 10:45:32 +02:00
										 |  |  |     QSharedPointer<CdbOptions> options(new CdbOptions); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     options->fromSettings(Core::ICore::instance()->settings()); | 
					
						
							| 
									
										
										
										
											2009-09-23 10:45:32 +02:00
										 |  |  |     CdbOptionsPage *optionsPage = new CdbOptionsPage(options); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     opts->push_back(optionsPage); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |     if (!cmdLineEnabled || !options->enabled) | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     // Create engine
 | 
					
						
							|  |  |  |     QString errorMessage; | 
					
						
							| 
									
										
										
										
											2009-09-23 10:45:32 +02:00
										 |  |  |     IDebuggerEngine *engine = CdbDebugEngine::create(parent, options, &errorMessage); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     if (!engine) { | 
					
						
							|  |  |  |         optionsPage->setFailureMessage(errorMessage); | 
					
						
							| 
									
										
										
										
											2009-05-25 16:22:11 +02:00
										 |  |  |         qWarning("%s\n" ,qPrintable(errorMessage)); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-08 16:56:48 +02:00
										 |  |  |     QObject::connect(optionsPage, SIGNAL(debuggerPathsChanged()), engine, SLOT(syncDebuggerPaths())); | 
					
						
							| 
									
										
										
										
											2009-04-17 09:03:32 +02:00
										 |  |  |     return engine; | 
					
						
							| 
									
										
										
										
											2009-02-23 16:13:35 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-23 10:45:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace Debugger
 | 
					
						
							|  |  |  | 
 |