blob: 68d6563f7c39fd5157dcb5a97b33bff7973fdb4e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
#include "ResumeContextAction.h"
#include "TCFContext.h"
#include "WinProcess.h"
#include "WinThread.h"
#include "WinDebugMonitor.h"
#include "RunControlService.h"
#include "BreakpointsService.h"
ResumeContextAction::ResumeContextAction(const AgentActionParams& params,
WinProcess& process,
WinThread& thread,
long resumeMode) : AgentAction(params), process_(process), thread_(thread) {
resumeMode_ = resumeMode;
}
ResumeContextAction::~ResumeContextAction(void) {
}
/*
* This will & must be run in debugger monitor thread.
*/
void ResumeContextAction::Run() {
// Single step over a breakpoint (if any) at current PC.
//
TBreakpoint* bpAtStartAddress
= BreakpointsService::FindBreakpointByAddress(process_.GetProcessHandle(), thread_.GetPCAddress());
if (bpAtStartAddress) {
BreakpointsService::ClearBreak(bpAtStartAddress);
thread_.EnableSingleStep();
} else if (resumeMode_ == RM_STEP_INTO)
thread_.EnableSingleStep();
thread_.MarkResumed();
::ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), thread_.GetContinueStatus());
// notify host the Resume action is done before
// any suspend event is reported.
params.reportSuccessForAction();
if (bpAtStartAddress) {
DEBUG_EVENT debugEvent;
if (::WaitForDebugEvent(&debugEvent, 200 /* ms */)) {
// Done executing single instruction.
BreakpointsService::InsertBreak(bpAtStartAddress); // restore the bp
if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) {
if (resumeMode_ == RM_STEP_INTO)
// single-step done, report suspend event to host.
process_.GetMonitor()->HandleDebugEvent(debugEvent);
else
// other resume modes
// Ignore the SINGLE_STEP event, go on to Resume again
::ContinueDebugEvent(process_.GetOSID(), thread_.GetOSID(), DBG_CONTINUE);
} else {
// Other exceptions
// Handle the event, say, report to host.
process_.GetMonitor()->HandleDebugEvent(debugEvent);
}
} else {
trace(LOG_ALWAYS, "Failed to execute one instruction. Error: %d", GetLastError());
}
}
// else the event loop of monitor thread would catch and report event.
}