Files
qt-creator/src/plugins/debugger/cdb/cdbdebugengine.cpp

649 lines
19 KiB
C++
Raw Normal View History

2009-02-20 17:07:00 +01:00
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
2009-02-09 13:07:38 +01:00
#include "cdbdebugengine.h"
2009-02-20 17:07:00 +01:00
#include "cdbdebugengine_p.h"
2009-02-09 11:35:43 +01:00
#include "debuggermanager.h"
#include "breakhandler.h"
#include "stackhandler.h"
2009-02-17 11:16:23 +01:00
#include <utils/qtcassert.h>
2009-02-23 14:46:46 +01:00
#include <QtCore/QDebug>
#include <QtCore/QTimerEvent>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
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
using namespace Debugger;
using namespace Debugger::Internal;
2009-02-20 17:07:00 +01:00
CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEngine* engine) :
2009-02-09 11:35:43 +01:00
m_hDebuggeeProcess(0),
m_hDebuggeeThread(0),
m_bIgnoreNextDebugEvent(false),
m_watchTimer(-1),
2009-02-20 17:07:00 +01:00
m_debugEventCallBack(engine),
m_debugOutputCallBack(engine),
2009-02-23 14:46:46 +01:00
m_engine(engine),
m_debuggerManager(parent),
m_debuggerManagerAccess(parent->engineInterface())
2009-02-09 11:35:43 +01:00
{
HRESULT hr;
hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
if (FAILED(hr)) m_pDebugClient = 0;
hr = DebugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl));
if (FAILED(hr)) m_pDebugControl = 0;
hr = DebugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects));
if (FAILED(hr)) m_pDebugSystemObjects = 0;
hr = DebugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols));
if (FAILED(hr)) m_pDebugSymbols = 0;
hr = DebugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
if (FAILED(hr)) m_pDebugRegisters = 0;
if (m_pDebugControl) {
m_pDebugControl->SetCodeLevel(DEBUG_LEVEL_SOURCE);
}
if (m_pDebugClient) {
m_pDebugClient->SetOutputCallbacks(&m_debugOutputCallBack);
m_pDebugClient->SetEventCallbacks(&m_debugEventCallBack);
}
}
2009-02-20 17:07:00 +01:00
CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
2009-02-09 11:35:43 +01:00
{
if (m_pDebugClient)
m_pDebugClient->Release();
if (m_pDebugControl)
m_pDebugControl->Release();
if (m_pDebugSystemObjects)
m_pDebugSystemObjects->Release();
if (m_pDebugSymbols)
m_pDebugSymbols->Release();
if (m_pDebugRegisters)
m_pDebugRegisters->Release();
}
2009-02-20 17:07:00 +01:00
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
: IDebuggerEngine(parent),
m_d(new CdbDebugEnginePrivate(parent, this))
{
}
CdbDebugEngine::~CdbDebugEngine()
{
delete m_d;
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::startWatchTimer()
2009-02-09 11:35:43 +01:00
{
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-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-02-20 14:56:36 +01:00
void CdbDebugEngine::setToolTipExpression(const QPoint & /*pos*/, const QString & /*exp*/)
2009-02-09 11:35:43 +01:00
{
}
2009-02-09 13:07:38 +01:00
bool CdbDebugEngine::startDebugger()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
2009-02-09 11:35:43 +01:00
//if (!q->m_workingDir.isEmpty())
// m_gdbProc.setWorkingDirectory(q->m_workingDir);
//if (!q->m_environment.isEmpty())
// m_gdbProc.setEnvironment(q->m_environment);
DEBUG_CREATE_PROCESS_OPTIONS dbgopts;
memset(&dbgopts, 0, sizeof(dbgopts));
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
2009-02-23 14:46:46 +01:00
const QString filename(m_d->m_debuggerManager->m_executable);
if (debugCDB)
qDebug() << Q_FUNC_INFO <<filename;
2009-02-09 11:35:43 +01:00
2009-02-23 14:46:46 +01:00
const QFileInfo fi(filename);
m_d->m_pDebugSymbols->AppendImagePathWide(QDir::toNativeSeparators(fi.absolutePath()).utf16());
2009-02-09 11:35:43 +01:00
//m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
2009-02-20 17:07:00 +01:00
m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
2009-02-09 11:35:43 +01:00
//m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
2009-02-23 14:46:46 +01:00
if (m_d->m_debuggerManager->startMode() == DebuggerManager::AttachExternal) {
2009-02-09 13:07:38 +01:00
qWarning("CdbDebugEngine: attach to process not yet implemented!");
2009-02-23 14:46:46 +01:00
return false;
2009-02-09 11:35:43 +01:00
} else {
2009-02-23 14:46:46 +01:00
HRESULT hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
2009-02-09 11:35:43 +01:00
const_cast<PWSTR>(filename.utf16()),
&dbgopts,
sizeof(dbgopts),
NULL, // TODO: think about the initial directory
NULL); // TODO: think about setting the environment
if (FAILED(hr)) {
//qWarning("CreateProcess2Wide failed");
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManagerAccess->notifyInferiorExited();
2009-02-09 11:35:43 +01:00
return false;
}
}
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
2009-02-09 11:35:43 +01:00
startWatchTimer();
return true;
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::exitDebugger()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO;
2009-02-20 17:07:00 +01:00
m_d->m_pDebugClient->TerminateCurrentProcess();
2009-02-09 11:35:43 +01:00
killWatchTimer();
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::updateWatchModel()
2009-02-09 11:35:43 +01:00
{
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::stepExec()
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
//m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
HRESULT hr;
2009-02-20 17:07:00 +01:00
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO);
m_d->m_bIgnoreNextDebugEvent = true;
2009-02-09 11:35:43 +01:00
startWatchTimer();
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::stepOutExec()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO;
StackHandler* sh = m_d->m_debuggerManagerAccess->stackHandler();
2009-02-09 11:35:43 +01:00
const int idx = sh->currentIndex() + 1;
QList<StackFrame> stackframes = sh->frames();
if (idx < 0 || idx >= stackframes.size()) {
qWarning("cannot step out");
return;
}
const StackFrame& frame = stackframes.at(idx);
bool ok;
ULONG64 address = frame.address.toULongLong(&ok, 16);
if (!ok) {
qWarning("stepOutExec: cannot obtain address from stack frame");
return;
}
IDebugBreakpoint2* pBP;
2009-02-20 17:07:00 +01:00
HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
2009-02-09 11:35:43 +01:00
if (FAILED(hr) || !pBP) {
qWarning("stepOutExec: cannot create temporary breakpoint");
return;
}
pBP->SetOffset(address);
//QString str = '`' + frame.file + ':' + frame.line + '`';
//hr = pBP->SetOffsetExpressionWide(str.utf16());
//if (FAILED(hr)) {
// qWarning("SetOffsetExpressionWide failed");
// return;
//}
pBP->AddFlags(DEBUG_BREAKPOINT_ENABLED);
pBP->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT);
//hr = m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
continueInferior();
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::nextExec()
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
HRESULT hr;
2009-02-20 17:07:00 +01:00
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
2009-02-09 11:35:43 +01:00
startWatchTimer();
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::stepIExec()
2009-02-09 11:35:43 +01:00
{
2009-02-09 13:07:38 +01:00
qWarning("CdbDebugEngine::stepIExec() not implemented");
2009-02-09 11:35:43 +01:00
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::nextIExec()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO;
2009-02-20 17:07:00 +01:00
m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
2009-02-09 11:35:43 +01:00
startWatchTimer();
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::continueInferior()
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
killWatchTimer();
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManager->resetLocation();
2009-02-09 11:35:43 +01:00
ULONG executionStatus;
2009-02-20 17:07:00 +01:00
HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus);
2009-02-09 11:35:43 +01:00
if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO)
2009-02-20 17:07:00 +01:00
m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
2009-02-09 11:35:43 +01:00
startWatchTimer();
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManagerAccess->notifyInferiorRunning();
2009-02-09 11:35:43 +01:00
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::interruptInferior()
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
//TODO: better use IDebugControl::SetInterrupt?
2009-02-20 17:07:00 +01:00
if (!m_d->m_hDebuggeeProcess)
2009-02-09 11:35:43 +01:00
return;
2009-02-20 17:07:00 +01:00
if (!DebugBreakProcess(m_d->m_hDebuggeeProcess)) {
2009-02-09 11:35:43 +01:00
qWarning("DebugBreakProcess failed.");
return;
}
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManagerAccess->notifyInferiorStopped();
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-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
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-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO << functionName;
2009-02-09 11:35:43 +01:00
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber)
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
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-02-09 11:35:43 +01:00
}
2009-02-23 14:46:46 +01:00
void CdbDebugEngine::executeDebuggerCommand(const QString &command)
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO << command;
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;
if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped)
2009-02-09 11:35:43 +01:00
return;
2009-02-23 14:46:46 +01:00
StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler();
2009-02-20 17:07:00 +01:00
const int oldIndex = stackHandler->currentIndex();
2009-02-09 11:35:43 +01:00
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex
// << stackHandler->currentIndex();
2009-02-17 11:16:23 +01:00
QTC_ASSERT(frameIndex < stackHandler->stackSize(), return);
2009-02-09 11:35:43 +01:00
if (oldIndex != frameIndex) {
stackHandler->setCurrentIndex(frameIndex);
//updateLocals();
}
const StackFrame &frame = stackHandler->currentFrame();
2009-02-20 17:07:00 +01:00
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
2009-02-09 11:35:43 +01:00
if (usable)
2009-02-23 14:46:46 +01:00
m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
2009-02-09 11:35:43 +01:00
else
qDebug() << "FULL NAME NOT USABLE: " << frame.file;
}
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-02-23 14:46:46 +01:00
m_d->m_debuggerManager->resetLocation();
2009-02-09 11:35:43 +01:00
2009-02-23 14:46:46 +01:00
ThreadsHandler *threadsHandler = m_d->m_debuggerManagerAccess->threadsHandler();
2009-02-09 11:35:43 +01:00
threadsHandler->setCurrentThread(index);
2009-02-20 17:07:00 +01:00
m_d->m_currentThreadId = index;
m_d->updateStackTrace();
2009-02-09 11:35:43 +01:00
}
2009-02-23 14:46:46 +01:00
static inline QString breakPointExpression(const QString &fileName, const QString &lineNumber)
{
QString str;
str += QLatin1Char('`');
str += QDir::toNativeSeparators(fileName);
str += QLatin1Char(':');
str += lineNumber;
str += QLatin1Char('`');
return str;
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::attemptBreakpointSynchronization()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO;
if (!m_d->m_hDebuggeeProcess) {
qWarning("attemptBreakpointSynchronization() called while debugger is not running");
return;
}
BreakHandler *handler = m_d->m_debuggerManagerAccess->breakHandler();
2009-02-09 11:35:43 +01:00
for (int i=0; i < handler->size(); ++i) {
BreakpointData* breakpoint = handler->at(i);
if (breakpoint->pending) {
2009-02-23 14:46:46 +01:00
const QString expr = breakPointExpression(breakpoint->fileName, breakpoint->lineNumber);
2009-02-09 11:35:43 +01:00
IDebugBreakpoint2* pBP = 0;
2009-02-20 17:07:00 +01:00
HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
2009-02-09 11:35:43 +01:00
if (FAILED(hr) || !pBP) {
2009-02-23 14:46:46 +01:00
qWarning("m_pDebugControl->AddBreakpoint2 %s failed.", qPrintable(expr));
2009-02-09 11:35:43 +01:00
continue;
}
2009-02-23 14:46:46 +01:00
hr = pBP->SetOffsetExpressionWide(expr.utf16());
2009-02-09 11:35:43 +01:00
if (FAILED(hr)) {
2009-02-23 14:46:46 +01:00
qWarning("SetOffsetExpressionWide %s failed", qPrintable(expr));
2009-02-09 11:35:43 +01:00
continue;
}
bool ok;
ULONG ul;
ul = breakpoint->ignoreCount.toULong(&ok);
if (ok) pBP->SetPassCount(ul);
//TODO: handle breakpoint->condition
pBP->AddFlags(DEBUG_BREAKPOINT_ENABLED);
//pBP->AddFlags(DEBUG_BREAKPOINT_GO_ONLY);
breakpoint->pending = false;
}
}
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::loadSessionData()
2009-02-09 11:35:43 +01:00
{
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::saveSessionData()
2009-02-09 11:35:43 +01:00
{
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::reloadDisassembler()
2009-02-09 11:35:43 +01:00
{
}
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-02-09 13:07:38 +01:00
void CdbDebugEngine::reloadRegisters()
2009-02-09 11:35:43 +01:00
{
}
2009-02-09 13:07:38 +01:00
void CdbDebugEngine::timerEvent(QTimerEvent* te)
2009-02-23 14:46:46 +01:00
{
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-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << Q_FUNC_INFO;
2009-02-09 11:35:43 +01:00
HRESULT hr;
2009-02-20 17:07:00 +01:00
hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
2009-02-09 11:35:43 +01:00
switch (hr) {
case S_OK:
2009-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << "WaitForEvent S_OK";
2009-02-09 11:35:43 +01:00
killWatchTimer();
2009-02-20 17:07:00 +01:00
m_d->handleDebugEvent();
2009-02-09 11:35:43 +01:00
break;
case S_FALSE:
2009-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << "WaitForEvent S_FALSE";
2009-02-09 11:35:43 +01:00
break;
case E_PENDING:
2009-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << "WaitForEvent E_PENDING";
2009-02-09 11:35:43 +01:00
break;
case E_UNEXPECTED:
2009-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << "WaitForEvent E_UNEXPECTED";
2009-02-09 11:35:43 +01:00
killWatchTimer();
break;
case E_FAIL:
2009-02-23 14:46:46 +01:00
if (debugCDB > 1)
qDebug() << "WaitForEvent E_FAIL";
2009-02-09 11:35:43 +01:00
break;
}
}
2009-02-20 17:07:00 +01:00
void CdbDebugEnginePrivate::handleDebugEvent()
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
if (m_bIgnoreNextDebugEvent) {
2009-02-20 17:07:00 +01:00
m_engine->startWatchTimer();
2009-02-09 11:35:43 +01:00
m_bIgnoreNextDebugEvent = false;
} else {
2009-02-23 14:46:46 +01:00
m_debuggerManagerAccess->notifyInferiorStopped();
2009-02-09 11:35:43 +01:00
updateThreadList();
updateStackTrace();
}
//ULONG executionStatus;
//HRESULT hr = m_pDebugControl->GetExecutionStatus(&executionStatus);
//if (SUCCEEDED(hr) && executionStatus == DEBUG_STATUS_STEP_INTO) {
// // check if stack trace is valid
// StackHandler* sh = qq->stackHandler();
// QList<StackFrame> frames = sh->frames();
// if (frames.size() > 0 && frames.first().file.isEmpty()) {
// stepExec();
// }
//}
}
2009-02-20 17:07:00 +01:00
void CdbDebugEnginePrivate::updateThreadList()
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
if (debugCDB)
qDebug() << Q_FUNC_INFO;
ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler();
2009-02-09 11:35:43 +01:00
QList<ThreadData> threads;
HRESULT hr;
ULONG numberOfThreads;
hr = m_pDebugSystemObjects->GetNumberThreads(&numberOfThreads);
const ULONG maxThreadIds = 256;
ULONG threadIds[maxThreadIds];
ULONG biggestThreadId = qMin(maxThreadIds, numberOfThreads - 1);
hr = m_pDebugSystemObjects->GetThreadIdsByIndex(0, biggestThreadId, threadIds, 0);
for (ULONG threadId = 0; threadId <= biggestThreadId; ++threadId) {
ThreadData thread;
thread.id = threadId;
threads.append(thread);
}
th->setThreads(threads);
}
2009-02-20 17:07:00 +01:00
void CdbDebugEnginePrivate::updateStackTrace()
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
//qDebug() << "updateStackTrace()";
2009-02-20 17:07:00 +01:00
HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
2009-02-09 11:35:43 +01:00
//ULONG64 frameOffset, instructionOffset, stackOffset;
//if (FAILED(m_pDebugRegisters->GetFrameOffset2(DEBUG_REGSRC_DEBUGGEE, &frameOffset)) ||
// FAILED(m_pDebugRegisters->GetInstructionOffset2(DEBUG_REGSRC_DEBUGGEE, &instructionOffset)) ||
// FAILED(m_pDebugRegisters->GetStackOffset2(DEBUG_REGSRC_DEBUGGEE, &stackOffset)))
//{
// frameOffset = instructionOffset = stackOffset = 0;
//}
//frameOffset = instructionOffset = stackOffset = 0;
const ULONG numFrames = 100;
ULONG numFramesFilled = 0;
DEBUG_STACK_FRAME frames[numFrames];
//hr = m_pDebugControl->GetStackTrace(frameOffset, stackOffset, instructionOffset, frames, numFrames, &numFramesFilled);
hr = m_pDebugControl->GetStackTrace(0, 0, 0, frames, numFrames, &numFramesFilled);
if (FAILED(hr))
qDebug() << "GetStackTrace failed";
QList<StackFrame> stackFrames;
WCHAR wszBuf[MAX_PATH];
for (ULONG i=0; i < numFramesFilled; ++i) {
StackFrame frame;
frame.line = 0;
frame.level = i;
2009-02-23 14:46:46 +01:00
frame.address = QString::fromLatin1("0x%1").arg(frames[i].InstructionOffset, 0, 16);
2009-02-09 11:35:43 +01:00
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
frame.function = QString::fromUtf16(wszBuf);
ULONG ulLine;
ULONG ulFileNameSize;
ULONG64 ul64Displacement;
hr = m_pDebugSymbols->GetLineByOffsetWide(frames[i].InstructionOffset, &ulLine, wszBuf, MAX_PATH, &ulFileNameSize, &ul64Displacement);
if (SUCCEEDED(hr)) {
frame.line = ulLine;
frame.file = QString::fromUtf16(wszBuf, ulFileNameSize);
}
stackFrames.append(frame);
}
2009-02-23 14:46:46 +01:00
m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames);
2009-02-09 11:35:43 +01:00
// find the first usable frame and select it
for (int i=0; i < stackFrames.count(); ++i) {
const StackFrame &frame = stackFrames.at(i);
2009-02-23 14:46:46 +01:00
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
2009-02-09 11:35:43 +01:00
if (usable) {
2009-02-23 14:46:46 +01:00
m_debuggerManagerAccess->stackHandler()->setCurrentIndex(i);
m_debuggerManager->gotoLocation(frame.file, frame.line, true);
2009-02-09 11:35:43 +01:00
break;
}
}
//m_pDebugSymbols->GetImagePathWide(wszBuf, buflen, 0);
//qDebug() << "ImagePath" << QString::fromUtf16(wszBuf);
//m_pDebugSymbols->GetSymbolPathWide(wszBuf, buflen, 0);
//qDebug() << "SymbolPath" << QString::fromUtf16(wszBuf);
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, 0, 2, DEBUG_STACK_FRAME_ADDRESSES | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_FRAME_NUMBERS);
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, frames, numFramesFilled, DEBUG_STACK_SOURCE_LINE);
}
2009-02-20 17:07:00 +01:00
void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString)
2009-02-09 11:35:43 +01:00
{
2009-02-23 14:46:46 +01:00
m_debuggerManagerAccess->showApplicationOutput(QString::fromLocal8Bit(szOutputString));
2009-02-09 11:35:43 +01:00
}
2009-02-20 17:07:00 +01:00
void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT 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
}
IDebuggerEngine *createWinEngine(DebuggerManager *parent)
{
2009-02-09 13:07:38 +01:00
return new CdbDebugEngine(parent);
2009-02-09 11:35:43 +01:00
}
2009-02-20 14:56:36 +01:00
void CdbDebugEngine::setDebugDumpers(bool on)
{
Q_UNUSED(on)
}
void CdbDebugEngine::setUseCustomDumpers(bool on)
{
Q_UNUSED(on)
}
void CdbDebugEngine::reloadSourceFiles()
{
}