diff options
author | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2009-04-21 12:30:12 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2009-04-21 12:30:12 +0200 |
commit | 471d31ac9c495c97ef2ddf5861d650179c1309d6 (patch) | |
tree | 7cdbe643f451e16b1e7a998798703a7849d0cde4 /src/plugins/debugger/cdb | |
parent | 6e9a237c76798f2fcaeb2bb7da60fa6ca5a283aa (diff) | |
download | qt-creator-471d31ac9c495c97ef2ddf5861d650179c1309d6.tar.gz |
CDB refactoring, introduce typedefs to remove version numbers.
Log exceptions with stacktrace.
Diffstat (limited to 'src/plugins/debugger/cdb')
19 files changed, 353 insertions, 125 deletions
diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri index c11f3846bd..c5680e705c 100644 --- a/src/plugins/debugger/cdb/cdb.pri +++ b/src/plugins/debugger/cdb/cdb.pri @@ -27,6 +27,7 @@ INCLUDEPATH*=$$PWD CDB_LIBPATH=$$CDB_PATH/lib/$$CDB_PLATFORM HEADERS += \ + $$PWD/cdbcom.h \ $$PWD/cdbdebugengine.h \ $$PWD/cdbdebugengine_p.h \ $$PWD/cdbdebugeventcallback.h \ diff --git a/src/plugins/debugger/cdb/cdbassembler.cpp b/src/plugins/debugger/cdb/cdbassembler.cpp index ae030578c9..c23b3b628a 100644 --- a/src/plugins/debugger/cdb/cdbassembler.cpp +++ b/src/plugins/debugger/cdb/cdbassembler.cpp @@ -42,8 +42,8 @@ namespace Internal { typedef QList<DisassemblerLine> DisassemblerLineList; -bool getRegisters(IDebugControl4 *ctl, - IDebugRegisters2 *ireg, +bool getRegisters(CIDebugControl *ctl, + CIDebugRegisters *ireg, QList<Register> *registers, QString *errorMessage, int base) { @@ -194,8 +194,8 @@ void DisassemblerOutputParser::parse(const QStringList &l) } } -bool dissassemble(IDebugClient5 *client, - IDebugControl4 *ctl, +bool dissassemble(CIDebugClient *client, + CIDebugControl *ctl, ULONG64 offset, unsigned long beforeLines, unsigned long afterLines, diff --git a/src/plugins/debugger/cdb/cdbassembler.h b/src/plugins/debugger/cdb/cdbassembler.h index e43492ebaf..49c4e0fd81 100644 --- a/src/plugins/debugger/cdb/cdbassembler.h +++ b/src/plugins/debugger/cdb/cdbassembler.h @@ -33,8 +33,7 @@ #include <QtCore/QList> #include <QtCore/QString> -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" namespace Debugger { namespace Internal { @@ -44,14 +43,14 @@ class DisassemblerLine; // Utilities related to assembler code. class Register; -bool getRegisters(IDebugControl4 *ctl, - IDebugRegisters2 *ireg, +bool getRegisters(CIDebugControl *ctl, + CIDebugRegisters *ireg, QList<Register> *registers, QString *errorMessage, int base = 10 /* 16 for hex, etc */); -bool dissassemble(IDebugClient5 *client, - IDebugControl4 *ctl, +bool dissassemble(CIDebugClient *client, + CIDebugControl *ctl, ULONG64 offset, unsigned long beforeLines, unsigned long afterLines, diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index 6ef96f5597..6cb8ebdd91 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -131,7 +131,7 @@ QString CDBBreakPoint::expression() const return rc; } -bool CDBBreakPoint::apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const +bool CDBBreakPoint::apply(CIDebugBreakpoint *ibp, QString *errorMessage) const { const QString expr = expression(); if (debugCDB) @@ -148,7 +148,7 @@ bool CDBBreakPoint::apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const return true; } -bool CDBBreakPoint::add(IDebugControl4* debugControl, QString *errorMessage) const +bool CDBBreakPoint::add(CIDebugControl* debugControl, QString *errorMessage) const { IDebugBreakpoint2* ibp = 0; const HRESULT hr = debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &ibp); @@ -176,7 +176,7 @@ QString CDBBreakPoint::canonicalSourceFile(const QString &f) return rc; } -bool CDBBreakPoint::retrieve(IDebugBreakpoint2 *ibp, QString *errorMessage) +bool CDBBreakPoint::retrieve(CIDebugBreakpoint *ibp, QString *errorMessage) { clear(); WCHAR wszBuf[MAX_PATH]; @@ -245,7 +245,7 @@ bool CDBBreakPoint::parseExpression(const QString &expr) return true; } -bool CDBBreakPoint::getBreakPointCount(IDebugControl4* debugControl, ULONG *count, QString *errorMessage /* = 0*/) +bool CDBBreakPoint::getBreakPointCount(CIDebugControl* debugControl, ULONG *count, QString *errorMessage /* = 0*/) { const HRESULT hr = debugControl->GetNumberBreakpoints(count); if (FAILED(hr)) { @@ -257,7 +257,7 @@ bool CDBBreakPoint::getBreakPointCount(IDebugControl4* debugControl, ULONG *coun return true; } -bool CDBBreakPoint::getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage) +bool CDBBreakPoint::getBreakPoints(CIDebugControl* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage) { ULONG count = 0; bps->clear(); diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.h b/src/plugins/debugger/cdb/cdbbreakpoint.h index 3d925b2577..f1a775fe6e 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.h +++ b/src/plugins/debugger/cdb/cdbbreakpoint.h @@ -30,8 +30,7 @@ #ifndef CDBBREAKPOINTS_H #define CDBBREAKPOINTS_H -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" #include <QtCore/QString> #include <QtCore/QList> @@ -64,16 +63,16 @@ struct CDBBreakPoint // Apply parameters bool apply(IDebugBreakpoint2 *ibp, QString *errorMessage) const; // Convenience to add to a IDebugControl4 - bool add(IDebugControl4* debugControl, QString *errorMessage) const; + bool add(CIDebugControl* debugControl, QString *errorMessage) const; // Retrieve/parse breakpoints from the interfaces bool retrieve(IDebugBreakpoint2 *ibp, QString *errorMessage); bool parseExpression(const QString &expr); // Retrieve all breakpoints from the engine - static bool getBreakPointCount(IDebugControl4* debugControl, ULONG *count, QString *errorMessage = 0); - static bool getBreakPoints(IDebugControl4* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage); + static bool getBreakPointCount(CIDebugControl* debugControl, ULONG *count, QString *errorMessage = 0); + static bool getBreakPoints(CIDebugControl* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage); // Synchronize (halted) engine with BreakHandler. - static bool synchronizeBreakPoints(IDebugControl4* ctl, IDebugSymbols3 *syms, + static bool synchronizeBreakPoints(CIDebugControl* ctl, CIDebugSymbols *syms, BreakHandler *bh, QString *errorMessage); // Return a 'canonical' file (using '/' and capitalized drive letter) diff --git a/src/plugins/debugger/cdb/cdbcom.h b/src/plugins/debugger/cdb/cdbcom.h new file mode 100644 index 0000000000..8a631e3f1f --- /dev/null +++ b/src/plugins/debugger/cdb/cdbcom.h @@ -0,0 +1,46 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** 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. +** +** GNU Lesser General Public License Usage +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef CDBCOM_H +#define CDBCOM_H + +#include <windows.h> +#include <inc/dbgeng.h> + +// typedef out the version numbers +typedef IDebugClient5 CIDebugClient; +typedef IDebugControl4 CIDebugControl; +typedef IDebugSystemObjects4 CIDebugSystemObjects; +typedef IDebugSymbols3 CIDebugSymbols; +typedef IDebugRegisters2 CIDebugRegisters; +typedef IDebugDataSpaces4 CIDebugDataSpaces; + +typedef IDebugSymbolGroup2 CIDebugSymbolGroup; +typedef IDebugBreakpoint2 CIDebugBreakpoint; +#endif // CDBCOM_H diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index 35028561a0..2aec4e327c 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -125,25 +125,74 @@ static inline QString msgLibLoadFailed(const QString &lib, const QString &why) // ----- Engine helpers -static inline ULONG getInterruptTimeOutSecs(IDebugControl4 *ctl) +static inline ULONG getInterruptTimeOutSecs(CIDebugControl *ctl) { ULONG rc = 0; ctl->GetInterruptTimeout(&rc); return rc; } -static inline bool getExecutionStatus(IDebugControl4 *ctl, - ULONG *executionStatus, - QString *errorMessage) +bool getExecutionStatus(CIDebugControl *ctl, + ULONG *executionStatus, + QString *errorMessage /* = 0 */) { const HRESULT hr = ctl->GetExecutionStatus(executionStatus); if (FAILED(hr)) { - *errorMessage = msgComFailed("GetExecutionStatus", hr); + if (errorMessage) + *errorMessage = msgComFailed("GetExecutionStatus", hr); return false; } return true; } +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>"; +} + // --------- DebuggerEngineLibrary DebuggerEngineLibrary::DebuggerEngineLibrary() : m_debugCreate(0) @@ -189,7 +238,7 @@ bool DebuggerEngineLibrary::init(const QString &path, QString *errorMessage) } // ----- SyntaxSetter -SyntaxSetter::SyntaxSetter(IDebugControl4 *ctl, ULONG desiredSyntax) : +SyntaxSetter::SyntaxSetter(CIDebugControl *ctl, ULONG desiredSyntax) : m_desiredSyntax(desiredSyntax), m_ctl(ctl) { @@ -385,8 +434,10 @@ void CdbDebugEngine::shutdown() exitDebugger(); } -void CdbDebugEngine::setToolTipExpression(const QPoint & /*pos*/, const QString & /*exp*/) +void CdbDebugEngine::setToolTipExpression(const QPoint & pos, const QString & exp) { + if (debugCDB) + qDebug() << Q_FUNC_INFO << '\n' << pos << exp; } void CdbDebugEnginePrivate::clearDisplay() @@ -939,7 +990,7 @@ void CdbDebugEngine::executeDebuggerCommand(const QString &command) qWarning("%s\n", qPrintable(errorMessage)); } -bool CdbDebugEnginePrivate::executeDebuggerCommand(IDebugControl4 *ctrl, const QString &command, QString *errorMessage) +bool CdbDebugEnginePrivate::executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage) { if (debugCDB) qDebug() << Q_FUNC_INFO << command; @@ -1186,6 +1237,10 @@ void CdbDebugEngine::reloadRegisters() void CdbDebugEngine::timerEvent(QTimerEvent* te) { + // 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). if (te->timerId() != m_d->m_watchTimer) return; @@ -1319,8 +1374,7 @@ void CdbDebugEnginePrivate::updateStackTrace() QString errorMessage; m_engine->reloadRegisters(); m_currentStackTrace = - CdbStackTraceContext::create(m_cif.debugControl, m_cif.debugSystemObjects, - m_cif.debugSymbols, m_currentThreadId, &errorMessage); + CdbStackTraceContext::create(&m_cif, m_currentThreadId, &errorMessage); if (!m_currentStackTrace) { qWarning("%s: failed to create trace context: %s", Q_FUNC_INFO, qPrintable(errorMessage)); return; diff --git a/src/plugins/debugger/cdb/cdbdebugengine_p.h b/src/plugins/debugger/cdb/cdbdebugengine_p.h index 88cbb2725c..95cdc759f9 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine_p.h +++ b/src/plugins/debugger/cdb/cdbdebugengine_p.h @@ -73,11 +73,11 @@ private: class SyntaxSetter { Q_DISABLE_COPY(SyntaxSetter) public: - explicit inline SyntaxSetter(IDebugControl4 *ctl, ULONG desiredSyntax); + explicit inline SyntaxSetter(CIDebugControl *ctl, ULONG desiredSyntax); inline ~SyntaxSetter(); private: const ULONG m_desiredSyntax; - IDebugControl4 *m_ctl; + CIDebugControl *m_ctl; ULONG m_oldSyntax; }; @@ -85,12 +85,12 @@ private: struct CdbComInterfaces { CdbComInterfaces(); - IDebugClient5* debugClient; - IDebugControl4* debugControl; - IDebugSystemObjects4* debugSystemObjects; - IDebugSymbols3* debugSymbols; - IDebugRegisters2* debugRegisters; - IDebugDataSpaces4* debugDataSpaces; + CIDebugClient* debugClient; + CIDebugControl* debugControl; + CIDebugSystemObjects* debugSystemObjects; + CIDebugSymbols* debugSymbols; + CIDebugRegisters* debugRegisters; + CIDebugDataSpaces* debugDataSpaces; }; struct CdbDebugEnginePrivate @@ -130,7 +130,7 @@ struct CdbDebugEnginePrivate bool attemptBreakpointSynchronization(QString *errorMessage); - static bool executeDebuggerCommand(IDebugControl4 *ctrl, const QString &command, QString *errorMessage); + static bool executeDebuggerCommand(CIDebugControl *ctrl, const QString &command, QString *errorMessage); const QSharedPointer<CdbOptions> m_options; HANDLE m_hDebuggeeProcess; @@ -154,6 +154,12 @@ struct CdbDebugEnginePrivate Core::Utils::ConsoleProcess m_consoleStubProc; }; +// helper functions + +bool getExecutionStatus(CIDebugControl *ctl, ULONG *executionStatus, QString *errorMessage = 0); +const char *executionStatusString(ULONG executionStatus); +const char *executionStatusString(CIDebugControl *ctl); + // Message QString msgDebugEngineComResult(HRESULT hr); QString msgComFailed(const char *func, HRESULT hr); diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index 2e6b2178f1..05bbb897bf 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -32,8 +32,12 @@ #include "cdbdebugengine_p.h" #include "debuggermanager.h" #include "breakhandler.h" +#include "cdbstacktracecontext.h" + +enum { cppExceptionCode = 0xe06d7363 }; #include <QtCore/QDebug> +#include <QtCore/QTextStream> namespace Debugger { namespace Internal { @@ -198,7 +202,7 @@ STDMETHODIMP CdbDebugEventCallbackBase::ChangeSymbolState( return S_OK; } -IDebugEventCallbacksWide *CdbDebugEventCallbackBase::getEventCallback(IDebugClient5 *clnt) +IDebugEventCallbacksWide *CdbDebugEventCallbackBase::getEventCallback(CIDebugClient *clnt) { IDebugEventCallbacksWide *rc = 0; if (SUCCEEDED(clnt->GetEventCallbacksWide(&rc))) @@ -231,26 +235,116 @@ STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT2 Bp) return S_OK; } -static inline QString msgException(const EXCEPTION_RECORD64 *Exception, ULONG FirstChance) +// Simple exception formatting +void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str) +{ + str.setIntegerBase(16); + str << "\nException at 0x" << e->ExceptionAddress + << ", code: 0x" << e->ExceptionCode << ": "; + switch (e->ExceptionCode) { + case cppExceptionCode: + str << "C++ exception"; + break; + case EXCEPTION_ACCESS_VIOLATION: { + const bool writeOperation = e->ExceptionInformation[0]; + str << (writeOperation ? "write access violation" : "read access violation"); + } + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + str << "arrary bounds exceeded"; + break; + case EXCEPTION_BREAKPOINT: + str << "breakpoint"; + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + str << "datatype misalignment"; + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + str << "floating point exception"; + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + str << "division by zero"; + break; + case EXCEPTION_FLT_INEXACT_RESULT: + str << " floating-point operation cannot be represented exactly as a decimal fraction"; + break; + case EXCEPTION_FLT_INVALID_OPERATION: + str << "invalid floating-point operation"; + break; + case EXCEPTION_FLT_OVERFLOW: + str << "floating-point overflow"; + break; + case EXCEPTION_FLT_STACK_CHECK: + str << "floating-point operation stack over/underflow"; + break; + case EXCEPTION_FLT_UNDERFLOW: + str << "floating-point UNDERFLOW"; + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + str << "invalid instruction"; + break; + case EXCEPTION_IN_PAGE_ERROR: + str << "page in error"; + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + str << "integer division by zero"; + break; + case EXCEPTION_INT_OVERFLOW: + str << "integer overflow"; + break; + case EXCEPTION_INVALID_DISPOSITION: + str << "invalid disposition to exception dispatcher"; + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + str << "attempt to continue execution after noncontinuable exception"; + break; + case EXCEPTION_PRIV_INSTRUCTION: + str << "priviledged instruction"; + break; + case EXCEPTION_SINGLE_STEP: + str << "single step"; + break; + case EXCEPTION_STACK_OVERFLOW: + str << "stack_overflow"; + break; + } + str << ", flags=0x" << e->ExceptionFlags; + if (e->ExceptionFlags == EXCEPTION_NONCONTINUABLE) { + str << " (execution cannot be continued)"; + } + str << "\n\n"; + str.setIntegerBase(10); +} + +// Format exception with stacktrace in case of C++ exception +void formatException(const EXCEPTION_RECORD64 *e, CdbComInterfaces &cif, QTextStream &str) { - return QString::fromLatin1("An exception occurred: Code=0x%1 FirstChance=%2"). - arg(QString::number(Exception->ExceptionCode, 16)). - arg(FirstChance); + formatException(e, str); + if (e->ExceptionCode == cppExceptionCode) { + QString errorMessage; + ULONG currentThreadId = 0; + cif.debugSystemObjects->GetCurrentThreadId(¤tThreadId); + if (CdbStackTraceContext *stc = CdbStackTraceContext::create(&cif, currentThreadId, &errorMessage)) { + str << "at:\n"; + stc->format(str); + str <<'\n'; + delete stc; + } + } } STDMETHODIMP CdbDebugEventCallback::Exception( THIS_ __in PEXCEPTION_RECORD64 Exception, - __in ULONG FirstChance + __in ULONG /* FirstChance */ ) { - Q_UNUSED(Exception) - if (debugCDB) - qDebug() << Q_FUNC_INFO << msgException(Exception, FirstChance); - - // First chance are harmless - if (!FirstChance) - qWarning("%s", qPrintable(msgException(Exception, FirstChance))); + QString msg; + { + QTextStream str(&msg); + formatException(Exception, m_pEngine->m_d->m_cif, str); + } + m_pEngine->m_d->m_debuggerManagerAccess->showApplicationOutput(msg); return S_OK; } @@ -395,7 +489,7 @@ STDMETHODIMP IgnoreDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask) } // --------- EventCallbackRedirector -EventCallbackRedirector::EventCallbackRedirector(IDebugClient5 *client, IDebugEventCallbacksWide *cb) : +EventCallbackRedirector::EventCallbackRedirector(CIDebugClient *client, IDebugEventCallbacksWide *cb) : m_client(client), m_oldCb(CdbDebugEventCallbackBase::getEventCallback(client)) { diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.h b/src/plugins/debugger/cdb/cdbdebugeventcallback.h index d33aa43755..d7fa7f8829 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.h +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.h @@ -30,8 +30,8 @@ #ifndef DEBUGGER_CDBDEBUGEVENTCALLBACK_H #define DEBUGGER_CDBDEBUGEVENTCALLBACK_H -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" + #include <QtCore/QtGlobal> namespace Debugger { @@ -151,7 +151,7 @@ public: ); - static IDebugEventCallbacksWide *getEventCallback(IDebugClient5 *clnt); + static IDebugEventCallbacksWide *getEventCallback(CIDebugClient *clnt); }; class CdbDebugEventCallback : public CdbDebugEventCallbackBase @@ -252,10 +252,10 @@ public: class EventCallbackRedirector { Q_DISABLE_COPY(EventCallbackRedirector) public: - explicit EventCallbackRedirector(IDebugClient5 *client, IDebugEventCallbacksWide *cb); + explicit EventCallbackRedirector(CIDebugClient *client, IDebugEventCallbacksWide *cb); ~EventCallbackRedirector(); private: - IDebugClient5 *m_client; + CIDebugClient *m_client; IDebugEventCallbacksWide *m_oldCb; }; diff --git a/src/plugins/debugger/cdb/cdbdebugoutput.cpp b/src/plugins/debugger/cdb/cdbdebugoutput.cpp index 8517b0f220..bb89a2f7ec 100644 --- a/src/plugins/debugger/cdb/cdbdebugoutput.cpp +++ b/src/plugins/debugger/cdb/cdbdebugoutput.cpp @@ -84,7 +84,7 @@ STDMETHODIMP CdbDebugOutputBase::Output( return S_OK; } -IDebugOutputCallbacksWide *CdbDebugOutputBase::getOutputCallback(IDebugClient5 *client) +IDebugOutputCallbacksWide *CdbDebugOutputBase::getOutputCallback(CIDebugClient *client) { IDebugOutputCallbacksWide *rc; if (FAILED(client->GetOutputCallbacksWide(&rc))) @@ -157,7 +157,7 @@ void CdbDebugOutput::output(ULONG mask, const QString &msg) // Utility class to temporarily redirect output to another handler // as long as in scope -OutputRedirector::OutputRedirector(IDebugClient5 *client, IDebugOutputCallbacksWide *newHandler) : +OutputRedirector::OutputRedirector(CIDebugClient *client, IDebugOutputCallbacksWide *newHandler) : m_client(client), m_oldHandler(CdbDebugOutputBase::getOutputCallback(client)) { diff --git a/src/plugins/debugger/cdb/cdbdebugoutput.h b/src/plugins/debugger/cdb/cdbdebugoutput.h index 9deb527e9a..135fa2ae02 100644 --- a/src/plugins/debugger/cdb/cdbdebugoutput.h +++ b/src/plugins/debugger/cdb/cdbdebugoutput.h @@ -30,8 +30,7 @@ #ifndef DEBUGGER_CDBOUTPUT_H #define DEBUGGER_CDBOUTPUT_H -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" #include <QtCore/QObject> @@ -65,7 +64,7 @@ public: ); // Helpers to retrieve the output callbacks IF - static IDebugOutputCallbacksWide *getOutputCallback(IDebugClient5 *client); + static IDebugOutputCallbacksWide *getOutputCallback(CIDebugClient *client); protected: CdbDebugOutputBase(); @@ -110,10 +109,10 @@ private: class OutputRedirector { Q_DISABLE_COPY(OutputRedirector) public: - explicit OutputRedirector(IDebugClient5 *client, IDebugOutputCallbacksWide *newHandler); + explicit OutputRedirector(CIDebugClient *client, IDebugOutputCallbacksWide *newHandler); ~OutputRedirector(); private: - IDebugClient5 *m_client; + CIDebugClient *m_client; IDebugOutputCallbacksWide *m_oldHandler; }; diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp index d0b4332811..16c734164e 100644 --- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp +++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp @@ -42,8 +42,8 @@ namespace Internal { // Alloc memory in debuggee using the ".dvalloc" command as // there seems to be no API for it. -static bool allocDebuggeeMemory(IDebugControl4 *ctl, - IDebugClient5 *client, +static bool allocDebuggeeMemory(CIDebugControl *ctl, + CIDebugClient *client, int size, ULONG64 *address, QString *errorMessage) { *address = 0; @@ -69,9 +69,9 @@ static bool allocDebuggeeMemory(IDebugControl4 *ctl, } // Alloc an AscII string in debuggee -static bool createDebuggeeAscIIString(IDebugControl4 *ctl, - IDebugClient5 *client, - IDebugDataSpaces4 *data, +static bool createDebuggeeAscIIString(CIDebugControl *ctl, + CIDebugClient *client, + CIDebugDataSpaces *data, const QString &s, ULONG64 *address, QString *errorMessage) @@ -90,7 +90,7 @@ static bool createDebuggeeAscIIString(IDebugControl4 *ctl, // Locate 'qstrdup' in the (potentially namespaced) corelib. For some // reason, the symbol is present in QtGui as well without type information. -static inline QString resolveStrdup(IDebugSymbols3 *syms, QString *errorMessage) +static inline QString resolveStrdup(CIDebugSymbols *syms, QString *errorMessage) { QStringList matches; const QString pattern = QLatin1String("*qstrdup"); @@ -111,10 +111,10 @@ static inline QString resolveStrdup(IDebugSymbols3 *syms, QString *errorMessage) // the QtCored4.pdb file to be present as we need "qstrdup" // as dummy symbol. This is ok ATM since dumpers only // make sense for Qt apps. -static bool debuggeeLoadLibrary(IDebugControl4 *ctl, - IDebugClient5 *client, - IDebugSymbols3 *syms, - IDebugDataSpaces4 *data, +static bool debuggeeLoadLibrary(CIDebugControl *ctl, + CIDebugClient *client, + CIDebugSymbols *syms, + CIDebugDataSpaces *data, const QString &moduleName, QString *errorMessage) { if (loadDebug) @@ -179,7 +179,7 @@ bool CdbDumperHelper::moduleLoadHook(const QString &name, bool *ignoreNextBreakP // Load once QtCore is there. if (name.contains(QLatin1String("QtCore"))) { if (loadDebug) - qDebug() << Q_FUNC_INFO << '\n' << name << m_state; + qDebug() << Q_FUNC_INFO << '\n' << name << m_state << executionStatusString(m_cif->debugControl); ok = debuggeeLoadLibrary(m_cif->debugControl, m_cif->debugClient, m_cif->debugSymbols, m_cif->debugDataSpaces, m_library, &m_errorMessage); if (ok) { @@ -188,6 +188,8 @@ bool CdbDumperHelper::moduleLoadHook(const QString &name, bool *ignoreNextBreakP } else { m_state = Failed; } + if (loadDebug) + qDebug() << m_state << executionStatusString(m_cif->debugControl); } break; case Loading: diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp index 237ead9331..d3e4250e5c 100644 --- a/src/plugins/debugger/cdb/cdbmodules.cpp +++ b/src/plugins/debugger/cdb/cdbmodules.cpp @@ -36,7 +36,7 @@ namespace Debugger { namespace Internal { -bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorMessage) +bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage) { modules->clear(); ULONG loadedCount, unloadedCount; @@ -80,7 +80,7 @@ bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorM } // Search symbols matching a pattern -bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern, +bool searchSymbols(CIDebugSymbols *syms, const QString &pattern, QStringList *matches, QString *errorMessage) { matches->clear(); @@ -113,7 +113,7 @@ bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern, // Add missing the module specifier: "main" -> "project!main" -ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, +ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol, QString *errorMessage) { // Is it an incomplete symbol? @@ -138,7 +138,7 @@ ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, } // List symbols of a module -bool getModuleSymbols(IDebugSymbols3 *syms, const QString &moduleName, +bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName, QList<Symbol> *symbols, QString *errorMessage) { // Search all symbols and retrieve addresses diff --git a/src/plugins/debugger/cdb/cdbmodules.h b/src/plugins/debugger/cdb/cdbmodules.h index 9a375cdb03..9df7dbf28b 100644 --- a/src/plugins/debugger/cdb/cdbmodules.h +++ b/src/plugins/debugger/cdb/cdbmodules.h @@ -33,8 +33,7 @@ #include <QtCore/QList> #include <QtCore/QString> -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" namespace Debugger { namespace Internal { @@ -42,9 +41,9 @@ namespace Internal { class Module; class Symbol; -bool getModuleList(IDebugSymbols3 *syms, QList<Module> *modules, QString *errorMessage); +bool getModuleList(CIDebugSymbols *syms, QList<Module> *modules, QString *errorMessage); // Search symbols matching a pattern -bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern, +bool searchSymbols(CIDebugSymbols *syms, const QString &pattern, QStringList *matches, QString *errorMessage); // ResolveSymbol: For symbols that are missing the module specifier, @@ -53,10 +52,10 @@ bool searchSymbols(IDebugSymbols3 *syms, const QString &pattern, enum ResolveSymbolResult { ResolveSymbolOk, ResolveSymbolAmbiguous, ResolveSymbolNotFound, ResolveSymbolError }; -ResolveSymbolResult resolveSymbol(IDebugSymbols3 *syms, QString *symbol, QString *errorMessage); +ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol, QString *errorMessage); // List symbols of a module -bool getModuleSymbols(IDebugSymbols3 *syms, const QString &moduleName, +bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName, QList<Symbol> *symbols, QString *errorMessage); } // namespace Internal diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp index 07bf81c5bd..d769817c7e 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -33,27 +33,24 @@ #include "cdbdebugengine_p.h" #include <QtCore/QDir> +#include <QtCore/QTextStream> namespace Debugger { namespace Internal { -CdbStackTraceContext::CdbStackTraceContext(IDebugSystemObjects4* pDebugSystemObjects, - IDebugSymbols3* pDebugSymbols) : - m_pDebugSystemObjects(pDebugSystemObjects), - m_pDebugSymbols(pDebugSymbols), +CdbStackTraceContext::CdbStackTraceContext(CdbComInterfaces *cif) : + m_cif(cif), m_instructionOffset(0) { } -CdbStackTraceContext *CdbStackTraceContext::create(IDebugControl4* pDebugControl, - IDebugSystemObjects4* pDebugSystemObjects, - IDebugSymbols3* pDebugSymbols, +CdbStackTraceContext *CdbStackTraceContext::create(CdbComInterfaces *cif, unsigned long threadId, QString *errorMessage) { if (debugCDB) qDebug() << Q_FUNC_INFO << threadId; - HRESULT hr = pDebugSystemObjects->SetCurrentThreadId(threadId); + HRESULT hr = cif->debugSystemObjects->SetCurrentThreadId(threadId); if (FAILED(hr)) { *errorMessage = QString::fromLatin1("%1: SetCurrentThreadId %2 failed: %3"). arg(QString::fromLatin1(Q_FUNC_INFO)). @@ -63,8 +60,8 @@ CdbStackTraceContext *CdbStackTraceContext::create(IDebugControl4* pDebugControl } // fill the DEBUG_STACK_FRAME array ULONG frameCount; - CdbStackTraceContext *ctx = new CdbStackTraceContext(pDebugSystemObjects, pDebugSymbols); - hr = pDebugControl->GetStackTrace(0, 0, 0, ctx->m_cdbFrames, CdbStackTraceContext::maxFrames, &frameCount); + CdbStackTraceContext *ctx = new CdbStackTraceContext(cif); + hr = cif->debugControl->GetStackTrace(0, 0, 0, ctx->m_cdbFrames, CdbStackTraceContext::maxFrames, &frameCount); if (FAILED(hr)) { delete ctx; *errorMessage = msgComFailed("GetStackTrace", hr); @@ -100,12 +97,12 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa m_instructionOffset = instructionOffset; frame.address = QString::fromLatin1("0x%1").arg(instructionOffset, 0, 16); - m_pDebugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0); + m_cif->debugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0); frame.function = QString::fromUtf16(wszBuf); ULONG ulLine; ULONG64 ul64Displacement; - const HRESULT hr = m_pDebugSymbols->GetLineByOffsetWide(instructionOffset, &ulLine, wszBuf, MAX_PATH, 0, &ul64Displacement); + const HRESULT hr = m_cif->debugSymbols->GetLineByOffsetWide(instructionOffset, &ulLine, wszBuf, MAX_PATH, 0, &ul64Displacement); if (SUCCEEDED(hr)) { frame.line = ulLine; // Vitally important to use canonical file that matches editormanager, @@ -131,7 +128,7 @@ CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupContextAt(int index, QSt if (m_symbolContexts.at(index)) return m_symbolContexts.at(index); - IDebugSymbolGroup2 *sg = createSymbolGroup(index, errorMessage); + CIDebugSymbolGroup *sg = createSymbolGroup(index, errorMessage); if (!sg) return 0; CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, errorMessage); @@ -141,23 +138,23 @@ CdbSymbolGroupContext *CdbStackTraceContext::symbolGroupContextAt(int index, QSt return sc; } -IDebugSymbolGroup2 *CdbStackTraceContext::createSymbolGroup(int index, QString *errorMessage) +CIDebugSymbolGroup *CdbStackTraceContext::createSymbolGroup(int index, QString *errorMessage) { - IDebugSymbolGroup2 *sg = 0; - HRESULT hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &sg); + CIDebugSymbolGroup *sg = 0; + HRESULT hr = m_cif->debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, NULL, &sg); if (FAILED(hr)) { *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); return 0; } - hr = m_pDebugSymbols->SetScope(0, m_cdbFrames + index, NULL, 0); + hr = m_cif->debugSymbols->SetScope(0, m_cdbFrames + index, NULL, 0); if (FAILED(hr)) { *errorMessage = msgComFailed("SetScope", hr); sg->Release(); return 0; } // refresh with current frame - hr = m_pDebugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, sg, &sg); + hr = m_cif->debugSymbols->GetScopeSymbolGroup2(DEBUG_SCOPE_GROUP_LOCALS, sg, &sg); if (FAILED(hr)) { *errorMessage = msgComFailed("GetScopeSymbolGroup", hr); sg->Release(); @@ -166,5 +163,34 @@ IDebugSymbolGroup2 *CdbStackTraceContext::createSymbolGroup(int index, QString * return sg; } +QString CdbStackTraceContext::toString() const +{ + QString rc; + QTextStream str(&rc); + format(str); + return rc; +} + +void CdbStackTraceContext::format(QTextStream &str) const +{ + const int count = m_frames.count(); + const int defaultFieldWidth = str.fieldWidth(); + const QTextStream::FieldAlignment defaultAlignment = str.fieldAlignment(); + for (int f = 0; f < count; f++) { + const StackFrame &frame = m_frames.at(f); + const bool hasFile = !frame.file.isEmpty(); + // left-pad level + str << qSetFieldWidth(6) << left << f; + str.setFieldWidth(defaultFieldWidth); + str.setFieldAlignment(defaultAlignment); + if (hasFile) + str << QDir::toNativeSeparators(frame.file) << ':' << frame.line << " ("; + str << frame.function; + if (hasFile) + str << ')'; + str << '\n'; + } +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h index efbd1c1e81..56389481c6 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.h +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h @@ -32,15 +32,19 @@ #include "stackhandler.h" -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" #include <QtCore/QString> #include <QtCore/QVector> +QT_BEGIN_NAMESPACE +class QTextStream; +QT_END_NAMESPACE + namespace Debugger { namespace Internal { +struct CdbComInterfaces; class CdbSymbolGroupContext; /* Context representing a break point stack consisting of several frames. @@ -51,15 +55,12 @@ class CdbStackTraceContext { Q_DISABLE_COPY(CdbStackTraceContext) - explicit CdbStackTraceContext(IDebugSystemObjects4* pDebugSystemObjects, - IDebugSymbols3* pDebugSymbols); + explicit CdbStackTraceContext(CdbComInterfaces *cif); public: enum { maxFrames = 100 }; ~CdbStackTraceContext(); - static CdbStackTraceContext *create(IDebugControl4* pDebugControl, - IDebugSystemObjects4* pDebugSystemObjects, - IDebugSymbols3* pDebugSymbols, + static CdbStackTraceContext *create(CdbComInterfaces *cif, unsigned long threadid, QString *errorMessage); @@ -71,12 +72,15 @@ public: CdbSymbolGroupContext *symbolGroupContextAt(int index, QString *errorMessage); + // Format for logging + void format(QTextStream &str) const; + QString toString() const; + private: bool init(unsigned long frameCount, QString *errorMessage); - IDebugSymbolGroup2 *createSymbolGroup(int index, QString *errorMessage); + CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage); - IDebugSystemObjects4* m_pDebugSystemObjects; - IDebugSymbols3* m_pDebugSymbols; + CdbComInterfaces *m_cif; DEBUG_STACK_FRAME m_cdbFrames[maxFrames]; QVector <CdbSymbolGroupContext*> m_symbolContexts; diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp index 5f23419278..857a80912f 100644 --- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.cpp @@ -105,7 +105,7 @@ static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMB } CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix, - IDebugSymbolGroup2 *symbolGroup) : + CIDebugSymbolGroup *symbolGroup) : m_prefix(prefix), m_nameDelimiter(QLatin1Char('.')), m_symbolGroup(symbolGroup) @@ -118,7 +118,7 @@ CdbSymbolGroupContext::~CdbSymbolGroupContext() } CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix, - IDebugSymbolGroup2 *symbolGroup, + CIDebugSymbolGroup *symbolGroup, QString *errorMessage) { CdbSymbolGroupContext *rc= new CdbSymbolGroupContext(prefix, symbolGroup); @@ -343,7 +343,7 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const return m_inameIndexMap.key(index); } -static inline QString hexSymbolOffset(IDebugSymbolGroup2 *sg, unsigned long index) +static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index) { ULONG64 rc = 0; if (FAILED(sg->GetSymbolOffset(index, &rc))) @@ -436,7 +436,7 @@ template <class Integer> return rc; } -QString CdbSymbolGroupContext::debugValueToString(const DEBUG_VALUE &dv, IDebugControl4 *ctl, +QString CdbSymbolGroupContext::debugValueToString(const DEBUG_VALUE &dv, CIDebugControl *ctl, QString *qType, int integerBase) { diff --git a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h index 0773133c18..31beb1d8d7 100644 --- a/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h +++ b/src/plugins/debugger/cdb/cdbsymbolgroupcontext.h @@ -30,8 +30,7 @@ #ifndef CDBSYMBOLGROUPCONTEXT_H #define CDBSYMBOLGROUPCONTEXT_H -#include <windows.h> -#include <inc/dbgeng.h> +#include "cdbcom.h" #include <QtCore/QString> #include <QtCore/QVector> @@ -60,12 +59,12 @@ class CdbSymbolGroupContext { Q_DISABLE_COPY(CdbSymbolGroupContext); explicit CdbSymbolGroupContext(const QString &prefix, - IDebugSymbolGroup2 *symbolGroup); + CIDebugSymbolGroup *symbolGroup); public: ~CdbSymbolGroupContext(); static CdbSymbolGroupContext *create(const QString &prefix, - IDebugSymbolGroup2 *symbolGroup, + CIDebugSymbolGroup *symbolGroup, QString *errorMessage); QString prefix() const { return m_prefix; } @@ -92,7 +91,7 @@ public: inline bool isExpanded(const QString &prefix) const { return symbolState(prefix) == ExpandedSymbol; } // Helper to convert a DEBUG_VALUE structure to a string representation - static QString debugValueToString(const DEBUG_VALUE &dv, IDebugControl4 *ctl, QString *type = 0, int integerBase = 10); + static QString debugValueToString(const DEBUG_VALUE &dv, CIDebugControl *ctl, QString *type = 0, int integerBase = 10); // format an array of unsigned longs as "0x323, 0x2322, ..." static QString hexFormatArray(const unsigned short *array, int size); @@ -121,7 +120,7 @@ private: const QString m_prefix; const QChar m_nameDelimiter; - IDebugSymbolGroup2 *m_symbolGroup; + CIDebugSymbolGroup *m_symbolGroup; NameIndexMap m_inameIndexMap; QVector<DEBUG_SYMBOL_PARAMETERS> m_symbolParameters; }; |