| /******************************************************************************* | |
| * 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(); | |
| 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. | |
| } | |
| } |