/*******************************************************************************
 * Copyright (c) 2009, 2011 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
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.internal.services.dsf;

import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.core.breakpointactions.ILogActionEnabler;
import org.eclipse.cdt.debug.core.breakpointactions.IResumeActionEnabler;
import org.eclipse.cdt.debug.edc.IAddressExpressionEvaluator;
import org.eclipse.cdt.debug.edc.IJumpToAddress;
import org.eclipse.cdt.debug.edc.JumpToAddress;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembledInstruction;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembler;
import org.eclipse.cdt.debug.edc.disassembler.IDisassembler.IDisassemblerOptions;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.EDCTrace;
import org.eclipse.cdt.debug.edc.internal.breakpointactions.LogActionEnabler;
import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Breakpoints.BreakpointDMData;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;
import org.eclipse.cdt.debug.edc.internal.snapshot.Album;
import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
import org.eclipse.cdt.debug.edc.services.DMContext;
import org.eclipse.cdt.debug.edc.services.Disassembly;
import org.eclipse.cdt.debug.edc.services.IDSFServiceUsingTCF;
import org.eclipse.cdt.debug.edc.services.IEDCDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCExecutionDMC;
import org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCModules;
import org.eclipse.cdt.debug.edc.services.IEDCSymbols;
import org.eclipse.cdt.debug.edc.services.ITargetEnvironment;
import org.eclipse.cdt.debug.edc.services.Registers;
import org.eclipse.cdt.debug.edc.services.Registers.RegisterDMC;
import org.eclipse.cdt.debug.edc.services.Registers.RegisterGroupDMC;
import org.eclipse.cdt.debug.edc.services.Stack;
import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
import org.eclipse.cdt.debug.edc.services.Stack.VariableDMC;
import org.eclipse.cdt.debug.edc.snapshot.IAlbum;
import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;
import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
import org.eclipse.cdt.debug.edc.symbols.IFunctionScope;
import org.eclipse.cdt.debug.edc.symbols.ILineEntry;
import org.eclipse.cdt.debug.edc.symbols.IModuleLineEntryProvider;
import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants;
import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext;
import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl2;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.model.MemoryByte;
import org.eclipse.tm.tcf.protocol.IService;
import org.eclipse.tm.tcf.protocol.IToken;
import org.eclipse.tm.tcf.protocol.Protocol;
import org.eclipse.tm.tcf.services.IRunControl.DoneCommand;
import org.eclipse.tm.tcf.services.IRunControl.RunControlContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class RunControl extends AbstractEDCService implements IRunControl2, ICachingService, ISnapshotContributor,
		IDSFServiceUsingTCF {

	public static final String EXECUTION_CONTEXT = "execution_context";
	public static final String EXECUTION_CONTEXT_REGISTERS = "execution_context_registers";
	public static final String EXECUTION_CONTEXT_MODULES = "execution_context_modules";
	public static final String EXECUTION_CONTEXT_FRAMES = "execution_context_frames";
	/**
	 * Context property names. Properties that are optional but have default
	 * implicit values are indicated below
	 */
	public static final String 
			PROP_PARENT_ID = "ParentID", 
			PROP_IS_CONTAINER = "IsContainer",	 // default = true
			PROP_HAS_STATE = "HasState",
			PROP_CAN_RESUME = "CanResume",       // default = true
			PROP_CAN_COUNT = "CanCount",
			PROP_CAN_SUSPEND = "CanSuspend",     // default = true
			PROP_CAN_TERMINATE = "CanTerminate", // default = false
			PROP_IS_SUSPENDED = "State",         // default = false		 
			PROP_MESSAGE = "Message", 
			PROP_SUSPEND_PC = "SuspendPC",
			PROP_DISABLE_STEPPING = "DisableStepping";

	public static final String STEP_RETURN_NOT_SUPPORTED
	  = "the current Execution context does not support StepType.STEP_RETURN"; //$NON-NLS-1$

	/*
	 * See where this is used for more.
	 */
	private static final int RESUME_NOTIFICATION_DELAY = 1000;	// milliseconds
	
	// Whether module is being loaded (if true) or unloaded (if false)

	public abstract static class DMCSuspendedEvent extends AbstractDMEvent<IExecutionDMContext> {

		private final StateChangeReason reason;
		private final Map<String, Object> params;

		public DMCSuspendedEvent(IExecutionDMContext dmc, StateChangeReason reason, Map<String, Object> params) {
			super(dmc);
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { dmc, reason, params })); }
			this.reason = reason;
			this.params = params;
		}

		public StateChangeReason getReason() {
			return reason;
		}

		public Map<String, Object> getParams() {
			return params;
		}
		
	}
	
	public static class SuspendedEvent extends DMCSuspendedEvent implements ISuspendedDMEvent {

		public SuspendedEvent(IExecutionDMContext dmc,
				StateChangeReason reason, Map<String, Object> params) {
			super(dmc, reason, params);
		}

	}

	public static class ContainerSuspendedEvent extends DMCSuspendedEvent implements IContainerSuspendedDMEvent {

		public ContainerSuspendedEvent(IExecutionDMContext dmc,
				StateChangeReason reason, Map<String, Object> params) {
			super(dmc, reason, params);
		}

		public IExecutionDMContext[] getTriggeringContexts() {
			return new IExecutionDMContext[]{getDMContext()};
		}
	}

	public abstract static class DMCResumedEvent extends AbstractDMEvent<IExecutionDMContext> {

		public DMCResumedEvent(IExecutionDMContext dmc) {
			super(dmc);
		}

		public StateChangeReason getReason() {
			return StateChangeReason.USER_REQUEST;
		}
	}

	public static class ResumedEvent extends DMCResumedEvent implements IResumedDMEvent {

		public ResumedEvent(IExecutionDMContext dmc) {
			super(dmc);
		}
	}

	public static class ContainerResumedEvent extends DMCResumedEvent implements IContainerResumedDMEvent {

		public ContainerResumedEvent(IExecutionDMContext dmc) {
			super(dmc);
		}

		public IExecutionDMContext[] getTriggeringContexts() {
			return new IExecutionDMContext[]{getDMContext()};
		}
}

	private static StateChangeReason toDsfStateChangeReason(String tcfReason) {
		if (tcfReason == null)
			return StateChangeReason.UNKNOWN;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_USER_REQUEST))
			return StateChangeReason.USER_REQUEST;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_STEP))
			return StateChangeReason.STEP;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_BREAKPOINT))
			return StateChangeReason.BREAKPOINT;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_EXCEPTION))
			return StateChangeReason.EXCEPTION;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_CONTAINER))
			return StateChangeReason.CONTAINER;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_WATCHPOINT))
			return StateChangeReason.WATCHPOINT;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SIGNAL))
			return StateChangeReason.SIGNAL;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SHAREDLIB))
			return StateChangeReason.SHAREDLIB;
		if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_ERROR))
			return StateChangeReason.ERROR;
		return StateChangeReason.UNKNOWN;
	}

	@Immutable
	private static class ExecutionData implements IExecutionDMData2 {
		private final StateChangeReason reason;
		private final String details;

		ExecutionData(StateChangeReason reason, String details) {
			this.reason = reason;
			this.details = details;
		}

		public StateChangeReason getStateChangeReason() {
			return reason;
		}

		public String getDetails() {
			return details;
		}
	}

	public abstract class ExecutionDMC extends DMContext implements IExecutionDMContext,
			ISnapshotContributor, IEDCExecutionDMC {

		private final List<ExecutionDMC> children = Collections.synchronizedList(new ArrayList<ExecutionDMC>());
		private StateChangeReason stateChangeReason = StateChangeReason.UNKNOWN;
		private String stateChangeDetails = null;
		private final RunControlContext tcfContext;
		private final ExecutionDMC parentExecutionDMC;
		/**
		 * Hex string without "0x".
		 */
		private String latestPC = null;
		private RequestMonitor steppingRM = null;
		private boolean isStepping = false;
		private RequestMonitorWithProgress bpActionRM = null;
		
		// See where this is used for more.
		private int countOfScheduledNotifications = 0 ;

		/**
		 * Whether user chose to "terminate" or "disconnect" the context.
		 */
		private boolean isTerminatingThanDisconnecting = false;
		
		private boolean suspendEventsEnabled = true;
		private DMCSuspendedEvent cachedSuspendedEvent = null;
		
		public ExecutionDMC(ExecutionDMC parent, Map<String, Object> props, RunControlContext tcfContext) {
			super(RunControl.this, parent == null ? new IDMContext[0] : new IDMContext[] { parent }, props);
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { parent, properties })); }
			this.parentExecutionDMC = parent;
			this.tcfContext = tcfContext;
			if (props != null) {
				dmcsByID.put(getID(), this);
			}
			if (parent != null)
				parent.addChild(this);
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		private void addChild(ExecutionDMC executionDMC) {
			synchronized (children) {
				children.add(executionDMC);
			}
		}

		private void removeChild(IEDCExecutionDMC executionDMC) {
			synchronized (children) {
				children.remove(executionDMC);
			}
		}

		public ExecutionDMC[] getChildren() {
			synchronized (children) {
				return children.toArray(new ExecutionDMC[children.size()]);
			}
		}

		public boolean wantFocusInUI() {
			Boolean wantFocus = (Boolean)properties.get(ProtocolConstants.PROP_WANT_FOCUS_IN_UI);
			if (wantFocus == null)
				wantFocus = true;	// default if unknown (not set by debug agent).
			return wantFocus;
		}

		public abstract ExecutionDMC contextAdded(Map<String, Object> properties, RunControlContext tcfContext);

		public abstract boolean canDetach();
		
		public abstract boolean canStep();

		public void loadSnapshot(Element element) throws Exception {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(element)); } 
			NodeList ecElements = element.getElementsByTagName(EXECUTION_CONTEXT);
			int numcontexts = ecElements.getLength();
			for (int i = 0; i < numcontexts; i++) {
				Element contextElement = (Element) ecElements.item(i);
				if (contextElement.getParentNode().equals(element)) {
					try {
						Element propElement = (Element) contextElement.getElementsByTagName(SnapshotUtils.PROPERTIES)
								.item(0);
						HashMap<String, Object> properties = new HashMap<String, Object>();
						SnapshotUtils.initializeFromXML(propElement, properties);
						ExecutionDMC exeDMC = contextAdded(properties, null);
						exeDMC.loadSnapshot(contextElement);
					} catch (CoreException e) {
						EDCDebugger.getMessageLogger().logError(null, e);
					}
				}

			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor)throws Exception {
			Element contextElement = document.createElement(EXECUTION_CONTEXT);
			contextElement.setAttribute(PROP_ID, this.getID());

			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
			contextElement.appendChild(propsElement);

			ExecutionDMC[] dmcs = getChildren();
			SubMonitor progress = SubMonitor.convert(monitor, dmcs.length * 1000);
			progress.subTask(getName());
			
			for (ExecutionDMC executionDMC : dmcs) {
				Element dmcElement = executionDMC.takeSnapshot(album, document, progress.newChild(1000));
				contextElement.appendChild(dmcElement);
			}

			return contextElement;
		}

		public boolean isSuspended() {
			synchronized (properties) {
				return RunControl.getProperty(properties, PROP_IS_SUSPENDED, false);
			}
		}

		public StateChangeReason getStateChangeReason() {
			return stateChangeReason;
		}

		public String getStateChangeDetails() {
			return stateChangeDetails;
		}

		public void setIsSuspended(boolean isSuspended) {
			synchronized (properties) {
				properties.put(PROP_IS_SUSPENDED, isSuspended);
			}
			if (getParent() != null)
				getParent().childIsSuspended(isSuspended);
		}

		private void childIsSuspended(boolean isSuspended) {
			if (isSuspended) {
				setIsSuspended(true);
			} else {
				boolean anySuspended = false;
				for (ExecutionDMC childDMC : getChildren()) {
					if (childDMC.isSuspended()) {
						anySuspended = true;
						break;
					}
				}
				if (!anySuspended)
					setIsSuspended(false);
			}
		}

		protected void contextException(String msg) {
	        assert getExecutor().isInExecutorThread();

	        setIsSuspended(true);
			synchronized (properties) {
				properties.put(PROP_MESSAGE, msg);
			}
			stateChangeReason = StateChangeReason.EXCEPTION;
			getSession().dispatchEvent(
					createSuspendedEvent(StateChangeReason.EXCEPTION, new HashMap<String, Object>()),
					RunControl.this.getProperties());
		}

		protected void contextSuspended(String pc, String reason, final Map<String, Object> params) {
	        assert getExecutor().isInExecutorThread();

	        if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(new Object[] { pc, reason, params })); }
			if (pc != null) {
				// the PC from TCF agent is decimal string.
				// convert it to hex string.
				pc = Long.toHexString(Long.parseLong(pc));
			}

			latestPC = pc;

			setIsSuspended(true);
			synchronized (properties) {
				properties.put(PROP_MESSAGE, reason);
				properties.put(PROP_SUSPEND_PC, pc);
			}
			stateChangeReason = toDsfStateChangeReason(reason);

			if (stateChangeReason == StateChangeReason.SHAREDLIB) {
				handleModuleEvent(this, params);
			} else {

				properties.put(PROP_DISABLE_STEPPING, params.get(ProtocolConstants.PROP_DISABLE_STEPPING));
				properties.put(ProtocolConstants.PROP_WANT_FOCUS_IN_UI, params.get(ProtocolConstants.PROP_WANT_FOCUS_IN_UI));

				stateChangeDetails = (String) params.get(ProtocolConstants.PROP_SUSPEND_DETAIL);
				
				// TODO This is not what the stateChangeDetails is for, we need an extended thread description
				// and is "foreground" really the right term?
				
				// Show the context is foreground one, if possible.
				//
				Boolean isForeground = (Boolean)params.get(ProtocolConstants.PROP_IS_FOREGROUND);
				if (isForeground != null)
					stateChangeDetails += isForeground ? " [foreground]" : "";
				
				final ExecutionDMC dmc = this;

				final DataRequestMonitor<Object> preprocessDrm = new DataRequestMonitor<Object>(getExecutor(), null) {
					@Override
					protected void handleCompleted() {
						Boolean honorSuspend;
						Breakpoints.BreakpointDMData bp;
						Object drmData = getData();
						if (drmData instanceof Breakpoints.BreakpointDMData) {
							bp = (Breakpoints.BreakpointDMData)drmData;
							honorSuspend = true;
						} else { 
							bp = null;
							honorSuspend = (drmData instanceof Boolean) ? (Boolean)getData() : true;
						}
						
						if (honorSuspend!=null && honorSuspend) { // do suspend

							// All the following must be done in DSF dispatch
							// thread to ensure data integrity.

							// see if there are any actions, and perform them if so
							if (bp != null && bp.hasActions()) {
								bp.executeActions(ExecutionDMC.this, newBreakpointActionRM());
							}

							// Mark done of the single step RM, if any pending.
							if (steppingRM != null) {
								steppingRM.done();
								steppingRM = null;
							}

							// Mark any stepping as done.
							setStepping(false);

							// Remove temporary breakpoints set by stepping.
							// Note we don't want to do this on a sharedLibrary
							// event as otherwise
							// stepping will be screwed up by that event.
							//
							Breakpoints bpService = getService(Breakpoints.class);
							bpService.removeAllTempBreakpoints(new RequestMonitor(getExecutor(), null));
							
							/*
							 * Don't report suspendedEvent to upper layer
							 * resulting from prepareToRun() to avoid
							 * unnecessary suspend-handling. But we need to
							 * fire the event if the stepping is finished after
							 * prepareToRun(). So remember it.
							 */
							DMCSuspendedEvent e = dmc.createSuspendedEvent(stateChangeReason, params);
							if (dmc.suspendEventsEnabled())
								getSession().dispatchEvent(e, RunControl.this.getProperties());
							else
								dmc.cacheSuspendedEvent(e);
						} else { 
							// ignore suspend if, say, breakpoint condition is not met.
							RunControl.this.resume(dmc, new RequestMonitor(getExecutor(), null));
						}
					}
				};
				
				preprocessOnSuspend(dmc, latestPC, preprocessDrm);
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		void clearBreakpointActionRM() {
			synchronized (this) {
				if (bpActionRM != null) {
					if (!bpActionRM.getSubmitted()) {
						bpActionRM.cancel();
					}
					IProgressMonitor progress = bpActionRM.getProgressMonitor();
					if (progress != null && !progress.isCanceled()) {
						progress.setCanceled(true);
					}
					bpActionRM = null;
				}
			}
		}

		public RequestMonitorWithProgress getBreakpointActionRM() {
			return bpActionRM;
		}

		RequestMonitorWithProgress newBreakpointActionRM() {
			clearBreakpointActionRM();
			bpActionRM = new RequestMonitorWithProgress(getExecutor(), new NullProgressMonitor()) {
				@Override
				public void handleCompleted() {
					super.handleCompleted();
					clearBreakpointActionRM();
				}
			};
			return bpActionRM;
		}

		protected boolean suspendEventsEnabled() {
			return suspendEventsEnabled ;
		}
		
		protected void setSuspendEventsEnabled(boolean enabled)
		{
			suspendEventsEnabled = enabled;
		}

		/**
		 * handle module load event and unload event. A module is an executable file
		 * or a library (e.g. DLL or shared lib).
		 * 
		 * @param dmc
		 * @param moduleProperties
		 */
		private void handleModuleEvent(final IEDCExecutionDMC dmc, final Map<String, Object> moduleProperties) {
			// The following needs be done in DSF dispatch thread.
			getSession().getExecutor().execute(new Runnable() {
				public void run() {
					// based on properties, either load or unload the module
					boolean loaded = true;
					Object loadedValue = moduleProperties.get(IModuleProperty.PROP_MODULE_LOADED);
					if (loadedValue != null) {
						if (loadedValue instanceof Boolean)
							loaded = (Boolean) loadedValue;
					}

					if (loaded)
						handleModuleLoadedEvent(dmc, moduleProperties);
					else
						handleModuleUnloadedEvent(dmc, moduleProperties);
				}
			});
		}
		
		public Boolean canTerminate() {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null); }
			boolean result = false;
			synchronized (properties) {
				result = RunControl.getProperty(properties, PROP_CAN_TERMINATE, result);
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null, result); }
			return result;
		}

		/**
		 * Resume the context.
		 * 
		 * @param rm
		 *            this is marked done as long as the resume command
		 *            succeeds.
		 */
		public boolean supportsStepMode(StepType type) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }

			int mode = 0;
			switch (type) {
			case STEP_OVER:
				mode = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER_RANGE;
				break;
			case STEP_INTO:
				mode = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO_RANGE;
				break;
			case STEP_RETURN:
				mode = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OUT;
				break;
			case INSTRUCTION_STEP_OVER:
				mode = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER;
				break;
			case INSTRUCTION_STEP_INTO:
				mode = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO;
				break;
			}

			if (hasTCFContext())
				return getTCFContext().canResume(mode);
			else
				return false;
		}

		/**
		 * Resume the context.
		 * 
		 * @param rm
		 *            this is marked done as long as the resume command
		 *            succeeds.
		 */
		public void resume(final RequestMonitor rm) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }

			flushCache(this);

			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						getTCFContext()
								.resume(org.eclipse.tm.tcf.services.IRunControl.RM_RESUME,
										0, new DoneCommand() {

											public void doneCommand(
													IToken token,
													final Exception error) {
												getExecutor().execute(
														new Runnable() {
															public void run() {
																if (error == null) {
																	contextResumed(true);
																	if (EDCTrace.RUN_CONTROL_TRACE_ON) {
																		EDCTrace.getTrace().trace(null, "Resume command succeeded.");
																	}
																} else {
																	if (EDCTrace.RUN_CONTROL_TRACE_ON) {
																		EDCTrace.getTrace().trace(null, "Resume command failed.");
																	}
																	rm.setStatus(new Status(
																			IStatus.ERROR,
																			EDCDebugger.PLUGIN_ID,
																			REQUEST_FAILED,
																			"Resume failed.",
																			null));
																}
																rm.done();
															}
														});
											}
										});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		/**
		 * Resume the context but the request monitor is only marked done when
		 * the context is suspended. (vs. regular resume()). <br>
		 * Note this method does not wait for suspended-event.
		 * 
		 * @param rm
		 */
		protected void resumeForStepping(final RequestMonitor rm) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }

			setStepping(true);

			flushCache(this);

			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						getTCFContext().resume(org.eclipse.tm.tcf.services.IRunControl.RM_RESUME, 0, new DoneCommand() {

							public void doneCommand(IToken token, final Exception error) {
								// do this in DSF executor thread.
								getExecutor().execute(new Runnable() {
									public void run() {
										handleTCFResumeDoneForStepping(
												"ResumeForStepping",
												error,
												rm);
									}
								});
							}
						});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		private void handleTCFResumeDoneForStepping(String command, Exception tcfError, RequestMonitor rm) {
			assert getExecutor().isInExecutorThread();
			
			String msg = command;
			if (tcfError == null) {
				msg += " succeeded.";
				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().trace(null, msg); }
				contextResumed(false);

				// we'll mark it as done when we get next
				// suspend event.
				assert steppingRM == null;
				steppingRM = rm;
			} else {
				msg += " failed.";
				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().trace(null, msg); }

				setStepping(false);
				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, msg, tcfError));
				rm.done();
			}
		}

		public void suspend(final RequestMonitor requestMonitor) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }
			if (isSnapshot())
			{
				Album.getAlbumBySession(getSession().getId()).stopPlayingSnapshots();				
			}
			else
			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						getTCFContext().suspend(new DoneCommand() {

							public void doneCommand(IToken token,
									Exception error) {
								if (EDCTrace.RUN_CONTROL_TRACE_ON) {
									EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this));
								}
								requestMonitor.done();
								if (EDCTrace.RUN_CONTROL_TRACE_ON) {
									EDCTrace.getTrace().traceExit(null);
								}
							}
						});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		public void terminate(final RequestMonitor requestMonitor) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }

			isTerminatingThanDisconnecting = true;

			clearBreakpointActionRM();

			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						getTCFContext().terminate(new DoneCommand() {

							public void doneCommand(IToken token, Exception error) {
								if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this)); }
								if (error != null) {
									requestMonitor.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, 
											"terminate() failed.", error));
								}
								
								requestMonitor.done();
								if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
							}
						});
					}
				});
			} else {	
				// Snapshots, for e.g., don't have a TCF RunControlContext, so just remove all the contexts recursively
				detachAllContexts();
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		protected ExecutionDMC getParent() {
			return parentExecutionDMC;
		}

		/**
		 * get latest PC register value of the context.
		 * 
		 * @return hex string of the PC value.
		 */
		public String getPC() {
			return latestPC;
		}
		
		/**
		 * Change cached PC value.
		 * This is only supposed to be used for move-to-line & resume-from-line commands.
		 *  
		 * @param pc
		 */
		private void setPC(String pc) {
			latestPC = pc;
		}

		/**
		 * Detach debugger from this context and all its children.
		 */
		public void detach(){
			isTerminatingThanDisconnecting = false;
			/**
			 * agent side detaching is invoked by Processes service.
			 * Here we just purge the context.
			 */
			purgeFromDebugger();
		}

		/**
		 * Purge this context and all its children and grand-children
		 * from debugger UI and internal data cache.
		 */
		public void purgeFromDebugger(){
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null); }

			for (ExecutionDMC e : getChildren())
				// recursively forget children first
				e.purgeFromDebugger();

			ExecutionDMC parent = getParent();
			if (parent != null)
				parent.removeChild(this);
			
			getSession().dispatchEvent(new ExitedEvent(this, isTerminatingThanDisconnecting), RunControl.this.getProperties());
			
			if (getRootDMC().getChildren().length == 0) 
				// no more contexts under debug, fire exitedEvent for the rootDMC which
				// will trigger shutdown of the debug session.
				// See EDCLaunch.eventDispatched(IExitedDMEvent e).
				// Whether the root is terminated or disconnected depends on whether 
				// the last context is terminated or disconnected.
				getSession().dispatchEvent(new ExitedEvent(getRootDMC(), isTerminatingThanDisconnecting), RunControl.this.getProperties());
			
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		/**
		 * Recursively marks all execution contexts as resumed
		 * @param dmc
		 */
		public void resumeAll(){
			contextResumed(true);			
			for (ExecutionDMC e : getChildren()){
				e.resumeAll();
			}
		}
		
		protected void contextResumed(boolean fireResumeEventNow) {
	        assert getExecutor().isInExecutorThread();

	        if (children.size() > 0) {
	        	// If it has kids (e.g. a process has threads), only need
	        	// to mark the kids as resumed.
		        for (ExecutionDMC e : children){
					e.contextResumed(fireResumeEventNow);
				}
		        return;
	        }
	        
	        if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { this, fireResumeEventNow })); }
			
			setIsSuspended(false);
			
			if (fireResumeEventNow)
				getSession().dispatchEvent(this.createResumedEvent(), RunControl.this.getProperties());
			else
				scheduleResumeEvent();

			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		/** 
		 * Schedule a task to run after some time which will
		 * notify platform that the context is running.
		 */
		private void scheduleResumeEvent() {
			countOfScheduledNotifications++;

			final ExecutionDMC dmc = this;
			
			Runnable notifyPlatformTask = new Runnable() {
				public void run() {
					/*
					 * Notify platform the context is running.
					 * 
					 * But don't do that if another such task is scheduled
					 * (namely current stepping is done within the RESUME_NOTIFICATION_DELAY and
					 * another stepping/resume is underway).
					 */
					countOfScheduledNotifications--;
					if (countOfScheduledNotifications == 0 && !isSuspended())
						getSession().dispatchEvent(dmc.createResumedEvent(), RunControl.this.getProperties());
				}};
			
			getExecutor().schedule(notifyPlatformTask, RESUME_NOTIFICATION_DELAY, TimeUnit.MILLISECONDS);
		}

		/**
		 * Execute a single instruction. Note the "rm" is marked done() only
		 * when we get the suspend event, not when we successfully send the
		 * command to TCF agent.
		 * 
		 * @param rm
		 */
		protected void singleStep(final boolean stepInto, final RequestMonitor rm) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this.getName())); }

			setStepping(true);

			flushCache(this);

			if (hasTCFContext())
			{
				Protocol.invokeLater(new Runnable() {
					public void run() {
						int mode = stepInto ? org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO
								: org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER;
						getTCFContext().resume(mode, 1, new DoneCommand() {
							public void doneCommand(IToken token, final Exception error) {
								// do this in DSF executor thread.
								getExecutor().execute(new Runnable() {
									public void run() {
										handleTCFResumeDoneForStepping("SingleStep", error, rm);
									}
								});
							}
						});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		/**
		 * Step out of the current function. Note the "rm" is marked done() only
		 * when we get the suspend event, not when we successfully send the
		 * command to TCF agent.
		 * 
		 * @param rm
		 */
		protected void stepOut(final RequestMonitor rm) {
			assert supportsStepMode(StepType.STEP_RETURN) : STEP_RETURN_NOT_SUPPORTED;

			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this.getName())); }

			setStepping(true);

			flushCache(this);

			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						getTCFContext()
								.resume(org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OUT,
										0, new DoneCommand() {

											public void doneCommand(
													IToken token,
													final Exception error) {
												// do this in DSF executor thread.
												getExecutor().execute(
														new Runnable() {
															public void run() {
																handleTCFResumeDoneForStepping(
																		"StepOut",
																		error,
																		rm);
															}
														});
											}
										});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		protected void stepRange(final boolean stepInto, final IAddress rangeStart, final IAddress rangeEnd,
				final RequestMonitor rm) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(this.getName())); }

			setStepping(true);

			flushCache(this);

			if (hasTCFContext()) {
				Protocol.invokeLater(new Runnable() {
					public void run() {
						int mode = stepInto ? org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO_RANGE
								: org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER_RANGE;
						Map<String, Object> params = new HashMap<String, Object>();
						params.put("RANGE_START", rangeStart.getValue());
						params.put("RANGE_END", rangeEnd.getValue());

						getTCFContext().resume(mode, 0, params, new DoneCommand() {

							public void doneCommand(IToken token,
									final Exception error) {
								// do this in DSF executor thread.
								getExecutor().execute(new Runnable() {
									public void run() {
										handleTCFResumeDoneForStepping(
												"StepRange", error, rm);
									}
								});
							}
						});
					}
				});
			}
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
		}

		/**
		 * set whether debugger is stepping in the context.
		 * 
		 * @param isStepping
		 */
		public void setStepping(boolean isStepping) {
			this.isStepping = isStepping;
		}

		/**
		 * @return whether debugger is stepping the context.
		 */
		public boolean isStepping() {
			return isStepping;
		}

		protected DMCSuspendedEvent createSuspendedEvent(StateChangeReason reason, Map<String, Object> properties) {
			return new SuspendedEvent(this, reason, properties);
		}

		/**
		 * Cache a suspendedEvent for this context. Note only one
		 * event will be cached at a time.
		 * 
		 * @param e
		 *            The event to cache. 
		 */
		private void cacheSuspendedEvent(DMCSuspendedEvent e) {
			cachedSuspendedEvent  = e;
		}
		
		/**
		 * The event should be used only once, thus this will clear
		 * the cache for that sake.
		 * @return
		 */
		private DMCSuspendedEvent getCachedSuspendedEvent() {
			DMCSuspendedEvent e = cachedSuspendedEvent;
			cachedSuspendedEvent = null;
			return e;
		}
		
		protected DMCResumedEvent createResumedEvent() {
			return new ResumedEvent(this);
		}

		public RunControlContext getTCFContext() {
			return tcfContext;
		}

		public boolean hasTCFContext() {
			return tcfContext != null;
		}

		@Override
		public Object getAdapter(@SuppressWarnings("rawtypes") Class adapterType) {
			if (adapterType.equals(ILogActionEnabler.class)) {
				Stack stackService = getService(Stack.class);
				IFrameDMContext[] frames;
				try {
					frames = stackService.getFramesForDMC(this, 0, 0);
					Expressions exprService = getService(Expressions.class);
					return new LogActionEnabler(exprService, frames[0]);
				} catch (CoreException e) {
					return null;
				}
			}
			if (adapterType.equals(IResumeActionEnabler.class)) {
				RunControl.ThreadExecutionDMC threadDMC
				  = DMContexts.getAncestorOfType(this, RunControl.ThreadExecutionDMC.class);
				return new ResumeActionEnabler(threadDMC);
			}
			if (adapterType.equals(AbstractEDCService.class)) {
				return RunControl.this;
			}
			return super.getAdapter(adapterType);
		}

	}

	public class ProcessExecutionDMC extends ExecutionDMC implements IContainerDMContext, IProcessDMContext,
			ISymbolDMContext, IBreakpointsTargetDMContext, IDisassemblyDMContext {

		public ProcessExecutionDMC(ExecutionDMC parent, Map<String, Object> properties, RunControlContext tcfContext) {
			super(parent, properties, tcfContext);
		}

		@Override
		public ExecutionDMC contextAdded(Map<String, Object> properties, RunControlContext tcfContext) {
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(properties)); }
			ThreadExecutionDMC newDMC = new ThreadExecutionDMC(this, properties, tcfContext);
			getSession().dispatchEvent(new StartedEvent(newDMC), RunControl.this.getProperties());
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(newDMC)); }
			return newDMC;
		}

		public ISymbolDMContext getSymbolDMContext() {
			return this;
		}

		@Override
		public void loadSnapshot(Element element) throws Exception {
			// load modules first, since this loads a stack which must consult modules and symbolics
			Modules modulesService = getService(Modules.class);
			modulesService.loadModulesForContext(this, element);
			super.loadSnapshot(element);
		}

		@Override
		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor)throws Exception {
			SubMonitor progress = SubMonitor.convert(monitor, 1000);
			progress.subTask(getName());
			Element contextElement = super.takeSnapshot(album, document, progress.newChild(500));
			Element modulesElement = document.createElement(EXECUTION_CONTEXT_MODULES);
			Modules modulesService = getService(Modules.class);

			IModuleDMContext[] modules = modulesService.getModulesForContext(this.getID());
			SubMonitor modulesMonitor = progress.newChild(500);
			modulesMonitor.setWorkRemaining(modules.length * 1000);
			modulesMonitor.subTask("Modules");
			for (IModuleDMContext moduleContext : modules) {
				ModuleDMC moduleDMC = (ModuleDMC) moduleContext;
				modulesElement.appendChild(moduleDMC.takeSnapshot(album, document, modulesMonitor.newChild(1000)));
			}
			
			contextElement.appendChild(modulesElement);
			return contextElement;
		}

		@Override
		public boolean canDetach() {
			// Can detach from a process unless we're part of a snapshot.
			return hasTCFContext();
		}

		@Override
		public boolean canStep() {
			// can't step a process.
			return false;
		}
	}

	public class ThreadExecutionDMC extends ExecutionDMC implements IThreadDMContext, IDisassemblyDMContext {

		public ThreadExecutionDMC(ExecutionDMC parent, Map<String, Object> properties, RunControlContext tcfContext) {
			super(parent, properties, tcfContext);
			if (EDCTrace.RUN_CONTROL_TRACE_ON) { 
				EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { parent, properties })); 
				EDCTrace.getTrace().traceExit(null);
			}
		}

		public ISymbolDMContext getSymbolDMContext() {
			return DMContexts.getAncestorOfType(this, ISymbolDMContext.class);
		}

		@Override
		public void loadSnapshot(Element element) throws Exception {
			super.loadSnapshot(element);
			Registers regService = getService(Registers.class);
			regService.loadGroupsForContext(this, element);

			Stack stackService = getService(Stack.class);
			NodeList frameElements = element.getElementsByTagName(EXECUTION_CONTEXT_FRAMES);
			for (int i = 0; i < frameElements.getLength(); i++) {
				Element frameElement = (Element) frameElements.item(i);
				stackService.loadFramesForContext(this, frameElement);
			}

			getSession().dispatchEvent(
					createSuspendedEvent(StateChangeReason.EXCEPTION, new HashMap<String, Object>()),
					RunControl.this.getProperties());
		}

		@Override
		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor)throws Exception {
			SubMonitor progress = SubMonitor.convert(monitor, 1000);
			progress.subTask(getName());
			Element contextElement = super.takeSnapshot(album, document, progress.newChild(100));
			Element registersElement = document.createElement(EXECUTION_CONTEXT_REGISTERS);
			Registers regService = getService(Registers.class);
			
			IRegisterGroupDMContext[] regGroups = regService.getGroupsForContext(this);
			SubMonitor registerMonitor = progress.newChild(300);
			registerMonitor.setWorkRemaining(regGroups.length * 1000);
			registerMonitor.subTask("Registers");
			for (IRegisterGroupDMContext registerGroupDMContext : regGroups) {
				RegisterGroupDMC regDMC = (RegisterGroupDMC) registerGroupDMContext;
				registersElement.appendChild(regDMC.takeSnapshot(album, document, registerMonitor.newChild(1000)));
			}
			
			contextElement.appendChild(registersElement);

			Element framesElement = document.createElement(EXECUTION_CONTEXT_FRAMES);
			Stack stackService = getService(Stack.class);
			Expressions expressionsService = getService(Expressions.class);

			IFrameDMContext[] frames = stackService.getFramesForDMC(this, 0, IStack.ALL_FRAMES);
			SubMonitor framesMonitor = progress.newChild(600);
			framesMonitor.setWorkRemaining(frames.length * 2000);
			framesMonitor.subTask("Stack Frames");
			for (IFrameDMContext frameDMContext : frames) {
				StackFrameDMC frameDMC = (StackFrameDMC) frameDMContext;
				
				// Get the local variables for each frame
				IVariableDMContext[] variables = frameDMC.getLocals();
				SubMonitor variablesMonitor = framesMonitor.newChild(1000);
				variablesMonitor.setWorkRemaining(variables.length * 10);
				variablesMonitor.subTask("Variables");
				for (IVariableDMContext iVariableDMContext : variables) {
					VariableDMC varDMC = (VariableDMC) iVariableDMContext;
					IExpressionDMContext expression = expressionsService.createExpression(frameDMContext, varDMC.getName());
					boolean wasEnabled = FormatExtensionManager.instance().isEnabled();
					FormatExtensionManager.instance().setEnabled(true);
					expressionsService.loadExpressionValues(expression, Album.getVariableCaptureDepth());
					FormatExtensionManager.instance().setEnabled(wasEnabled);
					variablesMonitor.worked(10);
					variablesMonitor.subTask("Variables - " + varDMC.getName());
				}
				
				framesElement.appendChild(frameDMC.takeSnapshot(album, document, framesMonitor.newChild(1000)));
			}
			contextElement.appendChild(framesElement);

			return contextElement;
		}

		@Override
		public ExecutionDMC contextAdded(Map<String, Object> properties, RunControlContext tcfContext) {
			assert (false);
			return null;
		}

		@Override
		public boolean canDetach() {
			// Cannot detach from a thread.
			return false;
		}

		@Override
		public boolean canStep() {
			if (isSuspended()) {
				synchronized (properties) {
					return !RunControl.getProperty(properties, PROP_DISABLE_STEPPING, false);
				}
			}
			
			return false;
		}
	}

	/**
	 * Context representing a program running on a bare device without OS, which
	 * can also be the boot-up "process" of an OS.
	 * <p>
	 * It's like a thread context as it has its registers and stack frames, but
	 * also like a process as it has modules associated with it. Currently we
	 * set it as an IProcessDMContext so that it appears as a ContainerVMNode in
	 * debug view. See LaunchVMProvider for more. Also it's treated like a
	 * process in
	 * {@link Processes#getProcessesBeingDebugged(IDMContext, DataRequestMonitor)}
	 */
	public class BareDeviceExecutionDMC extends ThreadExecutionDMC 
				implements IProcessDMContext, ISymbolDMContext, IBreakpointsTargetDMContext {

		public BareDeviceExecutionDMC(ExecutionDMC parent,
				Map<String, Object> properties, RunControlContext tcfContext) {
			super(parent, properties, tcfContext);
			assert !RunControl.getProperty(properties, PROP_IS_CONTAINER, true);
		}

		@Override
		protected DMCSuspendedEvent createSuspendedEvent(StateChangeReason reason, Map<String, Object> properties) {
			return new ContainerSuspendedEvent(this, reason, properties);
		}

		@Override
		protected DMCResumedEvent createResumedEvent() {
			return new ContainerResumedEvent(this);
		}

		@Override
		public boolean canDetach() {
			return true;
		}
		
	}
	
	public class RootExecutionDMC extends ExecutionDMC implements ISourceLookupDMContext {

		public RootExecutionDMC(Map<String, Object> props) {
			super(null, props, null);
		}

		@Override
		public ExecutionDMC contextAdded(Map<String, Object> properties, RunControlContext tcfContext) {
			ExecutionDMC newDMC;
			// If the new context being added under root is a container context,
			// we treat it as a Process, otherwise a bare device program context.
			//
			if (RunControl.getProperty(properties, PROP_IS_CONTAINER, true))
				newDMC = new ProcessExecutionDMC(this, properties, tcfContext);
			else
				newDMC = new BareDeviceExecutionDMC(this, properties, tcfContext);
			
			getSession().dispatchEvent(new StartedEvent(newDMC), RunControl.this.getProperties());
			return newDMC;
		}

		public ISymbolDMContext getSymbolDMContext() {
			return null;
		}

		@Override
		public boolean canDetach() {
			return false;
		}

		@Override
		public boolean canStep() {
			return false;
		}
	}

	public class ResumeActionEnabler implements IResumeActionEnabler {

		ExecutionDMC executionDMC;

		public ResumeActionEnabler(final ExecutionDMC exeDMC) {
			executionDMC = exeDMC;
		}

		public void resume() throws Exception {
			RunControl.this.resume(executionDMC, new RequestMonitor(getExecutor(), null));
		}

	}

	private static final String EXECUTION_CONTEXTS = "execution_contexts";

	private org.eclipse.tm.tcf.services.IRunControl tcfRunService;
	private RootExecutionDMC rootExecutionDMC;
	private final Map<String, ExecutionDMC> dmcsByID = new HashMap<String, ExecutionDMC>();
	
	public RunControl(DsfSession session) {
		super(session, new String[] { 
				IRunControl.class.getName(), 
				IRunControl2.class.getName(), 
				RunControl.class.getName(),
				ISnapshotContributor.class.getName() });
		initializeRootExecutionDMC();
	}

	private void initializeRootExecutionDMC() {
		HashMap<String, Object> props = new HashMap<String, Object>();
		props.put(IEDCDMContext.PROP_ID, "root");
		rootExecutionDMC = new RootExecutionDMC(props);
	}

	public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
		rm.setData(((ExecutionDMC) context).isSuspended() ? Boolean.TRUE : Boolean.FALSE);
		rm.done();
	}

	public void canStep(IExecutionDMContext context, StepType stepType, DataRequestMonitor<Boolean> rm) {
		rm.setData(((ExecutionDMC) context).canStep() ? Boolean.TRUE : Boolean.FALSE);
		rm.done();
	}

	public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
		if (isSnapshot())
			rm.setData(Album.getAlbumBySession(getSession().getId()).isPlayingSnapshots());
		else
			rm.setData(((ExecutionDMC) context).isSuspended() ? Boolean.FALSE : Boolean.TRUE);
		rm.done();
	}

	public void getExecutionContexts(IContainerDMContext c, DataRequestMonitor<IExecutionDMContext[]> rm) {
		if (c instanceof ProcessExecutionDMC) {
			ProcessExecutionDMC edmc = (ProcessExecutionDMC) c;
			IEDCExecutionDMC[] threads = edmc.getChildren();
			IExecutionDMContext[] threadArray = new IExecutionDMContext[threads.length];
			System.arraycopy(threads, 0, threadArray, 0, threads.length);
			rm.setData(threadArray);
		}
		rm.done();
	}

	public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm) {
		if (dmc instanceof ExecutionDMC) {
			ExecutionDMC exedmc = (ExecutionDMC) dmc;
			if (exedmc.isSuspended()) {
				rm.setData(new ExecutionData(exedmc.getStateChangeReason(), exedmc.getStateChangeDetails()));
			} else {
				rm.setData(new ExecutionData(StateChangeReason.UNKNOWN, null));
			}
		} else
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE,
					"Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
		rm.done();
	}

	public boolean isStepping(IExecutionDMContext context) {
		if (context instanceof ExecutionDMC) {
			ExecutionDMC exedmc = (ExecutionDMC) context;
			return exedmc.isStepping();
		}
		return false;
	}

	public boolean isSuspended(IExecutionDMContext context) {
		if (context instanceof ExecutionDMC) {
			ExecutionDMC exedmc = (ExecutionDMC) context;
			return exedmc.isSuspended();
		}
		return false;
	}

	/**
	 * Preprocessing for suspend event. This is done before we broadcast the
	 * suspend event across the debugger. Here's what's done in the
	 * preprocessing by default: <br>
	 * 1. Adjust PC after control hits a software breakpoint where the PC
	 * points at the byte right after the breakpoint instruction. This is to
	 * move PC back to the address of the breakpoint instruction.<br>
	 * 2. If we stops at a breakpoint, evaluate condition of the breakpoint
	 * and determine if we should ignore the suspend event and resume or
	 * should honor the suspend event and sent it up the ladder.
	 * <p>
	 * Subclass can override this method to add their own special preprocessing,
	 * while calling super implementation to carry out the default common.
	 * <p>
	 * This must be called in DSF executor thread.
	 * 
	 * @param pc
	 *            program pointer value from the event, in the format of
	 *            big-endian hex string. Can be null.
	 * @param drm
	 *            DataRequestMonitor whose result indicates whether to honor
	 *            the suspend.
	 */
	protected void preprocessOnSuspend(final ExecutionDMC dmc, final String pc,
			final DataRequestMonitor<Object> drm) {
		
		assert getExecutor().isInExecutorThread();

		asyncExec(new Runnable() {
			
			public void run() {
				try {
					Breakpoints bpService = getService(Breakpoints.class);
					Registers regService = getService(Registers.class);
					String pcString = pc;

					if (pc == null) {
						// read PC register
						pcString = regService.getRegisterValue(dmc, getTargetEnvironmentService().getPCRegisterID());
					}

					dmc.setPC(pcString);

					// This check is to speed up handling of suspend due to
					// other reasons such as "step".
					// The TCF agents should always report the
					// "stateChangeReason" as BREAKPOINT when a breakpoint
					// is hit.

					if (dmc.getStateChangeReason() != StateChangeReason.BREAKPOINT) {
						drm.setData(true);
						drm.done();
						return;
					}

					BreakpointDMData bp;
					if (!bpService.usesTCFBreakpointService()) {
						// generic software breakpoint is used.
						// We need to move PC back to the breakpoint
						// instruction.

						long pcValue
						  = Long.valueOf(pcString, 16) 
							- getTargetEnvironmentService()
								.getBreakpointInstruction(dmc, new Addr64(pcString, 16))
								.length;
						pcString = Long.toHexString(pcValue);

						bp = bpService.findBreakpoint(new Addr64(pcString, 16)); 

						// Stopped but not due to breakpoint set by debugger.
						// For instance, some Windows DLL has "int 3"
						// instructions in it.
						if (bp != null) {
							// Now adjust PC register.
							regService.writeRegister(dmc, getTargetEnvironmentService().getPCRegisterID(), pcString);
							dmc.setPC(pcString);
						}
					} else {
						bp = bpService.findUserBreakpoint(new Addr64(pcString, 16));						
					}

					// check if a conditional breakpoint (must be a user bp) is hit
					//
					if (bp != null) {
						// evaluate the condition
						bpService.evaluateBreakpointCondition(dmc, bp, drm);
					} else {
						drm.setData(true);
						drm.done();
					}
				} catch (CoreException e) {
					Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
					EDCDebugger.getMessageLogger().log(s);
					drm.setStatus(s);
					drm.done();
				}
				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(drm.getData())); }
			}
			
		}, drm);
	}

	public void resume(IExecutionDMContext context, final RequestMonitor rm) {
		if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(MessageFormat.format("resume context {0}", context))); }

		if (!(context instanceof ExecutionDMC)) {
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, MessageFormat.format(
					"The context [{0}] is not a recognized execution context.", context), null));
			rm.done();
		}

		final ExecutionDMC dmc = (ExecutionDMC) context;

		prepareToRun(dmc, new DataRequestMonitor<Boolean>(getExecutor(), rm) {

			@Override
			protected void handleSuccess() {
				dmc.resume(rm);
				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(MessageFormat.format("resume() done on context {0}", dmc))); }
			}
		});
	}

	/**
	 * Prepare for resuming or stepping by <br>
	 * - executing current instruction if PC is at a breakpoint.
	 * 
	 * @param dmc
	 *            - the execution context, usually a thread.
	 * @param drm
	 *            - data request monitor which will contain boolean value on
	 *            done indicating whether an instruction is executed during the
	 *            preparation.
	 */
	private void prepareToRun(final ExecutionDMC dmc, final DataRequestMonitor<Boolean> drm) {
		// if there are actions associated with the last breakpoint,
		// cancel the RM (and the action list for them) and resume
		dmc.clearBreakpointActionRM();

		// If there is breakpoint at current PC, remove it => Single step =>
		// Restore it.

		final Breakpoints bpService = getService(Breakpoints.class);
		if (bpService.usesTCFBreakpointService()) {
			// It's currently required that the agent can single-step past a breakpoint 
			// if it offers TCF breakpoints service. It's not a solid requirement but just
			// nice for the sake of stepping performance.
			drm.setData(false);
			drm.done();
			return;
		}
		
		String latestPC = dmc.getPC();

		if (latestPC != null) {
			final BreakpointDMData bp = bpService.findUserBreakpoint(new Addr64(latestPC, 16));
			if (bp != null) {
				bpService.disableBreakpoint(bp, new RequestMonitor(getExecutor(), drm) {

					@Override
					protected void handleSuccess() {
						// Now step over the instruction
						//
						dmc.setSuspendEventsEnabled(false);
						dmc.singleStep(true, new RequestMonitor(getExecutor(), drm) {
							@Override
							protected void handleCompleted() {
								dmc.setSuspendEventsEnabled(true);
								super.handleCompleted();
							}

							@Override
							protected void handleSuccess() {
								// At this point the single instruction
								// execution should be done
								// and the context being suspended.
								//
								drm.setData(true); // indicates an instruction
								// is executed

								// Now restore the breakpoint.
								bpService.enableBreakpoint(bp, drm);
							}
						});
					}
				});
			} else { // no breakpoint at PC
				drm.setData(false);
				drm.done();
			}
		} else {
			drm.setData(false);
			drm.done();
		}
	}

	// This is a coarse timer on stepping for internal use.
	// When needed, turn it on and watch output in console.
	//
	private static long steppingStartTime = 0;
	public static boolean timeStepping() {
		return false;
	}
	
	public static long getSteppingStartTime() {
		return steppingStartTime;
	}
	
	public void step(final IExecutionDMContext context, final StepType outerStepType, final RequestMonitor rm) {
		
		asyncExec(new Runnable() {
			
			public void run() {
				StepType stepType = outerStepType;
				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(MessageFormat.format("{0} context {1}", stepType, context))); }

				if (!(context instanceof ExecutionDMC)) {
					rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, MessageFormat.format(
							"The context [{0}] is not a recognized execution context.", context), null));
					rm.done();
				}

				if (timeStepping())
					steppingStartTime = System.currentTimeMillis();
				
				final ExecutionDMC dmc = (ExecutionDMC) context;

				dmc.setStepping(true);

				IAddress pcAddress = null;

				if (dmc.getPC() == null) { // PC is even unknown, can only do
					// one-instruction step.
					stepType = StepType.INSTRUCTION_STEP_INTO;
				} else
					pcAddress = new Addr64(dmc.getPC(), 16);

				// For step-out (step-return), no difference between source level or
				// instruction level.
				//
				if (stepType == StepType.STEP_RETURN)
					stepType = StepType.INSTRUCTION_STEP_RETURN;

				// Source level stepping request.
				// 
				if (stepType == StepType.STEP_OVER || stepType == StepType.STEP_INTO) {
					IEDCModules moduleService = getService(Modules.class);

					ISymbolDMContext symCtx = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);

					IEDCModuleDMContext module = moduleService.getModuleByAddress(symCtx, pcAddress);

					// Check if there is source info for PC address.
					//
					if (module != null) {
						IEDCSymbolReader reader = module.getSymbolReader();
						assert pcAddress != null;
						if (reader != null) {
							IAddress linkAddress = module.toLinkAddress(pcAddress);
							IModuleLineEntryProvider lineEntryProvider
							  = reader.getModuleScope().getModuleLineEntryProvider();
							ILineEntry line = lineEntryProvider.getLineEntryAtAddress(linkAddress);
							if (line != null) {
								// get runtime addresses of the line boundaries.
								IAddress endAddr = getAddressForNextLine(dmc, pcAddress, module,
										linkAddress, lineEntryProvider, line,
										stepType == StepType.STEP_OVER);

								/*
								 * It's possible that PC is larger than startAddr
								 * (e.g. user does a few instruction level stepping
								 * then switch to source level stepping; or when we
								 * just step out a function). We just parse and
								 * stepping instructions within [pcAddr, endAddr)
								 * instead of all those within [startAddr, endAddr).
								 * One possible problem with the solution is when
								 * control jumps from within [pcAddress, endAddr) to
								 * somewhere within [startAddr, pcAddress), the
								 * stepping would stop at somewhere within
								 * [startAddr, pcAddress) instead of outside of the
								 * [startAddr, endAddr). But that case is rare (e.g.
								 * a source line contains a bunch of statements) and
								 * that "problem" is not unacceptable as user could
								 * just keep stepping or set a breakpoint and run.
								 * 
								 * We can overcome the problem but that would incur
								 * much more complexity in the stepping code and
								 * brings down the stepping speed.
								 * ........................ 08/30/2009
								 */

								stepAddressRange(dmc, stepType == StepType.STEP_INTO, pcAddress, endAddr, rm);

								if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null, "source level stepping."); }
								return;
							}
						}
					}

					// No source found, fall back to instruction level step.
					if (stepType == StepType.STEP_INTO)
						stepType = StepType.INSTRUCTION_STEP_INTO;
					else
						stepType = StepType.INSTRUCTION_STEP_OVER;
				}

				// instruction level step
				// 
				if (stepType == StepType.INSTRUCTION_STEP_OVER)
					stepOverOneInstruction(dmc, pcAddress, rm);
				else if (stepType == StepType.INSTRUCTION_STEP_INTO)
					stepIntoOneInstruction(dmc, rm);
				else if (stepType == StepType.INSTRUCTION_STEP_RETURN)
					stepOut(dmc, pcAddress, rm);

				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
			}
		}, rm);
	}

	private void stepOut(final ExecutionDMC dmc, IAddress pcAddress, final RequestMonitor rm) {

		if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "Step out from address " + pcAddress.toHexAddressString()); }

		if (dmc.supportsStepMode(StepType.STEP_RETURN)) {
			dmc.stepOut(rm);
			return;
		}

		Stack stackService = getService(Stack.class);
		IFrameDMContext[] frames;
		try {
			frames = stackService.getFramesForDMC(dmc, 0, 1);
		} catch (CoreException e) {
			Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
			EDCDebugger.getMessageLogger().log(s);
			rm.setStatus(s);
			rm.done();
			return;
		}
		if (frames.length <= 1) {
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
					"Cannot step out as no caller frame is available.", null));
			rm.done();
			return;
		}

		if (handleSteppingOutOfInLineFunctions(dmc, frames, rm))
			return;

		final IAddress stepToAddress = ((StackFrameDMC) frames[1]).getInstructionPtrAddress();
		
		final Breakpoints bpService = getService(Breakpoints.class);

		prepareToRun(dmc, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {

				boolean goon = true;

				if (getData() == true) {
					// one instruction has been executed
					IAddress newPC = new Addr64(dmc.getPC(), 16);

					// And we already stepped out (that instruction is return
					// instruction).
					//
					if (newPC.equals(stepToAddress)) {
						goon = false;
					}
				}

				if (goon) {
					bpService.setTempBreakpoint(dmc, stepToAddress, new RequestMonitor(getExecutor(), rm) {
						@Override
						protected void handleSuccess() {
							dmc.resumeForStepping(rm);
						}
					});
				} else {
					// Stepping finished after prepareToRun().
					DMCSuspendedEvent e = dmc.getCachedSuspendedEvent();
					if (e != null)
						getSession().dispatchEvent(e, RunControl.this.getProperties());
					
					rm.done();
				}
			}
		});
	}

	/**
	 * handle module load event. A module is an executable file
	 * or a library (e.g. DLL or shared lib).
	 * Allow subclass to override for special handling if needed.
	 * This must be called in DSF dispatch thread.
	 * 
	 * @param dmc
	 * @param moduleProperties
	 */
	protected void handleModuleLoadedEvent(IEDCExecutionDMC dmc, Map<String, Object> moduleProperties) {
		ISymbolDMContext symbolContext = dmc.getSymbolDMContext();

		if (symbolContext != null) {
			Modules modulesService = getService(Modules.class);
			modulesService.moduleLoaded(symbolContext, dmc, moduleProperties);
		}
	}
		
	/**
	 * handle module unload event. A module is an executable file
	 * or a library (e.g. DLL or shared lib).
	 * Allow subclass to override for special handling if needed.
	 * This must be called in DSF dispatch thread.
	 * 
	 * @param dmc
	 * @param moduleProperties
	 */
	protected void handleModuleUnloadedEvent(IEDCExecutionDMC dmc, Map<String, Object> moduleProperties) {
		ISymbolDMContext symbolContext = dmc.getSymbolDMContext();

		if (symbolContext != null) {
			Modules modulesService = getService(Modules.class);
			modulesService.moduleUnloaded(symbolContext, dmc, moduleProperties);
		}
	}

	private boolean handleSteppingOutOfInLineFunctions(final ExecutionDMC dmc,
			IFrameDMContext[] frames, final RequestMonitor rm) {

		assert frames.length > 1 && frames[0] instanceof StackFrameDMC;

		StackFrameDMC currentFrame = ((StackFrameDMC) frames[0]);

		IEDCModuleDMContext module = currentFrame.getModule();
		if (module != null) {
			IFunctionScope func = currentFrame.getFunctionScope();
			// if inline ...
			if (func != null && (func.getParent() instanceof IFunctionScope)) {

				// ... but if PC is at beginning of function, then act like not in inline
				// (i.e. step-out as though standing at call to any non-inline function)
				if (currentFrame.isInlineShouldBeHidden(null))
					return false;

				// ... or if PC at at high-address, that means we're actually done with it
				IAddress functRuntimeHighAddr = module.toRuntimeAddress(func.getHighAddress());
				IAddress frameInstrPtr = currentFrame.getInstructionPtrAddress();
				if (functRuntimeHighAddr.equals(frameInstrPtr))
					return false;
		
				// getting here means treat the line as a regular line to step over
				stepAddressRange(dmc, false, frameInstrPtr, functRuntimeHighAddr,
								 new RequestMonitor(getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						rm.done();
					}});
		
				return true;
			}
		}
		return false;
	}

	/**
	 * check if the instruction at PC is a subroutine call. If yes, set a
	 * breakpoint after it and resume; otherwise just execute one instruction.
	 * 
	 * @param dmc
	 * @param pcAddress
	 * @param rm
	 */
	private void stepOverOneInstruction(final ExecutionDMC dmc, final IAddress pcAddress, final RequestMonitor rm) {

		if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, "address " + pcAddress.toHexAddressString()); }

		if (dmc.supportsStepMode(StepType.INSTRUCTION_STEP_OVER)) {
			dmc.singleStep(false, rm);
			return;
		}

		ITargetEnvironment env = getTargetEnvironmentService();
		final IDisassembler disassembler = (env != null) ? env.getDisassembler() : null;
		if (disassembler == null) {
			rm.setStatus(Disassembly.statusNoDisassembler());
			rm.done();
			return;
		}

		Memory memoryService = getService(Memory.class);
		IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(dmc, IMemoryDMContext.class);

		// We need to get the instruction at the PC. We have to
		// retrieve memory bytes for longest instruction.
		@SuppressWarnings("null") // (env == null) -> (disassembler == null) -> return above
		int maxInstLength = env.getLongestInstructionLength();

		// Note this memory read will give us memory bytes with
		// debugger breakpoints removed, which is just what we want.
		memoryService.getMemory(mem_dmc, pcAddress, 0, 1, maxInstLength,
								new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				ByteBuffer codeBuf = Disassembly.translateMemoryBytes(getData(), pcAddress, rm);
				if (codeBuf == null) {
					return;	// rm status set in checkMemoryBytes()
				}

				IDisassemblyDMContext dis_dmc
				  = DMContexts.getAncestorOfType(dmc, IDisassemblyDMContext.class);
				Map<String, Object> options = new HashMap<String, Object>();
				options.put(IDisassemblerOptions.ADDRESS_IS_PC, 1);
				IDisassembledInstruction inst;
				try {
					inst = disassembler.disassembleOneInstruction(pcAddress, codeBuf, options, dis_dmc);
				} catch (CoreException e) {
					rm.setStatus(e.getStatus());
					rm.done();
					return;
				}

				final boolean isSubroutineCall = inst.getJumpToAddress() != null
						&& inst.getJumpToAddress().isSubroutineAddress();
				final IAddress nextInstructionAddress = pcAddress.add(inst.getSize());

				stepIntoOneInstruction(dmc, new RequestMonitor(getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						if (!isSubroutineCall)
							rm.done();
						else {
							// If current instruction is subroutine call, set a
							// temp
							// breakpoint at next instruction and resume ...
							//
							Breakpoints bpService = getService(Breakpoints.class);
							bpService.setTempBreakpoint(dmc, nextInstructionAddress,
														new RequestMonitor(getExecutor(), rm) {
								@Override
								protected void handleSuccess() {
									dmc.resumeForStepping(rm);
								}
							});
						}
					}
				});
			}
		});
	}

	/**
	 * Step into or over an address range. Note the startAddr is also the PC
	 * value.
	 * 
	 * @param dmc
	 * @param stepIn
	 *            - whether to step-in.
	 * @param startAddr
	 *            - also the PC register value.
	 * @param endAddr
	 * @param rm
	 *            - marked done after the stepping is over and context is
	 *            suspended again.
	 */
	private void stepAddressRange(final ExecutionDMC dmc, final boolean stepIn, final IAddress startAddr,
			final IAddress endAddr, final RequestMonitor rm) {
		if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, MessageFormat.format("address range [{0},{1})", startAddr.toHexAddressString(), endAddr.toHexAddressString())); }

		if (dmc.supportsStepMode(stepIn ? StepType.STEP_INTO : StepType.STEP_OVER)) {
			dmc.stepRange(stepIn, startAddr, endAddr, rm);
			return;
		}

		ITargetEnvironment env = getTargetEnvironmentService();
		final IDisassembler disassembler = (env != null) ? env.getDisassembler() : null;
		if (disassembler == null) {
			rm.setStatus(Disassembly.statusNoDisassembler());
			rm.done();
			return;
		}

		final Memory memoryService = getService(Memory.class);
		IMemoryDMContext mem_dmc = DMContexts.getAncestorOfType(dmc, IMemoryDMContext.class);

		int memSize = startAddr.distanceTo(endAddr).intValue();

		final IAddress pcAddress = startAddr;

		// Note this memory read will give us memory bytes with
		// debugger breakpoints removed, which is just what we want.
		memoryService.getMemory(mem_dmc, startAddr, 0, 1, memSize,
								new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				ByteBuffer codeBuf = Disassembly.translateMemoryBytes(getData(), startAddr, rm);
				if (codeBuf == null) {
					return;	// rm status set in checkMemoryBytes()
				}

				IDisassemblyDMContext dis_dmc
				  = DMContexts.getAncestorOfType(dmc, IDisassemblyDMContext.class);

				Map<String, Object> options = new HashMap<String, Object>();

				List<IDisassembledInstruction> instList;
				try {
					instList
					  = disassembler.disassembleInstructions(startAddr, endAddr, codeBuf,
							  								 options, dis_dmc);
				} catch (CoreException e) {
					rm.setStatus(e.getStatus());
					rm.done();
					return;
				}

				// Now collect all possible stop points
				//
				final List<IAddress> stopPoints = new ArrayList<IAddress>();
				final List<IAddress> runToAndCheckPoints = new ArrayList<IAddress>();
				boolean insertBPatRangeEnd = true;

				for (IDisassembledInstruction inst : instList) {
					final IAddress instAddr = inst.getAddress();
					if (insertBPatRangeEnd == false)
						insertBPatRangeEnd = true;
					IJumpToAddress jta = inst.getJumpToAddress();
					if (jta == null)
						continue;
					
					// the instruction is a control-change instruction
					//
					if (!jta.isImmediate()) {

						if (inst.getAddress().equals(pcAddress)) {
							// Control is already at the instruction, evaluate
							// it.
							//
							String expr = (String) jta.getValue();
							if (expr.equals(JumpToAddress.EXPRESSION_RETURN_FAR)
									|| expr.equals(JumpToAddress.EXPRESSION_RETURN_NEAR)
									|| expr.equals(JumpToAddress.EXPRESSION_LR)) {
								// The current instruction is return instruction. Just execute it
								// to step-out and we are done with the stepping. This way we avoid
								// looking for return address from caller stack frame which may not
								// even available.
								// Is it possible that the destination address of the step-out
								// is still within the [startAddr, endAddr)range ? In theory
								// yes, but in practice it means one source line has several
								// function bodies in it, who would do that?
								//
								stepIntoOneInstruction(dmc, rm);
								return;
							}
							// evaluate the address expression

							if (!jta.isSubroutineAddress() || stepIn)
							{
								IAddressExpressionEvaluator evaluator = getTargetEnvironmentService()
								.getAddressExpressionEvaluator();
								if (evaluator == null) {
									rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
											"No evaluator for address expression yet.", null));
									rm.done();
									return;
								}

								Registers regService = getService(Registers.class);

								IAddress addr;
								try {
									addr = evaluator.evaluate(dmc, expr, regService, memoryService);
								} catch (CoreException e) {
									rm.setStatus(e.getStatus());
									rm.done();
									return;
								}
								// don't add an address if we already have it
								if (!stopPoints.contains(addr))
									stopPoints.add(addr);
							}
						} else {
							// we must run to this instruction first
							//
							/*
							 * What if control would skip (jump-over) this
							 * instruction within the [startAddr, endAddr) range
							 * ? So we should go on collecting stop points from
							 * the remaining instructions in the range and then
							 * do our two-phase stepping (see below)
							 */
							if (!runToAndCheckPoints.contains(instAddr))
								runToAndCheckPoints.add(instAddr);
						}
					} else { // "jta" is immediate address.

						IAddress jumpAddress = (IAddress) jta.getValue();

						if (jta.isSoleDestination()) {
							if (jta.isSubroutineAddress()) {
								// is subroutine call
								if (stepIn && !stopPoints.contains(jumpAddress)) {
									stopPoints.add(jumpAddress);
									// no need to check remaining instructions
									// !! Wrong. Control may jump over (skip)this instruction
									// within the [startAddr, endAddr) range, so we still need
									// to parse instructions after this instruction.
									// break;
								} else {
									// step over the call instruction. Just stop
									// at next instruction.
									// nothing to do.
								}
							} else {
								// Unconditional jump instruction
								// ignore jump within the address range
								if (!(startAddr.compareTo(jumpAddress) <= 0 && jumpAddress.compareTo(endAddr) < 0)) {
									insertBPatRangeEnd = false;
									if (!stopPoints.contains(jumpAddress))
										stopPoints.add(jumpAddress);
								}
							}
						} else {
							// conditional jump
							// ignore jump within the address range
							if (!(startAddr.compareTo(jumpAddress) <= 0 && jumpAddress.compareTo(endAddr) < 0) 
														&& !stopPoints.contains(jumpAddress))
							{
								stopPoints.add(jumpAddress);
							}
						}
					}
				} // end of parsing instructions

				// need a temp breakpoint at the "endAddr".
				if (insertBPatRangeEnd && !stopPoints.contains(endAddr))
					stopPoints.add(endAddr);

				if (runToAndCheckPoints.size() > 0) {
					// Now do our two-phase stepping.
					//

					if (runToAndCheckPoints.size() > 1) {
						/*
						 * Wow, there are two control-change instructions in the
						 * range that requires run-to-check (let's call them RTC
						 * point). In theory the stepping might fail (not stop
						 * as desired) in such case: When we try to run to the
						 * first RTC, the control may skip the first RTC and run
						 * to second RTC (note we don't know the stop points of
						 * the second RTC yet) and run out of the range and be
						 * gone with the wind...
						 * 
						 * There is no way we can solve the problem. Good thing
						 * is, in practice is the case even possible ?
						 */
						// Log (and show it, get rid of the "show" part after
						// tons of test) warning here.
						EDCDebugger.getMessageLogger().log(
								new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,
										MessageFormat.format(
												"More than one run-to-check points in the address range [{0},{1}). Stepping might fail.",
												startAddr.toHexAddressString(), endAddr.toHexAddressString())));
					}

					// ------------ Phase 1: run to the first RTC.
					//
					// recursive call
					stepAddressRange(dmc, stepIn, startAddr, runToAndCheckPoints.get(0), new RequestMonitor(
							getExecutor(), rm) {
						@Override
						protected void handleSuccess() {
							IAddress newPC = new Addr64(dmc.getPC(), 16);

							boolean doneWithStepping = false;
							for (IAddress addr : stopPoints)
								if (newPC.equals(addr)) {
									// done with the stepping
									doneWithStepping = true; 
									break;
								}

							Breakpoints bpService = getService(Breakpoints.class);
							if (bpService.findUserBreakpoint(newPC) != null) { 
								// hit a user bp
								doneWithStepping = true;
							}

							if (!doneWithStepping)
								// -------- Phase 2: run to the "endAddr".
								//
								stepAddressRange(dmc, stepIn, newPC, endAddr, rm); // Recursive
							// call
							else
								rm.done();
						}
					});
				} else { 
					// no RTC points, set temp breakpoints at stopPoints
					// and run...

					// Make sure we step over breakpoint at PC (if any)
					//
					prepareToRun(dmc, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
						@Override
						protected void handleSuccess() {

							boolean goon = true;

							Breakpoints bpService = getService(Breakpoints.class);

							if (getData() == true) {
								// one instruction has been executed
								IAddress newPC = new Addr64(dmc.getPC(), 16);

								if (bpService.findUserBreakpoint(newPC) != null) {
									// hit a user breakpoint. Stepping finishes.
									goon = false;
								} else {
									// Check if we finish the stepping by
									// checking the newPC against
									// our stopPoints instead of checking if
									// newPC is outside of [startAddr, endAddr)
									// so that such case would not fail: step
									// over this address range:
									//
									// 0x10000 call ...(a user bp is set here)
									// 0x10004 ...
									// 0x1000c ...
									// 
									//
									for (IAddress addr : stopPoints)
										if (newPC.equals(addr)) {
											goon = false;
											break;
										}
								}
							}

							if (goon) {
								// Now set temp breakpoints at our stop points.
								//
								CountingRequestMonitor setTempBpRM = new CountingRequestMonitor(getExecutor(), rm) {
									@Override
									protected void handleSuccess() {
										// we are done setting all temporary
										// breakpoints
										dmc.resumeForStepping(rm);
									}
								};

								setTempBpRM.setDoneCount(stopPoints.size());

								for (IAddress addr : stopPoints) {
									bpService.setTempBreakpoint(dmc, addr, setTempBpRM);
								}
							} else {
								// Stepping finished after prepareToRun().
								DMCSuspendedEvent e = dmc.getCachedSuspendedEvent();
								if (e != null)
									getSession().dispatchEvent(e, RunControl.this.getProperties());
								rm.done();
							}
						}
					});
				}

			}
		});
	}

	/**
	 * step-into one instruction at current PC, namely execute only one
	 * instruction.
	 * 
	 * @param dmc
	 * @param rm
	 *            - this RequestMonitor is marked done when the execution
	 *            finishes and target suspends again.
	 */
	private void stepIntoOneInstruction(final ExecutionDMC dmc, final RequestMonitor rm) {

		prepareToRun(dmc, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				if (getData() == true /* already executed one instruction */) {
					// Stepping finished after prepareToRun().
					DMCSuspendedEvent e = dmc.getCachedSuspendedEvent();
					if (e != null)
						getSession().dispatchEvent(e, RunControl.this.getProperties());
					rm.done();
				}
				else {
					dmc.singleStep(true, rm);
				}
			}
		});
	}

	public void suspend(IExecutionDMContext context, RequestMonitor requestMonitor) {
		if (context instanceof ExecutionDMC) {
			((ExecutionDMC) context).suspend(requestMonitor);
		} else {
			requestMonitor.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, MessageFormat
					.format("The context [{0}] is not a recognized execution context.", context), null));
			requestMonitor.done();
		}
	}

	public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
		rm.done();
	}

	public void flushCache(IDMContext context) {
		if (isSnapshot())
			return;
		// Flush the Registers cache immediately
		// For instance the readPCRegister() may get wrong PC value when an
		// asynchronous suspend event comes too quick after resume.
		Registers regService = getService(Registers.class);
		regService.flushCache(context);
	}

	@Override
	public void shutdown(RequestMonitor monitor) {
		if (tcfRunService != null) {
			Protocol.invokeLater(new Runnable() {
				public void run() {
					tcfRunService.removeListener(runListener);
				}
			});
		}
		unregister();
		super.shutdown(monitor);
	}

	public RootExecutionDMC getRootDMC() {
		return rootExecutionDMC;
	}

	public static class StartedEvent extends AbstractDMEvent<IExecutionDMContext> implements IStartedDMEvent {

		public StartedEvent(IExecutionDMContext context) {
			super(context);
		}
	}

	public static class ExitedEvent extends AbstractDMEvent<IExecutionDMContext> implements IExitedDMEvent {
		private boolean isTerminatedThanDisconnected;
		
		public ExitedEvent(IExecutionDMContext context, boolean isTerminatedThanDisconnected) {
			super(context);
			this.isTerminatedThanDisconnected = isTerminatedThanDisconnected;
		}

		public boolean isTerminatedThanDisconnected() {
			return isTerminatedThanDisconnected;
		}
	}

	/*
	 * NOTE: 
	 * Methods in this listener are invoked in TCF dispatch thread.
	 * When they call into DSF services/objects, make sure it's done in 
	 * DSF executor thread so as to avoid possible racing condition.
	 */
	private final org.eclipse.tm.tcf.services.IRunControl.RunControlListener runListener = new org.eclipse.tm.tcf.services.IRunControl.RunControlListener() {

		public void containerResumed(String[] context_ids) {
		}

		public void containerSuspended(String context, String pc, String reason, Map<String, Object> params,
				String[] suspended_ids) {
		}

		public void contextAdded(final RunControlContext[] contexts) {
			getExecutor().execute(new Runnable() {
				public void run() {
					for (RunControlContext ctx : contexts) {
						ExecutionDMC dmc = rootExecutionDMC;
						String parentID = ctx.getParentID();
						if (parentID != null)
							dmc = dmcsByID.get(parentID);
						if (dmc != null) {
							dmc.contextAdded(ctx.getProperties(), ctx);
						}
					}
				}
			});
		}

		public void contextChanged(RunControlContext[] contexts) {
		}

		public void contextException(final String context, final String msg) {
			getExecutor().execute(new Runnable() {
				public void run() {
					ExecutionDMC dmc = getContext(context);
					if (dmc != null)
						dmc.contextException(msg);
				}
			});
		}

		public void contextRemoved(final String[] context_ids) {
			getExecutor().execute(new Runnable() {
				public void run() {
					for (String contextID : context_ids) {
						ExecutionDMC dmc = getContext(contextID);
						assert dmc != null;
						if (dmc != null)
							dmc.purgeFromDebugger();
					}
				}
			});
		}

		public void contextResumed(final String context) {
			getExecutor().execute(new Runnable() {
				public void run() {
					ExecutionDMC dmc = getContext(context);
					if (dmc != null)
						dmc.contextResumed(false);
				}
			});
		}

		public void contextSuspended(final String context, final String pc, final String reason,
				final Map<String, Object> params) {
			getExecutor().execute(new Runnable() {
				public void run() {
					ExecutionDMC dmc = getContext(context);
					if (dmc != null)
						dmc.contextSuspended(pc, reason, params);
					else {
						EDCDebugger.getMessageLogger().logError(
							MessageFormat.format("Unkown context [{0}] is reported in suspended event. Make sure TCF agent has reported contextAdded event first.", context), 
							null);
					}
				}
			});
		}
	};

	public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor)throws Exception {
		Element contextsElement = document.createElement(EXECUTION_CONTEXTS);
		ExecutionDMC[] dmcs = rootExecutionDMC.getChildren();
		SubMonitor progress = SubMonitor.convert(monitor, dmcs.length * 1000);

		for (ExecutionDMC executionDMC : dmcs) {
			Element dmcElement = executionDMC.takeSnapshot(album, document, progress.newChild(1000));
			contextsElement.appendChild(dmcElement);
		}
		return contextsElement;
	}

	public ExecutionDMC getContext(String contextID) {
		return dmcsByID.get(contextID);
	}

	public void loadSnapshot(Element snapshotRoot) throws Exception {
		NodeList ecElements = snapshotRoot.getElementsByTagName(EXECUTION_CONTEXTS);
		rootExecutionDMC.resumeAll();
		initializeRootExecutionDMC();
		rootExecutionDMC.loadSnapshot((Element) ecElements.item(0));
	}

	public void tcfServiceReady(IService service) {
		if (service instanceof org.eclipse.tm.tcf.services.IRunControl) {
			tcfRunService = (org.eclipse.tm.tcf.services.IRunControl) service;
			Protocol.invokeLater(new Runnable() {
				public void run() {
					tcfRunService.addListener(runListener);
				}
			});
		} else
			assert false;
	}

	/**
	 * Stop debugging all execution contexts. This does not kill/terminate
	 * the actual process or thread.
	 * See: {@link #terminateAllContexts(RequestMonitor)}
	 */
	private void detachAllContexts(){
		getRootDMC().detach();
	}

	/**
	 * Terminate all contexts so as to terminate the debug session.
	 * 
	 * @param rm can be null.
	 */
	public void terminateAllContexts(final RequestMonitor rm){

		CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleError() {
				// failed to terminate at least one process, usually
				// because connection to target is lost, or some processes
				// cannot be killed (e.g. OS does not permit that).
				// Just untarget the contexts.
				detachAllContexts();
		
				if (rm != null)
					rm.done();
			}
			
		};
		
		// It's assumed 
		// 1. First level of children under rootDMC are processes.
		// 2. Killing them would kill all contexts (processes and threads) being debugged.
		//
		ExecutionDMC[] processes = getRootDMC().getChildren();
		crm.setDoneCount(processes.length);
		
		for (ExecutionDMC e : processes) {
			e.terminate(crm);
		}
	}

	public void canRunToLine(IExecutionDMContext context, String sourceFile,
			int lineNumber, final DataRequestMonitor<Boolean> rm) {
		// I tried to have better filtering as shown in commented code. But that 
		// just made the command fail to be enabled as desired. Not sure about the 
		// exact cause yet, but one problem (from the upper framework) I've seen is 
		// this API is not called whenever user selects a line in source editor (or
		// disassembly view) and bring up context menu.
		// Hence we blindly answer yes. The behavior is on par with DSF-GDB.
		// ................. 03/11/10  
		rm.setData(true);
		rm.done();
		
//		// Return true if we can find address(es) for the line in the context.
//		//
//		getLineAddress(context, sourceFile, lineNumber, new DataRequestMonitor<List<IAddress>>(getExecutor(), rm){
//			@Override
//			protected void handleCompleted() {
//				if (! isSuccess())
//					rm.setData(false);
//				else {
//					rm.setData(getData().size() > 0);
//				}
//				rm.done();
//			}});
	}

	public void runToLine(final IExecutionDMContext context, String sourceFile,
			int lineNumber, boolean skipBreakpoints, final RequestMonitor rm) {
		
		getLineAddress(context, sourceFile, lineNumber, new DataRequestMonitor<List<IAddress>>(getExecutor(), rm){
			@Override
			protected void handleCompleted() {
				if (! isSuccess()) {
					rm.setStatus(getStatus());
					rm.done();
				}
				else {
					runToAddresses(context, getData(), rm);
				}
			}});
	}

	private void runToAddresses(IExecutionDMContext context,
			final List<IAddress> addrs, final RequestMonitor rm) {
		// 1. Single step over breakpoint, if PC is at a breakpoint.
		// 2. Set temp breakpoint at the addresses.
		// 3. Resume the context.
		//
		final ExecutionDMC dmc = (ExecutionDMC)context;
		assert dmc != null;
		
		prepareToRun(dmc, new DataRequestMonitor<Boolean>(getExecutor(), rm){

			@Override
			protected void handleCompleted() {
				if (! isSuccess()) {
					rm.setStatus(getStatus());
					rm.done();
					return;
				}
				
				CountingRequestMonitor settingBP_crm = new CountingRequestMonitor(getExecutor(), rm) {
					@Override
					protected void handleCompleted() {
						if (! isSuccess()) {
							// as long as we fail to set on temp breakpoint, we bail out.
							rm.setStatus(getStatus());
							rm.done();
						}
						else {
							// all temp breakpoints are successfully set.
							// Now resume the context.
							dmc.resume(rm);
						}
					}};
				
				settingBP_crm.setDoneCount(addrs.size());
				
				Breakpoints bpService = getService(Breakpoints.class);
				
				for (IAddress a : addrs)
					bpService.setTempBreakpoint(dmc, a, settingBP_crm);
			}}
		);
	}

	public void canRunToAddress(IExecutionDMContext context, IAddress address,
			DataRequestMonitor<Boolean> rm) {
		// See comment in canRunToLine() for more.
		rm.setData(true);
		rm.done();

//		// If the address is not in any module of the run context, return false. 
//		Modules moduleService = getService(Modules.class);
//
//		ISymbolDMContext symCtx = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);
//
//		ModuleDMC m = moduleService.getModuleByAddress(symCtx, address);
//		rm.setData(m == null);
//		rm.done();
	}

	public void runToAddress(IExecutionDMContext context, IAddress address,
			boolean skipBreakpoints, RequestMonitor rm) {
		List<IAddress> addrs = new ArrayList<IAddress>(1);
		addrs.add(address);
		runToAddresses(context, addrs, rm);
	}

	public void canMoveToLine(IExecutionDMContext context, String sourceFile,
			int lineNumber, boolean resume, final DataRequestMonitor<Boolean> rm) {
		// See comment in canRunToLine() for more.
		rm.setData(true);
		rm.done();
		
		// Return true if we can find one and only one address for the line in the context.
		//
//		getLineAddress(context, sourceFile, lineNumber, new DataRequestMonitor<List<IAddress>>(getExecutor(), rm){
//			@Override
//			protected void handleCompleted() {
//				if (! isSuccess())
//					rm.setData(false);
//				else {
//					rm.setData(getData().size() == 1);
//				}
//				rm.done();
//			}});
	}

	public void moveToLine(final IExecutionDMContext context, String sourceFile,
			int lineNumber, final boolean resume, final RequestMonitor rm) {
		getLineAddress(context, sourceFile, lineNumber, new DataRequestMonitor<List<IAddress>>(getExecutor(), rm){
			@Override
			protected void handleCompleted() {
				if (! isSuccess()) {
					rm.setStatus(getStatus());
					rm.done();
				}
				else {
					List<IAddress> addrs = getData();
					// No, canMoveToLine() does not do sanity check now.
					// We just move to the first address we found, which may or
					// may not be the address user wants. Is it better we return
					// error if "addrs.size() > 1" ? .......03/28/10
					// assert addrs.size() == 1;	// ensured by canMoveToLine().
					moveToAddress(context, addrs.get(0), resume, rm);
				}
			}});
	}

	public void canMoveToAddress(IExecutionDMContext context, IAddress address,
			boolean resume, DataRequestMonitor<Boolean> rm) {
		// Allow moving to any address.
		rm.setData(true);
		rm.done();
	}

	public void moveToAddress(IExecutionDMContext context, IAddress address,
			boolean resume, RequestMonitor rm) {

		assert(context instanceof ExecutionDMC);
		final ExecutionDMC dmc = (ExecutionDMC)context;
		
		String newPC = address.toString(16);
		
		if (! newPC.equals(dmc.getPC())) {
			Registers regService = getService(Registers.class);
			
			try {
				// synchronously change PC, so that change occurs before any resume
				String regID = getTargetEnvironmentService().getPCRegisterID();
				RegisterDMC regDMC = regService.findRegisterDMCByName(dmc, regID);
				assert regDMC != null;
				
				regService.writeRegister(regDMC, newPC, IFormattedValues.HEX_FORMAT);
			} catch (CoreException e) {
				Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error adjusting the PC register", e);
				EDCDebugger.getMessageLogger().log(s);
				rm.setStatus(s);
				rm.done();
				return;
			}

			// update cached PC.
			dmc.setPC(newPC);
		}
		
		if (resume) {
			resume(context, rm);
		}
		else if (rm == dmc.getBreakpointActionRM()) {
			// if resume is false and our request monitor is
			// THE breakpointActionRM, then the caller (currently
			// only SkipAction) expects to stop at that bkpt.
			// but that bkpt may have actions to be executed.
			Breakpoints bpService = getService(Breakpoints.class);
			final Breakpoints.BreakpointDMData bp = bpService.findUserBreakpoint(address);
			if (bp.hasActions()) {
				bp.executeActions(dmc, dmc.getBreakpointActionRM());							
			} else
				rm.done();
		} else {
			rm.done();
		}
	}

	/**
	 * Get runtime addresses mapped to given source line in given run context.
	 *  
	 * @param context
	 * @param sourceFile
	 * @param lineNumber
	 * @param drm holds an empty list if no address found, or the run context is not suspended.
	 */
	private void getLineAddress(IExecutionDMContext context,
			String sourceFile, int lineNumber, DataRequestMonitor<List<IAddress>> drm) {
		List<IAddress> addrs = new ArrayList<IAddress>(1);
		
		ExecutionDMC dmc = (ExecutionDMC) context;
		if (dmc == null || ! dmc.isSuspended()) {
			drm.setData(addrs);
			drm.done();
			return;
		}
		
		Modules moduleService = getService(Modules.class);

		moduleService.getLineAddress(dmc, sourceFile, lineNumber, drm);
	}

	/**
	 * Check if this context is non-container. Only non-container context
	 * (thread and bare device context) can have register, stack frames, etc.
	 * 
	 * @param dmc
	 * @return
	 */
	static public boolean isNonContainer(IDMContext dmc) {
		return ! (dmc instanceof IContainerDMContext);
	}
	
	public ThreadExecutionDMC[] getSuspendedThreads()
	{
		ExecutionDMC[] dmcs = null;
		List<ThreadExecutionDMC> result = new ArrayList<ThreadExecutionDMC>();
		synchronized (dmcsByID)
		{
			Collection<ExecutionDMC> allDMCs = dmcsByID.values();
			dmcs = allDMCs.toArray(new ExecutionDMC[allDMCs.size()]);
		}
		for (ExecutionDMC executionDMC : dmcs) {
			if (executionDMC instanceof ThreadExecutionDMC && executionDMC.isSuspended())
				result.add((ThreadExecutionDMC) executionDMC);
		}
		return result.toArray(new ThreadExecutionDMC[result.size()]);
	}

	public IAddress getAddressForNextLine(final ExecutionDMC dmc, IAddress pcAddress,
			IEDCModuleDMContext module, IAddress linkAddress,
			IModuleLineEntryProvider lineEntryProvider, ILineEntry line,
			boolean treatAsStepOver) {
		IAddress endAddr = module.toRuntimeAddress(line.getHighAddress());

		// get the next source line entry that has a line #
		// greater than the current line # (and in the same file),
		// but is not outside of the function address range
		// if found, the start addr of that entry is our end
		// address, otherwise use the existing end address
		ILineEntry nextLine
		  = lineEntryProvider.getNextLineEntry(
				lineEntryProvider.getLineEntryAtAddress(linkAddress),
				treatAsStepOver);
		if (nextLine != null) {
			endAddr = module.toRuntimeAddress(nextLine.getLowAddress());
		} else {	// nextLine == null probably means last line
			IEDCSymbols symbolsService = getService(Symbols.class);
			IFunctionScope functionScope
			  = symbolsService.getFunctionAtAddress(dmc.getSymbolDMContext(), pcAddress);
			if (treatAsStepOver) {
				while (functionScope != null
						&& functionScope.getParent() instanceof IFunctionScope) {
					functionScope = (IFunctionScope)functionScope.getParent();
				}
			}
			if (functionScope != null)
				endAddr = module.toRuntimeAddress(functionScope.getHighAddress());
		}
		return endAddr;
	}

	/**
	 * Utility method for getting a context property using a default value
	 * if missing
	 */
	private static boolean getProperty(Map<String, Object> properties, String name, boolean defaultValue) {
		Boolean b = (Boolean)properties.get(name);
		return (b == null ? defaultValue : b);
	}
}
