Commit 0b527bfd authored by Friedemann Kleint's avatar Friedemann Kleint Committed by hjk

Fix CDB/trkgdbadapter.

parent 8ab4ed58
......@@ -78,7 +78,13 @@
#define DBGHELP_TRANSLATE_TCHAR
#include <inc/Dbghelp.h>
static const char *localSymbolRootC = "local";
static const char localSymbolRootC[] = "local";
#if 0
# define STATE_DEBUG(func, line, notifyFunc) qDebug("%s at %s:%d", notifyFunc, func, line);
#else
# define STATE_DEBUG(func, line, notifyFunc)
#endif
namespace Debugger {
namespace Internal {
......@@ -227,7 +233,9 @@ CdbEngine::~CdbEngine()
void CdbEngine::shutdownInferior()
{
notifyInferiorShutdownOk();
QString errorMessage;
if (!m_d->endInferior(false, &errorMessage))
showMessage(errorMessage, LogError);
}
void CdbEngine::shutdownEngine()
......@@ -377,7 +385,7 @@ void CdbEngine::setupEngine()
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
const DebuggerStartParameters &sp = startParameters();
if (debugCDBExecution)
qDebug() << "startDebugger";
qDebug("setupEngine");
CdbCore::BreakPoint::clearNormalizeFileNameCache();
startupChecks();
m_d->checkVersion();
......@@ -391,7 +399,7 @@ void CdbEngine::setupEngine()
case AttachToRemote:
warning(QLatin1String("Internal error: Mode not supported."));
notifyEngineSetupFailed();
break;
return;
default:
break;
}
......@@ -419,18 +427,22 @@ void CdbEngine::setupEngine()
}
}
m_d->m_dumper->reset(dumperLibName, dumperEnabled);
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk");
notifyEngineSetupOk();
}
void CdbEngine::setupInferior()
{
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorSetupOk");
notifyInferiorSetupOk();
}
void CdbEngine::runEngine()
{
QTC_ASSERT(state() == InferiorRunRequested, qDebug() << state());
if (debugCDBExecution)
qDebug("runEngine");
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
showStatusMessage("Starting Debugger", messageTimeOut);
const DebuggerStartParameters &sp = startParameters();
......@@ -475,10 +487,11 @@ void CdbEngine::runEngine()
if (rc) {
if (needWatchTimer)
m_d->startWatchTimer();
notifyEngineRunAndInferiorRunOk(); // FIXME AAA: correct?
// Continues processCreatedAttached().
} else {
warning(errorMessage);
notifyEngineRunAndInferiorStopOk(); // FIXME AAA: correct?
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyEngineRunFailed");
notifyEngineRunFailed();
}
}
......@@ -500,7 +513,10 @@ bool CdbEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QString *e
void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 initialThreadHandle)
{
m_engine->notifyInferiorRunRequested();
if (debugCDBExecution)
qDebug(">processCreatedAttached");
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyEngineRunAndInferiorStopOk");
m_engine->notifyEngineRunAndInferiorStopOk();
setDebuggeeHandles(reinterpret_cast<HANDLE>(processHandle), reinterpret_cast<HANDLE>(initialThreadHandle));
ULONG currentThreadId;
if (SUCCEEDED(interfaces().debugSystemObjects->GetThreadIdByHandle(initialThreadHandle, &currentThreadId))) {
......@@ -512,7 +528,7 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
m_engine->executeDebuggerCommand(QLatin1String("bc"));
if (m_engine->breakHandler()->hasPendingBreakpoints()) {
if (debugCDBExecution)
qDebug() << "processCreatedAttached: Syncing breakpoints";
qDebug("processCreatedAttached: Syncing breakpoints");
m_engine->attemptBreakpointSynchronization();
}
// Attaching to crashed: This handshake (signalling an event) is required for
......@@ -527,115 +543,119 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
m_engine->warning(QString::fromLatin1("Handshake failed on event #%1: %2").arg(evtNr).arg(CdbCore::msgComFailed("SetNotifyEventHandle", hr)));
}
}
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested()/notifyInferiorRunOk()");
m_engine->notifyInferiorRunRequested();
m_engine->notifyInferiorRunOk();
if (debugCDBExecution)
qDebug() << "<processCreatedAttached";
qDebug("<processCreatedAttached");
}
void CdbEngine::processTerminated(unsigned long exitCode)
{
if (debugCDBExecution)
qDebug("processTerminated: %lu", exitCode);
showMessage(tr("The process exited with exit code %1.").arg(exitCode));
//if (state() != InferiorStopRequested)
// setState(InferiorStopRequested, Q_FUNC_INFO, __LINE__);
//setState(InferiorStopOk, Q_FUNC_INFO, __LINE__);
//setState(InferiorShutdownRequested, Q_FUNC_INFO, __LINE__);
m_d->setDebuggeeHandles(0, 0);
m_d->clearForRun();
//setState(InferiorShutdownOk, Q_FUNC_INFO, __LINE__);
// Avoid calls from event handler.
//QTimer::singleShot(0, this, SLOT(quitDebugger()));
notifyInferiorExited(); // FIXME AAA: correnct?
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorExited");
notifyInferiorExited();
}
bool CdbEnginePrivate::endInferior(EndInferiorAction action, QString *errorMessage)
bool CdbEnginePrivate::endInferior(bool detachOnly, QString *errorMessage)
{
// Are we running
switch (m_engine->state()) {
case InferiorRunRequested:
case InferiorRunOk:
case InferiorRunFailed:
case InferiorStopRequested:
case InferiorStopOk:
case InferiorStopFailed:
break;
default:
return true;
}
// Detach or terminate?
if (!detachOnly && (m_mode == AttachExternal || m_mode == AttachCrashedExternal))
detachOnly = true;
// Process must be stopped in order to terminate
//m_engine->setState(InferiorShutdownRequested, Q_FUNC_INFO, __LINE__); // pretend it is shutdown
const bool wasRunning = isDebuggeeRunning();
if (debugCDBExecution)
qDebug("endInferior detach=%d, running=%d", detachOnly, wasRunning);
if (wasRunning) {
interruptInterferiorProcess(errorMessage);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
bool success = false;
switch (action) {
case DetachInferior:
if (detachCurrentProcess(errorMessage))
if (detachOnly) {
if (detachCurrentProcess(errorMessage))
success = true;
} else {
// Stop debuggee. Weird exit logic.
do {
// The exit process event handler will not be called.
terminateCurrentProcess(errorMessage);
if (wasRunning) {
success = true;
break;
case TerminateInferior:
do {
// The exit process event handler will not be called.
terminateCurrentProcess(errorMessage);
if (wasRunning) {
success = true;
break;
}
if (terminateProcesses(errorMessage))
success = true;
} while (false);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
break;
break;
}
if (terminateProcesses(errorMessage))
success = true;
} while (false);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
// Perform cleanup even when failed..no point clinging to the process
setDebuggeeHandles(0, 0);
killWatchTimer();
if (success)
clearForRun();
if (success) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownOk");
m_engine->notifyInferiorShutdownOk();
else
} else {
*errorMessage = QString::fromLatin1("Unable to detach from/end the debuggee: %1").arg(*errorMessage);
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorShutdownFailed");
m_engine->notifyInferiorShutdownFailed();
}
return success;
}
// 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 CdbEnginePrivate::endDebugging(EndDebuggingMode em)
void CdbEnginePrivate::endDebugging(bool detachOnly)
{
if (debugCDB)
qDebug() << Q_FUNC_INFO << em;
if (debugCDBExecution)
qDebug("endDebugging() detach=%d, state=%s", detachOnly, DebuggerEngine::stateName(m_engine->state()));
const DebuggerState oldState = m_engine->state();
if (oldState == DebuggerNotReady || m_mode == AttachCore)
switch (m_engine->state()) {
case DebuggerNotReady:
case EngineShutdownOk:
case EngineShutdownFailed:
case DebuggerFinished:
return;
default:
break;
}
// Do we need to stop the process?
QString errorMessage;
if (oldState != InferiorShutdownOk && 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);
m_engine->showMessage(errorMessage, LogError);
}
if (!endInferior(detachOnly, &errorMessage)) {
m_engine->showMessage(errorMessage, LogError);
errorMessage.clear();
}
// Clean up resources (open files, etc.)
//m_engine->setState(EngineShutdownRequested, Q_FUNC_INFO, __LINE__);
clearForRun();
const bool endedCleanly = endSession(&errorMessage);
//m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
if (!endedCleanly) {
if (endSession(&errorMessage)) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyEngineShutdownOk");
m_engine->notifyEngineShutdownOk();
errorMessage = QString::fromLatin1("There were errors trying to end debugging:\n%1").arg(errorMessage);
m_engine->showMessage(errorMessage, LogError);
} else {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyEngineShutdownFailed");
m_engine->notifyEngineShutdownFailed();
}
}
void CdbEngine::detachDebugger()
{
m_d->endDebugging(CdbEnginePrivate::EndDebuggingDetach);
m_d->endDebugging(true);
}
CdbSymbolGroupContext *CdbEnginePrivate::getSymbolGroupContext(int frameIndex, QString *errorMessage) const
......@@ -712,14 +732,17 @@ bool CdbEnginePrivate::executeContinueCommand(const QString &command)
qDebug() << Q_FUNC_INFO << command;
clearForRun();
updateCodeLevel(); // Step by instruction
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested");
m_engine->notifyInferiorRunRequested();
m_engine->showMessage(CdbEngine::tr("Continuing with '%1'...").arg(command));
QString errorMessage;
const bool success = executeDebuggerCommand(command, &errorMessage);
if (success) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk");
m_engine->notifyInferiorRunOk();
startWatchTimer();
} else {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunFailed");
m_engine->notifyInferiorRunFailed();
m_engine->warning(CdbEngine::tr("Unable to continue: %1").arg(errorMessage));
}
......@@ -772,6 +795,7 @@ bool CdbEngine::step(unsigned long executionStatus)
|| threadsHandler()->threads().size() == 1;
m_d->clearForRun(); // clears thread ids
m_d->updateCodeLevel(); // Step by instruction or source line
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested");
notifyInferiorRunRequested();
bool success = false;
if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API
......@@ -806,8 +830,10 @@ bool CdbEngine::step(unsigned long executionStatus)
if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO)
m_d->m_breakEventMode = CdbEnginePrivate::BreakEventIgnoreOnce;
m_d->startWatchTimer();
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk");
notifyInferiorRunOk();
} else {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunFailed");
notifyInferiorRunFailed();
}
if (debugCDBExecution)
......@@ -852,7 +878,7 @@ void CdbEngine::continueInferior()
bool CdbEnginePrivate::continueInferiorProcess(QString *errorMessagePtr /* = 0 */)
{
if (debugCDBExecution)
qDebug() << "continueInferiorProcess";
qDebug("continueInferiorProcess");
const HRESULT hr = interfaces().debugControl->SetExecutionStatus(DEBUG_STATUS_GO);
if (FAILED(hr)) {
const QString errorMessage = CdbCore::msgComFailed("SetExecutionStatus", hr);
......@@ -879,6 +905,7 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage)
return true;
}
// Request continue
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested");
m_engine->notifyInferiorRunRequested();
bool success = false;
do {
......@@ -895,8 +922,10 @@ bool CdbEnginePrivate::continueInferior(QString *errorMessage)
success = true;
} while (false);
if (success) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunOk");
m_engine->notifyInferiorRunOk();
} else {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorRunFailed");
m_engine->notifyInferiorRunFailed();
}
return true;
......@@ -939,12 +968,12 @@ void CdbEngine::slotBreakAttachToCrashed()
void CdbEngine::interruptInferior()
{
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
if (!m_d->m_hDebuggeeProcess || !m_d->isDebuggeeRunning())
return;
QString errorMessage;
if (!m_d->interruptInterferiorProcess(&errorMessage)) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "notifyInferiorStopFailed");
notifyInferiorStopFailed();
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
}
......@@ -1329,11 +1358,15 @@ void CdbEnginePrivate::handleDebugEvent()
switch (mode) {
case BreakEventHandle: {
if (m_interrupted) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "BreakEventHandle / notifyInferiorStopOk");
m_engine->notifyInferiorStopOk();
} else {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "BreakEventHandle / notifyInferiorSpontaneousStop");
m_engine->notifyInferiorSpontaneousStop();
}
// If this is triggered by breakpoint/crash: Set state to stopping
// to avoid warnings as opposed to interrupt inferior
//if (m_engine->state() != InferiorStopRequested) FIXME: AAA
// m_engine->setState(InferiorStopRequested, Q_FUNC_INFO, __LINE__);
m_engine->notifyInferiorStopOk();
// Indicate artifical thread that is created when interrupting as such,
// else use stop message with cleaned newlines and blanks.
const QString currentThreadState =
......@@ -1373,11 +1406,15 @@ void CdbEnginePrivate::handleDebugEvent()
break;
case BreakEventSyncBreakPoints: {
m_interrupted = false;
// Temp stop to sync breakpoints
// Temp stop to sync breakpoints (without invoking states).
// Triggered when the users changes breakpoints while running.
QString errorMessage;
attemptBreakpointSynchronization(&errorMessage);
startWatchTimer();
continueInferiorProcess(&errorMessage);
if (!continueInferiorProcess(&errorMessage)) {
STATE_DEBUG(Q_FUNC_INFO, __LINE__, "BreakEventSyncBreakPoints / notifyInferiorSpontaneousStop");
m_engine->notifyInferiorSpontaneousStop();
}
if (!errorMessage.isEmpty())
m_engine->warning(QString::fromLatin1("In handleDebugEvent: %1").arg(errorMessage));
}
......
......@@ -98,11 +98,10 @@ public:
bool attemptBreakpointSynchronization(QString *errorMessage);
void notifyException(long code, bool fatal, const QString &message);
enum EndInferiorAction { DetachInferior, TerminateInferior };
bool endInferior(EndInferiorAction a, QString *errorMessage);
enum EndDebuggingMode { EndDebuggingDetach, EndDebuggingTerminate, EndDebuggingAuto };
void endDebugging(EndDebuggingMode em = EndDebuggingAuto);
bool endInferior(bool detachOnly /* = false */, QString *errorMessage);
void endDebugging(bool detachOnly = false);
void updateCodeLevel();
......
......@@ -1202,7 +1202,7 @@ void DebuggerEngine::notifyInferiorShutdownOk()
void DebuggerEngine::notifyInferiorShutdownFailed()
{
showMessage(_("INFERIOR SHUTDOWN FAILED"));
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << this << state());
setState(InferiorShutdownFailed);
d->queueShutdownEngine();
}
......@@ -1226,7 +1226,8 @@ void DebuggerEngine::notifyInferiorIll()
void DebuggerEnginePrivate::doShutdownEngine()
{
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
QTC_ASSERT(state() == EngineShutdownRequested
|| state() == InferiorShutdownOk, qDebug() << state());
m_targetState = DebuggerFinished;
m_engine->showMessage(_("CALL: SHUTDOWN ENGINE"));
m_engine->shutdownEngine();
......
......@@ -244,8 +244,8 @@ public:
void handleCommand(int role, const QVariant &value);
// Convenience
void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const;
void showStatusMessage(const QString &msg, int timeout = -1) const;
Q_SLOT void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const;
Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
void resetLocation();
void openFile(const QString &fileName, int lineNumber = -1);
......
......@@ -1864,6 +1864,7 @@ void TrkGdbAdapter::shutdownInferior()
void TrkGdbAdapter::shutdownAdapter()
{
cleanup();
m_engine->notifyAdapterShutdownOk();
}
void TrkGdbAdapter::trkReloadRegisters()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment