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