Add RTTI support. Expand support for watchpoints, beef up unit tests,
improve symbol loading when triggered by stack frames.
diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/DisassemblyViewARMBlackFlagRVCT.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/DisassemblyViewARMBlackFlagRVCT.java
index 2fd655e..548080b 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/DisassemblyViewARMBlackFlagRVCT.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/DisassemblyViewARMBlackFlagRVCT.java
@@ -111,12 +111,23 @@
 

 	@Test

 	public void testARMDisassembly() throws Exception {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testARMDisassemblyGetInstructionsBigInteger() reporting PASSED but will be skipped.");

+			return;

+		}

 		armAlbum.openSnapshotAndWaitForSuspendedContext(0);

 		Thread.sleep(2500);	// wait a little to allow the view to populate and do work

 	}

 

 	@Test

 	public void testARMDisassemblyGetInstructionsBigInteger() throws Exception {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testARMDisassemblyGetInstructionsBigInteger() reporting PASSED but will be skipped.");

+			return;

+		}

+

 		// Use a Query to synchronize the downstream calls

 		Query<IInstruction[]> query = new Query<IInstruction[]>() {

 			@Override

@@ -170,7 +181,12 @@
 	}

 

 	@Test

-	public void testInternalTargetEnvironmentARM() throws Exception {

+	public void testInternalTargetEnvironmentARMevaluateLR() throws Exception {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testInternalTargetEnvironmentARMevaluateLR() reporting PASSED but will be skipped.");

+			return;

+		}

 		armAlbum.openSnapshotAndWaitForSuspendedContext(4);

 

 		final TargetEnvironmentARM env

@@ -204,6 +220,11 @@
 

 	@Test

 	public void testInternalTargetEnvironmentARMgetBasicTypeSizes() throws Exception {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testInternalTargetEnvironmentARMgetBasicTypeSizes() reporting PASSED but will be skipped.");

+			return;

+		}

 		armAlbum.openSnapshotAndWaitForSuspendedContext(4);

 

 		final TargetEnvironmentARM env

@@ -217,6 +238,11 @@
 

 	@Test

 	public void testInternalTargetEnvironmentARMgetBreapointInstruction() throws Exception {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testInternalTargetEnvironmentARMgetBreapointInstruction() reporting PASSED but will be skipped.");

+			return;

+		}

 		armAlbum.openSnapshotAndWaitForSuspendedContext(4);

 

 		final TargetEnvironmentARM env

@@ -228,115 +254,50 @@
 	}

 

 	@Test

-	public void testInternalTargetEnvironmentARMgetDisassembler() {

+	public void testInternalTargetEnvironmentARM() {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== testInternalTargetEnvironmentARM() reporting PASSED but will be skipped.");

+			return;

+		}

+		if (armDisasm == null) return;

 		TargetEnvironmentARM env

 		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

 		Assert.assertNotNull(env);

 

 		IDisassembler disassembler = env.getDisassembler();

 		Assert.assertTrue("instanceof check", disassembler instanceof DisassemblerARM);

-	}

 

-	@Test

-	public void testInternalTargetEnvironmentARMgetEnumSize() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		int enumSize = env.getEnumSize();

-		Assert.assertEquals("Enum Size Test", 4, enumSize);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMgetLongestInstructionLength() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

 

 		int longestInstLength = env.getLongestInstructionLength();

 		Assert.assertEquals("Longest Instruction Length Test", 4, longestInstLength);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMgetMemoryCacheMinimumBlockSize() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

 

 		int memoryCacheMinimumBlockSize = env.getMemoryCacheMinimumBlockSize();

 		Assert.assertEquals("Memory Cache Minimum Block Size Test", 64, memoryCacheMinimumBlockSize);

-	}

 

-	@Test

-	public void testInternalTargetEnvironmentARMgetOS() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

+		Assert.assertEquals("OS Test", ITargetEnvironment.OS_UNKNOWN, env.getOS());

+		Assert.assertEquals("PC Register ID Test", "PC", env.getPCRegisterID());

+		Assert.assertEquals("Pointer Size Test", 4, env.getPointerSize());

+		Assert.assertEquals("Enum Size Test", 4, env.getEnumSize());

+		Assert.assertFalse("Char Signed Test", env.isCharSigned());

+		Assert.assertTrue("Little Endian Test", env.isLittleEndian(disassemblyDMC));

 

-		String os = env.getOS();

-		Assert.assertEquals("OS Test", ITargetEnvironment.OS_UNKNOWN, os);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMgetPCRegisterID() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		String pcRegID = env.getPCRegisterID();

-		Assert.assertEquals("PC Register ID Test", "PC", pcRegID);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMgetPointerSize() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		int pointerSize = env.getPointerSize();

-		Assert.assertEquals("Pointer Size Test", 4, pointerSize);

+		boolean isThumbMode = env.isThumbMode(disassemblyDMC, new Addr32(0x788656e4), false);

+		Assert.assertTrue("Thumb Mode Test", isThumbMode);

 	}

 

 	@Test

 	public void coverageInternalTargetEnvironmentARMgetProperty() {

+		if (armAlbum == null) return;

+		if (armAlbum.launch == null) {

+			System.out.println("== coverageInternalTargetEnvironmentARMgetProperty() reporting PASSED but will be skipped.");

+			return;

+		}

+		if (armDisasm == null) return;

 		TargetEnvironmentARM env

 		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

 		Assert.assertNotNull(env);

 

 		Assert.assertNull("Property Test (no properties yet supported)", env.getProperty("x"));

 	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMisCharSigned() {

-		TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		boolean isCharSigned = env.isCharSigned();

-		Assert.assertFalse("Char Signed Test", isCharSigned);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMisLittleEndian() throws Exception {

-		armAlbum.openSnapshotAndWaitForSuspendedContext(4);

-

-		final TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		boolean isLittleEndian = env.isLittleEndian(disassemblyDMC);

-		Assert.assertTrue("Little Endian Test", isLittleEndian);

-	}

-

-	@Test

-	public void testInternalTargetEnvironmentARMisThumbMode() throws Exception {

-		armAlbum.openSnapshotAndWaitForSuspendedContext(4);

-

-		final TargetEnvironmentARM env

-		  = (TargetEnvironmentARM)armDisasm.getTargetEnvironmentService();

-		Assert.assertNotNull(env);

-

-		boolean isThumbMode = env.isThumbMode(disassemblyDMC, new Addr32(0x788656e4), false);

-		Assert.assertTrue("Thumb Mode Test", isThumbMode);

-	}

 }

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsCasting2.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsCasting2.java
index edabd11..e3fcd43 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsCasting2.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsCasting2.java
@@ -1,79 +1,85 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 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.debugger.tests;
-
-import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;
-import org.eclipse.cdt.dsf.debug.service.IExpressions2.CastInfo;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests of expression evaluation using cast operators.
- * 
- * Additional checks for code where variables are in registers.
- */
-public class ExpressionsCasting2 extends BaseExpressionTest {
-	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()
-	 */
-	@Override
-	protected String getRequiredLaunchConfigurationType() {
-		return "com.nokia.cdt.debug.launch.systemTRKLaunch";
-	}
-	
-
-	boolean formatterSetting;
-	
-	@Before
-	public void turnOnFormatter() {
-		formatterSetting = FormatExtensionManager.instance().isEnabled();
-		FormatExtensionManager.instance().setEnabled(true);
-	}
-	@After
-	public void restoreFormatter() {
-		FormatExtensionManager.instance().setEnabled(formatterSetting);
-	}
-	
-	
-	@Test
-	public void testCastingRegisters() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(1);
-		
-		// these variables are in registers
-		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg2", new CastInfo("TPtr8*"));
-		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", new CastInfo("TPtr8*"));
-		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", new CastInfo("TPtr8&"));
-		
-		// cast value in register directly to float, don't complain about "& of register"
-		checkCastedExpr(null, "5.962985E-39", "aArg2", new CastInfo("float"));
-	}
-	
-	@Test
-	public void testCastingArraysInRegisters() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(1);
-		
-		// these variables are in registers, don't complain about "& of register"
-		CastInfo arrayCast = new CastInfo("TPtr8*", 0, 2);
-		checkCastedChildExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", arrayCast, "aArg3[0]");
-
-	}
-	
-	@Override
-	public String getAlbumName() {
-		return "RegisterFrameTestsBlackFlagRVCT.dsa";
-	}
-
-}
+/*******************************************************************************

+ * Copyright (c) 2009, 2010 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.debugger.tests;

+

+import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;

+import org.eclipse.cdt.dsf.debug.service.IExpressions2.CastInfo;

+import org.junit.After;

+import org.junit.Before;

+import org.junit.Test;

+

+/**

+ * Tests of expression evaluation using cast operators.

+ * 

+ * Additional checks for code where variables are in registers.

+ */

+public class ExpressionsCasting2 extends BaseExpressionTest {

+	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()

+	 */

+	@Override

+	protected String getRequiredLaunchConfigurationType() {

+		return "com.nokia.cdt.debug.launch.systemTRKLaunch";

+	}

+	

+

+	boolean formatterSetting;

+	

+	@Before

+	public void turnOnFormatter() {

+		formatterSetting = FormatExtensionManager.instance().isEnabled();

+		FormatExtensionManager.instance().setEnabled(true);

+	}

+	@After

+	public void restoreFormatter() {

+		FormatExtensionManager.instance().setEnabled(formatterSetting);

+	}

+	

+	

+	@Test

+	public void testCastingRegisters() throws Exception {

+		if (launch == null) {

+			System.out.println("== testCastingRegisters() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(1);

+		

+		// these variables are in registers

+		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg2", new CastInfo("TPtr8*"));

+		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", new CastInfo("TPtr8*"));

+		checkCastedExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", new CastInfo("TPtr8&"));

+		

+		// cast value in register directly to float, don't complain about "& of register"

+		checkCastedExpr(null, "5.962985E-39", "aArg2", new CastInfo("float"));

+	}

+	

+	@Test

+	public void testCastingArraysInRegisters() throws Exception {

+		if (launch == null) {

+			System.out.println("== testCastingArraysInRegisters() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(1);

+		

+		// these variables are in registers, don't complain about "& of register"

+		CastInfo arrayCast = new CastInfo("TPtr8*", 0, 2);

+		checkCastedChildExpr(null, YOU_SHOULD_BE_SEEING_THIS_TEXT, "aArg3", arrayCast, "aArg3[0]");

+

+	}

+	

+	@Override

+	public String getAlbumName() {

+		return "RegisterFrameTestsBlackFlagRVCT.dsa";

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsServiceInternalsTest.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsServiceInternalsTest.java
index 09787a1..a11cd8d 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsServiceInternalsTest.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ExpressionsServiceInternalsTest.java
@@ -138,7 +138,7 @@
 //	}

 

 	/**

-	 * TODO method {@link Expressions#getModelData} currently almost nothing

+	 * TODO method {@link Expressions#getBaseExpressions} does currently almost nothing

 	 *      except setData(new IDCExpression[0]);

 	 * @throws Exception

 	 */

@@ -199,7 +199,7 @@
 		Expressions expressionsService = TestUtils.getService(session, Expressions.class);

 		IExpressions.IExpressionDMContext exprDMC = expressionsService.createExpression(frame, "lstruct");

 		Assert.assertNull(((IEDCExpression)exprDMC).getEvaluatedValue());

-		expressionsService.loadExpressionValues(exprDMC, 3);

+		expressionsService.snapshotValues(exprDMC, 3);

 //		Assert.assertNotNull("lstruct not yet evaluated after loadExpressionValues() depth 3", ((IEDCExpression)exprDMC).getEvaluatedValue());

 //		Assert.assertEquals(TODO, ((IEDCExpression)exprDMC).getEvaluatedValue().intValue());

 //		Assert.assertEquals("TODO", ((IEDCExpression)exprDMC).getEvaluatedValueString());

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ModulesTest.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ModulesTest.java
index 2414eed..9887b85 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ModulesTest.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/ModulesTest.java
@@ -218,8 +218,7 @@
 		// TODO Modules.ModuleDMData should return BaseAddress + size

 		Assert.assertEquals(MODULE_START, moduleDMData.getToAddress());

 

-		// TODO Modules.ModuleDMData.isSymbolsLoaded() always returns false right now

-		Assert.assertFalse(moduleDMData.isSymbolsLoaded());

+		Assert.assertTrue(moduleDMData.isSymbolsLoaded());

 	}

 

 	@Test

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/OpaqueTypeResolving.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/OpaqueTypeResolving.java
index ac7756c..832ee32 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/OpaqueTypeResolving.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/OpaqueTypeResolving.java
@@ -21,6 +21,7 @@
 import org.eclipse.cdt.debug.edc.tests.TestUtils;

 import org.eclipse.cdt.dsf.datamodel.DMContexts;

 import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext;

+import org.eclipse.core.runtime.NullProgressMonitor;

 import org.junit.Assert;

 import org.junit.Test;

 

@@ -45,12 +46,12 @@
 		//	   PrivatePTR  opaque_ptr = 0;

 		//

 		// At this point, debug session from the snapshot is stopped at

-		// a the end of the executable.

+		// the end of the executable.

 		

 		IEDCExpression exprVal = TestUtils.getExpressionDMC(session, frame, "opaque_ptr");

 		IType type = exprVal.getEvaluatedType();

 		

-		// First ensure if the original type of the var is an opaque type.

+		// First verify that the original type of the var is an opaque type.

 		//

 		Assert.assertTrue(type instanceof TypedefType);

 		type = type.getType();	// de-typedef

@@ -59,35 +60,36 @@
 

 		Assert.assertTrue(type instanceof ICompositeType);

 		Assert.assertTrue(((ICompositeType)type).isOpaque());

-		Assert.assertTrue("Type is not opaque type.", type.getByteSize() == 0);

-		

+		Assert.assertTrue("Type is not opaque type while it should be.", type.getByteSize() == 0);

+

 		// Now resolve the opaque type

 		//

 		Symbols symService = TestUtils.getService(session, Symbols.class);

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

-		ICompositeType defined = symService.resolveOpaqueType(symCtx, (ICompositeType) type);

+		ICompositeType defined

+		  = symService.resolveOpaqueType(symCtx, (ICompositeType) type, new NullProgressMonitor());

 		Assert.assertFalse(defined.isOpaque());

 		Assert.assertEquals(type.getName(), defined.getName());

 

 		// Resolve one that's not an opaque type, fail.

-		type = symService.resolveOpaqueType(symCtx, defined);

+		type = symService.resolveOpaqueType(symCtx, defined, new NullProgressMonitor());

 		Assert.assertNull(type);

 	}

-	

+

 	@Test

 	public void testOpaqueTypeNeverDefined() throws Exception {

-		// An opaque type that's never defined anywhere. We can resolve it.

+		// An opaque type that's never defined anywhere. We cannot resolve it.

 		//

 		//		typedef struct UndefinedStruct* UndefinedPTR;

 		//		UndefinedPTR opaque_ptr_to_undefined;

 		//

 		// At this point, debug session from the snapshot is stopped at

-		// a the end of the executable.

+		// the end of the executable.

 		

 		IEDCExpression exprVal = TestUtils.getExpressionDMC(session, frame, "opaque_ptr_to_undefined");

 		IType type = exprVal.getEvaluatedType();

 		

-		// First ensure if the original type of the var is an opaque type.

+		// First verify the original type of the var is an opaque type.

 		//

 		Assert.assertTrue(type instanceof TypedefType);

 		type = type.getType();	// de-typedef

@@ -96,13 +98,14 @@
 

 		Assert.assertTrue(type instanceof ICompositeType);

 		Assert.assertTrue(((ICompositeType)type).isOpaque());

-		Assert.assertTrue("Type is not opaque type.", type.getByteSize() == 0);

+		Assert.assertTrue("Type is not opaque type while it should be.", type.getByteSize() == 0);

 		

 		// Now try to resolve the opaque type, should fail

 		//

 		Symbols symService = TestUtils.getService(session, Symbols.class);

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

-		ICompositeType defined = symService.resolveOpaqueType(symCtx, (ICompositeType) type);

+		ICompositeType defined

+		  = symService.resolveOpaqueType(symCtx, (ICompositeType) type, new NullProgressMonitor());

 		Assert.assertNull(defined);

 	}

 }

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlag.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlag.java
index 42b5a04..c0b920a 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlag.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlag.java
@@ -1,125 +1,134 @@
-/*******************************************************************************
- * Copyright (c) 2010 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.debugger.tests;
-
-import static org.junit.Assert.*;
-
-import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;
-import org.eclipse.cdt.debug.edc.tests.TestUtils;
-import org.junit.Test;
-
-/**
- * Test that we can recover expressions from stack frames other than the TOS
- * 
- * (actual case in bug 304040)
- */
-public class RegisterFrameTestsBlackFlag extends SimpleDebuggerTest {
-	/**
-	 * 
-	 */
-	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";
-	boolean formatterSetting;
-	
-	public void setFormatter(boolean enable) {
-		formatterSetting = FormatExtensionManager.instance().isEnabled();
-		FormatExtensionManager.instance().setEnabled(enable);
-	}
-	public void restoreFormatter() {
-		FormatExtensionManager.instance().setEnabled(formatterSetting);
-	}
-
-	/** account for patchy decimal vs. hex outputs */
-	private void assertNumbersEquals(String exp, String value) {
-		try {
-			long expl, valuel;
-			if (exp.startsWith("0x"))
-				expl = Long.valueOf(exp.substring(2), 16);
-			else
-				expl = Long.valueOf(exp);
-			if (value.startsWith("0x"))
-				valuel = Long.valueOf(value.substring(2), 16);
-			else
-				valuel = Long.valueOf(value);
-			assertEquals(value, expl, valuel);
-		} catch (NumberFormatException e) {
-			// fail naturally
-			assertEquals(exp, value);
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()
-	 */
-	@Override
-	protected String getRequiredLaunchConfigurationType() {
-		return "com.nokia.cdt.debug.launch.systemTRKLaunch";
-	}
-	
-	@Test
-	public void testLength() throws Exception {
-		if (launch == null) return;
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 0);
-		
-		try {
-			setFormatter(false);
-			assertNumbersEquals("0x7907aee0", getExpressionValue("this"));
-		} finally {
-			restoreFormatter();
-		}
-	}
-	@Test
-	public void testShowConstArguments() throws Exception {
-		if (launch == null) return;
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);
-		try {
-			// note: formatter was half-showing decimal and hex at this time
-			setFormatter(false);
-			assertNumbersEquals("0x40ee38", getExpressionValue("aArg1"));
-			assertNumbersEquals("0x40ee38", getExpressionValue("aArg2"));
-			assertNumbersEquals("0x40ee38", getExpressionValue("aArg3"));
-			assertNumbersEquals("0x40ee38", getExpressionValue("aArg4"));
-			assertEquals("31", getExpressionValue("length"));
-			assertEquals("31", getExpressionValue("length2"));
-			assertEquals("31", getExpressionValue("length3"));
-			assertEquals("31", getExpressionValue("length4"));
-		} finally {
-			restoreFormatter();
-		}
-	}
-	@Test
-	public void testShowTPtr() throws Exception {
-		if (launch == null) return;
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 2);
-		try {
-			setFormatter(true);
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8p"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16p"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrp"));
-			
-		} finally {
-			restoreFormatter();
-		}
-	}
-	
-	@Override
-	public String getAlbumName() {
-		return "RegisterFrameTestsBlackFlag.dsa";
-	}
-
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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.debugger.tests;

+

+import static org.junit.Assert.*;

+

+import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;

+import org.eclipse.cdt.debug.edc.tests.TestUtils;

+import org.junit.Test;

+

+/**

+ * Test that we can recover expressions from stack frames other than the TOS

+ * 

+ * (actual case in bug 304040)

+ */

+public class RegisterFrameTestsBlackFlag extends SimpleDebuggerTest {

+	/**

+	 * 

+	 */

+	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";

+	boolean formatterSetting;

+	

+	public void setFormatter(boolean enable) {

+		formatterSetting = FormatExtensionManager.instance().isEnabled();

+		FormatExtensionManager.instance().setEnabled(enable);

+	}

+	public void restoreFormatter() {

+		FormatExtensionManager.instance().setEnabled(formatterSetting);

+	}

+

+	/** account for patchy decimal vs. hex outputs */

+	private void assertNumbersEquals(String exp, String value) {

+		try {

+			long expl, valuel;

+			if (exp.startsWith("0x"))

+				expl = Long.valueOf(exp.substring(2), 16);

+			else

+				expl = Long.valueOf(exp);

+			if (value.startsWith("0x"))

+				valuel = Long.valueOf(value.substring(2), 16);

+			else

+				valuel = Long.valueOf(value);

+			assertEquals(value, expl, valuel);

+		} catch (NumberFormatException e) {

+			// fail naturally

+			assertEquals(exp, value);

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()

+	 */

+	@Override

+	protected String getRequiredLaunchConfigurationType() {

+		return "com.nokia.cdt.debug.launch.systemTRKLaunch";

+	}

+	

+	@Test

+	public void testLength() throws Exception {

+		if (launch == null) {

+			System.out.println("== testLength() reporting PASSED but will be skipped.");

+			return;

+		}

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 0);

+		

+		try {

+			setFormatter(false);

+			assertNumbersEquals("0x7907aee0", getExpressionValue("this"));

+		} finally {

+			restoreFormatter();

+		}

+	}

+	@Test

+	public void testShowConstArguments() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments() reporting PASSED but will be skipped.");

+			return;

+		}

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);

+		try {

+			// note: formatter was half-showing decimal and hex at this time

+			setFormatter(false);

+			assertNumbersEquals("0x40ee38", getExpressionValue("aArg1"));

+			assertNumbersEquals("0x40ee38", getExpressionValue("aArg2"));

+			assertNumbersEquals("0x40ee38", getExpressionValue("aArg3"));

+			assertNumbersEquals("0x40ee38", getExpressionValue("aArg4"));

+			assertEquals("31", getExpressionValue("length"));

+			assertEquals("31", getExpressionValue("length2"));

+			assertEquals("31", getExpressionValue("length3"));

+			assertEquals("31", getExpressionValue("length4"));

+		} finally {

+			restoreFormatter();

+		}

+	}

+	@Test

+	public void testShowTPtr() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowTPtr() reporting PASSED but will be skipped.");

+			return;

+		}

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 2);

+		try {

+			setFormatter(true);

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8p"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16p"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrp"));

+			

+		} finally {

+			restoreFormatter();

+		}

+	}

+	

+	@Override

+	public String getAlbumName() {

+		return "RegisterFrameTestsBlackFlag.dsa";

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlagRVCT.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlagRVCT.java
index cd92cb6..295330e 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlagRVCT.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RegisterFrameTestsBlackFlagRVCT.java
@@ -1,159 +1,180 @@
-/*******************************************************************************
- * Copyright (c) 2010 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.debugger.tests;
-
-import static org.junit.Assert.*;
-
-import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;
-import org.eclipse.cdt.debug.edc.tests.TestUtils;
-import org.junit.Test;
-
-/**
- * Test that we can recover expressions from stack frames other than the TOS
- * 
- * (actual case in bug 304040)
- * 
- * Handle broken DWARF frame register format in RVCT
- */
-public class RegisterFrameTestsBlackFlagRVCT extends SimpleDebuggerTest {
-	/**
-	 * 
-	 */
-	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";
-	boolean formatterSetting;
-	
-	public void setFormatter(boolean enable) {
-		formatterSetting = FormatExtensionManager.instance().isEnabled();
-		FormatExtensionManager.instance().setEnabled(enable);
-	}
-	public void restoreFormatter() {
-		FormatExtensionManager.instance().setEnabled(formatterSetting);
-	}
-
-	/** account for patchy decimal vs. hex outputs */
-	private void assertNumbersEquals(String exp, String value) {
-		try {
-			long expl, valuel;
-			if (exp.startsWith("0x"))
-				expl = Long.valueOf(exp.substring(2), 16);
-			else
-				expl = Long.valueOf(exp);
-			if (value.startsWith("0x"))
-				valuel = Long.valueOf(value.substring(2), 16);
-			else
-				valuel = Long.valueOf(value);
-			assertEquals(value, expl, valuel);
-		} catch (NumberFormatException e) {
-			// fail naturally
-			assertEquals(exp, value);
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()
-	 */
-	@Override
-	protected String getRequiredLaunchConfigurationType() {
-		return "com.nokia.cdt.debug.launch.systemTRKLaunch";
-	}
-	
-	protected void doTestStringFormatting() throws Exception {
-		try {
-			setFormatter(true);
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8p"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16p"));
-			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrp"));
-			
-		} finally {
-			restoreFormatter();
-		}
-	}
-	
-	@Test
-	public void testBaseFunction() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(0);
-		doTestStringFormatting();
-	}
-	@Test
-	public void testShowConstArguments1() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(1);
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);
-		doTestStringFormatting();
-	}
-	@Test
-	public void testShowConstArguments2() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(2);
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);
-		doTestStringFormatting();
-		
-	}
-	@Test
-	public void testShowConstArguments3() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(3);
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);
-		doTestStringFormatting();
-	}
-	
-	@Test
-	public void testShowConstArguments4() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(4);
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);
-		doTestStringFormatting();
-	}
-	
-	@Test
-	public void testShowConstArguments5() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(4);
-
-		try {
-			setFormatter(false);
-			assertNumbersEquals("31", getExpressionValue("length"));
-			assertNumbersEquals("31", getExpressionValue("length2"));
-			assertNumbersEquals("31", getExpressionValue("length3"));
-			assertNumbersEquals("31", getExpressionValue("length4"));
-		} finally {
-			restoreFormatter();
-		}
-	}
-	
-	@Test
-	public void testShowE32Main() throws Exception {
-		if (launch == null) return;
-		openSnapshotAndWaitForSuspendedContext(4);
-		frame = TestUtils.waitForStackFrame(session, threadDMC, 5);
-		try {
-			setFormatter(false);
-			assertNumbersEquals("0", getExpressionValue("error"));
-		} finally {
-			restoreFormatter();
-		}
-	}
-	
-	@Override
-	public String getAlbumName() {
-		return "RegisterFrameTestsBlackFlagRVCT.dsa";
-	}
-
-}
+/*******************************************************************************

+ * Copyright (c) 2010 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.debugger.tests;

+

+import static org.junit.Assert.*;

+

+import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;

+import org.eclipse.cdt.debug.edc.tests.TestUtils;

+import org.junit.Test;

+

+/**

+ * Test that we can recover expressions from stack frames other than the TOS

+ * 

+ * (actual case in bug 304040)

+ * 

+ * Handle broken DWARF frame register format in RVCT

+ */

+public class RegisterFrameTestsBlackFlagRVCT extends SimpleDebuggerTest {

+	/**

+	 * 

+	 */

+	private static final String YOU_SHOULD_BE_SEEING_THIS_TEXT = "\"You should be seeing this text!\"";

+	boolean formatterSetting;

+	

+	public void setFormatter(boolean enable) {

+		formatterSetting = FormatExtensionManager.instance().isEnabled();

+		FormatExtensionManager.instance().setEnabled(enable);

+	}

+	public void restoreFormatter() {

+		FormatExtensionManager.instance().setEnabled(formatterSetting);

+	}

+

+	/** account for patchy decimal vs. hex outputs */

+	private void assertNumbersEquals(String exp, String value) {

+		try {

+			long expl, valuel;

+			if (exp.startsWith("0x"))

+				expl = Long.valueOf(exp.substring(2), 16);

+			else

+				expl = Long.valueOf(exp);

+			if (value.startsWith("0x"))

+				valuel = Long.valueOf(value.substring(2), 16);

+			else

+				valuel = Long.valueOf(value);

+			assertEquals(value, expl, valuel);

+		} catch (NumberFormatException e) {

+			// fail naturally

+			assertEquals(exp, value);

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest#getRequiredLaunchConfigurationType()

+	 */

+	@Override

+	protected String getRequiredLaunchConfigurationType() {

+		return "com.nokia.cdt.debug.launch.systemTRKLaunch";

+	}

+	

+	protected void doTestStringFormatting() throws Exception {

+		try {

+			setFormatter(true);

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("cstr"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrC"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr8p"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptr16p"));

+			assertEquals(YOU_SHOULD_BE_SEEING_THIS_TEXT, getExpressionValue("ptrp"));

+			

+		} finally {

+			restoreFormatter();

+		}

+	}

+	

+	@Test

+	public void testBaseFunction() throws Exception {

+		if (launch == null) {

+			System.out.println("== testBaseFunction() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(0);

+		doTestStringFormatting();

+	}

+	@Test

+	public void testShowConstArguments1() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments1() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(1);

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);

+		doTestStringFormatting();

+	}

+	@Test

+	public void testShowConstArguments2() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments2() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(2);

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);

+		doTestStringFormatting();

+		

+	}

+	@Test

+	public void testShowConstArguments3() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments3() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(3);

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);

+		doTestStringFormatting();

+	}

+	

+	@Test

+	public void testShowConstArguments4() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments4() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(4);

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 1);

+		doTestStringFormatting();

+	}

+	

+	@Test

+	public void testShowConstArguments5() throws Exception {

+		if (launch == null) {

+			System.out.println("== testShowConstArguments5() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(4);

+

+		try {

+			setFormatter(false);

+			assertNumbersEquals("31", getExpressionValue("length"));

+			assertNumbersEquals("31", getExpressionValue("length2"));

+			assertNumbersEquals("31", getExpressionValue("length3"));

+			assertNumbersEquals("31", getExpressionValue("length4"));

+		} finally {

+			restoreFormatter();

+		}

+	}

+	

+	@Test

+	public void testShowE32Main() throws Exception {

+		if (launch == null) {

+			System.out.println("testShowE32Main() reporting PASSED but will be skipped.");

+			return;

+		}

+		openSnapshotAndWaitForSuspendedContext(4);

+		frame = TestUtils.waitForStackFrame(session, threadDMC, 5);

+		try {

+			setFormatter(false);

+			assertNumbersEquals("0", getExpressionValue("error"));

+		} finally {

+			restoreFormatter();

+		}

+	}

+	

+	@Override

+	public String getAlbumName() {

+		return "RegisterFrameTestsBlackFlagRVCT.dsa";

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RunControlDMCSubclass.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RunControlDMCSubclass.java
index a48f69b..5df37fc 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RunControlDMCSubclass.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/RunControlDMCSubclass.java
@@ -10,13 +10,10 @@
  *******************************************************************************/

 package org.eclipse.cdt.debug.edc.debugger.tests;

 

-import java.lang.reflect.InvocationTargetException;

 import java.util.HashMap;

 import java.util.Map;

 import java.util.concurrent.TimeUnit;

 

-import junit.framework.Assert;

-

 import org.junit.After;

 import org.junit.Before;

 import org.junit.Test;

@@ -34,8 +31,8 @@
 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;

 import org.eclipse.cdt.dsf.concurrent.Query;

 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;

-import org.eclipse.cdt.dsf.datamodel.DMContexts;

 import org.eclipse.cdt.dsf.debug.service.IStack;

+import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;

 import org.eclipse.core.runtime.IStatus;

 import org.eclipse.core.runtime.Status;

 import org.eclipse.tm.tcf.services.IRunControl;

@@ -79,13 +76,13 @@
 		basicLaunch();

 		EDCServicesTracker edcTracker

 		  = new EDCServicesTracker(EDCDebugger.getBundleContext(), session.getId());

-		Assert.assertNotNull(edcTracker);

+		assertNotNull(edcTracker);

 		runControlService = edcTracker.getService(RunControl.class);

-		Assert.assertNotNull(runControlService);

+		assertNotNull(runControlService);

 		stackService = edcTracker.getService(Stack.class);

-		Assert.assertNotNull(stackService);

+		assertNotNull(stackService);

 		breakpointsService = edcTracker.getService(Breakpoints.class);

-		Assert.assertNotNull(breakpointsService);

+		assertNotNull(breakpointsService);

 	}

 

 	@After

@@ -120,12 +117,12 @@
 

 		Map<String, Object> cseParams = cse.getParams();

 		assertNotNull(cseParams);

-		Assert.assertEquals(cseProps, cseParams);

+		assertEquals(cseProps, cseParams);

 

 		RunControl.IExecutionDMContext[] dmc = cse.getTriggeringContexts();

 		assertNotNull(dmc);

 		assertEquals(1, dmc.length);

-		Assert.assertEquals(bdeDMC, dmc[0]);

+		assertEquals(bdeDMC, dmc[0]);

 

 		// 		protected DMCResumedEvent createResumedEvent()

 		RunControl.ContainerResumedEvent cre

@@ -136,52 +133,57 @@
 		dmc = cre.getTriggeringContexts();

 		assertNotNull(dmc);

 		assertEquals(1, dmc.length);

-		Assert.assertEquals(bdeDMC, dmc[0]);

+		assertEquals(bdeDMC, dmc[0]);

 	}

 

 	@Test

-	public void testExecutionDMCStepOut() throws Exception {

-		waitRunToLine(runControlService, dbg_derived_types_cpp, 57);

+	public void testRootDMC() {

+		RunControl.RootExecutionDMC rootDMC = runControlService.getRootDMC();

+		assertNotNull(rootDMC);

+		assertNull(rootDMC.getSymbolDMContext());

+		assertFalse(rootDMC.canDetach());

+		assertFalse(rootDMC.canStep());

+	}

+

+	@Test

+	public void testStepIntoOneInstruction() throws Exception {

+		waitRunToLine(runControlService, dbg_derived_types_cpp, 285);

+

+		Query<IStatus> query = new Query<IStatus>() {

+			@Override

+			protected void execute(final DataRequestMonitor<IStatus> drm) {

+				runControlService.step(threadDMC, StepType.INSTRUCTION_STEP_INTO, drm);

+			}

+		};

+

+		session.getExecutor().execute(query);

+

+		query.get(5, TimeUnit.SECONDS);

+		assertTrue(query.isDone());

+

+		updateSuspendedFrame(200);

+		assertControlIsAt("dbg_derived_types.cpp", "structs", 40);

+	}

+

+	@Test

+	public void testStepOut() throws Exception {

+		waitRunToLine(runControlService, dbg_derived_types_cpp, 57, 2000);

+		TestUtils.waitForUIUpdate(4000);

 

 		// set this so it stops someplace, even if it's after the expected step out point

 		setTempBreakpoint(breakpointsService, dbg_derived_types_cpp, 288);

 

-		// 	public abstract class ExectionDMC { protected void stepOut(RequestMonitor) }

-

-		final Class<?>[] stepOutArgClasses = new Class<?>[] {RequestMonitor.class};

 		Query<IStatus> query = new Query<IStatus>() {

 			@Override

 			protected void execute(final DataRequestMonitor<IStatus> drm) {

-				ExecutionDMC exeDMC = DMContexts.getAncestorOfType(threadDMC, ExecutionDMC.class);

-				Object[] stepOutArgs = new Object[] {drm};

-				try {

-					TestReflectionHelper.objectFromPrivateFunctionWithArgs(

-							exeDMC, ExecutionDMC.class, "stepOut", stepOutArgs, stepOutArgClasses);

-				} catch (InvocationTargetException ite) {

-					Throwable t = ite.getTargetException(); 

-					if ((t instanceof AssertionError)

-						&& t.getMessage().equals(RunControl.STEP_RETURN_NOT_SUPPORTED)) {

-						drm.setData(new Status(IStatus.INFO, EDCDebugger.PLUGIN_ID,

-							RunControl.STEP_RETURN_NOT_SUPPORTED));

-					} else {

-						drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,

-								"InvocationTargetException thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$

-								+ ite.getLocalizedMessage()));

-					}

-					drm.done();

-				} catch (Exception e) {

-					drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,

-							"exception thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$

-							+ e.getLocalizedMessage()));

-					drm.done();

-				}

+				runControlService.step(threadDMC, StepType.STEP_RETURN, drm);

 			}

 		};

 

 		try {

 			session.getExecutor().execute(query);

 		} catch (Exception e) {

-			Assert.fail(e.getLocalizedMessage());

+			fail(e.getLocalizedMessage());

 		}

 

 		IStatus status = query.get(5, TimeUnit.SECONDS);

@@ -195,15 +197,6 @@
 	}

 

 	@Test

-	public void testRootDMC() {

-		RunControl.RootExecutionDMC rootDMC = runControlService.getRootDMC();

-		assertNotNull(rootDMC);

-		assertNull(rootDMC.getSymbolDMContext());

-		assertFalse(rootDMC.canDetach());

-		assertFalse(rootDMC.canStep());

-	}

-

-	@Test

 	public void testThreadDMC() {

 		assertFalse(threadDMC.canDetach());

 		ExecutionDMC exeDMC = null;

@@ -232,38 +225,6 @@
 	}

 

 	@Test

-	public void unitTestRunControlStepIntoOneInstruction() throws Exception {

-		waitRunToLine(runControlService, dbg_derived_types_cpp, 285);

-

-		// 	private void stepOverOneInstruction(ExecutionDMC, IAddress, RequestMonitor)

-

-		final Class<?>[] stepIntoArgClasses = new Class<?>[] {ExecutionDMC.class, RequestMonitor.class};

-		Query<IStatus> query = new Query<IStatus>() {

-			@Override

-			protected void execute(final DataRequestMonitor<IStatus> drm) {

-				Object[] stepIntoArgs = new Object[] {threadDMC, drm};

-				try {

-					TestReflectionHelper.objectFromPrivateFunctionWithArgs(

-							runControlService, "stepIntoOneInstruction", stepIntoArgs, stepIntoArgClasses);

-				} catch (Exception e) {

-					drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,

-							"exception thrown invoking RunControl#stepIntoOneInstruction()"//$NON-NLS-1$

-							+ e.getLocalizedMessage()));

-					drm.done();

-				}

-			}

-		};

-

-		session.getExecutor().execute(query);

-

-		query.get(5, TimeUnit.SECONDS);

-		assertTrue(query.isDone());

-

-		updateSuspendedFrame(200);

-		assertControlIsAt("dbg_derived_types.cpp", "structs", 40);

-	}

-

-	@Test

 	public void unitTestRunControlStepOverOneInstruction() throws Exception {

 		waitRunToLine(runControlService, dbg_derived_types_cpp, 285);

 

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/SimpleDebuggerTest.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/SimpleDebuggerTest.java
index ed04436..bea6bb6 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/SimpleDebuggerTest.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/debugger/tests/SimpleDebuggerTest.java
@@ -53,12 +53,19 @@
 		String reqdLauncher = getRequiredLaunchConfigurationType();

 		if (reqdLauncher != null) {

 			if (!TestUtils.hasLaunchConfiguationType(reqdLauncher)) {

+				System.out.println("\n== " + getClass().getName()

+						+ ":\n== => Required Launcher " + reqdLauncher

+						+ " not found for album " + getAlbumName());

 				return;

 			}

 		}

 		reqdLauncher = getRequiredTCFAgentLauncher();

 		if (reqdLauncher != null) {

 			if (!TestUtils.hasTCFAgentLauncher(reqdLauncher)) {

+				System.out.println("\n== " + getClass().getName()

+						+ ":\n== => Required TCF Agent Launcher "

+						+ reqdLauncher + " not found for album "

+						+ getAlbumName());

 				return;

 			}

 		}

diff --git a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/tests/TestDwarfReader.java b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/tests/TestDwarfReader.java
index 6db3025..f21f295 100644
--- a/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/tests/TestDwarfReader.java
+++ b/org.eclipse.cdt.debug.edc.tests/src/org/eclipse/cdt/debug/edc/tests/TestDwarfReader.java
@@ -1446,7 +1446,10 @@
 			TestUtils.showDebugPerspective();

 			dwarfAlbum = DwarfFrameRegisterAlbum.openAlbum();

 			dwarfAlbum.launchAndWaitForSuspendedContext();

-			if (dwarfAlbum.getLaunch() == null) return;

+			if (dwarfAlbum.getLaunch() == null) {

+				System.out.println("== testShowTPtr() reporting PASSED but will be skipped.");

+				return;

+			}

 			edcTracker = new EDCServicesTracker(EDCDebugger.getBundleContext(), dwarfAlbum.getSession().getId());

 			Assert.assertNotNull(edcTracker);

 		} catch (Exception e) {

diff --git a/org.eclipse.cdt.debug.edc.x86/src/org/eclipse/cdt/debug/edc/x86/X86Stack.java b/org.eclipse.cdt.debug.edc.x86/src/org/eclipse/cdt/debug/edc/x86/X86Stack.java
index f4669f6..da97ce8 100644
--- a/org.eclipse.cdt.debug.edc.x86/src/org/eclipse/cdt/debug/edc/x86/X86Stack.java
+++ b/org.eclipse.cdt.debug.edc.x86/src/org/eclipse/cdt/debug/edc/x86/X86Stack.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 Nokia and others.
+ * 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
@@ -81,7 +81,7 @@
 		long eipValue = Long.valueOf(registersService.getRegisterValue(context, "EIP"), 16);
 		long espValue = Long.valueOf(registersService.getRegisterValue(context, "ESP"), 16);
 		long ebpValue = Long.valueOf(registersService.getRegisterValue(context, "EBP"), 16);
-		
+
 		long baseAddress = ebpValue;
 		long instructionAddress = eipValue;
 		long returnAddress = 0;
@@ -96,6 +96,11 @@
 			IEDCModuleDMContext module = modules.getModuleByAddress(context.getSymbolDMContext(), new Addr64(Long
 					.toString(instructionAddress)));
 			
+			if (module != null) {
+				// make sure the symbols are loaded for this module if they exist
+				module.getSymbolReader(true);
+			}
+
 			boolean isFramePushed = true;
 			boolean detected = false;
 			X86PreservedRegisters preserved = new X86PreservedRegisters();
@@ -166,20 +171,20 @@
 			properties.put(StackFrameDMC.PRESERVED_REGISTERS, preserved.getPreservedRegisters());
 			frames.add(new EdcStackFrame(properties));
 			
-			// avoid recursive loop
-			if (level > 0 && baseAddress == previousBaseAddress) {
+			if (previousBaseAddress == 0	// Bail out when we hit the top of the stack frame
+
+					// avoid recursive loop
+					|| level > 0 && baseAddress == previousBaseAddress
+
+					// no more than requested (well, 1 extra so <...more frames...> works)
+					|| endIndex != ALL_FRAMES && level == endIndex) {
+
 				properties.put(StackFrameDMC.ROOT_FRAME, true);
 				break;
 			}
-			
+
 			baseAddress = previousBaseAddress;
 			instructionAddress = returnAddress;
-			
-			// Bail out when we hit the top of the stack frame
-			if (baseAddress == 0) {
-				properties.put(StackFrameDMC.ROOT_FRAME, true);
-				break;
-			}
 		}
 	
 		return frames;
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/EvaluateID.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/EvaluateID.java
index 87a50ce..83ab2e1 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/EvaluateID.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/EvaluateID.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions;
 
+import java.math.BigInteger;
 import java.text.MessageFormat;
 import java.util.Collection;
 import java.util.List;
@@ -25,9 +26,24 @@
 import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ProcessExecutionDMC;
 import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ThreadExecutionDMC;
 import org.eclipse.cdt.debug.edc.internal.services.dsf.Symbols;
+import org.eclipse.cdt.debug.edc.internal.symbols.ConstType;
+import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IConstType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IInheritance;
+import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IQualifierType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeType;
+import org.eclipse.cdt.debug.edc.internal.symbols.ITypedef;
 import org.eclipse.cdt.debug.edc.internal.symbols.InvalidVariableLocation;
+import org.eclipse.cdt.debug.edc.internal.symbols.MemoryVariableLocation;
+import org.eclipse.cdt.debug.edc.internal.symbols.PointerType;
+import org.eclipse.cdt.debug.edc.internal.symbols.ReferenceType;
+import org.eclipse.cdt.debug.edc.internal.symbols.TypedefType;
+import org.eclipse.cdt.debug.edc.internal.symbols.VolatileType;
 import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
 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.Stack;
 import org.eclipse.cdt.debug.edc.services.Stack.EnumeratorDMC;
@@ -38,6 +54,7 @@
 import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
 import org.eclipse.cdt.debug.edc.symbols.ILocationProvider;
 import org.eclipse.cdt.debug.edc.symbols.IScope;
+import org.eclipse.cdt.debug.edc.symbols.IType;
 import org.eclipse.cdt.debug.edc.symbols.IVariable;
 import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
 import org.eclipse.cdt.debug.edc.symbols.TypeUtils;
@@ -126,6 +143,7 @@
 					valueLocation = provider.getLocation(servicesTracker, frame, module.toLinkAddress(frame.getInstructionPtrAddress()),
 														 TypeUtils.isConstType(variable.getVariable().getType()));
 				}
+
 				if (valueLocation == null) {
 					// unhandled
 					valueLocation
@@ -134,6 +152,11 @@
 												   variable.getName()));
 				}
 
+				// if requested, check for and use RTTI information
+				if (EDCDebugger.getResolveRttiTypes() && !(valueLocation instanceof InvalidVariableLocation)) {
+					handleRTTI(valueLocation, variable, servicesTracker, frame);
+				}
+
 				// create a VariableWithValue and push on the stack
 				VariableWithValue varWval = new VariableWithValue(servicesTracker, frame, variable.getVariable());
 				varWval.setValueLocation(valueLocation);
@@ -160,8 +183,9 @@
 				// first attempt to match against variable names in the module
 				IEDCSymbolReader reader = module.getSymbolReader();
 				if (reader instanceof EDCSymbolReader) {
-					if (findGlobalVariable(searchName, (EDCSymbolReader)reader, servicesTracker)
-						|| findLocalVariable(searchName, module, (EDCSymbolReader)reader, servicesTracker))
+					EDCSymbolReader edcReader = (EDCSymbolReader)reader;
+					if (findGlobalVariable(searchName, module, edcReader, servicesTracker)
+						|| findLocalVariable(searchName, module, edcReader, servicesTracker))
 						return;
 				}
 
@@ -184,12 +208,96 @@
 	}
 
 	/**
+	 * 
+	 * @param valueLocation
+	 * @param variable
+	 * @param servicesTracker
+	 * @param frame
+	 * @throws CoreException
+	 */
+	private void handleRTTI(IVariableLocation valueLocation, VariableDMC variable,
+			EDCServicesTracker servicesTracker,	StackFrameDMC frame) throws CoreException {
+
+		// only check for RTTI when you have a pointer or reference of a composite type
+		// that has RTTI info
+		IType varType = variable.getVariable().getType();
+		boolean pointerType = varType instanceof IPointerType;
+		boolean referenceType = varType instanceof IReferenceType;
+		if (!pointerType && !referenceType)
+			return;
+
+		IType pointedToType = TypeUtils.getStrippedType(varType.getType());
+
+		if (!(pointedToType instanceof ICompositeType)
+				|| !((ICompositeType)pointedToType).hasRuntimeTypeInfo())
+			return;
+
+		ICompositeType composite = (ICompositeType)pointedToType;
+
+		// determine the location of the runtime type info
+		long originalAddr = valueLocation.readValue(4).longValue();
+		long runtimeTypeAddr = originalAddr + composite.getRuntimeTypeOffset(); 
+		MemoryVariableLocation runtimeTypeLocation = new MemoryVariableLocation(
+				servicesTracker, frame, BigInteger.valueOf(runtimeTypeAddr), true);
+
+		// get the runtime type
+		IType runtimeType = composite.getRuntimeType(runtimeTypeLocation);
+
+		if (runtimeType != null && pointedToType != runtimeType) {
+			// the runtime type differs from the original type, so clone the variable,
+			// and make its type has the same qualifiers but with the runtime composite
+			IType subType = varType.getType();
+			IType valueType = varType.getType();
+			if (referenceType)
+				valueType = new ReferenceType("", valueType.getScope(),
+										valueType.getByteSize(), valueType.getProperties());
+			else
+				valueType = new PointerType("", valueType.getScope(),
+										4, valueType.getProperties());
+
+			// if there are qualifiers, copy them, too
+			IType type = valueType;
+			while (subType instanceof ITypedef || subType instanceof IQualifierType) {
+				IType newSubType = null;
+				if (subType instanceof ITypedef) {
+					ITypedef oldTypedef = (ITypedef)subType;
+					newSubType = new TypedefType(oldTypedef.getName(),
+							oldTypedef.getScope(),oldTypedef.getProperties());
+				} else {
+					IQualifierType oldQualifierType = (IQualifierType)subType;
+					if (subType instanceof IConstType)
+						newSubType = new ConstType(oldQualifierType.getScope(),
+								oldQualifierType.getProperties());
+					else
+						newSubType = new VolatileType(oldQualifierType.getScope(),
+								oldQualifierType.getProperties());
+				}
+				type.setType(newSubType);
+				type = newSubType;
+				subType = subType.getType();
+			}
+			type.setType(runtimeType);
+
+			IVariable variableWithNewType = variable.getVariable().copyWithNewType(type);
+			variable.setVariable(variableWithNewType);
+
+			IInheritance[] inheritances = ((ICompositeType)runtimeType).getInheritances();
+			for (IInheritance inheritance : inheritances) {
+				if (inheritance.getType() == composite) {
+					((IRuntimeType)valueType).setRuntimeOffset(-inheritance.getFieldsOffset());
+					break;
+				}
+			}
+		}
+	}
+
+	/**
 	 * @param servicesTracker
 	 * @param searchName
 	 * @param idip
 	 * @param baseLinkAddress
 	 */
-	private boolean findGlobalVariable(String searchName,
+	private boolean findGlobalVariable(String searchName, IEDCModuleDMContext module,
 			EDCSymbolReader reader, EDCServicesTracker servicesTracker) {
 
 		IDebugInfoProvider idip = reader.getDebugInfoProvider();
@@ -202,8 +310,10 @@
 			  = var.getLocationProvider()
 				   .getLocation(servicesTracker, null, reader.getBaseLinkAddress(), 
 								TypeUtils.isConstType(var.getType()));
-			if (loc instanceof InvalidVariableLocation)
+			if (!(loc instanceof MemoryVariableLocation))
 				continue;
+			MemoryVariableLocation memLoc = (MemoryVariableLocation)loc;
+			memLoc.setModuleContext(module);
 
 			VariableWithValue varWval
 			  = new VariableWithValue(servicesTracker, null, var);
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/FieldReference.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/FieldReference.java
index fd3daa6..1790a82 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/FieldReference.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/eval/ast/engine/instructions/FieldReference.java
@@ -22,6 +22,7 @@
 import org.eclipse.cdt.debug.edc.internal.symbols.IField;
 import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
 import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeType;
 import org.eclipse.cdt.debug.edc.symbols.IType;
 import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
 import org.eclipse.cdt.debug.edc.symbols.TypeUtils;
@@ -61,16 +62,17 @@
 		if (operand == null)
 			return;
 
-		IType variableType = TypeUtils.getStrippedType(operand.getValueType());
+		IType originalVariableType = TypeUtils.getStrippedType(operand.getValueType()); 
+		IType variableType = originalVariableType;
 
 		IVariableLocation location = null;
 		boolean referenceType = variableType instanceof IReferenceType;
+		boolean pointerType = variableType instanceof IPointerType;
 
 		if (refExpression.isPointerDereference()) {
 			// '->' operator requires a pointer type
-			boolean validPointerType = variableType instanceof IPointerType;
-			
-			if (!validPointerType) {
+
+			if (!pointerType) {
 				throw EDCDebugger.newCoreException(ASTEvalMessages.FieldReference_InvalidPointerDeref);
 			}
 
@@ -115,7 +117,10 @@
 			// pointer with '->' operator, or reference with '.' 
 			location = VariableLocationFactory.createMemoryVariableLocation(
 					fInterpreter.getServicesTracker(), fInterpreter.getContext(),
-					operand.getValue());
+					((referenceType || pointerType) ?
+							  Long.valueOf(operand.getValue().longValue()
+										+ ((IRuntimeType)originalVariableType).getRuntimeOffset())
+							: operand.getValue()));
 		} else {
 			// '.' operator
 			location = operand.getValueLocation();
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/BreakpointAttributeTranslator.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/BreakpointAttributeTranslator.java
index 4c1f78d..258fd42 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/BreakpointAttributeTranslator.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/BreakpointAttributeTranslator.java
@@ -20,13 +20,16 @@
 import org.eclipse.cdt.debug.core.model.ICBreakpoint;
 import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
 import org.eclipse.cdt.debug.core.model.ICWatchpoint;
+import org.eclipse.cdt.debug.core.model.ICWatchpoint2;
 import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
 import org.eclipse.cdt.debug.edc.internal.EDCTrace;
+import org.eclipse.cdt.debug.edc.internal.symbols.IBasicType;
+import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
 import org.eclipse.cdt.debug.edc.internal.symbols.InvalidVariableLocation;
-import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
 import org.eclipse.cdt.debug.edc.services.IEDCExpression;
 import org.eclipse.cdt.debug.edc.services.ITargetEnvironment;
-import org.eclipse.cdt.debug.edc.services.Stack;
+import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider;
+import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
 import org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider.ILineAddresses;
 import org.eclipse.cdt.debug.edc.symbols.IType;
 import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
@@ -48,6 +51,7 @@
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.DebugPlugin;
@@ -68,26 +72,35 @@
 		assert targetEnvService != null;
 	}
 
+	/**
+	 * This method decides whether we need to re-install the breakpoint
+	 * based on the attributes change (refer to caller in BreakpointsMediator).
+	 * <p>
+	 * For EDC, following changed attributes justify re-installation.<br>
+	 * - {@link IMarker#LINE_NUMBER}<br>
+	 * - {@link IBreakpoint#ENABLED}<br>
+	 * - {@link ICLineBreakpoint#FUNCTION}<br>
+	 * - {@link ICLineBreakpoint#ADDRESS}<br>
+	 * - {@link ICWatchpoint#EXPRESSION}<br>
+	 * - {@link ICWatchpoint#READ}<br>
+	 * - {@link ICWatchpoint#WRITE}<br>
+	 * - {@link ICWatchpoint2#RANGE}<br>
+	 */         
 	public boolean canUpdateAttributes(IBreakpointDMContext bp, Map<String, Object> delta) {
-		/*
-		 * This method decides whether we need to re-install the breakpoint
-		 * based on the attributes change (refer to caller in
-		 * BreakpointsMediator). For EDC, following changed attributes justify
-		 * re-installation.
-		 */         
         // Check if there is any modified attribute
         if (delta == null || delta.size() == 0)
             return true;
 
         // Check the "critical" attributes
         // TODO: threadID change
-        if (delta.containsKey(IMarker.LINE_NUMBER)     // Line number
+        if (delta.containsKey(IMarker.LINE_NUMBER)        // Line number
         ||  delta.containsKey(IBreakpoint.ENABLED)        // EDC don't handle enable/disable. TODO: ask ITargetEnvironment service if it can handle it. 
-        ||  delta.containsKey(ICLineBreakpoint.FUNCTION)        // Function name
-        ||  delta.containsKey(ICLineBreakpoint.ADDRESS)         // Absolute address
-        ||  delta.containsKey(ICWatchpoint.EXPRESSION)      // Watchpoint expression
-        ||  delta.containsKey(ICWatchpoint.READ)            // Watchpoint type
-        ||  delta.containsKey(ICWatchpoint.WRITE)) {        // Watchpoint type
+        ||  delta.containsKey(ICLineBreakpoint.FUNCTION)  // Function name
+        ||  delta.containsKey(ICLineBreakpoint.ADDRESS)   // Absolute address
+        ||  delta.containsKey(ICWatchpoint.EXPRESSION)    // Watchpoint expression
+        ||  delta.containsKey(ICWatchpoint.READ)          // Watchpoint type
+        ||  delta.containsKey(ICWatchpoint.WRITE)         // Watchpoint type
+        ||	delta.containsKey(ICWatchpoint2.RANGE)) {     // Watchpoint size
             return false;
         }
 
@@ -189,7 +202,89 @@
 		return new HashMap<String, Object>(platformBPAttrDelta);
 	}
 
-    public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint, 
+	private IAddress getWatchpointLocAddress(IVariableLocation wpLoc) {
+		return (wpLoc != null && !(wpLoc instanceof InvalidVariableLocation))
+			? wpLoc.getAddress() : null;
+	}
+
+	private boolean isValidWatchpointType(IType t) {
+		return t instanceof IPointerType
+			|| (t instanceof IBasicType
+				&& ((IBasicType)t).getBaseType() == IBasicType.t_int);
+	}
+
+	private String getWatchpointAddressFromValue(IEDCExpression expr, IType exprType) {
+		String result = null;
+		if (isValidWatchpointType(exprType)) {
+			result = expr.getEvaluatedValueString();
+			if (result.startsWith("0x"))
+				result.substring(2);
+		}
+		return result;
+	}
+
+	private Map<String, Object> setWatchpointAttrs(String wpAddr, IType type,
+			Map<String, Object> allAttr) {
+		Map<String,Object> wpAttr = new HashMap<String, Object>(allAttr);
+		wpAttr.put(Breakpoints.RUNTIME_ADDRESS, wpAddr);
+		Object range = wpAttr.get(CWatchpoint.RANGE);
+		if (range instanceof String) {
+			range = new Integer((String)range);
+			wpAttr.put(CWatchpoint.RANGE, range);	// even if 0, avoid classCastException later
+		}
+		if (type != null && (range == null
+				|| (range instanceof Number && ((Number)range).equals(0)))) {
+			wpAttr.put(CWatchpoint.RANGE, type.getByteSize());
+		}
+		return wpAttr;
+	}
+
+	private static IStatus warningStatus(String format, Object ... arguments) {
+		return new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,
+						  MessageFormat.format(format, arguments));
+	}
+
+	/**
+	 * if the module's symbolReader is an EDCSymbolReader, and points
+	 * to a debugInfoProvider that will give us files to compare to,
+	 * see if the file of interest is in the given module context,
+	 * and set a breakpoint problem marker if so.
+	 * @param icBP should be a CLineBreakpoint
+	 * @param context should be a Module-context
+	 * @param bpFile full-path to file CLineBreakpoint occurs in
+	 * @param statusMessage the warning message for the marker
+	 */
+	private void addBreakpointProblemMarker(final ICBreakpoint icBP,
+			final IBreakpointsTargetDMContext context, final String bpFile,
+			final String statusMessage) {
+		Modules.ModuleDMC module = (Modules.ModuleDMC)context;
+		IEDCSymbolReader reader = module.getSymbolReader(); 
+		if (! (reader instanceof EDCSymbolReader))
+			return;
+
+		IDebugInfoProvider debugInfoProvider
+		  = ((EDCSymbolReader)reader).getDebugInfoProvider();
+		if (debugInfoProvider == null)
+			return;
+
+		String[] sourceFiles = debugInfoProvider.getSourceFiles(new NullProgressMonitor());
+		if (sourceFiles == null)
+			return;
+
+		for (String file : sourceFiles) {
+			if (file.equals(bpFile)) {
+				Breakpoints bkptService
+				  = dsfServicesTracker.getService(Breakpoints.class);
+				IBreakpointDMContext targetBP
+				  = bkptService.getTargetBreakpoint(icBP, context);
+				bkptService.addBreakpointProblemMarker(targetBP, statusMessage,
+													   IMarker.SEVERITY_WARNING, icBP);
+				return;
+			}
+		}
+	}
+
+    public void resolveBreakpoint(final IBreakpointsTargetDMContext context, final IBreakpoint breakpoint, 
     		final Map<String, Object> attributes, final DataRequestMonitor<List<Map<String, Object>>> drm) {
 		
     	final List<Map<String, Object>>	targetBPAttrs = new ArrayList<Map<String, Object>>(1);
@@ -218,53 +313,43 @@
 										EDCServicesMessages
 										.BPAttrTranslator_WatchptNoExprService,
 										wpExpr)));
-				drm.done();
 			} else {
 				IEDCExpression exprDMC
 				  = (IEDCExpression)expressions.createExpression(module, wpExpr);
 				exprDMC.evaluateExpression();
+
+				/*
+				 * first, try to get the address as a variable location;
+				 * if that fails, try to evaluate it as a value to be
+				 * used as an address at which to set the watchpoint.
+				 */
+
 				IVariableLocation varLoc = exprDMC.getEvaluatedLocation();
-				IAddress wpAddr;
-				if (varLoc == null || varLoc instanceof InvalidVariableLocation
-						|| (wpAddr = varLoc.getAddress()) == null) {
-					drm.setStatus(
-							new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,
-									   MessageFormat.format(
-											   EDCServicesMessages
-											   .BPAttrTranslator_WatchptLocationInvalid,
-											   wpExpr, module.getName())));
+				IAddress wpAddr = getWatchpointLocAddress(varLoc);
+				IType wpType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());
+
+				String wpAddrString;
+				if (wpAddr != null) {
+					wpAddrString = wpAddr.toString(16);					
 				} else {
-					boolean wpValidForModule = module.containsAddress(wpAddr);
-					if (!wpValidForModule
-							&& varLoc.getContext() instanceof Stack.StackFrameDMC) {
-						Stack.StackFrameDMC frame
-						  = (Stack.StackFrameDMC)varLoc.getContext();
-						wpValidForModule = module == frame.getModule();
-					}
-
-					String wpAddrString = wpAddr.toString(16);
-					// used in both parts of "if (...) {...} else {...}" below
-
-					if (wpValidForModule) {
-						IType exprType
-						  = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());
-						Map<String,Object> wpAttr
-						  = new HashMap<String, Object>(attributes);
-						wpAttr.put(Breakpoints.RUNTIME_ADDRESS, wpAddrString);
-						wpAttr.put(CWatchpoint.RANGE, exprType.getByteSize());
-						targetBPAttrs.add(wpAttr);
-						drm.setData(targetBPAttrs);
-					} else {
-						drm.setStatus(
-								new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,
-										   MessageFormat.format(
-												   EDCServicesMessages
-												   .BPAttrTranslator_WatchptNotInModule,
-												   wpExpr, wpAddrString, module.getName())));
+					wpAddrString = getWatchpointAddressFromValue(exprDMC, wpType);
+					if (wpAddrString != null) {
+						wpAddr = new Addr64(wpAddrString);
+						if (wpAddr != null)	// guarantees value was well-formed addr
+							wpAddrString = wpAddr.toString(16);	// guarantees base16
 					}
 				}
-				drm.done();
+
+				if (wpAddr != null) {
+					targetBPAttrs.add(setWatchpointAttrs(wpAddrString, wpType, attributes));
+					drm.setData(targetBPAttrs);
+				} else {
+					drm.setStatus(
+							warningStatus(EDCServicesMessages.BPAttrTranslator_WatchptLocationInvalid,
+										  wpExpr, module.getName()));
+				}
 			}
+			drm.done();
 		} else {
 			String bpType = (String)attributes.get(Breakpoints.BREAKPOINT_SUBTYPE);
 			if (bpType.equals(Breakpoints.ADDRESS_BREAKPOINT)) {
@@ -284,10 +369,8 @@
 					drm.setData(targetBPAttrs);
 				} else {
 					drm.setStatus(
-							new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,
-									MessageFormat.format(
-											EDCServicesMessages.BPAttrTranslator_BkptAddressNotInModule,
-											addr, module.getName())));
+							warningStatus(EDCServicesMessages.BPAttrTranslator_BkptAddressNotInModule,
+										  addr, module.getName()));
 				}
 				
 				drm.done();
@@ -322,20 +405,19 @@
 				Modules modulesService = dsfServicesTracker.getService(Modules.class);
 				ISymbolDMContext sym_dmc = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);
 	
-				String compileFile = EDCLaunch.getLaunchForSession(dsfSession.getId()).getCompilationPath(bpFile);
-				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-						"BP file: " + bpFile + " Compile file: " + compileFile); }
 				/*
 				 * Look for code lines within five lines above and below the line in
 				 * question as we don't want to move a breakpoint too far.
 				 */
-				modulesService.findClosestLineWithCode(sym_dmc, compileFile, line, 5, 
+				modulesService.findClosestLineWithCode(sym_dmc, bpFile, line, 5, 
 						new DataRequestMonitor<ILineAddresses>(dsfSession.getExecutor(), drm) {
 	
 					@Override
 					protected void handleCompleted() {
 						if (! isSuccess()) {
-							drm.setStatus(getStatus());
+							final IStatus status = getStatus();
+							addBreakpointProblemMarker(icBP, context, bpFile, status.getMessage());
+							drm.setStatus(status);
 							drm.done();
 							if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
 									"findClosestLineWithCode failed: " + drm.getStatus()); }
@@ -361,12 +443,10 @@
 						}
 	
 						drm.setData(targetBPAttrs);
-						
+
 						int actualCodeLine = codeLine.getLineNumber();
 						
-						if (actualCodeLine == line)
-							drm.done();
-						else {		
+						if (actualCodeLine != line) {		
 							// breakpoint is resolved to a different line (the closest code line).
 							// If there is no user breakpoint at that line, we move the breakpoint there.
 							// Otherwise just mark this breakpoint as unresolved.
@@ -402,12 +482,11 @@
 								// At this point the "drm" contains a valid list of "targetBPAttrs", namely
 								// we treat this BP as resolved. This is needed for such moved-BP to work 
 								// on debugger start.
-								drm.done();
 							} else {
 								targetBPAttrs.clear();	// mark the BP as unresolved by clearing the list.
-								drm.done();
 							}
 						}
+						drm.done();
 					}
 				});
 			}
@@ -489,14 +568,14 @@
 		return canUpdateAttributes(null, attrDelta);
 	}
 
-    /**
-     * Find the CDT line breakpoint that exists at the given line of the 
-     * given file.
-     *  
-     * @param bpFile
-     * @param bpLine
-     * @return IBreakpoint if found, null otherwise.
-     */
+	/**
+	 * Find the CDT line breakpoint that exists at the given line of the 
+	 * given file.
+	 *  
+	 * @param bpFile
+	 * @param bpLine
+	 * @return IBreakpoint if found, null otherwise.
+	 */
 	static private IBreakpoint findUserBreakpointAt(
 			String bpFile, int bpLine) {
 		IBreakpoint[] platformBPs = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
@@ -529,4 +608,3 @@
 		return null;
 	}
 }
- 
\ No newline at end of file
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Breakpoints.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Breakpoints.java
index a41918a..561ee12 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Breakpoints.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Breakpoints.java
@@ -12,6 +12,7 @@
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.IllegalFormatException;
@@ -43,6 +44,7 @@
 import org.eclipse.cdt.debug.edc.services.Stack;
 import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;
 import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
+import org.eclipse.cdt.debug.internal.core.breakpoints.CWatchpoint;
 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
 import org.eclipse.cdt.dsf.concurrent.Immutable;
@@ -52,7 +54,6 @@
 import org.eclipse.cdt.dsf.datamodel.DMContexts;
 import org.eclipse.cdt.dsf.datamodel.IDMContext;
 import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2;
-import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslator;
 import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
 import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
 import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
@@ -152,7 +153,51 @@
 	static final String INVALID_CONDITION = "Invalid condition"; //$NON-NLS-1$
 
 	// User breakpoints (those from the IDE) currently installed.
-	private final Map<IBreakpointDMContext, BreakpointDMData> userBreakpoints = new HashMap<IBreakpointDMContext, BreakpointDMData>();
+	private final Map<IBreakpointDMContext, BreakpointDMData> userBreakpoints
+	  = Collections.synchronizedMap(new HashMap<IBreakpointDMContext, BreakpointDMData>());
+
+	private static class RuntimeWatchpoint {
+		final IExecutionDMContext context;
+		final String address;
+		final Number size;
+		RuntimeWatchpoint(IExecutionDMContext exeDMC, String addr, Number range) {
+			context = exeDMC;
+			address = addr;
+			size = range;
+		}
+
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + context.hashCode();
+			result = prime * result + address.hashCode();
+			result = prime * result + size.hashCode();
+			return result;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (getClass() != obj.getClass())
+				return false;
+			RuntimeWatchpoint other = (RuntimeWatchpoint) obj;
+			if (!context.equals(other.context))
+				return false;
+			if (!address.equals(other.address))
+				return false;
+			if (!size.equals(other.size))
+				return false;
+			return true;
+		}
+	}
+
+	/** a map of breakpoints to enabled watchpoints */
+	private final Map<IBreakpointDMContext, RuntimeWatchpoint> enabledWatchpoints
+	  = Collections.synchronizedMap(new HashMap<IBreakpointDMContext, RuntimeWatchpoint>());
 
 	/**
 	 * Internal temporary breakpoints set by debugger for stepping.
@@ -362,16 +407,21 @@
 
 		@Override
 		public String toString() {
-			String s = getFileName();
-			if (s == null) // address breakpoint
-				s = getAddresses()[0].toHexAddressString();
-			else {
-				if (getFunctionName() != null)
-					s += ": " + getFunctionName();
-				else
-					s += ":line " + getLineNumber();
-			}
-			return "Breakpoint@" + s;
+			String s = getBreakpointType();
+			boolean w = s.equals(WATCHPOINT);
+			String e = w ? getExpression() : null;
+			String f = getFileName();
+			if (f == null && e == null) // address breakpoint/watchpoint
+				s += "@" + getAddresses()[0].toHexAddressString();
+			else if (w)
+				s += ": expression \"" + e
+					 + ((f != null ) ? "\"; File: " + f : "\"");
+			else if (getFunctionName() != null)
+				s += "@" + f + ": " + getFunctionName();
+			else
+				s += "@" + f + ":line " + getLineNumber();
+
+			return s;
 		}
 
 		public void incrementHitCount() {
@@ -534,6 +584,9 @@
 			return;
 
 		for (BreakpointDMData edcBp : userBreakpoints.values()) {
+			String bpType = edcBp.getBreakpointType();
+			if (bpType != null && bpType.equals(WATCHPOINT))
+				continue;
 			// TODO: bail out if the bp is not software breakpoint.
 
 			IAddress bpAddr = edcBp.getAddresses()[0];
@@ -648,10 +701,15 @@
 
 		IExecutionDMContext exe_dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
 		String bpAddr = (String)attributes.get(RUNTIME_ADDRESS);
+		Number range = (Number)attributes.get(CWatchpoint.RANGE);
 
 		assert exe_dmc != null : "DMContext is unknown in addWatchpoint().";
 		assert bpAddr != null;
-		
+
+		final RuntimeWatchpoint newWatchpoint = new RuntimeWatchpoint(exe_dmc, bpAddr, range);
+		if (enabledWatchpoints.containsValue(newWatchpoint))
+			return;
+
 		createWatchpoint(exe_dmc, new Addr64(bpAddr, 16), attributes, new DataRequestMonitor<BreakpointDMData>(
 				getExecutor(), drm) {
 
@@ -668,6 +726,7 @@
 
 						// Remember this in our global list.
 						userBreakpoints.put(bp_dmc, bpd);
+						enabledWatchpoints.put(bp_dmc, newWatchpoint);
 
 						drm.done();
 					}
@@ -831,16 +890,16 @@
 	private void createWatchpoint(final IDMContext dmc, final IAddress address,
 			final Map<String, Object> allProps,
 			final DataRequestMonitor<BreakpointDMData> drm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				final long id = getNewBreakpointID();
-				final IBreakpointDMContext bp_dmc
-				  = new BreakpointDMContext(getSession().getId(),
-						  					new IDMContext[] { dmc },
-						  					id);
-				final IAddress[] bp_addrs = new IAddress[] { address };
+		if (hasTCFWatchpointSupport()) {
+			asyncExec(new Runnable() {
+				public void run() {
+					final long id = getNewBreakpointID();
+					final IBreakpointDMContext bp_dmc
+					  = new BreakpointDMContext(getSession().getId(),
+							  					new IDMContext[] { dmc },
+							  					id);
+					final IAddress[] bp_addrs = new IAddress[] { address };
 
-				if (hasTCFWatchpointSupport()) {
 					final Map<String, Object> tcfProperties = new HashMap<String, Object>();
 					tcfProperties.put(TCF_BP_ID, Long.toString(id));
 					tcfProperties.put(TCF_BP_ENABLED, true);
@@ -868,13 +927,15 @@
 					allProps.put(TCF_PROPERTIES, tcfProperties);
 
 					drm.setData(new BreakpointDMData(id, bp_dmc, bp_addrs, allProps));
-				} else { // generic software watchpoint?  i don't think so, tim!
-					drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
-							"Watchpoints not supported for this system", null));
-				}
-				drm.done();
-			}			
-		}, drm);
+					drm.done();
+
+				}}, drm);
+
+		} else { // generic software watchpoint?  i don't think so, tim!
+			drm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,
+						"Watchpoints not supported for this system", null));
+			drm.done();
+		}			
 	}
 
 
@@ -1025,6 +1086,7 @@
 			
 				// Remove it from our record.
 				userBreakpoints.remove(dmc);
+				enabledWatchpoints.remove(dmc);
 
 				// Remove problem marker if any. 
 				// Note this may be called when the debug session is shut down.
@@ -1069,20 +1131,23 @@
 		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null); }
 	}
 
+	/**
+	 * For EDC, we don't need to do any update on non-significant attribute
+	 * change, e.g. change of Install_count, ignore_count. For significant
+	 * change, the breakpoint will just be re-installed. 
+	 * See {@link BreakpointAttributeTranslator#canUpdateAttributes(IBreakpoints.IBreakpointDMContext, Map)}
+	 */
 	public void updateBreakpoint(IBreakpointDMContext dmc, Map<String, Object> delta, RequestMonitor rm) {
-		/*
-		 * For EDC, we don't need to do any update on non-significant attribute
-		 * change, e.g. change of Install_count, ignore_count. For significant
-		 * change, the breakpoint will just be re-installed. 
-		 * See canUpdateAttributes().
-		 */
 		BreakpointDMData bp = userBreakpoints.get(dmc);
 		if (bp == null)
 			assert false : "Fail to find BreakpointDMData linked with the IBreakpointDMContext:" + dmc;
 		else {
 			Map<String, Object> existingProps = bp.getProperties();
-			for (String key : delta.keySet())
+			for (String key : delta.keySet()) {
 				existingProps.put(key, delta.get(key));
+				if (key.equals(ICBreakpoint.CONDITION))
+					removeBreakpointProblemMarker(dmc);
+			}
 		}
 		rm.done();
 	}
@@ -1315,25 +1380,39 @@
 		BreakpointsMediator2 bmService = getService(BreakpointsMediator2.class);
 		if (bmService == null)
 			return;
-		
+
 		final IBreakpoint breakpoint = bmService.getPlatformBreakpoint(null, targetBP);
 		if (breakpoint == null)
 			return;
 
+		addBreakpointProblemMarker(targetBP, description, severity, breakpoint);
+	}
+
+	protected IBreakpointDMContext getTargetBreakpoint(final IBreakpoint breakpoint,
+			IBreakpointsTargetDMContext bkptTargetDMC) {
+		BreakpointsMediator2 bpm2 = getService(BreakpointsMediator2.class);
+		BreakpointsMediator2.ITargetBreakpointInfo[] targetBPs = bpm2.getTargetBreakpoints(bkptTargetDMC, breakpoint);
+		assert targetBPs == null || targetBPs.length <= 1 : "too many target-breakpoints for platform breakpoint";
+		return targetBPs != null ? targetBPs[0].getTargetBreakpoint() : null;
+	}
+
+	protected void addBreakpointProblemMarker(final IBreakpointDMContext targetBP,
+		final String description, final int severity, final IBreakpoint breakpoint) {
         if (! (breakpoint instanceof ICLineBreakpoint))
         	return;
-
         new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
             @Override
             protected IStatus run(IProgressMonitor monitor) {
             	// If we have already have a problem marker on this breakpoint
             	// we should remove it first.
-                IMarker marker = fBreakpointMarkers.remove(targetBP);
-                if (marker != null) {
-                    try {
-                        marker.delete();
-                    } catch (CoreException e) {
-                    }
+            	if (targetBP != null) {
+	                IMarker marker = fBreakpointMarkers.remove(targetBP);
+	                if (marker != null) {
+	                    try {
+	                        marker.delete();
+	                    } catch (CoreException e) {
+	                    }
+	            	}
             	}
 
                 ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
@@ -1350,8 +1429,8 @@
                     problem_marker.setAttribute(IMarker.SEVERITY,    severity);
                     problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);
 
-                    // And save the baby
-                    fBreakpointMarkers.put(targetBP, problem_marker);
+                    if (targetBP != null)
+                    	fBreakpointMarkers.put(targetBP, problem_marker);
                 } catch (CoreException e) {
                 }
                 
@@ -1359,7 +1438,7 @@
             }
         }.schedule();
 	}
-	
+
 	/**
 	 * Remove problem marker added for the given target breakpoint.
 	 * Note this may be called when debug session is shutdown.
@@ -1406,6 +1485,7 @@
 	public void evaluateBreakpointCondition(IExecutionDMContext context, final BreakpointDMData bp, final DataRequestMonitor<Object> drm) {
 		final String expr = bp.getCondition();
 		if (expr == null || expr.length() == 0) {
+			removeBreakpointProblemMarker(bp.getContext());
 			bp.incrementHitCount();
 			drm.setData(bp.getHitCount() > bp.getIgnoreCount() ? bp : false);
 			drm.done();
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.java
index 52d1e35..a53d21d 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.java
@@ -39,7 +39,9 @@
 
 	public static String BPAttrTranslator_WatchptNoExprService;
 
-	public static String BPAttrTranslator_WatchptNotInModule;
+	public static String Modules_CannotMoveBreakpoint;
+
+	public static String Modules_CannotFindBreakpointSource;
 
 	static {
 		// initialize resource bundle
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.properties b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.properties
index 29f43cd..1c1c9f3 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.properties
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/EDCServicesMessages.properties
@@ -21,4 +21,6 @@
 BPAttrTranslator_WatchptLocationInvalid=Cannot get address for expression "{0}" in module [{1}].
 BPAttrTranslator_WatchptNoContext=Cannot evaluate expression "{0}"; context unavailable.
 BPAttrTranslator_WatchptNoExprService=Cannot evaluate expression "{0}"; EDC Expression service unavailable.
-BPAttrTranslator_WatchptNotInModule=Watchpoint for expression "{0}" at address {1} does not fall in the module [{2}].
+
+Modules_CannotMoveBreakpoint=Unable to find address within {0} source lines of breakpoint in file {1} at line {2}
+Modules_CannotFindBreakpointSource=Unable to find address for source in file {0} at line {1}
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Expressions.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Expressions.java
index 2e9319a..7853025 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Expressions.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Expressions.java
@@ -1,1502 +1,1550 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010, 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.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.core.dom.ast.IASTTypeId;
-import org.eclipse.cdt.core.dom.ast.IBasicType;
-import org.eclipse.cdt.debug.edc.MemoryUtils;
-import org.eclipse.cdt.debug.edc.formatter.ITypeContentProvider;
-import org.eclipse.cdt.debug.edc.formatter.IVariableValueConverter;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.EDCTrace;
-import org.eclipse.cdt.debug.edc.internal.NumberFormatUtils;
-import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.ASTEvaluationEngine;
-import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.IArrayDimensionType;
-import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.InstructionSequence;
-import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.Interpreter;
-import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperandValue;
-import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;
-import org.eclipse.cdt.debug.edc.internal.symbols.IAggregate;
-import org.eclipse.cdt.debug.edc.internal.symbols.IArrayType;
-import org.eclipse.cdt.debug.edc.internal.symbols.ICPPBasicType;
-import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;
-import org.eclipse.cdt.debug.edc.internal.symbols.IEnumeration;
-import org.eclipse.cdt.debug.edc.internal.symbols.IField;
-import org.eclipse.cdt.debug.edc.internal.symbols.IInheritance;
-import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
-import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType;
-import org.eclipse.cdt.debug.edc.internal.symbols.ISubroutineType;
-import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
-import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
-import org.eclipse.cdt.debug.edc.services.DMContext;
-import org.eclipse.cdt.debug.edc.services.IEDCDMContext;
-import org.eclipse.cdt.debug.edc.services.IEDCExpression;
-import org.eclipse.cdt.debug.edc.services.IEDCExpressions;
-import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
-import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider;
-import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
-import org.eclipse.cdt.debug.edc.symbols.IEnumerator;
-import org.eclipse.cdt.debug.edc.symbols.IInvalidVariableLocation;
-import org.eclipse.cdt.debug.edc.symbols.IType;
-import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
-import org.eclipse.cdt.debug.edc.symbols.TypeEngine;
-import org.eclipse.cdt.debug.edc.symbols.TypeUtils;
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
-import org.eclipse.cdt.dsf.concurrent.Immutable;
-import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
-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.IExpressions;
-import org.eclipse.cdt.dsf.debug.service.IExpressions2;
-import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
-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.IRegisters.IRegisterDMContext;
-import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
-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.Status;
-import org.eclipse.core.runtime.jobs.Job;
-
-public class Expressions extends AbstractEDCService implements IEDCExpressions {
-
-	public abstract class BaseEDCExpressionDMC extends DMContext implements IEDCExpression {
-		protected String expression;
-		private InstructionSequence parsedExpression;
-		private final ASTEvaluationEngine engine;
-		private final StackFrameDMC frame;
-		protected Number value;
-		protected IStatus valueError;
-		private IVariableLocation valueLocation;
-		private IType valueType;
-		private boolean hasChildren = false;
-		private String valueString;
-
-		public BaseEDCExpressionDMC(IDMContext parent, String expression, String name) {
-			// use the full expression in the id as their hashcode is based on
-			// id, so they must be unique
-			super(Expressions.this, new IDMContext[] { parent }, name,
-				  ((IEDCDMContext)parent).getID() + '.' + expression);
-			this.expression = expression;
-			frame = DMContexts.getAncestorOfType(parent, StackFrameDMC.class);
-			engine = initEngine(parent);
-		}
-
-		private ASTEvaluationEngine initEngine(IDMContext parent) {
-			if (frame != null)
-				return new ASTEvaluationEngine(getEDCServicesTracker(), frame,
-												frame.getTypeEngine());
-
-			if (parent instanceof ModuleDMC) {
-				IEDCSymbolReader edcSymbolReader = ((ModuleDMC)parent).getSymbolReader();
-				if (edcSymbolReader instanceof EDCSymbolReader) {
-					IDebugInfoProvider debugInfoProvider
-					  = ((EDCSymbolReader)edcSymbolReader).getDebugInfoProvider();
-					TypeEngine typeEngine
-					  = new TypeEngine(getTargetEnvironmentService(), debugInfoProvider);
-					return new ASTEvaluationEngine(getEDCServicesTracker(), parent, typeEngine);
-				}
-			}
-
-			return null;
-		}
-
-		public BaseEDCExpressionDMC(IDMContext parent, String expression) {
-			this(parent, expression, expression);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.DMContext#toString()
-		 */
-		@Override
-		public String toString() {
-			return getExpression();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFrame()
-		 */
-		public IFrameDMContext getFrame() {
-			return frame;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getExpression()
-		 */
-		public String getExpression() {
-			return expression;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression()
-		 */
-		public synchronized void evaluateExpression() {
-			if (value != null || valueError != null)
-				return;
-			
-			String expression = getExpression();
-
-			if (parsedExpression == null) {
-				try {
-					parsedExpression = engine.getCompiledExpression(expression);
-				} catch (CoreException e) {
-					value = null;
-					valueError = e.getStatus();
-					valueLocation = null;
-					valueType = null;
-					return;
-				}
-			}
-
-			if (parsedExpression.getInstructions().length == 0) {
-				value = null;
-				valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,
-						EDCServicesMessages.Expressions_SyntaxError);
-				valueLocation = null;
-				valueType = null;
-				return;
-			}
-
-			Interpreter interpreter;
-			try {
-				interpreter = engine.evaluateCompiledExpression(parsedExpression);
-			} catch (CoreException e) {
-				value = null;
-				valueError = e.getStatus();
-				valueLocation = null;
-				valueType = null;
-				return;
-			}
-			
-			OperandValue variableValue = interpreter.getResult();
-			if (variableValue == null) {
-				value = null;
-				valueError = null;
-				valueLocation = null;
-				valueType = null;
-				return;
-			}
-
-			valueLocation = variableValue.getValueLocation();
-			valueType = variableValue.getValueType();
-			try {
-				value = variableValue.getValue();
-				valueString = variableValue.getStringValue();
-			} catch (CoreException e1) {
-				value = null;
-				valueError = e1.getStatus();
-				return;
-			}
-
-			// for a structured type or array, return the location and note
-			// that it has children
-			if (valueType instanceof IAggregate && valueLocation != null) {
-				// TODO
-				try {
-					value = variableValue.getValueLocationAddress();
-				} catch (CoreException e) {
-					value = null;
-					valueError = e.getStatus();
-				}
-				if (!(value instanceof IInvalidVariableLocation))
-					hasChildren = true;
-			}
-
-			// if the location evaluates to NotLive, the types and values do
-			// not matter
-			if (valueLocation instanceof IInvalidVariableLocation) {
-				value = null;
-				valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,
-						((IInvalidVariableLocation) valueLocation).getMessage());
-				valueLocation = null; //$NON-NLS-1$
-				return;
-			}
-
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFormattedValue(org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext)
-		 */
-		public FormattedValueDMData getFormattedValue(FormattedValueDMContext dmc) {
-			if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(dmc)); }
-			evaluateExpression();
-			String result = ""; //$NON-NLS-1$
-
-			if (valueError != null) {
-				result = valueError.getMessage();
-			} else if (value != null) {
-				result = value.toString();
-				
-				IType unqualifiedType = TypeUtils.getUnRefStrippedType(valueType);
-				
-				String temp = null;
-				String formatID = dmc.getFormatID();
-				
-				// the non-natural formats have expected representations in other
-				// parts of DSF, so be strict about what we return
-				if (formatID.equals(IFormattedValues.HEX_FORMAT)) {
-					temp = NumberFormatUtils.toHexString(value);
-				} else if (formatID.equals(IFormattedValues.OCTAL_FORMAT)) {
-					temp = NumberFormatUtils.toOctalString(value);
-				} else if (formatID.equals(IFormattedValues.BINARY_FORMAT)) {
-					temp = NumberFormatUtils.asBinary(value);
-				} else if (formatID.equals(IFormattedValues.NATURAL_FORMAT)) {
-					// convert non-integer types to original representation
-					if (unqualifiedType instanceof ICPPBasicType) {
-						ICPPBasicType basicType = (ICPPBasicType) unqualifiedType;
-						switch (basicType.getBaseType()) {
-						case ICPPBasicType.t_char:
-							temp = NumberFormatUtils.toCharString(value, valueType);
-							break;
-						case ICPPBasicType.t_wchar_t:
-							temp = NumberFormatUtils.toCharString(value, valueType);
-							break;
-						case ICPPBasicType.t_bool:
-							temp = Boolean.toString(value.longValue() != 0);
-							break;
-						default:
-							// account for other debug formats
-							if (basicType.getName().equals("wchar_t")) { //$NON-NLS-1$
-								temp = NumberFormatUtils.toCharString(value, valueType);
-							}
-							break;
-						}
-					} else if (unqualifiedType instanceof IAggregate || unqualifiedType instanceof IPointerType) {
-						// show addresses for aggregates and pointers as hex in natural format
-						temp = NumberFormatUtils.toHexString(value);
-					} 
-					
-					// TODO: add type suffix if the value cannot fit in
-					// the ordinary range of the base type.
-					// E.g., for an unsigned int, 0xFFFFFFFF should usually be 0xFFFFFFFFU,
-					// and for a long double, 1.E1000 should be 1.E1000L.
-					/*
-					// apply required integer and float suffixes
-					IType unqualifiedType = TypeUtils.getStrippedType(valueType);
-					if (unqualifiedType instanceof ICPPBasicType) {
-						ICPPBasicType basicType = (ICPPBasicType) unqualifiedType;
-						
-						if (basicType.getBaseType() == ICPPBasicType.t_float) {
-							//result += "F"; // no
-						} else if (basicType.getBaseType() == ICPPBasicType.t_double) {
-							if (basicType.isLong() AND actual value does not fit in a double)
-								result += "L";
-						} else if (basicType.getBaseType() == ICPPBasicType.t_int) {
-							if (basicType.isUnsigned() AND actual value does not fit in a signed int)
-								result += "U";
-							if (basicType.isLongLong() AND actual value does not fit in a signed int)
-								result += "LL";
-							else if (basicType.isLong() AND actual value does not fit in a signed int)
-								result += "L";
-						}
-					}
-					 */
-					
-					// for an enumerator, return the name, if any
-					if (unqualifiedType instanceof IEnumeration) {
-						long enumeratorValue = value.longValue();
-
-						IEnumerator enumerator = ((IEnumeration) unqualifiedType).getEnumeratorByValue(enumeratorValue);
-						if (enumerator != null) {
-							if (temp == null)
-								temp = result;
-							
-							temp = enumerator.getName() + " [" + temp + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-						}
-					}
-				}
-				if (temp != null)
-					result = temp; 
-				
-				// otherwise, leave value as is
-				
-				
-			}
-			if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(result)); }
-			return new FormattedValueDMData(result);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getValueLocation()
-		 */
-		public IVariableLocation getValueLocation() {
-			evaluateExpression();
-			return getEvaluatedLocation();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluationError()
-		 */
-		public IStatus getEvaluationError() {
-			return valueError;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedValue()
-		 */
-		public Number getEvaluatedValue() {
-			return value;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluatedValueString()
-		 */
-		public String getEvaluatedValueString() {
-			if (valueError != null)
-				return valueError.getMessage();
-			
-			if (valueString != null)
-				return valueString;
-			
-			valueString = value != null ? value.toString() : ""; //$NON-NLS-1$
-			return valueString;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#setEvaluatedValueString(java.lang.String)
-		 */
-		public void setEvaluatedValueString(String string) {
-			this.valueString = string;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#setEvaluatedValue(java.lang.Object)
-		 */
-		public void setEvaluatedValue(Number value) {
-			this.value = value;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedLocation()
-		 */
-		public IVariableLocation getEvaluatedLocation() {
-			return valueLocation;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType()
-		 */
-		public IType getEvaluatedType() {
-			return valueType;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getTypeName()
-		 */
-		public String getTypeName() {
-			evaluateExpression();
-			if (valueType == null)
-				if (valueError != null)
-					return ""; //$NON-NLS-1$
-				else
-					return ASTEvaluationEngine.UNKNOWN_TYPE;
-			return engine.getTypeEngine().getTypeName(valueType);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#hasChildren()
-		 */
-		public boolean hasChildren() {
-			return this.hasChildren;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getService()
-		 */
-		public Expressions getExpressionsService() {
-			return Expressions.this;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getExecutor()
-		 */
-		public Executor getExecutor() {
-			return getSession().getExecutor();
-		}
-	
-	}
-
-	/** A basic expression.  */
-	private class ExpressionDMC extends BaseEDCExpressionDMC {
-
-		public ExpressionDMC(IDMContext parent, String expression) {
-			super(parent, expression);
-		}
-		
-		
-		public ExpressionDMC(IDMContext parent, String expression, String name) {
-			super(parent, expression, name);
-		}
-		
-		/**
-		 * There is no casting on a vanilla expression.
-		 * @return <code>null</code>
-		 */
-		public CastInfo getCastInfo() {
-			return null;
-		}
-
-		
-	}
-
-	/** A casted or array-displayed expression.  */
-	private class CastedExpressionDMC extends BaseEDCExpressionDMC implements ICastedExpressionDMContext {
-
-		private final CastInfo castInfo;
-		/** if non-null, interpret result as this type rather than the raw expression's type */
-		private IType castType = null;
-		private IStatus castError;
-
-		public CastedExpressionDMC(IEDCExpression exprDMC, String expression, String name, CastInfo castInfo) {
-			super(exprDMC, name);
-			this.castInfo = castInfo;
-			
-			String castType = castInfo.getTypeString();
-			
-			String castExpression = expression;
-			
-			// If changing type, assume it's reinterpret_cast<>. 
-			// Once we support RTTI, this should be dynamic_cast<> when casting
-			// class pointers to class pointers.
-			if (castType != null) {
-				if (castInfo.getArrayCount() > 0) {
-					castType += "[]"; //$NON-NLS-1$
-					// Force non-pointer expressions to be pointers.
-					exprDMC.evaluateExpression();
-					IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());
-					if (exprType != null) {
-						if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) {
-							expression = "&" + expression; //$NON-NLS-1$
-						}
-					}
-				}
-				castExpression = "reinterpret_cast<" + castType +">(" + expression + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-			} else if (castInfo.getArrayCount() > 0) {
-				// For arrays, be sure the OperatorSubscript accepts the base type.
-				// Force non-pointer expressions to be pointers.
-				exprDMC.evaluateExpression();
-				IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());
-				if (exprType != null) {
-					if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) {
-						// cast to pointer if not already one (cast to array is not valid C/C++ but we support it)
-						castExpression = "("  + exprDMC.getTypeName() + "[])&" + expression; //$NON-NLS-1$ //$NON-NLS-2$
-					}
-				}
-			}
-			this.expression = castExpression;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression()
-		 */
-		public void evaluateExpression() {
-			if (castError != null) {
-				return;
-			}
-			
-			super.evaluateExpression();
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType()
-		 */
-		public IType getEvaluatedType() {
-			if (castType != null)
-				return castType;
-			return super.getEvaluatedType();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext#getCastInfo()
-		 */
-		public CastInfo getCastInfo() {
-			return castInfo;
-		}
-	}
-
-	public class ExpressionData implements IExpressionDMData {
-
-		private final IEDCExpression dmc;
-		private String typeName = "";
-
-		public ExpressionData(IEDCExpression dmc) {
-			this.dmc = dmc;
-			if (dmc != null)
-				this.typeName = dmc.getTypeName();
-		}
-
-		public BasicType getBasicType() {
-			BasicType basicType = BasicType.unknown;
-			if (dmc == null)
-				return basicType;
-			
-			IType type = dmc.getEvaluatedType();
-			type = TypeUtils.getStrippedType(type);
-			if (type instanceof IArrayType) {
-				basicType = BasicType.array;
-			}
-			else if (type instanceof IBasicType) {
-				basicType = BasicType.basic;
-			}
-			else if (type instanceof ICompositeType) {
-				basicType = BasicType.composite;
-			}
-			else if (type instanceof IEnumeration) {
-				basicType = BasicType.enumeration;
-			}
-			else if (type instanceof IPointerType) {
-				basicType = BasicType.pointer;
-			}
-			else if (type instanceof ISubroutineType) {
-				basicType = BasicType.function;
-			}
-			return basicType;
-		}
-
-		public String getEncoding() {
-			return null;
-		}
-
-		public Map<String, Integer> getEnumerations() {
-			return null;
-		}
-
-		public String getName() {
-			if (dmc != null)
-				return dmc.getName();
-			else
-				return ""; //$NON-NLS-1$
-		}
-
-		public IRegisterDMContext getRegister() {
-			return null;
-		}
-
-		public String getTypeId() {
-			return TYPEID_INTEGER;
-		}
-
-		public String getTypeName() {
-			return typeName;
-		}
-
-	}
-
-	protected static class InvalidContextExpressionDMC extends AbstractDMContext implements IExpressionDMContext {
-		private final String expression;
-
-		public InvalidContextExpressionDMC(String sessionId, String expr, IDMContext parent) {
-			super(sessionId, new IDMContext[] { parent });
-			expression = expr;
-		}
-
-		@Override
-		public boolean equals(Object other) {
-			return super.baseEquals(other) && expression == null ? ((InvalidContextExpressionDMC) other)
-					.getExpression() == null : expression.equals(((InvalidContextExpressionDMC) other).getExpression());
-		}
-
-		@Override
-		public int hashCode() {
-			return expression == null ? super.baseHashCode() : super.baseHashCode() ^ expression.hashCode();
-		}
-
-		@Override
-		public String toString() {
-			return baseToString() + ".invalid_expr[" + expression + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-		}
-
-		public String getExpression() {
-			return expression;
-		}
-	}
-
-	public class ExpressionDMAddress implements IExpressionDMLocation {
-
-		private final IVariableLocation valueLocation;
-
-		public ExpressionDMAddress(IExpressionDMContext exprContext) {
-			if (exprContext instanceof IEDCExpression)
-				valueLocation = ((IEDCExpression) exprContext).getValueLocation();
-			else
-				valueLocation = null;
-		}
-
-		public IAddress getAddress() {
-			if (valueLocation != null) {
-				IAddress address = valueLocation.getAddress();
-				if (address != null)
-					return address;
-			}
-			return new Addr64(BigInteger.ZERO);
-		}
-
-		public int getSize() {
-			return 4;
-		}
-
-		public String getLocation() {
-			if (valueLocation instanceof IInvalidVariableLocation) {
-				return ((IInvalidVariableLocation)valueLocation).getMessage();
-			}
-			if (valueLocation == null)
-				return ""; //$NON-NLS-1$
-			return valueLocation.getLocationName();
-		}
-
-	}
-
-	public Expressions(DsfSession session) {
-		super(session, new String[] { IExpressions.class.getName(), Expressions.class.getName(), IExpressions2.class.getName() });
-	}
-	
-	public boolean canWriteExpression(IEDCExpression expressionDMC) {
-		EDCLaunch launch = EDCLaunch.getLaunchForSession(getSession().getId());
-		if (launch.isSnapshotLaunch())
-			return false;
-		IVariableValueConverter converter = getCustomValueConverter(expressionDMC);
-		if (converter != null)
-			return converter.canEditValue();
-		
-		return !isComposite(expressionDMC);
-	}
-
-	public void canWriteExpression(IExpressionDMContext exprContext, DataRequestMonitor<Boolean> rm) {
-		IEDCExpression expressionDMC = (IEDCExpression) exprContext;
-		rm.setData(canWriteExpression(expressionDMC));
-		rm.done();
-	}
-
-	private boolean isComposite(IEDCExpression expressionDMC) {
-		IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType());
-		return exprType instanceof ICompositeType;
-	}
-
-	public IExpressionDMContext createExpression(IDMContext context, String expression) {
-		StackFrameDMC frameDmc = DMContexts.getAncestorOfType(context, StackFrameDMC.class);
-
-		if (frameDmc != null) {
-			return new ExpressionDMC(frameDmc, expression);
-		} else if (context instanceof IModuleDMContext) {
-			return new ExpressionDMC(context, expression); 
-		}
-		return new InvalidContextExpressionDMC(getSession().getId(), expression, context);
-	}
-	
-	class CastInfoCachedData  {
-
-		private CastInfo info;
-
-		private IType type;
-		private IStatus error;
-		private StackFrameDMC frameDmc;
-
-		public CastInfoCachedData(ExpressionDMC exprDMC, CastInfo info) {
-			this.info = info;
-			this.frameDmc = DMContexts.getAncestorOfType(exprDMC, StackFrameDMC.class);
-		}
-		
-		public String getTypeString() {
-			return info.getTypeString();
-		}
-		
-		public int getArrayStartIndex() {
-			return info.getArrayStartIndex();
-		}
-		
-		public int getArrayCount() {
-			return info.getArrayCount();
-		}
-		
-		/**
-		 * Get the compiled type
-		 * @return the type
-		 */
-		public IType getType() {
-			if (info.getTypeString() == null)
-				return null;
-			
-			if (type == null && error == null) {
-				if (frameDmc != null) {
-					ASTEvaluationEngine engine = new ASTEvaluationEngine(getEDCServicesTracker(), frameDmc, frameDmc.getTypeEngine());
-					try {
-						IASTTypeId typeId = engine.getCompiledType(info.getTypeString());
-						type = engine.getTypeEngine().getTypeForTypeId(typeId);
-					} catch (CoreException e) {
-						error = e.getStatus();
-					}
-				} else {
-					error = EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotCastOutsideFrame, null); 
-				}
-			}
-			return type;
-		}
-		
-		/**
-		 * @return the error
-		 */
-		public IStatus getError() {
-			if (type == null && error == null) {
-				getType();
-			}
-			return error;
-		}
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IExpressions2#createCastedExpression(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext)
-	 */
-	public ICastedExpressionDMContext createCastedExpression(IExpressionDMContext exprDMC,
-			CastInfo castInfo) {
-		
-		// then apply the casting stuff
-		if (exprDMC instanceof IEDCExpression) {
-			CastedExpressionDMC castedDMC = new CastedExpressionDMC((IEDCExpression) exprDMC, 
-					exprDMC.getExpression(), ((IEDCExpression) exprDMC).getName(), castInfo);
-			return castedDMC;
-		} else {
-			assert false;
-			return null;
-		}
-	}
-
-	/*
-	public void createCastedExpression(IDMContext context, String expression, 
-			ICastedExpressionDMContext castDMC, IArrayCastedExpressionDMContext arrayCastDMC,
-			DataRequestMonitor<IExpressionDMContext> rm) {
-		
-		// create an ordinary expression...
-		IExpressionDMContext exprDMC = createExpression(context, expression);
-		
-		// then apply the casting stuff
-		if (exprDMC instanceof ExpressionDMC 
-				&& (castDMC == null || castDMC instanceof CastedExpressionDMContext)
-				&& (arrayCastDMC == null || arrayCastDMC instanceof ArrayCastedExpressionDMContext)) {
-			ExpressionDMC expressionDMC = ((ExpressionDMC) exprDMC);
-			if (castDMC != null)
-				expressionDMC.setCastToType((CastedExpressionDMContext) castDMC);
-			if (arrayCastDMC != null)
-				expressionDMC.setArrayCast((ArrayCastedExpressionDMContext) arrayCastDMC);
-			rm.setData(expressionDMC);
-			rm.done();
-		} else {
-			assert false;
-			rm.setStatus(EDCDebugger.dsfRequestFailedStatus("unexpected cast information", null));
-			rm.done();
-		}
-	}
-	*/
-	
-	public void getBaseExpressions(IExpressionDMContext exprContext, DataRequestMonitor<IExpressionDMContext[]> rm) {
-		rm.setData(new IEDCExpression[0]);
-		rm.done();
-	}
-
-	public void getExpressionAddressData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMAddress> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				if (exprContext instanceof IEDCExpression)
-					rm.setData(new ExpressionDMAddress(exprContext));
-				else
-					rm.setData(new ExpressionDMAddress(null));
-				rm.done();
-			}
-		}, rm);
-	}
-
-	public void getExpressionData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMData> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				if (exprContext instanceof IEDCExpression)
-					rm.setData(new ExpressionData((IEDCExpression) exprContext));
-				else
-					rm.setData(new ExpressionData(null));
-				rm.done();
-			}
-		}, rm);
-	}
-
-	public void getSubExpressionCount(final IExpressionDMContext exprContext, final DataRequestMonitor<Integer> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				// handle array casts
-				CastInfo cast = null;
-				if (exprContext instanceof IEDCExpression && (cast = ((IEDCExpression) exprContext).getCastInfo()) != null) { 
-					if (cast.getArrayCount() > 0) {
-						if (((IEDCExpression)exprContext).getEvaluationError() != null) {
-							rm.setData(0);
-							rm.done();
-							return;
-						}
-						rm.setData(cast.getArrayCount());
-						rm.done();
-						return;
-					}
-				}
-
-				if (!(exprContext instanceof IEDCExpression)) {
-					rm.setData(0);
-					rm.done();
-					return;
-				}
-
-				IEDCExpression expr = (IEDCExpression) exprContext;
-
-				// if expression has no evaluated value, then it has not yet been evaluated
-				if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) {
-					expr.evaluateExpression();
-				}
-
-				IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType());
-				
-				// to expand it, it must either be a pointer, a reference to an aggregate,
-				// or an aggregate
-				boolean pointerType = exprType instanceof IPointerType;
-				boolean referenceType = exprType instanceof IReferenceType;
-				IType pointedTo = null;
-				if (referenceType)
-					pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType());
-				
-				if (!(exprType instanceof IAggregate) && !pointerType &&
-					!(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) {
-					rm.setData(0);
-					rm.done();
-					return;
-				}
-				
-				ITypeContentProvider customProvider = 
-					FormatExtensionManager.instance().getTypeContentProvider(exprType);
-				if (customProvider != null) {
-					try {
-						rm.setData(customProvider.getChildCount(expr));
-						rm.done();
-						return;
-					} catch (Throwable e) {
-					}
-				}
-
-				// TODO: maybe cache these subexpressions; they are just requested again in #getSubExpressions()
-				getSubExpressions(exprContext, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>(
-						getExecutor(), rm) {
-					/* (non-Javadoc)
-					 * @see org.eclipse.cdt.dsf.concurrent.RequestMonitor#handleSuccess()
-					 */
-					@Override
-					protected void handleSuccess() {
-						rm.setData(getData().length);
-						rm.done();
-					}
-				});
-			}
-		}, rm);
-	}
-
-	public void getSubExpressions(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMContext[]> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				if (!(exprContext instanceof IEDCExpression) || ((IEDCExpression) exprContext).getFrame() == null) {
-					rm.setData(new IEDCExpression[0]);
-					rm.done();
-					return;
-				}
-
-				IEDCExpression expr = (IEDCExpression) exprContext;
-
-				// if expression has no evaluated value, then it has not yet been evaluated
-				if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) {
-					expr.evaluateExpression();
-				}
-
-				StackFrameDMC frame = (StackFrameDMC) expr.getFrame();
-				IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType());
-
-				// if casted to an array, convert thusly
-		    	CastInfo castInfo = expr.getCastInfo();
-		    	if (castInfo != null && castInfo.getArrayCount() > 0) {
-		    		try {
-		    			exprType = frame.getTypeEngine().convertToArrayType(exprType, castInfo.getArrayCount());
-		    		} catch (CoreException e) {
-		    			rm.setStatus(e.getStatus());
-		    			rm.done();
-		    			return;
-		    		}
-		    	}
-		    	
-				
-				// to expand it, it must either be a pointer, a reference to an aggregate,
-				// or an aggregate
-				boolean pointerType = exprType instanceof IPointerType;
-				boolean referenceType = exprType instanceof IReferenceType;
-				IType pointedTo = null;
-				if (referenceType) {
-					pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType());
-					exprType = pointedTo;
-				}
-				
-				if (!(exprType instanceof IAggregate) && !pointerType &&
-					!(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) {
-					rm.setData(new IEDCExpression[0]);
-					rm.done();
-					return;
-				}
-				
-				ITypeContentProvider customProvider = 
-					FormatExtensionManager.instance().getTypeContentProvider(exprType);
-				if (customProvider != null) {
-					getSubExpressions(expr, frame, exprType, customProvider, rm);
-				}
-				else
-					getSubExpressions(expr, rm);
-			}
-		}, rm);
-	}
-
-	public void getSubExpressions(final IExpressionDMContext exprContext, final int startIndex_, final int length_,
-			final DataRequestMonitor<IExpressionDMContext[]> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				getSubExpressions(exprContext, new DataRequestMonitor<IExpressionDMContext[]>(getExecutor(), rm) {
-					@Override
-					protected void handleSuccess() {
-						IExpressionDMContext[] allExprs = getData();
-						if (startIndex_ == 0 && length_ >= allExprs.length) {
-							rm.setData(allExprs);
-							rm.done();
-						} else {
-							int startIndex = startIndex_, length = length_;
-							if (startIndex > allExprs.length) {
-								startIndex = allExprs.length;
-								length = 0;
-							} else if (startIndex + length > allExprs.length) {
-								length = allExprs.length - startIndex;
-								if (length < 0)
-									length = 0;
-							}
-								
-							IExpressionDMContext[] result = new IExpressionDMContext[length];
-							System.arraycopy(allExprs, startIndex, result, 0, length);
-							rm.setData(result);
-							rm.done();
-						}
-					}
-				});
-			}
-		}, rm);
-	}
-
-	private void getSubExpressions(final IEDCExpression expr, final StackFrameDMC frame, 
-			final IType exprType, final ITypeContentProvider customProvider,
-			final DataRequestMonitor<IExpressionDMContext[]> rm) {
-
-		List<IExpressionDMContext> children = new ArrayList<IExpressionDMContext>();
-		Iterator<IExpressionDMContext> childIterator;
-		try {
-			childIterator = customProvider.getChildIterator(expr);
-			while (childIterator.hasNext() && !rm.isCanceled()) {
-				children.add(childIterator.next());
-			}
-			rm.setData(children.toArray(new IExpressionDMContext[children.size()]));
-			rm.done();
-		} catch (CoreException e) {
-			// Checked exception. But we don't want to pass the error up as it
-			// would make the variable (say, a structure) not expandable on UI. 
-			// Just resort to the normal formatting.  
-			getSubExpressions(expr, rm);
-		} catch (Throwable e) {
-			// unexpected error. log it.
-			EDCDebugger.getMessageLogger().logError(
-					EDCServicesMessages.Expressions_ErrorInVariableFormatter + customProvider.getClass().getName(), e);
-			
-			// default to normal formatting
-			getSubExpressions(expr, rm);
-		}
-	}
-
-	private void getSubExpressions(final IEDCExpression expr, 
-			final DataRequestMonitor<IExpressionDMContext[]> rm) {
-		rm.setData(getLogicalSubExpressions(expr));
-		rm.done();
-	}
-	
-	/**
-	 * Get the logical subexpressions for the given expression context.  We want
-	 * to skip unnecessary nodes, e.g., a pointer to a composite, and directly
-	 * show the object contents.
-	 * @param expr the expression from which to start
-	 * @return array of children
-	 */
-	public IEDCExpression[] getLogicalSubExpressions(IEDCExpression expr) {
-
-		IType exprType = TypeUtils.getUnRefStrippedType(expr.getEvaluatedType());
-		
-		// cast to array?
-		CastInfo castInfo = expr.getCastInfo();
-		if (castInfo != null && castInfo.getArrayCount() > 0) {
-			
-			String exprName = expr.getExpression();
-			
-			// in case of casts, need to resolve that before dereferencing, so be safe
-			if (exprName.contains("(")) //$NON-NLS-1$
-				exprName = '(' + exprName + ')';
-
-			long lowerBound = castInfo.getArrayStartIndex();
-			long count = castInfo.getArrayCount();
-			
-			List<IEDCExpression> arrayChildren = new ArrayList<IEDCExpression>();
-			for (int i = 0; i < count; i++) {
-				String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-				IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), (exprName + arrayElement),
-						expr.getName() + arrayElement);
-				IEDCExpression exprChild = newExpr; //$NON-NLS-1$ //$NON-NLS-2$
-				if (exprChild != null) {
-					arrayChildren.add(exprChild);
-				}
-			}
-
-			return arrayChildren.toArray(new IEDCExpression[arrayChildren.size()]);
-		} 
-		
-		if (exprType instanceof IPointerType) {
-			// automatically dereference a pointer
-			String exprName = expr.getExpression();
-			IType typePointedTo = TypeUtils.getStrippedType(exprType.getType());
-
-			// Try to resolve opaque pointer. 
-			// Note this may take some time depending on symbol file size. 
-			// ........05/19/11
-			//
-			if (TypeUtils.isOpaqueType(typePointedTo)) {
-				final Symbols symService = getService(Symbols.class);
-				assert symService != null;
-				
-				final ISymbolDMContext symCtx = DMContexts.getAncestorOfType(expr, ISymbolDMContext.class);
-				if (symCtx != null) {
-					final ICompositeType[] resolved = {null};
-					final IType original = typePointedTo;
-					Job j = new Job("Resolving opaque type" + original.getName()) {
-						@Override
-						protected IStatus run(IProgressMonitor monitor) {
-							monitor.beginTask("Resolving opaque type: " + original.getName(), IProgressMonitor.UNKNOWN);
-							resolved[0] = symService.resolveOpaqueType(symCtx, (ICompositeType)original);
-							monitor.done();
-							return Status.OK_STATUS;
-						}};
-						
-					j.schedule();
-					try {
-						j.join();
-					} catch (InterruptedException e) {
-						// ignore
-					}
-					
-					if (resolved[0] != null) {
-						typePointedTo = resolved[0];
-						
-						// Make the pointer type points to the resolved type
-						// so that we won't need to resolve the opaque type again
-						// and again.
-						exprType.setType(resolved[0]);
-					}
-				}
-			}
-			
-			// If expression name already starts with "&" (e.g. "&struct"), indirect it first
-			boolean indirected = false;
-			
-			IEDCExpression exprChild;
-			
-			if (exprName.startsWith("&")) { //$NON-NLS-1$
-				exprName = exprName.substring(1);
-				IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), exprName);
-				exprChild = newExpr;
-				indirected = true;
-			} 
-			else {
-				// avoid dereferencing void pointer
-				if (typePointedTo instanceof ICPPBasicType 
-						&& ((ICPPBasicType) typePointedTo).getBaseType() == ICPPBasicType.t_void) {
-					return new IEDCExpression[0];
-				}
-				
-				// do not dereference null either
-				if (expr.getEvaluatedValue() != null && expr.getEvaluatedValue().intValue() == 0)
-					return new IEDCExpression[0];
-				IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), ("*" + exprName), "*" + expr.getName()); //$NON-NLS-1$ //$NON-NLS-2$
-					
-				// a pointer type has one child
-				exprChild = newExpr; //$NON-NLS-1$
-			}
-			
-			return doGetLogicalSubExpressions(exprChild, typePointedTo, indirected);
-		} 
-		else if (exprType instanceof IReferenceType) {
-			// and bypass a reference
-			
-			IType typePointedTo = TypeUtils.getStrippedType(exprType.getType());
-			return doGetLogicalSubExpressions(expr, typePointedTo, false);
-		}else {
-			// normal aggregate, just do it
-			return doGetLogicalSubExpressions(expr, exprType, false);
-		}
-		
-	}
-
-	/**
-	 * Get the logical subexpressions for the given expression context and string 
-	 * @param expr the expression from which to start
-	 * @param exprType the type in which to consider the expression
-	 * @param indirected if true, the expression was already indirected, as opposed to what the expression says
-	 * @return
-	 */
-	private IEDCExpression[] doGetLogicalSubExpressions(IEDCExpression expr, IType exprType, boolean indirected) {
-		ArrayList<IEDCExpression> exprList = new ArrayList<IEDCExpression>();
-		IEDCExpression exprChild;
-
-		String expression = expr.getExpression();
-		
-		// in case of casts, need to resolve that before dereferencing, so be safe
-		if (expression.contains("(")) //$NON-NLS-1$
-			expression = '(' + expression + ')';
-
-		/*
-		// cast to array?
-		CastInfo castInfo = expr.getCastInfo();
-		if (castInfo != null && castInfo.getArrayCount() > 0) {
-			long lowerBound = castInfo.getArrayStartIndex();
-			long count = castInfo.getArrayCount();
-			for (int i = 0; i < count; i++) {
-				exprChild = createDerivedExpression(expr, exprName + "[" + (i + lowerBound) + "]"); //$NON-NLS-1$ //$NON-NLS-2$
-				if (exprChild != null) {
-					exprList.add(exprChild);
-				}
-			}
-		
-		} 
-		else*/ if (exprType instanceof ICompositeType) {
-			// an artifact of following a pointer to a structure is that the
-			// name starts with '*'
-			if (expression.startsWith("*")) { //$NON-NLS-1$
-				if (expression.startsWith("**"))
-					expression = "(" + expression.substring(1) + ")->"; //$NON-NLS-1$
-				else
-					expression = expression.substring(1) + "->"; //$NON-NLS-1$
-			} else {
-				expression = expression + '.'; //$NON-NLS-1$
-			}
-
-			// for each field, evaluate an expression, then shorten the name
-			ICompositeType compositeType = (ICompositeType) exprType;
-
-			for (IField field : compositeType.getFields()) {
-				String fieldName = field.getName();
-				if (fieldName.length() == 0) {
-					// This makes an invalid expression
-					// The debug info provider should have filtered out or renamed such fields
-					assert false;
-					continue;
-				}
-				exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName);
-				if (exprChild != null) {
-					exprList.add(exprChild);
-				}
-			}
-
-			for (IInheritance inherited : compositeType.getInheritances()) {
-				String inheritedName = inherited.getName();
-				if (inheritedName.length() == 0) {
-					// This makes an invalid expression
-					// The debug info provider should have filtered out or renamed such fields
-					assert false;	// couldn't this be the case for an anonymous member, like a union?
-				} else if (!inheritedName.contains("<")) {
-					exprChild = new ExpressionDMC(expr.getFrame(), expression + inheritedName, inheritedName);
-					if (exprChild != null) {
-						exprList.add(exprChild);
-					}
-				} else {
-					IType inheritedType = inherited.getType(); 
-					if (inheritedType instanceof ICompositeType) {
-						for (IField field : ((ICompositeType)inheritedType).getFields()) {
-							String fieldName = field.getName();
-							if (fieldName.length() == 0) {
-								// This makes an invalid expression
-								// The debug info provider should have filtered out or renamed such fields
-								assert false;
-								continue;
-							}
-							exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName);
-							if (exprChild != null) {
-								exprList.add(exprChild);
-							}
-						}
-					}
-				}
-			}
-			
-		} 
-		else if (exprType instanceof IArrayType) {
-			IArrayType arrayType = (IArrayType) exprType;
-
-			if (arrayType.getBoundsCount() > 0) {
-				long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 
-					? expr.getCastInfo().getArrayStartIndex() : 0;
-				long upperBound = arrayType.getBound(0).getBoundCount();
-				if (upperBound == 0)
-					upperBound = 1;
-				for (int i = 0; i < upperBound; i++) {
-					String arrayElementName = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-					IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElementName,
-							expr.getName() + arrayElementName); 
-					exprChild = newExpr;
-					if (exprChild != null) {
-						exprList.add(exprChild);
-					}
-				}
-			}
-		} 
-		else if (exprType instanceof IArrayDimensionType) {
-			IArrayDimensionType arrayDimensionType = (IArrayDimensionType) exprType;
-			IArrayType arrayType = arrayDimensionType.getArrayType();
-
-			if (arrayType.getBoundsCount() > arrayDimensionType.getDimensionCount()) {
-				long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 
-				? expr.getCastInfo().getArrayStartIndex() : 0;
-				long upperBound = arrayType.getBound(arrayDimensionType.getDimensionCount()).getBoundCount();
-				for (int i = 0; i < upperBound; i++) {
-					String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
-					IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElement,
-							expr.getName() + arrayElement); 
-					exprChild = newExpr;
-					if (exprChild != null) {
-						exprList.add(exprChild);
-					}
-				}
-			}
-		} 
-		else {
-			// nothing interesting
-			exprList.add(expr);
-		}
-
-		return exprList.toArray(new IEDCExpression[exprList.size()]);
-	}
-
-	@Immutable
-    private static class ExpressionChangedDMEvent extends AbstractDMEvent<IExpressionDMContext> implements IExpressionChangedDMEvent {
-        ExpressionChangedDMEvent(IExpressionDMContext expression) {
-            super(expression);
-        }
-    }
-
-	public void writeExpression(final IExpressionDMContext exprContext, final String expressionValue, final String formatId, final RequestMonitor rm) {
-
-		asyncExec(new Runnable() {
-			public void run() {
-				IEDCExpression expressionDMC = (IEDCExpression) exprContext;
-				if (isComposite(expressionDMC)) {
-					rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotModifyCompositeValue, null));
-					rm.done();
-					return;
-				}
-
-				IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType());
-
-				// first try to get value by format as BigInteger
-				Number number = NumberFormatUtils.parseIntegerByFormat(expressionValue, formatId);
-		        if (number == null) {
-		       		IEDCExpression temp = (IEDCExpression) createExpression(expressionDMC.getFrame(), expressionValue);
-		       		temp.evaluateExpression();
-					number = temp.getEvaluatedValue();
-
-		       		if (number == null) {
-		       			rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotParseExpression, null));
-		       			rm.done();
-		       			return;
-		       		}
-		        }
-		        
-		        BigInteger value = null;
-				try {
-					value = MemoryUtils.convertValueToMemory(exprType, number);
-				} catch (CoreException e) {
-		   			rm.setStatus(e.getStatus());
-		   			rm.done();
-		   			return;
-				}
-		        
-		        IVariableLocation variableLocation = expressionDMC.getValueLocation();
-		        if (variableLocation == null) {
-		        	rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_ExpressionNoLocation, null));
-		   			rm.done();
-		   			return;
-		        }
-		        	
-		    	try {
-		    		variableLocation.writeValue(exprType.getByteSize(), value);
-		    		getSession().dispatchEvent(new ExpressionChangedDMEvent(exprContext), getProperties());
-				} catch (CoreException e) {
-					rm.setStatus(e.getStatus());
-				}
-		        
-				rm.done();
-			}
-		}, rm);
-
-	}
-
-	public void getAvailableFormats(IFormattedDataDMContext formattedDataContext, DataRequestMonitor<String[]> rm) {
-		rm.setData(new String[] { IFormattedValues.NATURAL_FORMAT, IFormattedValues.DECIMAL_FORMAT, 
-				IFormattedValues.HEX_FORMAT, IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT });
-		rm.done();
-	}
-
-	public void getFormattedExpressionValue(final FormattedValueDMContext formattedDataContext,
-			final DataRequestMonitor<FormattedValueDMData> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				try {
-					rm.setData(getFormattedExpressionValue(formattedDataContext));
-					rm.done();
-				} catch (CoreException ce) {
-					rm.setStatus(ce.getStatus());
-					rm.done();
-					return;
-				}
-			}
-		}, rm);
-	}
-
-	public String getExpressionValueString(IExpressionDMContext expression, String format) throws CoreException {
-		FormattedValueDMContext formattedDataContext = getFormattedValueContext(expression, format);
-		FormattedValueDMData formattedValue = getFormattedExpressionValue(formattedDataContext);
-		
-		return formattedValue != null ? formattedValue.getFormattedValue() : "";
-	}
-
-	public FormattedValueDMData getFormattedExpressionValue(FormattedValueDMContext formattedDataContext) throws CoreException {
-		IDMContext idmContext = formattedDataContext.getParents()[0];
-		FormattedValueDMData formattedValue = null;
-		IEDCExpression exprDMC = null;
-
-		if (idmContext instanceof IEDCExpression) {
-			exprDMC = (IEDCExpression) formattedDataContext.getParents()[0];
-
-			exprDMC.evaluateExpression();
-			
-			if (exprDMC != null && exprDMC.getEvaluationError() != null) {
-				throw new CoreException(exprDMC.getEvaluationError());
-			}
-			
-			formattedValue = exprDMC.getFormattedValue(formattedDataContext); // must call this to get type
-			
-			if (formattedDataContext.getFormatID().equals(IFormattedValues.NATURAL_FORMAT))
-			{
-				IVariableValueConverter customConverter = getCustomValueConverter(exprDMC);
-				if (customConverter != null) {
-					FormattedValueDMData customFormattedValue = null;
-					try {
-						customFormattedValue = new FormattedValueDMData(customConverter.getValue(exprDMC));
-						formattedValue = customFormattedValue;
-					}
-					catch (CoreException e) {
-						// Checked exception like failure in reading memory.  just re-throw
-						// it so it shows up in the variables view.
-						throw e;
-					} catch (Throwable t) {
-						// Other unexpected errors, usually bug in the formatter. Log it 
-						// so that user will be able to see and report the bug. 
-						// Meanwhile default to normal formatting so that user won't see 
-						// such error in Variable UI.
-						EDCDebugger.getMessageLogger().logError(
-								EDCServicesMessages.Expressions_ErrorInVariableFormatter + customConverter.getClass().getName(), t);
-					}
-				}
-			}
-		} else
-			formattedValue = new FormattedValueDMData(""); //$NON-NLS-1$
-		
-		return formattedValue;
-	}
-
-	private IVariableValueConverter getCustomValueConverter(IEDCExpression exprDMC) {
-		IType exprType = TypeUtils.getUnRefStrippedType(exprDMC.getEvaluatedType());
-		return FormatExtensionManager.instance().getVariableValueConverter(exprType);
-	}
-
-	public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext formattedDataContext,
-			String formatId) {
-		return new FormattedValueDMContext(this, formattedDataContext, formatId);
-	}
-
-	public void getModelData(IDMContext context, DataRequestMonitor<?> rm) {
-	}
-
-	public String getExpressionValue(IExpressionDMContext expression)
-	{
-		final StringBuffer holder = new StringBuffer();
-		FormattedValueDMContext formattedValueContext = getFormattedValueContext(expression, IFormattedValues.NATURAL_FORMAT);					
-		getFormattedExpressionValue(formattedValueContext, new DataRequestMonitor<FormattedValueDMData>(ImmediateExecutor.getInstance(), null) {
-			@Override
-			protected void handleSuccess() {
-				holder.append(this.getData().getFormattedValue());
-			}
-
-			@Override
-			protected void handleFailure() {
-				// RequestMonitor would by default log any error if it's not explicitly 
-				// handled. But we don't want to log those expected errors (checked exceptions)
-				// in such case as creating snapshot. Hence this dummy handler...02/17/10
-				
-				// DO nothing.
-			}
-			
-			
-		});
-		return holder.toString();
-	}
-
-	public void loadExpressionValues(IExpressionDMContext expression, int depth)
-	{
-		loadExpressionValues(expression, new Integer[] {depth});
-	}
-
-	private void loadExpressionValues(IExpressionDMContext expression, final Integer[] depth)
-	{
-		getExpressionValue(expression);
-		if (depth[0] > 0)
-		{
-			getSubExpressions(expression, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>(ImmediateExecutor.getInstance(), null) {
-
-				@Override
-				protected void handleSuccess() {
-					depth[0] = depth[0] - 1;
-					IExpressions.IExpressionDMContext[] subExpressions = getData();
-					for (IExpressionDMContext iExpressionDMContext : subExpressions) {
-						loadExpressionValues(iExpressionDMContext, depth);
-					}
-				}});
-		}
-	}
-}
+/*******************************************************************************

+ * Copyright (c) 2009, 2010, 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.math.BigInteger;

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import java.util.concurrent.Executor;

+

+import org.eclipse.cdt.core.IAddress;

+import org.eclipse.cdt.core.dom.ast.IASTTypeId;

+import org.eclipse.cdt.core.dom.ast.IBasicType;

+import org.eclipse.cdt.debug.edc.MemoryUtils;

+import org.eclipse.cdt.debug.edc.formatter.ITypeContentProvider;

+import org.eclipse.cdt.debug.edc.formatter.IVariableValueConverter;

+import org.eclipse.cdt.debug.edc.internal.EDCDebugger;

+import org.eclipse.cdt.debug.edc.internal.EDCTrace;

+import org.eclipse.cdt.debug.edc.internal.NumberFormatUtils;

+import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.ASTEvaluationEngine;

+import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.IArrayDimensionType;

+import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.InstructionSequence;

+import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.Interpreter;

+import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperandValue;

+import org.eclipse.cdt.debug.edc.internal.formatter.FormatExtensionManager;

+import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;

+import org.eclipse.cdt.debug.edc.internal.symbols.IAggregate;

+import org.eclipse.cdt.debug.edc.internal.symbols.IArrayType;

+import org.eclipse.cdt.debug.edc.internal.symbols.ICPPBasicType;

+import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;

+import org.eclipse.cdt.debug.edc.internal.symbols.IEnumeration;

+import org.eclipse.cdt.debug.edc.internal.symbols.IField;

+import org.eclipse.cdt.debug.edc.internal.symbols.IInheritance;

+import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;

+import org.eclipse.cdt.debug.edc.internal.symbols.IReferenceType;

+import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeType;

+import org.eclipse.cdt.debug.edc.internal.symbols.ISubroutineType;

+import org.eclipse.cdt.debug.edc.launch.EDCLaunch;

+import org.eclipse.cdt.debug.edc.services.AbstractEDCService;

+import org.eclipse.cdt.debug.edc.services.DMContext;

+import org.eclipse.cdt.debug.edc.services.IEDCDMContext;

+import org.eclipse.cdt.debug.edc.services.IEDCExpression;

+import org.eclipse.cdt.debug.edc.services.IEDCExpressions;

+import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;

+import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider;

+import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;

+import org.eclipse.cdt.debug.edc.symbols.IEnumerator;

+import org.eclipse.cdt.debug.edc.symbols.IInvalidVariableLocation;

+import org.eclipse.cdt.debug.edc.symbols.IType;

+import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;

+import org.eclipse.cdt.debug.edc.symbols.TypeEngine;

+import org.eclipse.cdt.debug.edc.symbols.TypeUtils;

+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;

+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;

+import org.eclipse.cdt.dsf.concurrent.Immutable;

+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;

+import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;

+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.IExpressions;

+import org.eclipse.cdt.dsf.debug.service.IExpressions2;

+import org.eclipse.cdt.dsf.debug.service.IFormattedValues;

+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.IRegisters.IRegisterDMContext;

+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;

+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.Status;

+import org.eclipse.core.runtime.jobs.Job;

+

+public class Expressions extends AbstractEDCService implements IEDCExpressions {

+

+	public abstract class BaseEDCExpressionDMC extends DMContext implements IEDCExpression {

+		protected String expression;

+		private InstructionSequence parsedExpression;

+		private final ASTEvaluationEngine engine;

+		private final StackFrameDMC frame;

+		protected Number value;

+		protected IStatus valueError;

+		private IVariableLocation valueLocation;

+		private IType valueType;

+		private boolean hasChildren = false;

+		private String valueString;

+

+		public BaseEDCExpressionDMC(IDMContext parent, String expression, String name) {

+			// use the full expression in the id as their hashcode is based on

+			// id, so they must be unique

+			super(Expressions.this, new IDMContext[] { parent }, name,

+				  ((IEDCDMContext)parent).getID() + '.' + expression);

+			this.expression = expression;

+			frame = DMContexts.getAncestorOfType(parent, StackFrameDMC.class);

+			engine = initEngine(parent);

+		}

+

+		private ASTEvaluationEngine initEngine(IDMContext parent) {

+			if (frame != null)

+				return new ASTEvaluationEngine(getEDCServicesTracker(), frame,

+												frame.getTypeEngine());

+

+			if (parent instanceof ModuleDMC) {

+				IEDCSymbolReader edcSymbolReader = ((ModuleDMC)parent).getSymbolReader();

+				if (edcSymbolReader instanceof EDCSymbolReader) {

+					IDebugInfoProvider debugInfoProvider

+					  = ((EDCSymbolReader)edcSymbolReader).getDebugInfoProvider();

+					TypeEngine typeEngine

+					  = new TypeEngine(getTargetEnvironmentService(), debugInfoProvider);

+					return new ASTEvaluationEngine(getEDCServicesTracker(), parent, typeEngine);

+				}

+			}

+

+			return null;

+		}

+

+		public BaseEDCExpressionDMC(IDMContext parent, String expression) {

+			this(parent, expression, expression);

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.DMContext#toString()

+		 */

+		@Override

+		public String toString() {

+			return getExpression();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFrame()

+		 */

+		public IFrameDMContext getFrame() {

+			return frame;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getExpression()

+		 */

+		public String getExpression() {

+			return expression;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression()

+		 */

+		public synchronized void evaluateExpression() {

+			if (value != null || valueError != null)

+				return;

+			

+			String expression = getExpression();

+

+			if (parsedExpression == null) {

+				try {

+					parsedExpression = engine.getCompiledExpression(expression);

+				} catch (CoreException e) {

+					value = null;

+					valueError = e.getStatus();

+					valueLocation = null;

+					valueType = null;

+					return;

+				}

+			}

+

+			if (parsedExpression.getInstructions().length == 0) {

+				value = null;

+				valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,

+						EDCServicesMessages.Expressions_SyntaxError);

+				valueLocation = null;

+				valueType = null;

+				return;

+			}

+

+			Interpreter interpreter;

+			try {

+				interpreter = engine.evaluateCompiledExpression(parsedExpression);

+			} catch (CoreException e) {

+				value = null;

+				valueError = e.getStatus();

+				valueLocation = null;

+				valueType = null;

+				return;

+			}

+			

+			OperandValue variableValue = interpreter.getResult();

+			if (variableValue == null) {

+				value = null;

+				valueError = null;

+				valueLocation = null;

+				valueType = null;

+				return;

+			}

+

+			valueLocation = variableValue.getValueLocation();

+

+			// if the location is invalid, the types and values do not matter

+			if (valueLocation instanceof IInvalidVariableLocation) {

+				value = null;

+				valueError = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,

+						((IInvalidVariableLocation) valueLocation).getMessage());

+				valueLocation = null; //$NON-NLS-1$

+				return;

+			}

+

+			try {

+				value = variableValue.getValue();

+				valueString = variableValue.getStringValue();

+			} catch (CoreException e1) {

+				value = null;

+				valueError = e1.getStatus();

+				return;

+			}

+

+			valueType = variableValue.getValueType();

+

+			// for a structured type or array, return the location and note

+			// that it has children

+			if (valueType instanceof IAggregate && valueLocation != null) {

+				// TODO

+				try {

+					value = variableValue.getValueLocationAddress();

+				} catch (CoreException e) {

+					value = null;

+					valueError = e.getStatus();

+				}

+				if (!(value instanceof IInvalidVariableLocation))

+					hasChildren = true;

+			} else if (valueType instanceof IRuntimeType

+						&& valueLocation != null

+						&& EDCDebugger.getResolveRttiTypes()) {

+				value = Long.valueOf(value.longValue() + ((IRuntimeType)valueType).getRuntimeOffset());

+			}

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getFormattedValue(org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext)

+		 */

+		public FormattedValueDMData getFormattedValue(FormattedValueDMContext dmc) {

+			if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(dmc)); }

+			evaluateExpression();

+			String result = ""; //$NON-NLS-1$

+

+			if (valueError != null) {

+				result = valueError.getMessage();

+			} else if (value != null) {

+				result = value.toString();

+				

+				IType unqualifiedType = TypeUtils.getUnRefStrippedType(valueType);

+				

+				String temp = null;

+				String formatID = dmc.getFormatID();

+				

+				// the non-natural formats have expected representations in other

+				// parts of DSF, so be strict about what we return

+				if (formatID.equals(IFormattedValues.HEX_FORMAT)) {

+					temp = NumberFormatUtils.toHexString(value);

+				} else if (formatID.equals(IFormattedValues.OCTAL_FORMAT)) {

+					temp = NumberFormatUtils.toOctalString(value);

+				} else if (formatID.equals(IFormattedValues.BINARY_FORMAT)) {

+					temp = NumberFormatUtils.asBinary(value);

+				} else if (formatID.equals(IFormattedValues.NATURAL_FORMAT)) {

+					// convert non-integer types to original representation

+					if (unqualifiedType instanceof ICPPBasicType) {

+						ICPPBasicType basicType = (ICPPBasicType) unqualifiedType;

+						switch (basicType.getBaseType()) {

+						case ICPPBasicType.t_char:

+							temp = NumberFormatUtils.toCharString(value, valueType);

+							break;

+						case ICPPBasicType.t_wchar_t:

+							temp = NumberFormatUtils.toCharString(value, valueType);

+							break;

+						case ICPPBasicType.t_bool:

+							temp = Boolean.toString(value.longValue() != 0);

+							break;

+						default:

+							// account for other debug formats

+							if (basicType.getName().equals("wchar_t")) { //$NON-NLS-1$

+								temp = NumberFormatUtils.toCharString(value, valueType);

+							}

+							break;

+						}

+					} else if (unqualifiedType instanceof IAggregate || unqualifiedType instanceof IPointerType) {

+						// show addresses for aggregates and pointers as hex in natural format

+						temp = NumberFormatUtils.toHexString(value);

+					} 

+					

+					// TODO: add type suffix if the value cannot fit in

+					// the ordinary range of the base type.

+					// E.g., for an unsigned int, 0xFFFFFFFF should usually be 0xFFFFFFFFU,

+					// and for a long double, 1.E1000 should be 1.E1000L.

+					/*

+					// apply required integer and float suffixes

+					IType unqualifiedType = TypeUtils.getStrippedType(valueType);

+					if (unqualifiedType instanceof ICPPBasicType) {

+						ICPPBasicType basicType = (ICPPBasicType) unqualifiedType;

+						

+						if (basicType.getBaseType() == ICPPBasicType.t_float) {

+							//result += "F"; // no

+						} else if (basicType.getBaseType() == ICPPBasicType.t_double) {

+							if (basicType.isLong() AND actual value does not fit in a double)

+								result += "L";

+						} else if (basicType.getBaseType() == ICPPBasicType.t_int) {

+							if (basicType.isUnsigned() AND actual value does not fit in a signed int)

+								result += "U";

+							if (basicType.isLongLong() AND actual value does not fit in a signed int)

+								result += "LL";

+							else if (basicType.isLong() AND actual value does not fit in a signed int)

+								result += "L";

+						}

+					}

+					 */

+					

+					// for an enumerator, return the name, if any

+					if (unqualifiedType instanceof IEnumeration) {

+						long enumeratorValue = value.longValue();

+

+						IEnumerator enumerator = ((IEnumeration) unqualifiedType).getEnumeratorByValue(enumeratorValue);

+						if (enumerator != null) {

+							if (temp == null)

+								temp = result;

+							

+							temp = enumerator.getName() + " [" + temp + "]"; //$NON-NLS-1$ //$NON-NLS-2$

+						}

+					}

+				}

+				if (temp != null)

+					result = temp; 

+				

+				// otherwise, leave value as is

+				

+				

+			}

+			if (EDCTrace.VARIABLE_VALUE_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(result)); }

+			return new FormattedValueDMData(result);

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getValueLocation()

+		 */

+		public IVariableLocation getValueLocation() {

+			evaluateExpression();

+			return getEvaluatedLocation();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluationError()

+		 */

+		public IStatus getEvaluationError() {

+			return valueError;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedValue()

+		 */

+		public Number getEvaluatedValue() {

+			return value;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getEvaluatedValueString()

+		 */

+		public String getEvaluatedValueString() {

+			if (valueError != null)

+				return valueError.getMessage();

+			

+			if (valueString != null)

+				return valueString;

+			

+			valueString = value != null ? value.toString() : ""; //$NON-NLS-1$

+			return valueString;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#setEvaluatedValueString(java.lang.String)

+		 */

+		public void setEvaluatedValueString(String string) {

+			this.valueString = string;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#setEvaluatedValue(java.lang.Object)

+		 */

+		public void setEvaluatedValue(Number value) {

+			this.value = value;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedLocation()

+		 */

+		public IVariableLocation getEvaluatedLocation() {

+			return valueLocation;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType()

+		 */

+		public IType getEvaluatedType() {

+			return valueType;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getTypeName()

+		 */

+		public String getTypeName() {

+			evaluateExpression();

+			if (valueType == null)

+				if (valueError != null)

+					return ""; //$NON-NLS-1$

+				else

+					return ASTEvaluationEngine.UNKNOWN_TYPE;

+			return engine.getTypeEngine().getTypeName(valueType);

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#hasChildren()

+		 */

+		public boolean hasChildren() {

+			return this.hasChildren;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getService()

+		 */

+		public Expressions getExpressionsService() {

+			return Expressions.this;

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCExpression#getExecutor()

+		 */

+		public Executor getExecutor() {

+			return getSession().getExecutor();

+		}

+	

+	}

+

+	/** A basic expression.  */

+	private class ExpressionDMC extends BaseEDCExpressionDMC {

+

+		public ExpressionDMC(IDMContext parent, String expression) {

+			super(parent, expression);

+		}

+		

+		

+		public ExpressionDMC(IDMContext parent, String expression, String name) {

+			super(parent, expression, name);

+		}

+		

+		/**

+		 * There is no casting on a vanilla expression.

+		 * @return <code>null</code>

+		 */

+		public CastInfo getCastInfo() {

+			return null;

+		}

+

+		

+	}

+

+	/** A casted or array-displayed expression.  */

+	private class CastedExpressionDMC extends BaseEDCExpressionDMC implements ICastedExpressionDMContext {

+

+		private final CastInfo castInfo;

+		/** if non-null, interpret result as this type rather than the raw expression's type */

+		private IType castType = null;

+		private IStatus castError;

+

+		public CastedExpressionDMC(IEDCExpression exprDMC, String expression, String name, CastInfo castInfo) {

+			super(exprDMC, name);

+			this.castInfo = castInfo;

+			

+			String castType = castInfo.getTypeString();

+			

+			String castExpression = expression;

+			

+			// If changing type, assume it's reinterpret_cast<>. 

+			// Once we support RTTI, this should be dynamic_cast<> when casting

+			// class pointers to class pointers.

+			if (castType != null) {

+				if (castInfo.getArrayCount() > 0) {

+					castType += "[]"; //$NON-NLS-1$

+					// Force non-pointer expressions to be pointers.

+					exprDMC.evaluateExpression();

+					IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());

+					if (exprType != null) {

+						if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) {

+							expression = "&" + expression; //$NON-NLS-1$

+						}

+					}

+				}

+				castExpression = "reinterpret_cast<" + castType +">(" + expression + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

+			} else if (castInfo.getArrayCount() > 0) {

+				// For arrays, be sure the OperatorSubscript accepts the base type.

+				// Force non-pointer expressions to be pointers.

+				exprDMC.evaluateExpression();

+				IType exprType = TypeUtils.getStrippedType(exprDMC.getEvaluatedType());

+				if (exprType != null) {

+					if (!(exprType instanceof IPointerType || exprType instanceof IArrayType)) {

+						// cast to pointer if not already one (cast to array is not valid C/C++ but we support it)

+						castExpression = "("  + exprDMC.getTypeName() + "[])&" + expression; //$NON-NLS-1$ //$NON-NLS-2$

+					}

+				}

+			}

+			this.expression = castExpression;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#evaluateExpression()

+		 */

+		public void evaluateExpression() {

+			if (castError != null) {

+				return;

+			}

+			

+			super.evaluateExpression();

+		}

+		

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCExpression#getEvaluatedType()

+		 */

+		public IType getEvaluatedType() {

+			if (castType != null)

+				return castType;

+			return super.getEvaluatedType();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext#getCastInfo()

+		 */

+		public CastInfo getCastInfo() {

+			return castInfo;

+		}

+	}

+

+	public class ExpressionData implements IExpressionDMData {

+

+		private final IEDCExpression dmc;

+		private String typeName = "";

+

+		public ExpressionData(IEDCExpression dmc) {

+			this.dmc = dmc;

+			if (dmc != null)

+				this.typeName = dmc.getTypeName();

+		}

+

+		public BasicType getBasicType() {

+			BasicType basicType = BasicType.unknown;

+			if (dmc == null)

+				return basicType;

+			

+			IType type = dmc.getEvaluatedType();

+			type = TypeUtils.getStrippedType(type);

+			if (type instanceof IArrayType) {

+				basicType = BasicType.array;

+			}

+			else if (type instanceof IBasicType) {

+				basicType = BasicType.basic;

+			}

+			else if (type instanceof ICompositeType) {

+				basicType = BasicType.composite;

+			}

+			else if (type instanceof IEnumeration) {

+				basicType = BasicType.enumeration;

+			}

+			else if (type instanceof IPointerType) {

+				basicType = BasicType.pointer;

+			}

+			else if (type instanceof ISubroutineType) {

+				basicType = BasicType.function;

+			}

+			return basicType;

+		}

+

+		public String getEncoding() {

+			return null;

+		}

+

+		public Map<String, Integer> getEnumerations() {

+			return null;

+		}

+

+		public String getName() {

+			if (dmc != null)

+				return dmc.getName();

+			else

+				return ""; //$NON-NLS-1$

+		}

+

+		public IRegisterDMContext getRegister() {

+			return null;

+		}

+

+		public String getTypeId() {

+			return TYPEID_INTEGER;

+		}

+

+		public String getTypeName() {

+			return typeName;

+		}

+

+	}

+

+	protected static class InvalidContextExpressionDMC extends AbstractDMContext implements IExpressionDMContext {

+		private final String expression;

+

+		public InvalidContextExpressionDMC(String sessionId, String expr, IDMContext parent) {

+			super(sessionId, new IDMContext[] { parent });

+			expression = expr;

+		}

+

+		@Override

+		public boolean equals(Object other) {

+			return super.baseEquals(other) && expression == null ? ((InvalidContextExpressionDMC) other)

+					.getExpression() == null : expression.equals(((InvalidContextExpressionDMC) other).getExpression());

+		}

+

+		@Override

+		public int hashCode() {

+			return expression == null ? super.baseHashCode() : super.baseHashCode() ^ expression.hashCode();

+		}

+

+		@Override

+		public String toString() {

+			return baseToString() + ".invalid_expr[" + expression + "]"; //$NON-NLS-1$ //$NON-NLS-2$

+		}

+

+		public String getExpression() {

+			return expression;

+		}

+	}

+

+	public class ExpressionDMAddress implements IExpressionDMLocation {

+

+		private final IVariableLocation valueLocation;

+

+		public ExpressionDMAddress(IExpressionDMContext exprContext) {

+			if (exprContext instanceof IEDCExpression)

+				valueLocation = ((IEDCExpression) exprContext).getValueLocation();

+			else

+				valueLocation = null;

+		}

+

+		public IAddress getAddress() {

+			if (valueLocation != null) {

+				IAddress address = valueLocation.getAddress();

+				if (address != null)

+					return address;

+			}

+			return new Addr64(BigInteger.ZERO);

+		}

+

+		public int getSize() {

+			return 4;

+		}

+

+		public String getLocation() {

+			if (valueLocation instanceof IInvalidVariableLocation) {

+				return ((IInvalidVariableLocation)valueLocation).getMessage();

+			}

+			if (valueLocation == null)

+				return ""; //$NON-NLS-1$

+			return valueLocation.getLocationName();

+		}

+

+	}

+

+	public Expressions(DsfSession session) {

+		super(session, new String[] { IExpressions.class.getName(), Expressions.class.getName(), IExpressions2.class.getName() });

+	}

+	

+	public boolean canWriteExpression(IEDCExpression expressionDMC) {

+		EDCLaunch launch = EDCLaunch.getLaunchForSession(getSession().getId());

+		if (launch.isSnapshotLaunch())

+			return false;

+		IVariableValueConverter converter = getCustomValueConverter(expressionDMC);

+		if (converter != null)

+			return converter.canEditValue();

+		

+		return !isComposite(expressionDMC);

+	}

+

+	public void canWriteExpression(IExpressionDMContext exprContext, DataRequestMonitor<Boolean> rm) {

+		IEDCExpression expressionDMC = (IEDCExpression) exprContext;

+		rm.setData(canWriteExpression(expressionDMC));

+		rm.done();

+	}

+

+	private boolean isComposite(IEDCExpression expressionDMC) {

+		IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType());

+		return exprType instanceof ICompositeType;

+	}

+

+	public IExpressionDMContext createExpression(IDMContext context, String expression) {

+		StackFrameDMC frameDmc = DMContexts.getAncestorOfType(context, StackFrameDMC.class);

+

+		if (frameDmc != null) {

+			return new ExpressionDMC(frameDmc, expression);

+		} else if (context instanceof IModuleDMContext) {

+			return new ExpressionDMC(context, expression); 

+		}

+		return new InvalidContextExpressionDMC(getSession().getId(), expression, context);

+	}

+	

+	class CastInfoCachedData  {

+

+		private CastInfo info;

+

+		private IType type;

+		private IStatus error;

+		private StackFrameDMC frameDmc;

+

+		public CastInfoCachedData(ExpressionDMC exprDMC, CastInfo info) {

+			this.info = info;

+			this.frameDmc = DMContexts.getAncestorOfType(exprDMC, StackFrameDMC.class);

+		}

+		

+		public String getTypeString() {

+			return info.getTypeString();

+		}

+		

+		public int getArrayStartIndex() {

+			return info.getArrayStartIndex();

+		}

+		

+		public int getArrayCount() {

+			return info.getArrayCount();

+		}

+		

+		/**

+		 * Get the compiled type

+		 * @return the type

+		 */

+		public IType getType() {

+			if (info.getTypeString() == null)

+				return null;

+			

+			if (type == null && error == null) {

+				if (frameDmc != null) {

+					ASTEvaluationEngine engine = new ASTEvaluationEngine(getEDCServicesTracker(), frameDmc, frameDmc.getTypeEngine());

+					try {

+						IASTTypeId typeId = engine.getCompiledType(info.getTypeString());

+						type = engine.getTypeEngine().getTypeForTypeId(typeId);

+					} catch (CoreException e) {

+						error = e.getStatus();

+					}

+				} else {

+					error = EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotCastOutsideFrame, null); 

+				}

+			}

+			return type;

+		}

+		

+		/**

+		 * @return the error

+		 */

+		public IStatus getError() {

+			if (type == null && error == null) {

+				getType();

+			}

+			return error;

+		}

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IExpressions2#createCastedExpression(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext)

+	 */

+	public ICastedExpressionDMContext createCastedExpression(IExpressionDMContext exprDMC,

+			CastInfo castInfo) {

+		

+		// then apply the casting stuff

+		if (exprDMC instanceof IEDCExpression) {

+			CastedExpressionDMC castedDMC = new CastedExpressionDMC((IEDCExpression) exprDMC, 

+					exprDMC.getExpression(), ((IEDCExpression) exprDMC).getName(), castInfo);

+			return castedDMC;

+		} else {

+			assert false;

+			return null;

+		}

+	}

+

+	/*

+	public void createCastedExpression(IDMContext context, String expression, 

+			ICastedExpressionDMContext castDMC, IArrayCastedExpressionDMContext arrayCastDMC,

+			DataRequestMonitor<IExpressionDMContext> rm) {

+		

+		// create an ordinary expression...

+		IExpressionDMContext exprDMC = createExpression(context, expression);

+		

+		// then apply the casting stuff

+		if (exprDMC instanceof ExpressionDMC 

+				&& (castDMC == null || castDMC instanceof CastedExpressionDMContext)

+				&& (arrayCastDMC == null || arrayCastDMC instanceof ArrayCastedExpressionDMContext)) {

+			ExpressionDMC expressionDMC = ((ExpressionDMC) exprDMC);

+			if (castDMC != null)

+				expressionDMC.setCastToType((CastedExpressionDMContext) castDMC);

+			if (arrayCastDMC != null)

+				expressionDMC.setArrayCast((ArrayCastedExpressionDMContext) arrayCastDMC);

+			rm.setData(expressionDMC);

+			rm.done();

+		} else {

+			assert false;

+			rm.setStatus(EDCDebugger.dsfRequestFailedStatus("unexpected cast information", null));

+			rm.done();

+		}

+	}

+	*/

+	

+	public void getBaseExpressions(IExpressionDMContext exprContext, DataRequestMonitor<IExpressionDMContext[]> rm) {

+		rm.setData(new IEDCExpression[0]);

+		rm.done();

+	}

+

+	public void getExpressionAddressData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMAddress> rm) {

+		asyncExec(new Runnable() {

+			public void run() {

+				if (exprContext instanceof IEDCExpression)

+					rm.setData(new ExpressionDMAddress(exprContext));

+				else

+					rm.setData(new ExpressionDMAddress(null));

+				rm.done();

+			}

+		}, rm);

+	}

+

+	public void getExpressionData(final IExpressionDMContext exprContext, final DataRequestMonitor<IExpressionDMData> rm) {

+		asyncExec(new Runnable() {

+			public void run() {

+				if (exprContext instanceof IEDCExpression)

+					rm.setData(new ExpressionData((IEDCExpression) exprContext));

+				else

+					rm.setData(new ExpressionData(null));

+				rm.done();

+			}

+		}, rm);

+	}

+

+	public void getSubExpressionCount(final IExpressionDMContext exprContext,

+			final DataRequestMonitor<Integer> rm) {

+

+		if ( !(exprContext instanceof IEDCExpression)) {

+			rm.setData(0);

+			rm.done();

+			return;

+		}

+

+		asyncExec(new Runnable() {

+			public void run() {

+				final IEDCExpression expr = (IEDCExpression) exprContext;

+

+				// handle array casts

+				CastInfo cast = null;

+				if ((cast = expr.getCastInfo()) != null) {

+					if (cast.getArrayCount() > 0) {

+						if (expr.getEvaluationError() != null) {

+							rm.setData(0);

+							rm.done();

+							return;

+						}

+						rm.setData(cast.getArrayCount());

+						rm.done();

+						return;

+					}

+				}

+

+				// if expression has no evaluated value, then it has not yet been evaluated

+				if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) {

+					expr.evaluateExpression();

+				}

+

+				IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType());

+				

+				// to expand it, it must either be a pointer, a reference to an aggregate,

+				// or an aggregate

+				boolean pointerType = exprType instanceof IPointerType;

+				boolean referenceType = exprType instanceof IReferenceType;

+				IType pointedTo = null;

+				if (referenceType)

+					pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType());

+				

+				if (!(exprType instanceof IAggregate) && !pointerType &&

+					!(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) {

+					rm.setData(0);

+					rm.done();

+					return;

+				}

+				

+				ITypeContentProvider customProvider = 

+					FormatExtensionManager.instance().getTypeContentProvider(exprType);

+				if (customProvider != null) {

+					try {

+						rm.setData(customProvider.getChildCount(expr));

+						rm.done();

+						return;

+					} catch (Throwable e) {

+					}

+				}

+

+				// TODO: maybe cache these subexpressions; they are just requested again in #getSubExpressions()

+				getSubExpressions(exprContext, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>(

+						getExecutor(), rm) {

+					/* (non-Javadoc)

+					 * @see org.eclipse.cdt.dsf.concurrent.RequestMonitor#handleSuccess()

+					 */

+					@Override

+					protected void handleSuccess() {

+						rm.setData(getData().length);

+						rm.done();

+					}

+				});

+			}

+		}, rm);

+	}

+

+	public void getSubExpressions(final IExpressionDMContext exprContext,

+			final DataRequestMonitor<IExpressionDMContext[]> rm) {

+

+		if (!(exprContext instanceof IEDCExpression)

+				|| ((IEDCExpression) exprContext).getFrame() == null) {

+			rm.setData(new IEDCExpression[0]);

+			rm.done();

+			return;

+		}

+

+		asyncExec(new Runnable() {

+			public void run() {

+

+				final IEDCExpression expr = (IEDCExpression) exprContext;

+

+				// if expression has no evaluated value, then it has not yet been evaluated

+				if (expr.getEvaluatedValue() == null && expr.getEvaluatedValueString() != null) {

+					expr.evaluateExpression();

+				}

+

+				StackFrameDMC frame = (StackFrameDMC) expr.getFrame();

+				IType exprType = TypeUtils.getStrippedType(expr.getEvaluatedType());

+

+				// if casted to an array, convert thusly

+				CastInfo castInfo = expr.getCastInfo();

+				if (castInfo != null && castInfo.getArrayCount() > 0) {

+					try {

+						exprType = frame.getTypeEngine().convertToArrayType(exprType, castInfo.getArrayCount());

+					} catch (CoreException e) {

+						rm.setStatus(e.getStatus());

+						rm.done();

+						return;

+					}

+				}

+

+				// to expand it, it must either be a pointer, a reference to an aggregate,

+				// or an aggregate

+				boolean pointerType = exprType instanceof IPointerType;

+				boolean referenceType = exprType instanceof IReferenceType;

+				IType pointedTo = null;

+				if (referenceType) {

+					pointedTo = TypeUtils.getStrippedType(((IReferenceType) exprType).getType());

+					exprType = pointedTo;

+				}

+				

+				if (!(exprType instanceof IAggregate) && !pointerType &&

+					!(referenceType && (pointedTo instanceof IAggregate || pointedTo instanceof IPointerType))) {

+					rm.setData(new IEDCExpression[0]);

+					rm.done();

+					return;

+				}

+				

+				ITypeContentProvider customProvider = 

+					FormatExtensionManager.instance().getTypeContentProvider(exprType);

+				if (customProvider != null)

+					getSubExpressions(expr, frame, exprType, customProvider, rm);

+				else

+					getSubExpressions(expr, rm);

+			}

+		}, rm);

+	}

+

+	public void getSubExpressions(final IExpressionDMContext exprContext, final int startIndex_, final int length_,

+			final DataRequestMonitor<IExpressionDMContext[]> rm) {

+		asyncExec(new Runnable() {

+			public void run() {

+				getSubExpressions(exprContext, new DataRequestMonitor<IExpressionDMContext[]>(getExecutor(), rm) {

+					@Override

+					protected void handleSuccess() {

+						IExpressionDMContext[] allExprs = getData();

+						if (startIndex_ == 0 && length_ >= allExprs.length) {

+							rm.setData(allExprs);

+							rm.done();

+						} else {

+							int startIndex = startIndex_, length = length_;

+							if (startIndex > allExprs.length) {

+								startIndex = allExprs.length;

+								length = 0;

+							} else if (startIndex + length > allExprs.length) {

+								length = allExprs.length - startIndex;

+								if (length < 0)

+									length = 0;

+							}

+								

+							IExpressionDMContext[] result = new IExpressionDMContext[length];

+							System.arraycopy(allExprs, startIndex, result, 0, length);

+							rm.setData(result);

+							rm.done();

+						}

+					}

+				});

+			}

+		}, rm);

+	}

+

+	private void getSubExpressions(final IEDCExpression expr, final StackFrameDMC frame, 

+			final IType exprType, final ITypeContentProvider customProvider,

+			final DataRequestMonitor<IExpressionDMContext[]> rm) {

+

+		List<IExpressionDMContext> children = new ArrayList<IExpressionDMContext>();

+		Iterator<IExpressionDMContext> childIterator;

+		try {

+			childIterator = customProvider.getChildIterator(expr);

+			while (childIterator.hasNext() && !rm.isCanceled()) {

+				children.add(childIterator.next());

+			}

+			rm.setData(children.toArray(new IExpressionDMContext[children.size()]));

+			rm.done();

+		} catch (CoreException e) {

+			// Checked exception. But we don't want to pass the error up as it

+			// would make the variable (say, a structure) not expandable on UI. 

+			// Just resort to the normal formatting.  

+			getSubExpressions(expr, rm);

+		} catch (Throwable e) {

+			// unexpected error. log it.

+			EDCDebugger.getMessageLogger().logError(

+					EDCServicesMessages.Expressions_ErrorInVariableFormatter + customProvider.getClass().getName(), e);

+			

+			// default to normal formatting

+			getSubExpressions(expr, rm);

+		}

+	}

+

+	private void getSubExpressions(final IEDCExpression expr,

+			final DataRequestMonitor<IExpressionDMContext[]> rm) {

+		rm.setData(getLogicalSubExpressions(expr));

+		rm.done();

+	}

+	

+	/**

+	 * Get the logical subexpressions for the given expression context.  We want

+	 * to skip unnecessary nodes, e.g., a pointer to a composite, and directly

+	 * show the object contents.

+	 * @param expr the expression from which to start

+	 * @return array of children

+	 */

+	public IEDCExpression[] getLogicalSubExpressions(IEDCExpression expr) {

+

+		IType exprType = TypeUtils.getUnRefStrippedType(expr.getEvaluatedType());

+		

+		// cast to array?

+		CastInfo castInfo = expr.getCastInfo();

+		if (castInfo != null && castInfo.getArrayCount() > 0) {

+			

+			String exprName = expr.getExpression();

+			

+			// in case of casts, need to resolve that before dereferencing, so be safe

+			if (exprName.contains("(")) //$NON-NLS-1$

+				exprName = '(' + exprName + ')';

+

+			long lowerBound = castInfo.getArrayStartIndex();

+			long count = castInfo.getArrayCount();

+			

+			List<IEDCExpression> arrayChildren = new ArrayList<IEDCExpression>();

+			for (int i = 0; i < count; i++) {

+				String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$

+				IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), (exprName + arrayElement),

+						expr.getName() + arrayElement);

+				IEDCExpression exprChild = newExpr; //$NON-NLS-1$ //$NON-NLS-2$

+				if (exprChild != null) {

+					arrayChildren.add(exprChild);

+				}

+			}

+

+			return arrayChildren.toArray(new IEDCExpression[arrayChildren.size()]);

+		} 

+

+		if (exprType instanceof IPointerType) {

+			// automatically dereference a pointer

+			String exprName = expr.getExpression();

+			IType typePointedTo = TypeUtils.getStrippedType(exprType.getType());

+

+			// Try to resolve opaque pointer. 

+			// Note this may take some time depending on symbol file size. 

+			// ........05/19/11

+			//

+			if (TypeUtils.isOpaqueType(typePointedTo) && resolveOpaqueType(expr)) {

+				final Symbols symService = getService(Symbols.class);

+				assert symService != null;

+				

+				final ISymbolDMContext symCtx = DMContexts.getAncestorOfType(expr, ISymbolDMContext.class);

+				if (symCtx != null) {

+					final ICompositeType[] resolved = {null};

+					final IType original = typePointedTo;

+					Job j = new Job("Resolving opaque type: " + original.getName()

+									+ " for expression " + exprName) {

+						@Override

+						protected IStatus run(IProgressMonitor monitor) {

+							monitor.beginTask("Resolving opaque type: " + original.getName(), IProgressMonitor.UNKNOWN);

+							resolved[0] = symService.resolveOpaqueType(symCtx, (ICompositeType)original, monitor);

+							monitor.done();

+							return Status.OK_STATUS;

+						}};

+						

+					j.schedule();

+					try {

+						j.join();

+					} catch (InterruptedException e) {

+						// ignore

+					}

+					

+					if (resolved[0] != null) {

+						typePointedTo = resolved[0];

+						

+						// Make the pointer type points to the resolved type

+						// so that we won't need to resolve the opaque type again

+						// and again.

+						exprType.setType(resolved[0]);

+					}

+				}

+			}

+			

+			// If expression name already starts with "&" (e.g. "&struct"), indirect it first

+			boolean indirected = false;

+			

+			IEDCExpression exprChild;

+			

+			if (exprName.startsWith("&")) { //$NON-NLS-1$

+				exprName = exprName.substring(1);

+				IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), exprName);

+				exprChild = newExpr;

+				indirected = true;

+			} else {

+				// avoid dereferencing void pointer

+				if (typePointedTo instanceof ICPPBasicType 

+						&& ((ICPPBasicType) typePointedTo).getBaseType() == ICPPBasicType.t_void) {

+					return new IEDCExpression[0];

+				}

+				

+				// do not dereference null either

+				if (expr.getEvaluatedValue() != null && expr.getEvaluatedValue().intValue() == 0)

+					return new IEDCExpression[0];

+

+				IEDCExpression newExpr = null;

+				newExpr = new ExpressionDMC(expr.getFrame(), ("*" + exprName), "*" + expr.getName()); //$NON-NLS-1$ //$NON-NLS-2$

+					

+				// a pointer type has one child

+				exprChild = newExpr; //$NON-NLS-1$

+			}

+			

+			return doGetLogicalSubExpressions(exprChild, typePointedTo, indirected);

+		} else if (exprType instanceof IReferenceType) {

+			// and bypass a reference

+			

+			IType typePointedTo = TypeUtils.getStrippedType(exprType.getType());

+			return doGetLogicalSubExpressions(expr, typePointedTo, false);

+		} else {

+			// normal aggregate, just do it

+			return doGetLogicalSubExpressions(expr, exprType, false);

+		}

+

+	}

+

+	/**

+	 * Get the logical subexpressions for the given expression context and string 

+	 * @param expr the expression from which to start

+	 * @param exprType the type in which to consider the expression

+	 * @param indirected if true, the expression was already indirected, as opposed to what the expression says

+	 * @return

+	 */

+	private IEDCExpression[] doGetLogicalSubExpressions(IEDCExpression expr, IType exprType, boolean indirected) {

+		ArrayList<IEDCExpression> exprList = new ArrayList<IEDCExpression>();

+		IEDCExpression exprChild;

+

+		String expression = expr.getExpression();

+		

+		// in case of casts, need to resolve that before dereferencing, so be safe

+		if (expression.contains("(")) //$NON-NLS-1$

+			expression = '(' + expression + ')';

+

+		/*

+		// cast to array?

+		CastInfo castInfo = expr.getCastInfo();

+		if (castInfo != null && castInfo.getArrayCount() > 0) {

+			long lowerBound = castInfo.getArrayStartIndex();

+			long count = castInfo.getArrayCount();

+			for (int i = 0; i < count; i++) {

+				exprChild = createDerivedExpression(expr, exprName + "[" + (i + lowerBound) + "]"); //$NON-NLS-1$ //$NON-NLS-2$

+				if (exprChild != null) {

+					exprList.add(exprChild);

+				}

+			}

+		

+		} 

+		else*/ if (exprType instanceof ICompositeType) {

+			// an artifact of following a pointer to a structure is that the

+			// name starts with '*'

+			if (expression.startsWith("*")) { //$NON-NLS-1$

+				if (expression.startsWith("**"))

+					expression = "(" + expression.substring(1) + ")->"; //$NON-NLS-1$

+				else

+					expression = expression.substring(1) + "->"; //$NON-NLS-1$

+			} else {

+				expression = expression + '.'; //$NON-NLS-1$

+			}

+

+			// for each field, evaluate an expression, then shorten the name

+			ICompositeType compositeType = (ICompositeType) exprType;

+

+			for (IField field : compositeType.getFields()) {

+				String fieldName = field.getName();

+				if (fieldName.length() == 0) {

+					// This makes an invalid expression

+					// The debug info provider should have filtered out or renamed such fields

+					assert false;

+					continue;

+				}

+				exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName);

+				if (exprChild != null) {

+					exprList.add(exprChild);

+				}

+			}

+

+			for (IInheritance inherited : compositeType.getInheritances()) {

+				String inheritedName = inherited.getName();

+				if (inheritedName.length() == 0) {

+					// This makes an invalid expression

+					// The debug info provider should have filtered out or renamed such fields

+					assert false;	// couldn't this be the case for an anonymous member, like a union?

+				} else if (!inheritedName.contains("<")) {

+					exprChild = new ExpressionDMC(expr.getFrame(), expression + inheritedName, inheritedName);

+					if (exprChild != null) {

+						exprList.add(exprChild);

+					}

+				} else {

+					IType inheritedType = inherited.getType(); 

+					if (inheritedType instanceof ICompositeType) {

+						for (IField field : ((ICompositeType)inheritedType).getFields()) {

+							String fieldName = field.getName();

+							if (fieldName.length() == 0) {

+								// This makes an invalid expression

+								// The debug info provider should have filtered out or renamed such fields

+								assert false;

+								continue;

+							}

+							exprChild = new ExpressionDMC(expr.getFrame(), expression + fieldName, fieldName);

+							if (exprChild != null) {

+								exprList.add(exprChild);

+							}

+						}

+					}

+				}

+			}

+			

+		} 

+		else if (exprType instanceof IArrayType) {

+			IArrayType arrayType = (IArrayType) exprType;

+

+			if (arrayType.getBoundsCount() > 0) {

+				long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 

+					? expr.getCastInfo().getArrayStartIndex() : 0;

+				long upperBound = arrayType.getBound(0).getBoundCount();

+				if (upperBound == 0)

+					upperBound = 1;

+				for (int i = 0; i < upperBound; i++) {

+					String arrayElementName = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$

+					IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElementName,

+							expr.getName() + arrayElementName); 

+					exprChild = newExpr;

+					if (exprChild != null) {

+						exprList.add(exprChild);

+					}

+				}

+			}

+		} 

+		else if (exprType instanceof IArrayDimensionType) {

+			IArrayDimensionType arrayDimensionType = (IArrayDimensionType) exprType;

+			IArrayType arrayType = arrayDimensionType.getArrayType();

+

+			if (arrayType.getBoundsCount() > arrayDimensionType.getDimensionCount()) {

+				long lowerBound = expr.getCastInfo() != null && expr.getCastInfo().getArrayCount() > 0 

+				? expr.getCastInfo().getArrayStartIndex() : 0;

+				long upperBound = arrayType.getBound(arrayDimensionType.getDimensionCount()).getBoundCount();

+				for (int i = 0; i < upperBound; i++) {

+					String arrayElement = "[" + (i + lowerBound) + "]"; //$NON-NLS-1$ //$NON-NLS-2$

+					IEDCExpression newExpr = new ExpressionDMC(expr.getFrame(), expression + arrayElement,

+							expr.getName() + arrayElement); 

+					exprChild = newExpr;

+					if (exprChild != null) {

+						exprList.add(exprChild);

+					}

+				}

+			}

+		} else {

+			// nothing interesting

+			exprList.add(expr);

+		}

+

+		return exprList.toArray(new IEDCExpression[exprList.size()]);

+	}

+

+	@Immutable

+	private static class ExpressionChangedDMEvent extends AbstractDMEvent<IExpressionDMContext> implements IExpressionChangedDMEvent {

+		ExpressionChangedDMEvent(IExpressionDMContext expression) {

+			super(expression);

+		}

+	}

+

+	public void writeExpression(final IExpressionDMContext exprContext, final String expressionValue, final String formatId, final RequestMonitor rm) {

+

+		asyncExec(new Runnable() {

+			public void run() {

+				IEDCExpression expressionDMC = (IEDCExpression) exprContext;

+				if (isComposite(expressionDMC)) {

+					rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotModifyCompositeValue, null));

+					rm.done();

+					return;

+				}

+

+				IType exprType = TypeUtils.getStrippedType(expressionDMC.getEvaluatedType());

+

+				// first try to get value by format as BigInteger

+				Number number = NumberFormatUtils.parseIntegerByFormat(expressionValue, formatId);

+				if (number == null) {

+					IEDCExpression temp = (IEDCExpression) createExpression(expressionDMC.getFrame(), expressionValue);

+					temp.evaluateExpression();

+					number = temp.getEvaluatedValue();

+

+					if (number == null) {

+						rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_CannotParseExpression, null));

+						rm.done();

+						return;

+					}

+				}

+				

+				BigInteger value = null;

+				try {

+					value = MemoryUtils.convertValueToMemory(exprType, number);

+				} catch (CoreException e) {

+					rm.setStatus(e.getStatus());

+					rm.done();

+					return;

+				}

+

+				IVariableLocation variableLocation = expressionDMC.getValueLocation();

+				if (variableLocation == null) {

+					rm.setStatus(EDCDebugger.dsfRequestFailedStatus(EDCServicesMessages.Expressions_ExpressionNoLocation, null));

+					rm.done();

+					return;

+				}

+

+				try {

+					variableLocation.writeValue(exprType.getByteSize(), value);

+					getSession().dispatchEvent(new ExpressionChangedDMEvent(exprContext), getProperties());

+				} catch (CoreException e) {

+					rm.setStatus(e.getStatus());

+				}

+

+				rm.done();

+			}

+		}, rm);

+

+	}

+

+	public void getAvailableFormats(IFormattedDataDMContext formattedDataContext, DataRequestMonitor<String[]> rm) {

+		rm.setData(new String[] { IFormattedValues.NATURAL_FORMAT, IFormattedValues.DECIMAL_FORMAT, 

+				IFormattedValues.HEX_FORMAT, IFormattedValues.OCTAL_FORMAT, IFormattedValues.BINARY_FORMAT });

+		rm.done();

+	}

+

+	public void getFormattedExpressionValue(final FormattedValueDMContext formattedDataContext,

+			final DataRequestMonitor<FormattedValueDMData> rm) {

+		IDMContext idmContext = formattedDataContext.getParents()[0];

+

+		if (! (idmContext instanceof IEDCExpression)) {

+			rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$)

+			rm.done();

+			return;

+		}

+

+		asyncExec(new Runnable() {

+			public void run() {

+				try {

+					rm.setData(getFormattedExpressionValue(formattedDataContext));

+					rm.done();

+				} catch (CoreException ce) {

+					rm.setStatus(ce.getStatus());

+					rm.done();

+				}

+			}

+		}, rm);

+	}

+

+	public String getExpressionValueString(IExpressionDMContext expression, String format) throws CoreException {

+		FormattedValueDMContext formattedDataContext = getFormattedValueContext(expression, format);

+		FormattedValueDMData formattedValue = getFormattedExpressionValue(formattedDataContext);

+		

+		return formattedValue != null ? formattedValue.getFormattedValue() : "";

+	}

+

+	private FormattedValueDMData getFormattedExpressionValue(FormattedValueDMContext formattedDataContext) throws CoreException {

+		IDMContext idmContext = formattedDataContext.getParents()[0];

+		FormattedValueDMData formattedValue = null;

+		IEDCExpression exprDMC = null;

+

+		if (idmContext instanceof IEDCExpression) {

+			exprDMC = (IEDCExpression) formattedDataContext.getParents()[0];

+

+			exprDMC.evaluateExpression();

+

+			if (exprDMC != null && exprDMC.getEvaluationError() != null) {

+				throw new CoreException(exprDMC.getEvaluationError());

+			}

+			

+			formattedValue = exprDMC.getFormattedValue(formattedDataContext); // must call this to get type

+			

+			if (formattedDataContext.getFormatID().equals(IFormattedValues.NATURAL_FORMAT))

+			{

+				IVariableValueConverter customConverter = getCustomValueConverter(exprDMC);

+				if (customConverter != null) {

+					FormattedValueDMData customFormattedValue = null;

+					try {

+						customFormattedValue = new FormattedValueDMData(customConverter.getValue(exprDMC));

+						formattedValue = customFormattedValue;

+					}

+					catch (CoreException e) {

+						// Checked exception like failure in reading memory.  just re-throw

+						// it so it shows up in the variables view.

+						throw e;

+					} catch (Throwable t) {

+						// Other unexpected errors, usually bug in the formatter. Log it 

+						// so that user will be able to see and report the bug. 

+						// Meanwhile default to normal formatting so that user won't see 

+						// such error in Variable UI.

+						EDCDebugger.getMessageLogger().logError(

+								EDCServicesMessages.Expressions_ErrorInVariableFormatter + customConverter.getClass().getName(), t);

+					}

+				}

+			}

+		} else

+			formattedValue = new FormattedValueDMData(""); //$NON-NLS-1$

+		

+		return formattedValue;

+	}

+

+	private IVariableValueConverter getCustomValueConverter(IEDCExpression exprDMC) {

+		IType exprType = TypeUtils.getUnRefStrippedType(exprDMC.getEvaluatedType());

+		return FormatExtensionManager.instance().getVariableValueConverter(exprType);

+	}

+

+	public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext formattedDataContext,

+			String formatId) {

+		return new FormattedValueDMContext(this, formattedDataContext, formatId);

+	}

+

+	public void getModelData(IDMContext context, DataRequestMonitor<?> rm) {

+	}

+

+// TODO for separate pref for snapshots 2 functions and their uses in snapshotValues() below

+//	private static void addSnapshotProperties(IExpressionDMContext expr) {

+//		if (expr instanceof IEDCExpression)

+//			((IEDCExpression)expr).setProperty(Album.PREF_RESOLVE_OPAQUE_TYPE,

+//											   new Boolean(Album.getResolveOpaqueType()));

+//	}

+//

+//	private static void removeSnapshotProperties(IExpressionDMContext expr) {

+//		if (expr instanceof IEDCExpression) {

+//			Map<String, Object> props = ((IEDCExpression)expr).getProperties();

+//			if (props != null)

+//				props.remove(Album.PREF_RESOLVE_OPAQUE_TYPE);

+//		}

+//	}

+

+	/**

+	 * @param expr ignored for now

+	 * @return true if the user has set the pref in the EDC Debugger pref panel

+	 */

+	private static boolean resolveOpaqueType(IExpressionDMContext expr) {

+// TODO for separate pref for snapshots, uncomment the following

+//		if (EDCDebugger.getResolveOpaqueType())

+//			return true;

+//		if (! (expr instanceof IEDCExpression) )

+//			return false;

+//		Object snapshotOpaquePointerDereference

+//		  = ((IEDCExpression)expr).getProperty(Album.PREF_RESOLVE_OPAQUE_TYPE);

+//		if (! (snapshotOpaquePointerDereference instanceof Boolean))

+//			return false;

+//		return (Boolean)snapshotOpaquePointerDereference;

+		return EDCDebugger.getResolveOpaqueTypes();

+	}

+

+	private String snapshotValue(final IExpressionDMContext expr) {

+		final StringBuffer holder = new StringBuffer();

+		FormattedValueDMContext snapshotValueContext

+		  = getFormattedValueContext(expr, IFormattedValues.NATURAL_FORMAT);

+		getFormattedExpressionValue(snapshotValueContext,

+				new DataRequestMonitor<FormattedValueDMData>(

+						ImmediateExecutor.getInstance(), null) {

+			@Override

+			protected void handleCompleted() {

+				if (isSuccess())

+					holder.append(this.getData().getFormattedValue());

+

+				// RequestMonitor would, by default, log any error if it's not

+				// explicitly handled. But during snapshot creation, we don't

+				// want to have to log those expected errors (checked exceptions)

+				// so, if (!isSuccess), do nothing.

+			}			

+		});

+		return holder.toString();

+	}

+

+	public void snapshotValues(IExpressionDMContext expression, int depth) {

+		snapshotValues(expression, new Integer[] {depth});

+	}

+

+	private void snapshotValues(final IExpressionDMContext expression,

+			final Integer[] depth) {

+//		addSnapshotProperties(expression);		// TODO for separate pref for snapshots

+		snapshotValue(expression);

+		if (depth[0] <= 0)

+			return;

+

+		getSubExpressions(expression, new DataRequestMonitor<IExpressions.IExpressionDMContext[]>(

+						ImmediateExecutor.getInstance(), null) {

+			@Override

+			protected void handleSuccess() {

+				--depth[0];

+				if (isSuccess()) {

+					IExpressionDMContext[] subExpressions = getData();

+					for (IExpressionDMContext iExpressionDMContext : subExpressions)

+						snapshotValues(iExpressionDMContext, depth);

+				}

+			}});

+//		removeSnapshotProperties(expression);	// TODO for separate pref for snapshots

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Modules.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Modules.java
index 4e0fa7b..d5a055c 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Modules.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Modules.java
@@ -1,1219 +1,1426 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010, 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
- * Broadcom - Process physical address in RuntimeSection for snapshots
- *******************************************************************************/
-package org.eclipse.cdt.debug.edc.internal.services.dsf;
-
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.EDCTrace;
-import org.eclipse.cdt.debug.edc.internal.PathUtils;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
-import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
-import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeSection;
-import org.eclipse.cdt.debug.edc.internal.symbols.ISection;
-import org.eclipse.cdt.debug.edc.internal.symbols.RuntimeSection;
-import org.eclipse.cdt.debug.edc.internal.symbols.Section;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;
-import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
-import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
-import org.eclipse.cdt.debug.edc.services.DMContext;
-import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
-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.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.ILineEntryProvider.ILineAddresses;
-import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;
-import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-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.IModules;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.utils.Addr64;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.debug.core.model.ISourceLocator;
-import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-public class Modules extends AbstractEDCService implements IModules, IEDCModules {
-
-	public static final String MODULE = "module";
-	public static final String SECTION = "section";
-
-	private static final String ADDRESS_RANGE_CACHE = "_address_range";
-	private static final String LINE_ADDRESSES_CACHE = "_line_addresses";
-	private static final String NO_FILE_CACHE = "_no_file";
-
-	/**
-	 * Modules that are loaded for each ISymbolDMContext (process).
-	 */
-	private final Map<String, List<ModuleDMC>> modules = Collections
-			.synchronizedMap(new HashMap<String, List<ModuleDMC>>());
-
-	private ISourceLocator sourceLocator;
-
-	public static class EDCAddressRange implements AddressRange, Serializable {
-		
-		private static final long serialVersionUID = -6475152211053407789L;
-		private IAddress startAddr, endAddr;
-
-		public EDCAddressRange(IAddress start, IAddress end) {
-			startAddr = start;
-			endAddr = end;
-		}
-
-		public IAddress getEndAddress() {
-			return endAddr;
-		}
-
-		public void setEndAddress(IAddress address) {
-			endAddr = address;
-		}
-
-		public IAddress getStartAddress() {
-			return startAddr;
-		}
-
-		public void setStartAddress(IAddress address) {
-			startAddr = address;
-		}
-
-		@Override
-		public String toString() {
-			return MessageFormat.format("[{0},{1})", startAddr.toHexAddressString(), endAddr.toHexAddressString());
-		}
-
-		public boolean contains(IAddress address) {
-			return getStartAddress().compareTo(address) <= 0
-			&& getEndAddress().compareTo(address) > 0;
-		}
-	}
-
-	public static class EDCLineAddresses implements ILineAddresses, Serializable {
-
-		private static final long serialVersionUID = 3263812332106024057L;
-
-		private int lineNumber;
-		private List<IAddress>	addresses;
-		
-		public EDCLineAddresses(int lineNumber, IAddress addr) {
-			super();
-			this.lineNumber = lineNumber;
-			addresses = new ArrayList<IAddress>();
-			addresses.add(addr);
-		}
-
-		public EDCLineAddresses(int lineNumber, List<IAddress> addrs) {
-			super();
-			this.lineNumber = lineNumber;
-			addresses = new ArrayList<IAddress>(addrs);
-		}
-
-		public int getLineNumber() {
-			return lineNumber;
-		}
-
-		public IAddress[] getAddress() {
-			return addresses.toArray(new IAddress[addresses.size()]);
-		}
-
-		/**
-		 * add addresses mapped to the line.
-		 * @param addr
-		 */
-		public void addAddress(List<IAddress> addrs) {
-			addresses.addAll(addrs);
-		}
-
-		/**
-		 * add addresses mapped to the line.
-		 * @param addrs
-		 */
-		public void addAddress(IAddress[] addrs) {
-			for (IAddress a : addrs)
-				addresses.add(a);
-		}
-
-		@Override
-		public String toString() {
-			String addrs = "";
-			for (IAddress a : addresses) {
-				addrs += a.toHexAddressString() + " ";
-			}
-			return "EDCLineAddresses [lineNumber=" + lineNumber
-					+ ", addresses=(" + addrs + ")]";
-		}
-	}
-	
-	public class ModuleDMC extends DMContext implements IEDCModuleDMContext, ISnapshotContributor,
-	// This means we'll install existing breakpoints
-			// for each newly loaded module
-			IBreakpointsTargetDMContext,
-			// This means calcAddressInfo() also applies to single module
-			// in addition to a process.
-			ISymbolDMContext  {
-		private final ISymbolDMContext symbolContext;
-
-		private final IPath hostFilePath;
-		private IEDCSymbolReader symReader;
-		private final List<IRuntimeSection> runtimeSections = new ArrayList<IRuntimeSection>();
-
-		public ModuleDMC(ISymbolDMContext symbolContext, Map<String, Object> props) {
-			super(Modules.this, symbolContext == null ? new IDMContext[0] : new IDMContext[] { symbolContext }, getModuleID(props), props);
-			this.symbolContext = symbolContext;
-
-			String filename = "";
-			if (props.containsKey(IModuleProperty.PROP_FILE))
-				filename = (String) props.get(IModuleProperty.PROP_FILE);
-
-			hostFilePath = locateModuleFileOnHost(filename);
-		}
-
-		public EDCServicesTracker getEDCServicesTracker() {
-			return Modules.this.getEDCServicesTracker();
-		}
-
-		public ISymbolDMContext getSymbolContext() {
-			return symbolContext;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#getSymbolReader()
-		 */
-		public IEDCSymbolReader getSymbolReader() {
-			return symReader;
-		}
-
-		public void loadSnapshot(Element element) throws Exception {
-			NodeList sectionElements = element.getElementsByTagName(SECTION);
-
-			int numSections = sectionElements.getLength();
-			for (int i = 0; i < numSections; i++) {
-				Element sectionElement = (Element) sectionElements.item(i);
-				Element propElement = (Element) sectionElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-				HashMap<String, Object> properties = new HashMap<String, Object>();
-				SnapshotUtils.initializeFromXML(propElement, properties);
-
-				IAddress linkAddress = new Addr64(sectionElement.getAttribute(ISection.PROPERTY_LINK_ADDRESS));
-				String physicalAddressString = sectionElement.getAttribute(ISection.PROPERTY_PHYSICAL_ADDRESS);
-				IAddress physicalAddress;
-				if (physicalAddressString != null && physicalAddressString.length() > 0) {
-					physicalAddress = new Addr64(physicalAddressString);
-				} else {
-					physicalAddress = null;
-				}
-				int sectionID = Integer.parseInt(sectionElement.getAttribute(ISection.PROPERTY_ID));
-				long size = Long.parseLong(sectionElement.getAttribute(ISection.PROPERTY_SIZE));
-
-				RuntimeSection section = new RuntimeSection(new Section(sectionID, size, linkAddress, physicalAddress, properties));
-				section.relocate(new Addr64(sectionElement.getAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS)));
-				runtimeSections.add(section);
-			}
-
-			initializeSymbolReader();
-		}
-
-		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor) {
-			SubMonitor progress = SubMonitor.convert(monitor, runtimeSections.size() + 1);
-			progress.subTask("Modules");
-			Element contextElement = document.createElement(MODULE);
-			contextElement.setAttribute(PROP_ID, this.getID());
-			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
-			contextElement.appendChild(propsElement);
-
-			for (IRuntimeSection s : runtimeSections) {
-				Element sectionElement = document.createElement(SECTION);
-				sectionElement.setAttribute(ISection.PROPERTY_ID, Integer.toString(s.getId()));
-				sectionElement.setAttribute(ISection.PROPERTY_SIZE, Long.toString(s.getSize()));
-				sectionElement.setAttribute(ISection.PROPERTY_LINK_ADDRESS, s.getLinkAddress().toHexAddressString());
-				IAddress physicalAddress = s.getPhysicalAddress();
-				if (physicalAddress != null) {
-					sectionElement.setAttribute(ISection.PROPERTY_PHYSICAL_ADDRESS, physicalAddress.toHexAddressString());
-				}
-				sectionElement.setAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS, s.getRuntimeAddress()
-						.toHexAddressString());
-				propsElement = SnapshotUtils.makeXMLFromProperties(document, s.getProperties());
-				sectionElement.appendChild(propsElement);
-				contextElement.appendChild(sectionElement);
-				progress.worked(1);
-			}
-
-			if (!hostFilePath.isEmpty()) {
-				album.addFile(hostFilePath);
-				IPath possibleSymFile = ExecutableSymbolicsReaderFactory.findSymbolicsFile(hostFilePath);
-				if (possibleSymFile != null) {
-					album.addFile(possibleSymFile);
-				}
-			}
-			progress.worked(1);
-			return contextElement;
-		}
-
-		/**
-		 * Relocate sections of the module. This should be called when the
-		 * module is loaded.<br>
-		 * <br>
-		 * The relocation handling is target environment dependent.
-		 * Implementation here has been tested for debug applications on
-		 * Windows, Linux and Symbian. <br>
-		 * 
-		 * @param props
-		 *            - runtime section properties from OS or from loader.
-		 */
-		public void relocateSections(Map<String, Object> props) {
-
-			initializeSymbolReader();
-
-			if (symReader != null) {	
-				for (ISection section: symReader.getSections())
-				{
-					runtimeSections.add(new RuntimeSection(section));
-				}
-			}
-			
-			if (props.containsKey(IModuleProperty.PROP_IMAGE_BASE_ADDRESS)) {
-				// Windows module (PE file)
-				//
-
-				Object base = props.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);
-				IAddress imageBaseAddr = null;
-				if (base != null) {
-					if (base instanceof Integer)
-						imageBaseAddr = new Addr64(base.toString());
-					else if (base instanceof Long)
-						imageBaseAddr = new Addr64(base.toString());
-					else if (base instanceof String) // the string should be hex
-						// string
-						imageBaseAddr = new Addr64((String) base, 16);
-					else
-						EDCDebugger.getMessageLogger().logError(
-								MessageFormat.format("Module property PROP_ADDRESS has invalid format {0}.", base
-										.getClass()), null);
-				}
-
-				Number size = 0;
-				if (props.containsKey(IModuleProperty.PROP_CODE_SIZE))
-					size = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);
-
-				if (symReader != null) {
-					// relocate
-					//
-					IAddress linkBase = symReader.getBaseLinkAddress();
-					if (linkBase != null && !linkBase.equals(imageBaseAddr)) {
-						BigInteger offset = linkBase.distanceTo(imageBaseAddr);
-						for (IRuntimeSection s : runtimeSections) {
-							IAddress runtimeB = s.getLinkAddress().add(offset);
-							s.relocate(runtimeB);
-						}
-					}
-				} else { // fill in fake section data
-					Map<String, Object> pp = new HashMap<String, Object>();
-					pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);
-					runtimeSections.add(new RuntimeSection(new Section(0, size.longValue(), imageBaseAddr, pp)));
-				}
-			} else if (props.containsKey(IModuleProperty.PROP_CODE_ADDRESS)) {
-				// platforms other than Windows
-				//
-				Number codeAddr = null, dataAddr = null, bssAddr = null;
-				Number codeSize = null, dataSize = null, bssSize = null;
-
-				try {
-					codeAddr = (Number) props.get(IModuleProperty.PROP_CODE_ADDRESS);
-					dataAddr = (Number) props.get(IModuleProperty.PROP_DATA_ADDRESS);
-					bssAddr = (Number) props.get(IModuleProperty.PROP_BSS_ADDRESS);
-					codeSize = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);
-					dataSize = (Number) props.get(IModuleProperty.PROP_DATA_SIZE);
-					bssSize = (Number) props.get(IModuleProperty.PROP_BSS_SIZE);
-				} catch (ClassCastException e) {
-					EDCDebugger.getMessageLogger().logError("Module property value has invalid format.", null);
-				}
-
-				if (symReader != null) {
-					// Relocate.
-					for (IRuntimeSection s : runtimeSections) {
-						if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_TEXT)
-								&& codeAddr != null)
-							s.relocate(new Addr64(codeAddr.toString()));
-						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_DATA)
-								&& dataAddr != null)
-							s.relocate(new Addr64(dataAddr.toString()));
-						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_BSS)
-								&& bssAddr != null)
-							s.relocate(new Addr64(bssAddr.toString()));
-					}
-				} else {
-					// binary file not available.
-					// fill in our fake sections. If no section size available,
-					// don't bother.
-					//
-					Map<String, Object> pp = new HashMap<String, Object>();
-
-					if (codeAddr != null && codeSize != null) {
-						pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);
-						runtimeSections.add(new RuntimeSection(new Section(0, codeSize.intValue(), new Addr64(codeAddr.toString()), pp)));
-					}
-					if (dataAddr != null && dataSize != null) {
-						pp.clear();
-						pp.put(ISection.PROPERTY_NAME, ISection.NAME_DATA);
-						runtimeSections.add(new RuntimeSection(new Section(0, dataSize.intValue(), new Addr64(dataAddr.toString()), pp)));
-					}
-					if (bssAddr != null && bssSize != null) {
-						pp.clear();
-						pp.put(ISection.PROPERTY_NAME, ISection.NAME_BSS);
-						runtimeSections.add(new RuntimeSection(new Section(0, bssSize.intValue(), new Addr64(bssAddr.toString()), pp)));
-					}
-				}
-			} else {
-				// No runtime address info available from target environment.
-				// The runtime sections will just be the link-time sections.
-				// 
-				// This works well for the case where no relocation is needed
-				// such as running the main executable (not DLLs nor shared
-				// libs)
-				// on Windows and Linux.
-				// 
-				// However, this may also indicate an error that the debug agent
-				// (or even the target OS or loader) is not doing its job of
-				// telling us the runtime address info.
-			}
-		}
-
-		private void initializeSymbolReader() {
-			if (hostFilePath.toFile().exists()) {
-				symReader = Symbols.getSymbolReader(hostFilePath);
-				if (symReader == null)
-					EDCDebugger.getMessageLogger().log(IStatus.WARNING,
-							MessageFormat.format("''{0}'' has no recognized file format.",
-									hostFilePath), null);
-				else if (! symReader.hasRecognizedDebugInformation()) {
-					// Log as INFO, not ERROR.
-					EDCDebugger.getMessageLogger().log(IStatus.INFO,
-							MessageFormat.format("''{0}'' has no recognized symbolics.",
-									hostFilePath), null);
-				}
-			} else {
-				// Binary file not on host. Do we want to prompt user for one ?
-				
-				// TODO: report this differently for the main executable vs. DLLs
-				EDCDebugger.getMessageLogger().log(IStatus.WARNING, MessageFormat
-						.format("Cannot debug ''{0}''; no match found on disk, through source lookup, or in Executables view",
-								hostFilePath), null);
-			
-			}
-		}
-
-		/**
-		 * Check if a given runtime address falls in this module
-		 * 
-		 * @param absoluteAddr
-		 *            - absolute runtime address.
-		 * @return
-		 */
-		public boolean containsAddress(IAddress runtimeAddress) {
-			for (IRuntimeSection s : runtimeSections) {
-				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();
-				if (offset >= 0 && offset < s.getSize())
-					return true;
-			}
-
-			return false;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#toLinkAddress(org.eclipse.cdt.core.IAddress)
-		 */
-		public IAddress toLinkAddress(IAddress runtimeAddress) {
-			IAddress ret = null;
-
-			for (IRuntimeSection s : runtimeSections) {
-				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();
-				if (offset >= 0 && offset < s.getSize()) {
-					return s.getLinkAddress().add(offset);
-				}
-			}
-
-			return ret;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModuleDMContext#toRuntimeAddress(org.eclipse.cdt.core.IAddress)
-		 */
-		public IAddress toRuntimeAddress(IAddress linkAddress) {
-			IAddress ret = null;
-
-			for (IRuntimeSection s : runtimeSections) {
-				long offset = s.getLinkAddress().distanceTo(linkAddress).longValue();
-				if (offset >= 0 && offset < s.getSize()) {
-					return s.getRuntimeAddress().add(offset);
-				}
-			}
-
-			return ret;
-		}
-
-		/**
-		 * Get file name (without path) of the module.
-		 * 
-		 * @return
-		 */
-		public String getFile() {
-			return hostFilePath.lastSegment();
-		}
-
-		@Override
-		public String toString() {
-			StringBuilder builder = new StringBuilder();
-			builder.append("\nModuleDMC [");
-			if (hostFilePath != null) {
-				builder.append("file=");
-				builder.append(hostFilePath.lastSegment());
-				builder.append(", ");
-			}
-			
-			if (symbolContext != null) {
-				builder.append("owner=");
-				builder.append(symbolContext.toString());
-			}
-			
-			for (IRuntimeSection s : runtimeSections) {
-				builder.append("\n");
-				builder.append(s);
-			}
-			
-			builder.append("]");
-			
-			return builder.toString();
-		}
-
-		@Override
-		public int hashCode() {
-			final int prime = 31;
-			int result = super.hashCode();
-			result = prime * result + getOuterType().hashCode();
-			result = prime * result + ((hostFilePath == null) ? 0 : hostFilePath.hashCode());
-			result = prime * result + ((symbolContext == null) ? 0 : symbolContext.hashCode());
-			return result;
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (this == obj)
-				return true;
-			if (!super.equals(obj))
-				return false;
-			if (getClass() != obj.getClass())
-				return false;
-			ModuleDMC other = (ModuleDMC) obj;
-			if (!getOuterType().equals(other.getOuterType()))
-				return false;
-			if (hostFilePath == null) {
-				if (other.hostFilePath != null)
-					return false;
-			} else if (!hostFilePath.equals(other.hostFilePath))
-				return false;
-			if (symbolContext == null) {
-				if (other.symbolContext != null)
-					return false;
-			} else if (!symbolContext.equals(other.symbolContext))
-				return false;
-			return true;
-		}
-
-		private IEDCModules getOuterType() {
-			return Modules.this;
-		}
-	}
-
-	static class ModuleDMData implements IModuleDMData {
-
-		private final Map<String, Object> properties;
-
-		public ModuleDMData(ModuleDMC dmc) {
-			properties = dmc.getProperties();
-		}
-
-		public String getFile() {
-			return (String) properties.get(IModuleProperty.PROP_FILE);
-		}
-
-		public String getName() {
-			return (String) properties.get(IEDCDMContext.PROP_NAME);
-		}
-
-		public long getTimeStamp() {
-			return 0;
-			// return (String) properties.get(IModuleProperty.PROP_TIME);
-		}
-
-		public String getBaseAddress() {
-			// return hex string representation.
-			//
-			Object baseAddress = properties.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);
-			if (baseAddress == null)
-				baseAddress = properties.get(IModuleProperty.PROP_CODE_ADDRESS);
-
-			if (baseAddress != null)
-				return baseAddress.toString();
-			else
-				return "";
-		}
-
-		public String getToAddress() {
-			// TODO this should return the end address, e.g. base + size
-			return getBaseAddress();
-		}
-
-		public boolean isSymbolsLoaded() {
-			return false;
-		}
-
-		public long getSize() {
-			Number moduleSize = (Number) properties.get(IModuleProperty.PROP_CODE_SIZE);
-			if (moduleSize != null)
-				return moduleSize.longValue();
-			else
-				return 0;
-		}
-
-	}
-
-	public static class ModuleLoadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleLoadedDMEvent {
-
-		private final ModuleDMC module;
-		private final IExecutionDMContext executionDMC;
-
-		public ModuleLoadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {
-			super(symbolContext);
-			this.module = module;
-			this.executionDMC = executionDMC;
-		}
-
-		public IExecutionDMContext getExecutionDMC() {
-			return executionDMC;
-		}
-
-		public IModuleDMContext getLoadedModuleContext() {
-			return module;
-		}
-
-	}
-
-	public static class ModuleUnloadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleUnloadedDMEvent {
-
-		private final ModuleDMC module;
-		private final IExecutionDMContext executionDMC;
-
-		public ModuleUnloadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {
-			super(symbolContext);
-			this.module = module;
-			this.executionDMC = executionDMC;
-		}
-
-		public IExecutionDMContext getExecutionDMC() {
-			return executionDMC;
-		}
-
-		public IModuleDMContext getUnloadedModuleContext() {
-			return module;
-		}
-
-	}
-
-	public Modules(DsfSession session) {
-		super(session, new String[] { IModules.class.getName(), IEDCModules.class.getName(), Modules.class.getName() });
-	}
-
-	public void setSourceLocator(ISourceLocator sourceLocator) {
-		this.sourceLocator = sourceLocator;
-	}
-
-	public ISourceLocator getSourceLocator() {
-		return sourceLocator;
-	}
-
-	private void addModule(ModuleDMC module) {
-		ISymbolDMContext symContext = module.getSymbolContext();
-		if (symContext instanceof IEDCDMContext) {
-			String symContextID = ((IEDCDMContext) symContext).getID();
-			synchronized (modules) {
-				List<ModuleDMC> moduleList = modules.get(symContextID);
-				if (moduleList == null) {
-					moduleList = Collections.synchronizedList(new ArrayList<ModuleDMC>());
-					modules.put(symContextID, moduleList);
-				}
-				moduleList.add(module);
-			}
-		}
-	}
-
-	private void removeModule(ModuleDMC module) {
-		ISymbolDMContext symContext = module.getSymbolContext();
-		if (symContext instanceof IEDCDMContext) {
-			String symContextID = ((IEDCDMContext) symContext).getID();
-			synchronized (modules) {
-				List<ModuleDMC> moduleList = modules.get(symContextID);
-				if (moduleList != null) {
-					moduleList.remove(module);
-				}
-			}
-		}
-	}
-
-	/*
-	 * The result AddressRange[] will contain absolute runtime addresses. And
-	 * the "symCtx" can be a process or a module.
-	 */
-	@SuppressWarnings("unchecked")
-	public void calcAddressInfo(ISymbolDMContext symCtx, String file, int line, int col,
-			DataRequestMonitor<AddressRange[]> rm) {
-		IModuleDMContext[] moduleList = null;
-
-		if (symCtx instanceof IEDCExecutionDMC) {
-			String symContextID = ((IEDCDMContext) symCtx).getID();
-			moduleList = getModulesForContext(symContextID);
-		} else if (symCtx instanceof IModuleDMContext) {
-			moduleList = new IModuleDMContext[1];
-			moduleList[0] = (IModuleDMContext) symCtx;
-		} else {
-			// should not happen
-			assert false : "Unknown ISymbolDMContext class.";
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
-					"Unknown class implementing ISymbolDMContext : {0}", symCtx.getClass().getName()), null));
-			rm.done();
-			return;
-		}
-
-		List<EDCAddressRange> addrRanges = new ArrayList<EDCAddressRange>(1);
-		
-		for (IModuleDMContext module : moduleList) {
-			ModuleDMC mdmc = (ModuleDMC) module;
-			IEDCSymbolReader reader = mdmc.getSymbolReader();
-
-			if (reader != null) {
-
-				Collection<AddressRange> linkAddressRanges = null;
-				Map<String, Collection<AddressRange>> cachedRanges = new HashMap<String, Collection<AddressRange>>();
-				// Check the persistent cache
-				String cacheKey = reader.getSymbolFile().toOSString() + ADDRESS_RANGE_CACHE;
-				String noFileCacheKey = reader.getSymbolFile().toOSString() + NO_FILE_CACHE;
-				Set<String> noFileCachedData = EDCDebugger.getDefault().getCache().getCachedData(noFileCacheKey, Set.class, reader.getModificationDate());
-				if (noFileCachedData != null && noFileCachedData.contains(file))
-					continue; // We have already determined that this file is not used by this module, don't bother checking again.
-				
-				Map<String, Collection<AddressRange>> cachedData = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class, reader.getModificationDate());
-				if (cachedData != null)
-				{
-					cachedRanges = cachedData;
-					linkAddressRanges = cachedRanges.get(file + line);
-				}
-				
-				if (linkAddressRanges == null)
-				{
-					linkAddressRanges = LineEntryMapper.getAddressRangesAtSource(  
-						reader.getModuleScope().getModuleLineEntryProvider(),
-						PathUtils.createPath(file),
-						line);
-					
-					if (linkAddressRanges == null)
-					{ // If this file is not used by this module, cache it so we can avoid searching it again.
-						if (noFileCachedData == null)
-							noFileCachedData = new HashSet<String>();
-						noFileCachedData.add(file);
-						EDCDebugger.getDefault().getCache().putCachedData(noFileCacheKey, (Serializable) noFileCachedData, reader.getModificationDate());				
-						continue;
-					}
-					cachedRanges.put(file + line, linkAddressRanges);
-					EDCDebugger.getDefault().getCache().putCachedData(cacheKey, (Serializable) cachedRanges, reader.getModificationDate());				
-				}
-								
-				// convert addresses to runtime ones.
-				for (AddressRange linkAddressRange : linkAddressRanges) {
-					EDCAddressRange addrRange = new EDCAddressRange(
-							mdmc.toRuntimeAddress(linkAddressRange.getStartAddress()),
-							mdmc.toRuntimeAddress(linkAddressRange.getEndAddress()));
-					addrRanges.add(addrRange);
-				}
-			}
-		}
-
-		if (addrRanges.size() > 0) {
-			AddressRange[] ar = addrRanges.toArray(new AddressRange[addrRanges.size()]);
-			rm.setData(ar);
-		} else {
-			/*
-			 * we try to set the breakpoint for every module since we don't know
-			 * which one the file is in. we report this error though if the file
-			 * isn't in the module, and let the caller handle the error.
-			 */
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
-					"Fail to find address for source line {0}: line# {1}", file, line), null));
-		}
-
-		rm.done();
-	}
-
-	public void calcLineInfo(ISymbolDMContext symCtx, IAddress address, DataRequestMonitor<LineInfo[]> rm) {
-		// TODO Auto-generated method stub
-
-	}
-
-	/**
-	 * Given a source line (let's call it anchor), find the line closest to the
-	 * anchor in the neighborhood (including the anchor itself) that has machine
-	 * code. If the anchor itself has code, it's returned. Otherwise neighbor
-	 * lines both above and below the anchor will be checked. If the closest
-	 * line above the anchor and the closest line below the anchor have the same
-	 * distance from the anchor, the one below will be selected.
-	 * 
-	 * This is mainly used in setting breakpoint at anchor line.
-	 * 
-	 * @param symCtx
-	 *            the symbol context in which to perform the lookup. It can be
-	 *            an execution context (e.g. a process), or a module (exe or
-	 *            dll) in a process.
-	 * @param file
-	 *            the file that contains the source lines in question.
-	 * @param anchor
-	 *            line number of the anchor source line.
-	 * @param neighbor_limit
-	 *            specify the limit of the neighborhood: up to this number of
-	 *            lines above the anchor and up to this number of lines below
-	 *            the anchor will be checked if needed. But the check will never
-	 *            go beyond the source file. When the limit is zero, no neighbor
-	 *            lines will be checked. If the limit has value of -1, it means
-	 *            the actual limit is the source file.
-	 * @param rm
-	 *            contains an object of {@link ILineAddresses} if the line with
-	 *            code is found. And addresses in it are runtime addresses. The
-	 *            RM will contain error status otherwise.
-	 */
-	public void findClosestLineWithCode(ISymbolDMContext symCtx, String file, int anchor, int neighbor_limit,
-			DataRequestMonitor<ILineAddresses> rm) {
-		IModuleDMContext[] moduleList = null;
-
-		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null,
-				"Find closest line with code. context: " + EDCTrace.fixArg(symCtx) + " file: " + file + " anchor: " + anchor + " limit: " + neighbor_limit); }
-
-		if (symCtx instanceof IEDCExecutionDMC) {
-			String symContextID = ((IEDCDMContext) symCtx).getID();
-			moduleList = getModulesForContext(symContextID);
-		} else if (symCtx instanceof IModuleDMContext) {
-			moduleList = new IModuleDMContext[1];
-			moduleList[0] = (IModuleDMContext) symCtx;
-		} else {
-			// should not happen
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
-					"Unknown class implementing ISymbolDMContext : {0}", symCtx.getClass().getName()), null));
-			rm.done();
-			if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null,
-					rm.getStatus()); }
-			return;
-		}
-
-		EDCLineAddresses result = null;
-		
-		for (IModuleDMContext module : moduleList) {
-			ModuleDMC mdmc = (ModuleDMC) module;
-			IEDCSymbolReader reader = mdmc.getSymbolReader();
-
-			if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-					"module: " + mdmc + " reader: " + reader); }
-
-			if (reader == null) 
-				continue;
-
-			List<ILineAddresses> codeLines = null;
-			
-			Map<String, List<ILineAddresses>> cache = new HashMap<String, List<ILineAddresses>>();
-			// Check the persistent cache
-			String cacheKey = reader.getSymbolFile().toOSString() + LINE_ADDRESSES_CACHE;
-			String noFileCacheKey = reader.getSymbolFile().toOSString() + NO_FILE_CACHE;
-			@SuppressWarnings("unchecked")
-			Set<String> noFileCachedData = EDCDebugger.getDefault().getCache().getCachedData(noFileCacheKey, Set.class, reader.getModificationDate());
-			if (noFileCachedData != null && noFileCachedData.contains(file))
-			{
-				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-						"Persistent cache says file not used by module"); }
-				continue; // We have already determined that this file is not used by this module, don't bother checking again.
-			}
-			
-			@SuppressWarnings("unchecked")
-			Map<String, List<ILineAddresses>> cachedData = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class, reader.getModificationDate());
-			if (cachedData != null)
-			{
-				cache = cachedData;
-				codeLines = cachedData.get(file + anchor);
-			}
-			
-			if (codeLines == null)	// cache missed
-			{
-				if (! reader.getModuleScope().getModuleLineEntryProvider().hasSourceFile(PathUtils.createPath(file)))
-				{ // If this file is not used by this module, cache it so we can avoid searching it again.
-					if (noFileCachedData == null)
-						noFileCachedData = new HashSet<String>();
-					noFileCachedData.add(file);
-					EDCDebugger.getDefault().getCache().putCachedData(noFileCacheKey, (Serializable) noFileCachedData, reader.getModificationDate());				
-					if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-					"File not used by module"); }
-					continue;
-				}
-			
-				codeLines = reader.getModuleScope().getModuleLineEntryProvider().findClosestLineWithCode(
-						PathUtils.createPath(file),	anchor, neighbor_limit);
-
-				if (codeLines == null)
-				{
-					if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-					"codeLines == null"); }
-					continue;	// should not happen
-				}
-				
-				// Cache code lines (with their link addresses), whether we find it or not.
-				cache.put(file + anchor, codeLines);
-				EDCDebugger.getDefault().getCache().putCachedData(cacheKey, (Serializable) cache, reader.getModificationDate());				
-				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,
-						"codeLines: " + codeLines); }
-			}
-
-			// convert addresses to runtime ones.
-			//
-			List<EDCLineAddresses> runtimeCLs = new ArrayList<Modules.EDCLineAddresses>(codeLines.size());
-			for (ILineAddresses cl : codeLines) {
-				List<IAddress> rt_addrs = new ArrayList<IAddress>(1);
-				for (IAddress a : cl.getAddress())
-					rt_addrs.add(mdmc.toRuntimeAddress(a));
-				runtimeCLs.add(new EDCLineAddresses(cl.getLineNumber(), rt_addrs));
-			}
-			
-			for (ILineAddresses l : runtimeCLs) 
-				result = selectCodeLine(result, l, anchor);
-		}
-
-		if (result != null) {
-			rm.setData(result);
-		} else {
-			/*
-			 * we try to set the breakpoint for every module since we don't know
-			 * which one the file is in. we report this error though if the file
-			 * isn't in the module, and let the caller handle the error.
-			 */
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
-					"Fail to find address sround source line {0}: line# {1}", file, anchor), null));
-		}
-
-		rm.done();
-	}
-	
-	private EDCLineAddresses selectCodeLine(EDCLineAddresses prevChoice,
-			ILineAddresses newLine, int anchor) {
-		
-		if (prevChoice == null)
-			prevChoice = (EDCLineAddresses)newLine;
-		else {
-			if (newLine.getLineNumber() == prevChoice.getLineNumber()) {
-				// merge the addresses. Same source line has different addresses in different module.
-				prevChoice.addAddress(newLine.getAddress());
-			}
-			else {
-				// code line is different for the anchor in different module
-				if (newLine.getLineNumber() == anchor) 
-					// always honor anchor itself
-					prevChoice = (EDCLineAddresses)newLine;
-				else if (prevChoice.getLineNumber() != anchor) {
-					/*
-					 * Two different code lines are found (from different
-					 * modules or different CUs) and neither of them is anchor.
-					 * Don't bother returning both of them as that would cause
-					 * unnecessary complexity to breakpoint setting as it means
-					 * moving breakpoint set on anchor line to two different
-					 * lines. Just keep the one closer to anchor. And user will
-					 * see the breakpoint works in one module (or CU) but not
-					 * the other.
-					 */
-					int new_distance = Math.abs(newLine.getLineNumber() - anchor);
-					int prev_distance = Math.abs(prevChoice.getLineNumber() - anchor);
-					
-					if (new_distance < prev_distance)
-						prevChoice = (EDCLineAddresses)newLine;
-					else if (new_distance == prev_distance) {
-						// Same distance from anchor, choose the one below anchor
-						if (newLine.getLineNumber() > prevChoice.getLineNumber())
-							prevChoice = (EDCLineAddresses)newLine;
-					}
-				}
-			}
-		}
-		
-		return prevChoice;
-	}
-
-	/**
-	 * Get runtime addresses mapped to given source line in given run context.
-	 *  
-	 * @param context
-	 * @param sourceFile
-	 * @param lineNumber
-	 * @param drm If no address found, holds an empty list.
-	 */
-	public void getLineAddress(IExecutionDMContext context,
-			String sourceFile, int lineNumber, final DataRequestMonitor<List<IAddress>> drm) {
-		final List<IAddress> addrs = new ArrayList<IAddress>(1);
-		
-		final ExecutionDMC dmc = (ExecutionDMC) context;
-		if (dmc == null) {
-			drm.setData(addrs);
-			drm.done();
-			return;
-		}
-		
-		ISymbolDMContext symCtx = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);
-
-		sourceFile = EDCLaunch.getLaunchForSession(getSession().getId()).getCompilationPath(sourceFile);
-
-		calcAddressInfo(symCtx, sourceFile, lineNumber, 0, 
-				new DataRequestMonitor<AddressRange[]>(getExecutor(), drm) {
-
-			@Override
-			protected void handleCompleted() {
-				if (! isSuccess()) {
-					drm.setStatus(getStatus());
-					drm.done();
-					return;
-				}
-
-				AddressRange[] addr_ranges = getData();
-
-				for (AddressRange range : addr_ranges) {
-					IAddress a = range.getStartAddress();  // this is runtime address
-					addrs.add(a);
-				}
-
-				drm.setData(addrs);
-				drm.done();
-			}
-		});
-	}
-		
-	public void getModuleData(IModuleDMContext dmc, DataRequestMonitor<IModuleDMData> rm) {
-		rm.setData(new ModuleDMData((ModuleDMC) dmc));
-		rm.done();
-	}
-
-	public void getModules(ISymbolDMContext symCtx, DataRequestMonitor<IModuleDMContext[]> rm) {
-		String symContextID = ((IEDCDMContext) symCtx).getID();
-		IModuleDMContext[] moduleList = getModulesForContext(symContextID);
-		rm.setData(moduleList);
-		rm.done();
-	}
-
-	public IModuleDMContext[] getModulesForContext(String symContextID) {
-		synchronized (modules) {
-			List<ModuleDMC> moduleList = modules.get(symContextID);
-			if (moduleList == null)
-				return new IModuleDMContext[0];
-			else
-				return moduleList.toArray(new IModuleDMContext[moduleList.size()]);
-		}
-	}
-
-	public void moduleLoaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, Map<String, Object> moduleProps) {
-		ModuleDMC module = new ModuleDMC(symbolContext, moduleProps);
-		module.relocateSections(moduleProps);
-		addModule(module);
-		getSession().dispatchEvent(new ModuleLoadedEvent(symbolContext, executionDMC, module),
-				Modules.this.getProperties());
-	}
-
-	public void moduleUnloaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC,
-			Map<String, Object> moduleProps) {
-		String moduleID = getModuleID(moduleProps); // the moduleProps comes from agent.
-		ModuleDMC module = getModuleByID(symbolContext, moduleID);
-		if (module == null) {
-			EDCDebugger.getMessageLogger().logError("Unexpected unload of module: " + moduleProps, null);
-			return;
-		}
-		System.out.println("module: " + module.toString());
-		Object requireResumeValue = moduleProps.get("RequireResume");
-		if (requireResumeValue != null && requireResumeValue instanceof Boolean)
-			module.setProperty("RequireResume", requireResumeValue);
-		removeModule(module);
-		getSession().dispatchEvent(new ModuleUnloadedEvent(symbolContext, executionDMC, module),
-				Modules.this.getProperties());
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModules#getModuleByAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)
-	 */
-	public ModuleDMC getModuleByAddress(ISymbolDMContext symCtx, IAddress instructionAddress) {
-		ModuleDMC bestMatch = null;
-		if (symCtx instanceof ModuleDMC) {
-			if (((ModuleDMC)symCtx).containsAddress(instructionAddress))
-				bestMatch = (ModuleDMC)symCtx;
-		}
-		else {
-			synchronized (modules) {
-				List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());
-				if (moduleList != null) {
-					for (ModuleDMC moduleDMC : moduleList) {
-						if (moduleDMC.containsAddress(instructionAddress)) {
-							bestMatch = moduleDMC;
-							break;
-						}
-					}
-	
-					if (bestMatch == null) {
-						// TODO: add a bogus wrap-all module ?
-					}
-				}
-			}
-		}
-		return bestMatch;
-	}
-
-	/**
-	 * Find the host file that corresponds to a given module file whose name
-	 * comes from target platform.
-	 * 
-	 * @param originalPath
-	 *            path or filename from target platform.
-	 * @return the path to an existing file on host, null otherwise.
-	 */
-	public IPath locateModuleFileOnHost(String originalPath) {
-		if (originalPath == null || originalPath.length() == 0)
-			return Path.EMPTY;
-
-		// Canonicalize path for the host OS, in hopes of finding a match directly on the host,
-		// and for searching sources and executables below.
-		//
-		IPath path = PathUtils.findExistingPathIfCaseSensitive(PathUtils.createPath(originalPath));
-
-		// Try source locator, use the host-correct path.
-		//
-		Object sourceElement = null;
-		ISourceLocator locator = getSourceLocator();
-		if (locator != null) {
-			if (locator instanceof ICSourceLocator || locator instanceof CSourceLookupDirector) {
-				if (locator instanceof ICSourceLocator)
-					sourceElement = ((ICSourceLocator) locator).findSourceElement(path.toOSString());
-				else
-					sourceElement = ((CSourceLookupDirector) locator).getSourceElement(path.toOSString());
-			}
-			if (sourceElement != null) {
-				if (sourceElement instanceof LocalFileStorage) {
-					return new Path(((LocalFileStorage) sourceElement).getFile().getAbsolutePath());
-				}
-			}
-		}
-		
-		return path;
-	}
-
-	public void loadModulesForContext(ISymbolDMContext context, Element element) throws Exception {
-
-		List<ModuleDMC> contextModules = Collections.synchronizedList(new ArrayList<ModuleDMC>());
-
-		NodeList moduleElements = element.getElementsByTagName(MODULE);
-
-		int numModules = moduleElements.getLength();
-		for (int i = 0; i < numModules; i++) {
-			Element moduleElement = (Element) moduleElements.item(i);
-			Element propElement = (Element) moduleElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-			HashMap<String, Object> properties = new HashMap<String, Object>();
-			SnapshotUtils.initializeFromXML(propElement, properties);
-
-			ModuleDMC module = new ModuleDMC(context, properties);
-			module.loadSnapshot(moduleElement);
-			contextModules.add(module);
-
-		}
-		modules.put(((IEDCDMContext) context).getID(), contextModules);
-
-	}
-	
-	private static String getModuleID(Map<String, Object> props) {
-		if (props.containsKey(IEDCDMContext.PROP_ID))
-			return props.get(IEDCDMContext.PROP_ID).toString();
-		if (props.containsKey(IModuleProperty.PROP_FILE))
-			return props.get(IModuleProperty.PROP_FILE).toString();
-		if (props.containsKey(IEDCDMContext.PROP_NAME))
-			return props.get(IEDCDMContext.PROP_NAME).toString();
-		assert(false); // One of these is required
-		return "";
-	}
-
-	/**
-	 * get module with given file name
-	 * 
-	 * @param symCtx
-	 * @param fileName
-	 *            executable name for module
-	 * @return null if not found.
-	 */
-	public ModuleDMC getModuleByName(ISymbolDMContext symCtx, Object fileName) {
-		ModuleDMC module = null;
-		synchronized (modules) {
-			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());
-			if (moduleList != null) {
-				for (ModuleDMC moduleDMC : moduleList) {
-					if ((moduleDMC.getName().compareToIgnoreCase((String) fileName)) == 0 ) {
-						module = moduleDMC;
-						break;
-					}
-				}
-			}
-		}
-		return module;
-	}
-
-	private ModuleDMC getModuleByID(ISymbolDMContext symCtx, String id) {
-		ModuleDMC module = null;
-		synchronized (modules) {
-			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());
-			if (moduleList != null) {
-				for (ModuleDMC moduleDMC : moduleList) {
-					if ((moduleDMC.getID().compareToIgnoreCase(id)) == 0 ) {
-						module = moduleDMC;
-						break;
-					}
-				}
-			}
-		}
-		return module;
-	}
-
-}
+/*******************************************************************************

+ * Copyright (c) 2009, 2010, 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

+ * Broadcom - Process physical address in RuntimeSection for snapshots

+ *******************************************************************************/

+package org.eclipse.cdt.debug.edc.internal.services.dsf;

+

+import java.io.Serializable;

+import java.math.BigInteger;

+import java.text.MessageFormat;

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+

+import org.eclipse.cdt.core.IAddress;

+import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;

+import org.eclipse.cdt.debug.edc.internal.EDCDebugger;

+import org.eclipse.cdt.debug.edc.internal.EDCTrace;

+import org.eclipse.cdt.debug.edc.internal.PathUtils;

+import org.eclipse.cdt.debug.edc.internal.PersistentCache;

+import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;

+import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ThreadExecutionDMC;

+import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;

+import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeSection;

+import org.eclipse.cdt.debug.edc.internal.symbols.ISection;

+import org.eclipse.cdt.debug.edc.internal.symbols.RuntimeSection;

+import org.eclipse.cdt.debug.edc.internal.symbols.Section;

+import org.eclipse.cdt.debug.edc.launch.EDCLaunch;

+import org.eclipse.cdt.debug.edc.services.AbstractEDCService;

+import org.eclipse.cdt.debug.edc.services.DMContext;

+import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;

+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.Stack;

+import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;

+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.ILineEntryProvider.ILineAddresses;

+import org.eclipse.cdt.debug.edc.symbols.IModuleLineEntryProvider;

+import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;

+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;

+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;

+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.IModules;

+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;

+import org.eclipse.cdt.dsf.debug.service.IStack;

+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;

+import org.eclipse.cdt.dsf.service.DsfSession;

+import org.eclipse.cdt.utils.Addr64;

+import org.eclipse.core.runtime.CoreException;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.core.runtime.SubMonitor;

+import org.eclipse.debug.core.model.ISourceLocator;

+import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.NodeList;

+

+public class Modules extends AbstractEDCService implements IModules, IEDCModules {

+

+	public static final String MODULE = "module";

+	public static final String SECTION = "section";

+

+	private static final String ADDRESS_RANGE_CACHE = "_address_range";

+	private static final String LINE_ADDRESSES_CACHE = "_line_addresses";

+	private static final String NO_FILE_CACHE = "_no_file";

+

+	private static final String PROP_SYMBOLS_LOADED = "PROP_SYMBOLS_LOADED";

+

+	/**

+	 * Modules that are loaded for each ISymbolDMContext (process).

+	 */

+	private final Map<String, List<ModuleDMC>> modules = Collections

+			.synchronizedMap(new HashMap<String, List<ModuleDMC>>());

+

+	private ISourceLocator sourceLocator;

+

+	/**

+	 * Report problems loading symbols for modules by default, but allow subclasses

+	 * to override this.

+	 */

+	protected boolean reportReaderProblems = true;

+

+	

+	public static class EDCAddressRange implements AddressRange, Serializable {

+		

+		private static final long serialVersionUID = -6475152211053407789L;

+		private IAddress startAddr, endAddr;

+

+		public EDCAddressRange(IAddress start, IAddress end) {

+			startAddr = start;

+			endAddr = end;

+		}

+

+		public IAddress getEndAddress() {

+			return endAddr;

+		}

+

+		public void setEndAddress(IAddress address) {

+			endAddr = address;

+		}

+

+		public IAddress getStartAddress() {

+			return startAddr;

+		}

+

+		public void setStartAddress(IAddress address) {

+			startAddr = address;

+		}

+

+		@Override

+		public String toString() {

+			return MessageFormat.format("[{0},{1})", startAddr.toHexAddressString(), endAddr.toHexAddressString());

+		}

+

+		public boolean contains(IAddress address) {

+			return getStartAddress().compareTo(address) <= 0

+			&& getEndAddress().compareTo(address) > 0;

+		}

+

+		// necessary so we can perform meaningful .contains() checks on lists of ranges

+		@Override

+		public boolean equals(Object o) {

+			if (this == o)

+				return true;

+			if (o == null)

+				return false;

+			if (getClass() != o.getClass())

+				return false;

+			EDCAddressRange other = (EDCAddressRange)o;

+			return startAddr.equals(other.startAddr) && endAddr.equals(other.endAddr);

+		}

+	}

+

+	public static class EDCLineAddresses implements ILineAddresses, Serializable {

+

+		private static final long serialVersionUID = 3263812332106024057L;

+

+		private int lineNumber;

+		private List<IAddress>	addresses;

+		

+		public EDCLineAddresses(int lineNumber, IAddress addr) {

+			super();

+			this.lineNumber = lineNumber;

+			addresses = new ArrayList<IAddress>();

+			addresses.add(addr);

+		}

+

+		public EDCLineAddresses(int lineNumber, List<IAddress> addrs) {

+			super();

+			this.lineNumber = lineNumber;

+			addresses = new ArrayList<IAddress>(addrs);

+		}

+

+		public int getLineNumber() {

+			return lineNumber;

+		}

+

+		public IAddress[] getAddress() {

+			return addresses.toArray(new IAddress[addresses.size()]);

+		}

+

+		/**

+		 * add addresses mapped to the line.

+		 * @param addr

+		 */

+		public void addAddress(List<IAddress> addrs) {

+			addresses.addAll(addrs);

+		}

+

+		/**

+		 * add addresses mapped to the line.

+		 * @param addrs

+		 */

+		public void addAddress(IAddress[] addrs) {

+			for (IAddress a : addrs)

+				addresses.add(a);

+		}

+

+		@Override

+		public String toString() {

+			String addrs = "";

+			for (IAddress a : addresses) {

+				addrs += a.toHexAddressString() + " ";

+			}

+			return "EDCLineAddresses [lineNumber=" + lineNumber

+					+ ", addresses=(" + addrs + ")]";

+		}

+	}

+	

+	public class ModuleDMC extends DMContext implements IEDCModuleDMContext, ISnapshotContributor,

+	// This means we'll install existing breakpoints

+			// for each newly loaded module

+			IBreakpointsTargetDMContext,

+			// This means calcAddressInfo() also applies to single module

+			// in addition to a process.

+			ISymbolDMContext  {

+		private final ISymbolDMContext symbolContext;

+

+		private final IPath hostFilePath;

+		private IEDCSymbolReader symReader;

+		private final List<IRuntimeSection> runtimeSections = new ArrayList<IRuntimeSection>();

+

+		public ModuleDMC(ISymbolDMContext symbolContext, Map<String, Object> props) {

+			super(Modules.this, symbolContext == null ? new IDMContext[0] : new IDMContext[] { symbolContext }, getModuleID(props), props);

+			this.symbolContext = symbolContext;

+

+			String filename = "";

+			if (props.containsKey(IModuleProperty.PROP_FILE))

+				filename = (String) props.get(IModuleProperty.PROP_FILE);

+

+			hostFilePath = locateModuleFileOnHost(filename);

+		}

+

+		public EDCServicesTracker getEDCServicesTracker() {

+			return Modules.this.getEDCServicesTracker();

+		}

+

+		public ISymbolDMContext getSymbolContext() {

+			return symbolContext;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#getSymbolReader()

+		 */

+		public IEDCSymbolReader getSymbolReader() {

+			return symReader;

+		}

+

+		public IEDCSymbolReader getSymbolReader(boolean create) {

+			if (symReader == null && create) {

+				// clear any dummy sections and relocate

+				runtimeSections.clear();

+				relocateSections(properties, true);

+			}

+			return symReader;

+		}

+		

+		public void loadSnapshot(Element element) throws Exception {

+			NodeList sectionElements = element.getElementsByTagName(SECTION);

+

+			int numSections = sectionElements.getLength();

+			for (int i = 0; i < numSections; i++) {

+				Element sectionElement = (Element) sectionElements.item(i);

+				Element propElement = (Element) sectionElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);

+				HashMap<String, Object> properties = new HashMap<String, Object>();

+				SnapshotUtils.initializeFromXML(propElement, properties);

+

+				IAddress linkAddress = new Addr64(sectionElement.getAttribute(ISection.PROPERTY_LINK_ADDRESS));

+				String physicalAddressString = sectionElement.getAttribute(ISection.PROPERTY_PHYSICAL_ADDRESS);

+				IAddress physicalAddress;

+				if (physicalAddressString != null && physicalAddressString.length() > 0) {

+					physicalAddress = new Addr64(physicalAddressString);

+				} else {

+					physicalAddress = null;

+				}

+				int sectionID = Integer.parseInt(sectionElement.getAttribute(ISection.PROPERTY_ID));

+				long size = Long.parseLong(sectionElement.getAttribute(ISection.PROPERTY_SIZE));

+

+				RuntimeSection section = new RuntimeSection(new Section(sectionID, size, linkAddress, physicalAddress, properties));

+				section.relocate(new Addr64(sectionElement.getAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS)));

+				runtimeSections.add(section);

+			}

+

+			initializeSymbolReader();

+		}

+

+		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor) {

+			SubMonitor progress = SubMonitor.convert(monitor, runtimeSections.size() + 1);

+			progress.subTask("Modules");

+			Element contextElement = document.createElement(MODULE);

+			contextElement.setAttribute(PROP_ID, this.getID());

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

+			contextElement.appendChild(propsElement);

+

+			for (IRuntimeSection s : runtimeSections) {

+				Element sectionElement = document.createElement(SECTION);

+				sectionElement.setAttribute(ISection.PROPERTY_ID, Integer.toString(s.getId()));

+				sectionElement.setAttribute(ISection.PROPERTY_SIZE, Long.toString(s.getSize()));

+				sectionElement.setAttribute(ISection.PROPERTY_LINK_ADDRESS, s.getLinkAddress().toHexAddressString());

+				IAddress physicalAddress = s.getPhysicalAddress();

+				if (physicalAddress != null) {

+					sectionElement.setAttribute(ISection.PROPERTY_PHYSICAL_ADDRESS, physicalAddress.toHexAddressString());

+				}

+				sectionElement.setAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS, s.getRuntimeAddress()

+						.toHexAddressString());

+				propsElement = SnapshotUtils.makeXMLFromProperties(document, s.getProperties());

+				sectionElement.appendChild(propsElement);

+				contextElement.appendChild(sectionElement);

+				progress.worked(1);

+			}

+			progress.worked(1);

+			return contextElement;

+		}

+

+		/**

+		 * Relocate sections of the module. This should be called when the

+		 * module is loaded.<br>

+		 * <br>

+		 * The relocation handling is target environment dependent.

+		 * Implementation here has been tested for debug applications on

+		 * Windows, Linux and Symbian. <br>

+		 * 

+		 * @param props

+		 *            - runtime section properties from OS or from loader.

+		 */

+		public void relocateSections(Map<String, Object> props, boolean loadSymbols) {

+

+			if (loadSymbols) {

+				initializeSymbolReader();

+			}

+

+			if (symReader != null) {	

+				for (ISection section: symReader.getSections())

+				{

+					runtimeSections.add(new RuntimeSection(section));

+				}

+			}

+			

+			if (props.containsKey(IModuleProperty.PROP_IMAGE_BASE_ADDRESS)) {

+				// Windows module (PE file)

+				//

+

+				Object base = props.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);

+				IAddress imageBaseAddr = null;

+				if (base != null) {

+					if (base instanceof Integer)

+						imageBaseAddr = new Addr64(base.toString());

+					else if (base instanceof Long)

+						imageBaseAddr = new Addr64(base.toString());

+					else if (base instanceof String) // the string should be hex

+						// string

+						imageBaseAddr = new Addr64((String) base, 16);

+					else

+						EDCDebugger.getMessageLogger().logError(

+								MessageFormat.format("Module property PROP_ADDRESS has invalid format {0}.", base

+										.getClass()), null);

+				}

+

+				Number size = 0;

+				if (props.containsKey(IModuleProperty.PROP_CODE_SIZE))

+					size = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);

+

+				if (symReader != null) {

+					// relocate

+					//

+					IAddress linkBase = symReader.getBaseLinkAddress();

+					if (linkBase != null && !linkBase.equals(imageBaseAddr)) {

+						BigInteger offset = linkBase.distanceTo(imageBaseAddr);

+						for (IRuntimeSection s : runtimeSections) {

+							IAddress runtimeB = s.getLinkAddress().add(offset);

+							s.relocate(runtimeB);

+						}

+					}

+				} else { // fill in fake section data

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

+					pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);

+					runtimeSections.add(new RuntimeSection(new Section(0, size.longValue(), imageBaseAddr, pp)));

+				}

+			} else if (props.containsKey(IModuleProperty.PROP_CODE_ADDRESS)) {

+				// platforms other than Windows

+				//

+				Number codeAddr = null, dataAddr = null, bssAddr = null;

+				Number codeSize = null, dataSize = null, bssSize = null;

+

+				try {

+					codeAddr = (Number) props.get(IModuleProperty.PROP_CODE_ADDRESS);

+					dataAddr = (Number) props.get(IModuleProperty.PROP_DATA_ADDRESS);

+					bssAddr = (Number) props.get(IModuleProperty.PROP_BSS_ADDRESS);

+					codeSize = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);

+					dataSize = (Number) props.get(IModuleProperty.PROP_DATA_SIZE);

+					bssSize = (Number) props.get(IModuleProperty.PROP_BSS_SIZE);

+				} catch (ClassCastException e) {

+					EDCDebugger.getMessageLogger().logError("Module property value has invalid format.", null);

+				}

+

+				if (symReader != null) {

+					// Relocate.

+					for (IRuntimeSection s : runtimeSections) {

+						if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_TEXT)

+								&& codeAddr != null)

+							s.relocate(new Addr64(codeAddr.toString()));

+						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_DATA)

+								&& dataAddr != null)

+							s.relocate(new Addr64(dataAddr.toString()));

+						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_BSS)

+								&& bssAddr != null)

+							s.relocate(new Addr64(bssAddr.toString()));

+					}

+				} else {

+					// binary file not available.

+					// fill in our fake sections. If no section size available,

+					// don't bother.

+					//

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

+

+					if (codeAddr != null && codeSize != null) {

+						pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);

+						runtimeSections.add(new RuntimeSection(new Section(0, codeSize.intValue(), new Addr64(codeAddr.toString()), pp)));

+					}

+					if (dataAddr != null && dataSize != null) {

+						pp.clear();

+						pp.put(ISection.PROPERTY_NAME, ISection.NAME_DATA);

+						runtimeSections.add(new RuntimeSection(new Section(0, dataSize.intValue(), new Addr64(dataAddr.toString()), pp)));

+					}

+					if (bssAddr != null && bssSize != null) {

+						pp.clear();

+						pp.put(ISection.PROPERTY_NAME, ISection.NAME_BSS);

+						runtimeSections.add(new RuntimeSection(new Section(0, bssSize.intValue(), new Addr64(bssAddr.toString()), pp)));

+					}

+				}

+			} else {

+				// No runtime address info available from target environment.

+				// The runtime sections will just be the link-time sections.

+				// 

+				// This works well for the case where no relocation is needed

+				// such as running the main executable (not DLLs nor shared

+				// libs)

+				// on Windows and Linux.

+				// 

+				// However, this may also indicate an error that the debug agent

+				// (or even the target OS or loader) is not doing its job of

+				// telling us the runtime address info.

+			}

+		}

+

+		private void initializeSymbolReader() {

+			if (hostFilePath.toFile().exists()) {

+				symReader = Symbols.getSymbolReader(hostFilePath);

+				if (symReader == null) {

+					if (reportReaderProblems) {

+						EDCDebugger.getMessageLogger().log(IStatus.WARNING,

+								MessageFormat.format("''{0}'' has no recognized file format.",

+										hostFilePath), null);

+					}

+				} else if (! symReader.hasRecognizedDebugInformation()) {

+					if (reportReaderProblems) {

+						// Log as INFO, not ERROR.

+						EDCDebugger.getMessageLogger().log(IStatus.INFO,

+								MessageFormat.format("''{0}'' has no recognized symbolics.",

+										hostFilePath), null);

+					}

+				} else {

+					// set property that symbols are loaded

+					properties.put(PROP_SYMBOLS_LOADED, Boolean.TRUE);

+				}

+			} else {

+				// Binary file not on host. Do we want to prompt user for one ?

+				

+				if (reportReaderProblems) {

+					// TODO: report this differently for the main executable vs. DLLs

+					EDCDebugger.getMessageLogger().log(IStatus.WARNING, MessageFormat

+							.format("Cannot debug ''{0}''; no match found on disk, through source lookup, or in Executables view",

+									hostFilePath), null);

+				}

+			}

+		}

+

+		/**

+		 * Check if a given runtime address falls in this module

+		 * 

+		 * @param absoluteAddr

+		 *            - absolute runtime address.

+		 * @return

+		 */

+		public boolean containsAddress(IAddress runtimeAddress) {

+			for (IRuntimeSection s : runtimeSections) {

+				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();

+				if (offset >= 0 && offset < s.getSize())

+					return true;

+			}

+

+			return false;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#toLinkAddress(org.eclipse.cdt.core.IAddress)

+		 */

+		public IAddress toLinkAddress(IAddress runtimeAddress) {

+			IAddress ret = null;

+

+			for (IRuntimeSection s : runtimeSections) {

+				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();

+				if (offset >= 0 && offset < s.getSize()) {

+					return s.getLinkAddress().add(offset);

+				}

+			}

+

+			return ret;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModuleDMContext#toRuntimeAddress(org.eclipse.cdt.core.IAddress)

+		 */

+		public IAddress toRuntimeAddress(IAddress linkAddress) {

+			IAddress ret = null;

+

+			for (IRuntimeSection s : runtimeSections) {

+				long offset = s.getLinkAddress().distanceTo(linkAddress).longValue();

+				if (offset >= 0 && offset < s.getSize()) {

+					return s.getRuntimeAddress().add(offset);

+				}

+			}

+

+			return ret;

+		}

+

+		/**

+		 * Get file name (without path) of the module.

+		 * 

+		 * @return

+		 */

+		public String getFile() {

+			return hostFilePath.lastSegment();

+		}

+

+		@Override

+		public String toString() {

+			StringBuilder builder = new StringBuilder();

+			builder.append("\nModuleDMC [");

+			if (hostFilePath != null) {

+				builder.append("file=");

+				builder.append(hostFilePath.lastSegment());

+				builder.append(", ");

+			}

+			

+			if (symbolContext != null) {

+				builder.append("owner=");

+				builder.append(symbolContext.toString());

+			}

+			

+			for (IRuntimeSection s : runtimeSections) {

+				builder.append("\n");

+				builder.append(s);

+			}

+			

+			builder.append("]");

+			

+			return builder.toString();

+		}

+

+		@Override

+		public int hashCode() {

+			final int prime = 31;

+			int result = super.hashCode();

+			result = prime * result + getOuterType().hashCode();

+			result = prime * result + ((hostFilePath == null) ? 0 : hostFilePath.hashCode());

+			result = prime * result + ((symbolContext == null) ? 0 : symbolContext.hashCode());

+			return result;

+		}

+

+		@Override

+		public boolean equals(Object obj) {

+			if (this == obj)

+				return true;

+			if (!super.equals(obj))

+				return false;

+			if (getClass() != obj.getClass())

+				return false;

+			ModuleDMC other = (ModuleDMC) obj;

+			if (!getOuterType().equals(other.getOuterType()))

+				return false;

+			if (hostFilePath == null) {

+				if (other.hostFilePath != null)

+					return false;

+			} else if (!hostFilePath.equals(other.hostFilePath))

+				return false;

+			if (symbolContext == null) {

+				if (other.symbolContext != null)

+					return false;

+			} else if (!symbolContext.equals(other.symbolContext))

+				return false;

+			return true;

+		}

+

+		private IEDCModules getOuterType() {

+			return Modules.this;

+		}

+

+		public IPath getHostFilePath() {

+			return hostFilePath;

+		}

+	}

+

+	static class ModuleDMData implements IModuleDMData {

+

+		private final Map<String, Object> properties;

+

+		public ModuleDMData(ModuleDMC dmc) {

+			properties = dmc.getProperties();

+		}

+

+		public String getFile() {

+			return (String) properties.get(IModuleProperty.PROP_FILE);

+		}

+

+		public String getName() {

+			return (String) properties.get(IEDCDMContext.PROP_NAME);

+		}

+

+		public long getTimeStamp() {

+			return 0;

+			// return (String) properties.get(IModuleProperty.PROP_TIME);

+		}

+

+		public String getBaseAddress() {

+			// return hex string representation.

+			//

+			Object baseAddress = properties.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);

+			if (baseAddress == null)

+				baseAddress = properties.get(IModuleProperty.PROP_CODE_ADDRESS);

+

+			if (baseAddress != null)

+				return baseAddress.toString();

+			else

+				return "";

+		}

+

+		public String getToAddress() {

+			// TODO this should return the end address, e.g. base + size

+			return getBaseAddress();

+		}

+

+		public boolean isSymbolsLoaded() {

+			Object loaded = properties.get(PROP_SYMBOLS_LOADED);

+			if (loaded != null && loaded instanceof Boolean) {

+				return ((Boolean) loaded).booleanValue();

+			}

+

+			return false;

+		}

+

+		public long getSize() {

+			Number moduleSize = (Number) properties.get(IModuleProperty.PROP_CODE_SIZE);

+			if (moduleSize != null)

+				return moduleSize.longValue();

+			else

+				return 0;

+		}

+

+	}

+

+	public static class ModuleLoadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleLoadedDMEvent {

+

+		private final ModuleDMC module;

+		private final IExecutionDMContext executionDMC;

+

+		public ModuleLoadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {

+			super(symbolContext);

+			this.module = module;

+			this.executionDMC = executionDMC;

+		}

+

+		public IExecutionDMContext getExecutionDMC() {

+			return executionDMC;

+		}

+

+		public IModuleDMContext getLoadedModuleContext() {

+			return module;

+		}

+

+	}

+

+	public static class ModuleUnloadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleUnloadedDMEvent {

+

+		private final ModuleDMC module;

+		private final IExecutionDMContext executionDMC;

+

+		public ModuleUnloadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {

+			super(symbolContext);

+			this.module = module;

+			this.executionDMC = executionDMC;

+		}

+

+		public IExecutionDMContext getExecutionDMC() {

+			return executionDMC;

+		}

+

+		public IModuleDMContext getUnloadedModuleContext() {

+			return module;

+		}

+

+	}

+

+	public Modules(DsfSession session) {

+		super(session, new String[] { IModules.class.getName(), IEDCModules.class.getName(), Modules.class.getName() });

+	}

+

+	public void setSourceLocator(ISourceLocator sourceLocator) {

+		this.sourceLocator = sourceLocator;

+	}

+

+	public ISourceLocator getSourceLocator() {

+		return sourceLocator;

+	}

+

+	protected void addModule(ModuleDMC module) {

+		ISymbolDMContext symContext = module.getSymbolContext();

+		if (symContext instanceof IEDCDMContext) {

+			String symContextID = ((IEDCDMContext) symContext).getID();

+			synchronized (modules) {

+				List<ModuleDMC> moduleList = modules.get(symContextID);

+				if (moduleList == null) {

+					moduleList = Collections.synchronizedList(new ArrayList<ModuleDMC>());

+					modules.put(symContextID, moduleList);

+				}

+				moduleList.add(module);

+			}

+		}

+	}

+

+	private void removeModule(ModuleDMC module) {

+		ISymbolDMContext symContext = module.getSymbolContext();

+		if (symContext instanceof IEDCDMContext) {

+			String symContextID = ((IEDCDMContext) symContext).getID();

+			synchronized (modules) {

+				List<ModuleDMC> moduleList = modules.get(symContextID);

+				if (moduleList != null) {

+					moduleList.remove(module);

+				}

+			}

+		}

+	}

+

+	/**

+	 * The result AddressRange[] will contain absolute runtime addresses. And

+	 * the "symCtx" can be a process or a module.

+	 */

+	public void calcAddressInfo(ISymbolDMContext symCtx, String file, int line, int col,

+			DataRequestMonitor<AddressRange[]> rm) {

+		IModuleDMContext[] moduleList = null;

+

+		if (symCtx instanceof IEDCExecutionDMC) {

+			String symContextID = ((IEDCDMContext) symCtx).getID();

+			moduleList = getModulesForContext(symContextID);

+		} else if (symCtx instanceof IModuleDMContext) {

+			moduleList = new IModuleDMContext[1];

+			moduleList[0] = (IModuleDMContext) symCtx;

+		} else {

+			// should not happen

+			assert false : "Unknown ISymbolDMContext class.";

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(

+					"Unknown class implementing ISymbolDMContext : {0}", symCtx.getClass().getName()), null));

+			rm.done();

+			return;

+		}

+

+		if (!calcAddressRanges(moduleList, file, line, true, rm)) {

+			/*

+			 * we try to set the breakpoint for every module since we don't know

+			 * which one the file is in. we report this error though if the file

+			 * isn't in the module, and let the caller handle the error.

+			 */

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,

+									MessageFormat.format(

+											EDCServicesMessages.Modules_CannotFindBreakpointSource,

+											file, line), null));

+		}

+	}

+

+	/**

+	 * for use with runToLine/resumeAtLine/moveToLine ... in most cases (and in all

+	 * cases for the last two) the location has to be on the stack already,

+	 * and since we have the thread-context passed to us, make use of it

+	 * @param threadDMC

+	 * @param file

+	 * @param line

+	 * @param col

+	 * @param rm

+	 */

+	private void calcAddressInfo(ThreadExecutionDMC threadDMC, String file,

+			int line, int col, DataRequestMonitor<AddressRange[]> rm) {

+		// create a set with the modules from the stack on the front 

+		Stack stackService = getService(Stack.class);

+		List<IEDCModuleDMContext> framesList

+		  = new ArrayList<IEDCModuleDMContext>();

+		IFrameDMContext[] frames = null;

+		try {

+			frames = stackService.getFramesForDMC(threadDMC, 0, IStack.ALL_FRAMES);

+		} catch (CoreException e) {

+		}

+		boolean success = false;

+		IModuleDMContext[] moduleList;

+		if (frames != null && frames.length > 0) {

+			for (IFrameDMContext frame : frames) {

+				if (frame instanceof StackFrameDMC) {

+					IEDCModuleDMContext frameModule

+					  = ((StackFrameDMC)frame).getModule();

+					if (!framesList.contains(frameModule))

+						framesList.add(frameModule);

+				}

+			}

+			moduleList = framesList.toArray(new IModuleDMContext[framesList.size()]);

+

+			// 4th arg == false means don't get "all address ranges" for line

+			success = calcAddressRanges(moduleList, file, line, false, rm);

+			// sets rm.done() if returning true

+

+			if (!success)

+				// set a warning, but try other modules

+				rm.setStatus(new Status(IStatus.WARNING, EDCDebugger.PLUGIN_ID,

+										MessageFormat.format(

+												EDCServicesMessages.Modules_CannotFindBreakpointSource,

+												file, line), null));

+		}

+

+		if (!success) {

+			// for runToLine, we still need to get test all addresses in all modules;

+			// so sort the rest for whatever's not on the stack and add them to the end

+			// of the list.

+			ISymbolDMContext symCtx = DMContexts.getAncestorOfType(threadDMC, ISymbolDMContext.class);

+			String symContextID = ((IEDCDMContext) symCtx).getID();

+			List<ModuleDMC> allModulesList = modules.get(symContextID);

+			if (allModulesList != null && allModulesList.size() > 0) {

+				for (int i = allModulesList.size(); i > 0;) {

+					ModuleDMC testModule = allModulesList.get(--i);

+					if (framesList.contains(testModule)

+							|| null == testModule.getSymbolReader())

+						allModulesList.remove(i);				

+				}

+				moduleList = allModulesList.toArray(new IModuleDMContext[allModulesList.size()]);

+

+				// 4th arg == false means don't get "all address ranges" for line

+				success = calcAddressRanges(moduleList, file, line, false, rm);

+				// sets rm.done() if returning true

+			}

+

+			if (!success) {

+				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,

+										MessageFormat.format(

+												EDCServicesMessages.Modules_CannotFindBreakpointSource,

+												file, line), null));

+			}

+			rm.done();

+		}

+	}

+

+	/**

+	 * used by both {@link #calcAddressInfo(IModules.ISymbolDMContext, String, int, int, DataRequestMonitor)}

+	 * and {@link #calcAddressInfo(ThreadExecutionDMC, String, int, int, DataRequestMonitor)}

+	 * to compute the ranges once the list of modules to search has been determined

+	 * @param file

+	 * @param line

+	 * @param moduleList

+	 * @return true if any addresses were calculated

+	 */

+	private boolean calcAddressRanges(IModuleDMContext[] moduleList, String file, int line,

+			boolean getAllAddressRanges, DataRequestMonitor<AddressRange[]> rm) {

+

+		List<EDCAddressRange> addrRanges = new ArrayList<EDCAddressRange>(1);

+		IPath originalPath = null, compilationPath = null;

+		for (IModuleDMContext module : moduleList) {

+			ModuleDMC mdmc = (ModuleDMC) module;

+			IEDCSymbolReader reader = mdmc.getSymbolReader();

+

+			if (reader == null)

+				continue;

+

+			Map<String, Collection<AddressRange>> cachedRanges = new HashMap<String, Collection<AddressRange>>();

+			// Check the persistent cache

+			String cacheKey = reader.getSymbolFile().toOSString() + ADDRESS_RANGE_CACHE;

+			String noFileCacheKey = reader.getSymbolFile().toOSString() + NO_FILE_CACHE;

+

+			@SuppressWarnings("unchecked")

+			Set<String> noFileCachedData

+			  = EDCDebugger.getDefault().getCache().getCachedData(noFileCacheKey, Set.class, reader.getModificationDate());

+

+			if (noFileCachedData != null && noFileCachedData.contains(file))

+				continue; // We have already determined that this file is not used by this module, don't bother checking again.

+			

+			Collection<AddressRange> linkAddressRanges = null;

+

+			@SuppressWarnings("unchecked")

+			Map<String, Collection<AddressRange>> cachedData

+			  = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class, reader.getModificationDate());

+

+			if (cachedData != null) {

+				cachedRanges = cachedData;

+				linkAddressRanges = cachedRanges.get(file + line);

+			}

+			

+			IModuleLineEntryProvider lineEntryProvider;

+			if (linkAddressRanges == null) {

+				lineEntryProvider = reader.getModuleScope().getModuleLineEntryProvider();

+

+				// always try the compilationPath first; this mimics the

+				// pre-2011.09.17 behavior, where this was passed in

+				// from getAddressForLine() .

+				if (compilationPath == null)

+					compilationPath

+					  = PathUtils.createPath(

+							  EDCLaunch.getLaunchForSession(

+									  getSession().getId())

+									  .getCompilationPath(file));

+				linkAddressRanges

+				  = LineEntryMapper.getAddressRangesAtSource(lineEntryProvider,

+															 compilationPath, line);

+

+				// if using the compilation path didn't work, try the source-path;

+				// sometimes, that is what gets stuffed in the executable instead

+				// for runToLine/resumeAtLine/moveToLine

+				if (originalPath == null)

+					originalPath = PathUtils.createPath(file);

+				if (linkAddressRanges == null && compilationPath != originalPath) {

+					linkAddressRanges

+					  = LineEntryMapper.getAddressRangesAtSource(lineEntryProvider,

+																 originalPath, line);

+				}

+			}

+

+			if (linkAddressRanges == null) {

+				// If this file is not used by this module, cache it so we can avoid searching it again.

+				if (noFileCachedData == null)

+					noFileCachedData = new HashSet<String>();

+				noFileCachedData.add(file);

+				EDCDebugger.getDefault().getCache().putCachedData(noFileCacheKey, (Serializable) noFileCachedData, reader.getModificationDate());

+				continue;

+			}

+

+			cachedRanges.put(file + line, linkAddressRanges);

+			EDCDebugger.getDefault().getCache().putCachedData(cacheKey, (Serializable) cachedRanges, reader.getModificationDate());

+							

+			// convert addresses to runtime ones.

+			for (AddressRange linkAddressRange : linkAddressRanges) {

+				EDCAddressRange addrRange = new EDCAddressRange(

+						mdmc.toRuntimeAddress(linkAddressRange.getStartAddress()),

+						mdmc.toRuntimeAddress(linkAddressRange.getEndAddress()));

+				if (!addrRanges.contains(addrRange)) {

+					addrRanges.add(addrRange);

+					if (!getAllAddressRanges)

+						break;

+				}

+			}

+		}

+

+		if (addrRanges.size() > 0) {

+			AddressRange[] ar = addrRanges.toArray(new AddressRange[addrRanges.size()]);

+			rm.setData(ar);

+			rm.done();

+			return true;

+		}

+

+		return false;

+	}

+

+	public void calcLineInfo(ISymbolDMContext symCtx, IAddress address, DataRequestMonitor<LineInfo[]> rm) {

+		// TODO Auto-generated method stub

+

+	}

+

+	/**

+	 * Given a source line (let's call it anchor), find the line closest to the

+	 * anchor in the neighborhood (including the anchor itself) that has machine

+	 * code. If the anchor itself has code, it's returned. Otherwise neighbor

+	 * lines both above and below the anchor will be checked. If the closest

+	 * line above the anchor and the closest line below the anchor have the same

+	 * distance from the anchor, the one below will be selected.

+	 * 

+	 * This is mainly used in setting breakpoint at anchor line.

+	 * 

+	 * @param symCtx

+	 *            the symbol context in which to perform the lookup. It can be

+	 *            an execution context (e.g. a process), or a module (exe or

+	 *            dll) in a process.

+	 * @param bpPath

+	 *            the file that contains the source lines in question.

+	 * @param anchor

+	 *            line number of the anchor source line.

+	 * @param neighbor_limit

+	 *            specify the limit of the neighborhood: up to this number of

+	 *            lines above the anchor and up to this number of lines below

+	 *            the anchor will be checked if needed. But the check will never

+	 *            go beyond the source file. When the limit is zero, no neighbor

+	 *            lines will be checked. If the limit has value of -1, it means

+	 *            the actual limit is the source file.

+	 * @param rm

+	 *            contains an object of {@link ILineAddresses} if the line with

+	 *            code is found. And addresses in it are runtime addresses. The

+	 *            RM will contain error status otherwise.

+	 */

+	/* package private */	// used only by BreakpointAttributeTranslator#resolveBreakpoint

+	void findClosestLineWithCode(ISymbolDMContext symCtx, String bpPath,

+			int anchor, int neighbor_limit,

+			DataRequestMonitor<ILineAddresses> rm) {

+		IModuleDMContext[] moduleList = null;

+

+		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceEntry(null,

+				"Find closest line with code. context: " + EDCTrace.fixArg(symCtx) + " original file: " + bpPath + " anchor: " + anchor + " limit: " + neighbor_limit); }

+

+		if (symCtx instanceof IEDCExecutionDMC) {

+			String symContextID = ((IEDCDMContext) symCtx).getID();

+			moduleList = getModulesForContext(symContextID);

+		} else if (symCtx instanceof IModuleDMContext) {

+			moduleList = new IModuleDMContext[1];

+			moduleList[0] = (IModuleDMContext) symCtx;

+		} else {

+			// should not happen

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,

+									MessageFormat.format("Unknown class implementing ISymbolDMContext : {0}",

+														 symCtx.getClass().getName()), null));

+			rm.done();

+			if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().traceExit(null, rm.getStatus()); }

+			return;

+		}

+

+		String compilationPath = EDCLaunch.getLaunchForSession(getSession().getId()).getCompilationPath(bpPath);

+		if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,

+				"BP file: " + bpPath + " Compile file: " + compilationPath); }

+

+		EDCLineAddresses result = null;

+		PersistentCache pCache = EDCDebugger.getDefault().getCache();

+		for (IModuleDMContext module : moduleList) {

+			ModuleDMC mdmc = (ModuleDMC) module;

+			IEDCSymbolReader reader = mdmc.getSymbolReader();

+

+			if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "module: " + mdmc + " reader: " + reader); }

+

+			if (reader == null) 

+				continue;

+

+			long readerModDate = reader.getModificationDate();

+

+			List<ILineAddresses> codeLines = null;

+			

+			Map<String, List<ILineAddresses>> cache = new HashMap<String, List<ILineAddresses>>();

+

+			// Check the persistent cache

+			String symFile = reader.getSymbolFile().toOSString();

+			String cacheKey = symFile + LINE_ADDRESSES_CACHE;

+			String noFileCacheKey = symFile + NO_FILE_CACHE;

+

+			@SuppressWarnings("unchecked")

+			Set<String> noFileCachedData

+			  = pCache.getCachedData(noFileCacheKey, Set.class, readerModDate);

+			if (noFileCachedData != null && noFileCachedData.contains(compilationPath)

+					&& noFileCachedData.contains(bpPath)) {

+				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null,

+						"Persistent cache says file not used by module"); }

+				continue; // We have already determined that this file is not used by this module, don't bother checking again.

+			}

+			

+			@SuppressWarnings("unchecked")

+			Map<String, List<ILineAddresses>> cachedData

+			  = pCache.getCachedData(cacheKey, Map.class, readerModDate);

+			if (cachedData != null) {

+				cache = cachedData;

+				// cache is always stored based on compilation path below,

+				// even if the path passed was the original file location path

+				codeLines = cachedData.get(compilationPath + anchor);

+			}

+			

+			if (codeLines == null) {	// cache missed

+				IModuleLineEntryProvider lnt = reader.getModuleScope().getModuleLineEntryProvider(); 

+

+				// try compilationPath first

+				if (lnt.hasSourceFile(PathUtils.createPath(compilationPath))) {

+					codeLines = lnt.findClosestLineWithCode(PathUtils.createPath(compilationPath), anchor, neighbor_limit);

+				} else {

+					// If this file is not used by this module, cache it so we can avoid searching it again.

+					if (noFileCachedData == null)

+						noFileCachedData = new HashSet<String>();

+					noFileCachedData.add(compilationPath);

+					pCache.putCachedData(noFileCacheKey, (Serializable) noFileCachedData, readerModDate);

+

+					// sometimes eclipse core passes the original file path instead

+					if (lnt.hasSourceFile(PathUtils.createPath(bpPath))) {

+						codeLines = lnt.findClosestLineWithCode(PathUtils.createPath(bpPath), anchor, neighbor_limit);						

+					} else {

+						// same with the original bpPath

+						noFileCachedData.add(bpPath);

+						pCache.putCachedData(noFileCacheKey, (Serializable) noFileCachedData, readerModDate);				

+						if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "File not used by module"); }

+						continue;	// nothing else here to check, move on to next module

+					}

+				}

+

+				if (codeLines == null) {

+					if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "codeLines == null"); }

+					continue;	// should not happen ... except if bp set in comments or whitespace ... right?

+				}

+

+				// Cache code lines (with their link addresses), whether we find it or not,

+				// and always cache based on compilationPath, even if found using original bpPath

+				cache.put(compilationPath + anchor, codeLines);

+				pCache.putCachedData(cacheKey, (Serializable) cache, readerModDate);				

+				if (EDCTrace.BREAKPOINTS_TRACE_ON) { EDCTrace.getTrace().trace(null, "codeLines: " + codeLines); }

+			}

+

+			// convert addresses to runtime ones.

+			//

+			List<EDCLineAddresses> runtimeCLs = new ArrayList<Modules.EDCLineAddresses>(codeLines.size());

+			for (ILineAddresses cl : codeLines) {

+				List<IAddress> rt_addrs = new ArrayList<IAddress>(1);

+				for (IAddress a : cl.getAddress())

+					rt_addrs.add(mdmc.toRuntimeAddress(a));

+				runtimeCLs.add(new EDCLineAddresses(cl.getLineNumber(), rt_addrs));

+			}

+			

+			for (ILineAddresses l : runtimeCLs) 

+				result = selectCodeLine(result, l, anchor);

+		}

+

+		if (result != null) {

+			rm.setData(result);

+		} else {

+			/*

+			 * we try to set the breakpoint for every module since we don't know

+			 * which one the file is in. we report this error though if the file

+			 * isn't in the module, and let the caller handle the error.

+			 */

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED,

+									MessageFormat.format(EDCServicesMessages.Modules_CannotMoveBreakpoint,

+														 neighbor_limit, compilationPath, anchor),

+									null));

+		}

+

+		rm.done();

+	}

+

+	private EDCLineAddresses selectCodeLine(EDCLineAddresses prevChoice,

+			ILineAddresses newLine, int anchor) {

+		

+		if (prevChoice == null)

+			prevChoice = (EDCLineAddresses)newLine;

+		else {

+			if (newLine.getLineNumber() == prevChoice.getLineNumber()) {

+				// merge the addresses. Same source line has different addresses in different module.

+				prevChoice.addAddress(newLine.getAddress());

+			}

+			else {

+				// code line is different for the anchor in different module

+				if (newLine.getLineNumber() == anchor) 

+					// always honor anchor itself

+					prevChoice = (EDCLineAddresses)newLine;

+				else if (prevChoice.getLineNumber() != anchor) {

+					/*

+					 * Two different code lines are found (from different

+					 * modules or different CUs) and neither of them is anchor.

+					 * Don't bother returning both of them as that would cause

+					 * unnecessary complexity to breakpoint setting as it means

+					 * moving breakpoint set on anchor line to two different

+					 * lines. Just keep the one closer to anchor. And user will

+					 * see the breakpoint works in one module (or CU) but not

+					 * the other.

+					 */

+					int new_distance = Math.abs(newLine.getLineNumber() - anchor);

+					int prev_distance = Math.abs(prevChoice.getLineNumber() - anchor);

+					

+					if (new_distance < prev_distance)

+						prevChoice = (EDCLineAddresses)newLine;

+					else if (new_distance == prev_distance) {

+						// Same distance from anchor, choose the one below anchor

+						if (newLine.getLineNumber() > prevChoice.getLineNumber())

+							prevChoice = (EDCLineAddresses)newLine;

+					}

+				}

+			}

+		}

+		

+		return prevChoice;

+	}

+

+	/**

+	 * Get runtime addresses mapped to given source line in given run context.

+	 *  

+	 * @param context

+	 * @param sourceFile

+	 * @param lineNumber

+	 * @param drm If no address found, holds an empty list.

+	 */

+	public void getLineAddress(IExecutionDMContext context,

+			String sourceFile, int lineNumber, final DataRequestMonitor<List<IAddress>> drm) {

+		final List<IAddress> addrs = new ArrayList<IAddress>(1);

+		

+		final ExecutionDMC dmc = (ExecutionDMC) context;

+		if (dmc == null) {

+			drm.setData(addrs);

+			drm.done();

+			return;

+		}

+

+		// this calculation is now pushed all the way down to calcAddressRanges()

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

+

+		// establish this here so it can be used in either call below.

+		DataRequestMonitor<AddressRange[]> calcAddressDRM

+		  = new DataRequestMonitor<AddressRange[]>(getExecutor(), drm) {

+

+			@Override

+			protected void handleCompleted() {

+				if (isSuccess()) {

+					AddressRange[] addr_ranges = getData();

+

+					for (AddressRange range : addr_ranges) {

+						IAddress a = range.getStartAddress();  // this is runtime address

+						addrs.add(a);

+					}

+

+					drm.setData(addrs);

+				} else {

+					drm.setStatus(getStatus());

+				}

+				drm.done();

+			}

+		};

+

+		if (context instanceof RunControl.ThreadExecutionDMC) {

+			RunControl.ThreadExecutionDMC threadDMC = (RunControl.ThreadExecutionDMC)context;

+			calcAddressInfo(threadDMC, sourceFile, lineNumber, 0, calcAddressDRM);

+		} else {

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

+			calcAddressInfo(symCtx, sourceFile, lineNumber, 0, calcAddressDRM);

+		}

+	}

+		

+	public void getModuleData(IModuleDMContext dmc, DataRequestMonitor<IModuleDMData> rm) {

+		rm.setData(new ModuleDMData((ModuleDMC) dmc));

+		rm.done();

+	}

+

+	public void getModules(ISymbolDMContext symCtx, DataRequestMonitor<IModuleDMContext[]> rm) {

+		String symContextID = ((IEDCDMContext) symCtx).getID();

+		IModuleDMContext[] moduleList = getModulesForContext(symContextID);

+		rm.setData(moduleList);

+		rm.done();

+	}

+

+	public IModuleDMContext[] getModulesForContext(String symContextID) {

+		synchronized (modules) {

+			List<ModuleDMC> moduleList = modules.get(symContextID);

+			if (moduleList == null)

+				return new IModuleDMContext[0];

+			else

+				return moduleList.toArray(new IModuleDMContext[moduleList.size()]);

+		}

+	}

+

+	public void moduleLoaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, Map<String, Object> moduleProps) {

+		ModuleDMC module = new ModuleDMC(symbolContext, moduleProps);

+		module.relocateSections(moduleProps, true);

+		addModule(module);

+		getSession().dispatchEvent(new ModuleLoadedEvent(symbolContext, executionDMC, module),

+				Modules.this.getProperties());

+	}

+

+	public void moduleUnloaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC,

+			Map<String, Object> moduleProps) {

+		String moduleID = getModuleID(moduleProps); // the moduleProps comes from agent.

+		ModuleDMC module = getModuleByID(symbolContext, moduleID);

+		if (module == null) {

+			EDCDebugger.getMessageLogger().logError("Unexpected unload of module: " + moduleProps, null);

+			return;

+		}

+

+		Object requireResumeValue = moduleProps.get(IModuleProperty.PROP_RESUME);

+		if (requireResumeValue != null && requireResumeValue instanceof Boolean)

+			module.setProperty(IModuleProperty.PROP_RESUME, requireResumeValue);

+		

+		removeModule(module);

+		

+		getSession().dispatchEvent(new ModuleUnloadedEvent(symbolContext, executionDMC, module),

+				Modules.this.getProperties());

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModules#getModuleByAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)

+	 */

+	public ModuleDMC getModuleByAddress(ISymbolDMContext symCtx, IAddress instructionAddress) {

+		ModuleDMC bestMatch = null;

+		if (symCtx instanceof ModuleDMC) {

+			if (((ModuleDMC)symCtx).containsAddress(instructionAddress))

+				bestMatch = (ModuleDMC)symCtx;

+		}

+		else {

+			synchronized (modules) {

+				List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());

+				if (moduleList != null) {

+					for (ModuleDMC moduleDMC : moduleList) {

+						if (moduleDMC.containsAddress(instructionAddress)) {

+							bestMatch = moduleDMC;

+							break;

+						}

+					}

+	

+					if (bestMatch == null) {

+						// TODO: add a bogus wrap-all module ?

+					}

+				}

+			}

+		}

+		return bestMatch;

+	}

+

+	/**

+	 * Find the host file that corresponds to a given module file whose name

+	 * comes from target platform.

+	 * 

+	 * @param originalPath

+	 *            path or filename from target platform.

+	 * @return the path to an existing file on host, null otherwise.

+	 */

+	public IPath locateModuleFileOnHost(String originalPath) {

+		if (originalPath == null || originalPath.length() == 0)

+			return Path.EMPTY;

+

+		// Canonicalize path for the host OS, in hopes of finding a match directly on the host,

+		// and for searching sources and executables below.

+		//

+		IPath path = PathUtils.findExistingPathIfCaseSensitive(PathUtils.createPath(originalPath));

+

+		// Try source locator, use the host-correct path.

+		//

+		Object sourceElement = null;

+		ISourceLocator locator = getSourceLocator();

+		if (locator != null) {

+			if (locator instanceof ICSourceLocator || locator instanceof CSourceLookupDirector) {

+				if (locator instanceof ICSourceLocator)

+					sourceElement = ((ICSourceLocator) locator).findSourceElement(path.toOSString());

+				else

+					sourceElement = ((CSourceLookupDirector) locator).getSourceElement(path.toOSString());

+			}

+			if (sourceElement != null) {

+				if (sourceElement instanceof LocalFileStorage) {

+					return new Path(((LocalFileStorage) sourceElement).getFile().getAbsolutePath());

+				}

+			}

+		}

+		

+		return path;

+	}

+

+	public void loadModulesForContext(ISymbolDMContext context, Element element) throws Exception {

+

+		List<ModuleDMC> contextModules = Collections.synchronizedList(new ArrayList<ModuleDMC>());

+

+		NodeList moduleElements = element.getElementsByTagName(MODULE);

+

+		int numModules = moduleElements.getLength();

+		for (int i = 0; i < numModules; i++) {

+			Element moduleElement = (Element) moduleElements.item(i);

+			Element propElement = (Element) moduleElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);

+			HashMap<String, Object> properties = new HashMap<String, Object>();

+			SnapshotUtils.initializeFromXML(propElement, properties);

+

+			ModuleDMC module = new ModuleDMC(context, properties);

+			module.loadSnapshot(moduleElement);

+			contextModules.add(module);

+

+		}

+		modules.put(((IEDCDMContext) context).getID(), contextModules);

+

+	}

+	

+	private static String getModuleID(Map<String, Object> props) {

+		if (props.containsKey(IEDCDMContext.PROP_ID))

+			return props.get(IEDCDMContext.PROP_ID).toString();

+		if (props.containsKey(IModuleProperty.PROP_FILE))

+			return props.get(IModuleProperty.PROP_FILE).toString();

+		if (props.containsKey(IEDCDMContext.PROP_NAME))

+			return props.get(IEDCDMContext.PROP_NAME).toString();

+		assert(false); // One of these is required

+		return "";

+	}

+

+	/**

+	 * get module with given file name

+	 * 

+	 * @param symCtx

+	 * @param fileName

+	 *            executable name for module

+	 * @return null if not found.

+	 */

+	public ModuleDMC getModuleByName(ISymbolDMContext symCtx, Object fileName) {

+		ModuleDMC module = null;

+		synchronized (modules) {

+			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());

+			if (moduleList != null) {

+				for (ModuleDMC moduleDMC : moduleList) {

+					if ((moduleDMC.getName().compareToIgnoreCase((String) fileName)) == 0 ) {

+						module = moduleDMC;

+						break;

+					}

+				}

+			}

+		}

+		return module;

+	}

+

+	private ModuleDMC getModuleByID(ISymbolDMContext symCtx, String id) {

+		ModuleDMC module = null;

+		synchronized (modules) {

+			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());

+			if (moduleList != null) {

+				for (ModuleDMC moduleDMC : moduleList) {

+					if ((moduleDMC.getID().compareToIgnoreCase(id)) == 0 ) {

+						module = moduleDMC;

+						break;

+					}

+				}

+			}

+		}

+		return module;

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/RunControl.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/RunControl.java
index fe65b9a..881c196 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/RunControl.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/RunControl.java
@@ -1,3081 +1,3107 @@
-/*******************************************************************************
- * 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.EDCLogActionEnabler;
-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.EDCAddressRange;
-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 Map<String, StateChangeReason> reasons;
-	private static StateChangeReason toDsfStateChangeReason(String tcfReason) {
-		if (tcfReason == null)
-			return StateChangeReason.UNKNOWN;		
-		if (reasons == null)
-			reasons = new HashMap<String, IRunControl.StateChangeReason>();
-		StateChangeReason reason = reasons.get(tcfReason);
-		if (reason == null) {
-	
-			if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_USER_REQUEST))
-				reason = StateChangeReason.USER_REQUEST;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_STEP))
-				reason = StateChangeReason.STEP;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_BREAKPOINT))
-				reason = StateChangeReason.BREAKPOINT;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_EXCEPTION))
-				reason = StateChangeReason.EXCEPTION;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_CONTAINER))
-				reason = StateChangeReason.CONTAINER;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_WATCHPOINT))
-				reason = StateChangeReason.WATCHPOINT;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SIGNAL))
-				reason = StateChangeReason.SIGNAL;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SHAREDLIB))
-				reason = StateChangeReason.SHAREDLIB;
-			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_ERROR))
-				reason = StateChangeReason.ERROR;
-			else 
-				reason = StateChangeReason.UNKNOWN;
-			reasons.put(tcfReason, reason);
-		}
-		return reason;
-	}
-
-	@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;
-		
-		/**
-		 * Code ranges to step outside of.
-		 *
-		 * Certain source line may have two separate sections of
-		 * . For instance, the following lines <pre>
-		 * 	 for (i=0; i<3; i++) 
-		 * 	   k *= k;
-		 * </pre>
-		 * will have such code generated by MinGW GCC compiler:
-		 * <pre>
-			184               	for (i=0; i<3; i++)
-			00000000004017f7:   movl      $0x0,-0x8(%ebp)
-			00000000004017fe:   jmp       0x40180d
-			185               		k *= k;
-			0000000000401800:   mov       -0x10(%ebp),%eax
-			0000000000401803:   imul      -0x10(%ebp),%eax
-			0000000000401807:   mov       %eax,-0x10(%ebp)
-			184               	for (i=0; i<3; i++)
-			000000000040180a:   incl      -0x8(%ebp)
-			000000000040180d:   cmpl      $0x2,-0x8(%ebp)
-			0000000000401811:   setle     %al
-			0000000000401814:   test      %al,%al
-			0000000000401816:   jne       0x401800
-		   </pre>
-		 *  To step over the above "for()" statement, we need
-		 *  to make sure stepping does not stop in its second
-		 *  code section.
-		 */
-		private List<EDCAddressRange> stepRanges = Collections.synchronizedList(new ArrayList<EDCAddressRange>());
-		
-		private boolean suspendEventsEnabled = true;
-		private DMCSuspendedEvent cachedSuspendedEvent = null;
-
-		/**
-		 * All possible function call destination addresses when we perform a
-		 * StepIn.<br>
-		 * This is to help auto-step through glue code in a function call (e.g.
-		 * the jmp instruction in a jump table for calling a Win32 DLL).
-		 */
-		private List<IAddress> functionCallDestinations = Collections.synchronizedList(new ArrayList<IAddress>());
-		
-		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;
-		}
-
-		protected void setStateChangeDetails(String newStateChangeDetails) {
-			stateChangeDetails = newStateChangeDetails;
-		}
-
-		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) {
-								if (bp == null) {
-									stateChangeReason = StateChangeReason.STEP;
-									stateChangeDetails = 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;
-		}
-
-		private void addStepRange(IAddress lowAddress, IAddress highAddress) {
-			stepRanges.add(new EDCAddressRange(lowAddress, highAddress));
-		}
-
-		/**
-		 * Check if the give address is in current step ranges, if yes, return 
-		 * the range that contains it.
-		 * 
-		 * @param address
-		 * @return null if not found.
-		 */
-		private EDCAddressRange findStepRange(IAddress address) {
-			for (EDCAddressRange r : stepRanges) {
-				if (r.contains(address))
-					return r;
-			}
-			return null;
-		}
-
-		private void clearStepRanges() {
-			stepRanges.clear();
-		}
-
-		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 EDCLogActionEnabler(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);
-		}
-
-		private void addFunctionCallDestination(IAddress addr) {
-			functionCallDestinations.add(addr);
-		}
-		
-		private void clearFunctionCallDestinations() {
-			functionCallDestinations.clear();
-		}
-		
-		private boolean isFunctionCallDestination(IAddress addr) {
-			return functionCallDestinations.contains(addr);
-		}
-	}
-
-	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.
-
-					StateChangeReason stateChangeReason = dmc.getStateChangeReason();
-					if (stateChangeReason != StateChangeReason.BREAKPOINT
-							&& stateChangeReason != StateChangeReason.WATCHPOINT) {
-						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 {
-						if (stateChangeReason == StateChangeReason.BREAKPOINT)
-							bp = bpService.findUserBreakpoint(new Addr64(pcString, 16));
-						else {// condition above means this is a StateChangeReason.WATCHPOINT
-							bp = bpService.findUserBreakpoint(new Addr64(dmc.getStateChangeDetails(), 16));
-							if (bp != null)
-								dmc.setStateChangeDetails("[" + bp.getExpression() + "]");
-						}
-					}
-
-					// 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) {
-		/*
-		 * Step from current PC in "context"
-		 */
-		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);
-				dmc.clearFunctionCallDestinations();
-
-				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);
-								
-								dmc.clearStepRanges();
-								
-								// If the line has two or more code ranges, record them
-								// 
-								Collection<ILineEntry> ranges
-								  = lineEntryProvider.getLineEntriesForLines(line.getFilePath(),
-																			 line.getLineNumber(),
-																			 line.getLineNumber());
-								if (ranges.size() > 1)
-								{
-									for (ILineEntry iLineEntry : ranges) {
-										dmc.addStepRange(module.toRuntimeAddress(iLineEntry.getLowAddress()),
-															 module.toRuntimeAddress(iLineEntry.getHighAddress()));
-									}
-								}
-
-								/*
-								 * It's possible that PC is larger than
-								 * startAddr (e.g. user does a few instruction
-								 * level stepping then switch to source level
-								 * stepping). We just parse and step past
-								 * instructions within [pcAddr, endAddr) instead
-								 * of all those within [startAddr, endAddr). One
-								 * possible problem with the solution is when
-								 * control jumps from a point within [pcAddress,
-								 * endAddr) to a point within [startAddr,
-								 * pcAddress), the stepping would stop within
-								 * 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
-								 */
-								final boolean stepIn = stepType == StepType.STEP_INTO;
-								stepAddressRange(dmc, stepIn, pcAddress, endAddr, new RequestMonitor(getExecutor(), rm) {
-									@Override
-									protected void handleSuccess() {
-										handleStepAddressRangeDone(stepIn, dmc, 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)
-					// Note when do StepIn at instruction level, we
-					// don't bother checking and stepping past glue code.
-					//
-					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 handleStepAddressRangeDone(final boolean stepIn, final ExecutionDMC dmc, final RequestMonitor rm) {
-		IAddress newPC = new Addr64(dmc.getPC(), 16);
-
-		boolean done = false;
-		EDCAddressRange r = dmc.findStepRange(newPC);
-
-		if (r == null)
-			// PC is out of line code ranges, done
-			done = true;
-		else {
-			Breakpoints bpService = getService(Breakpoints.class);
-			if (bpService.findUserBreakpoint(newPC) != null) 
-				// hit a user breakpoint
-				done = true;
-		}
-		
-		if (done) {
-			if (stepIn) {
-				// Only when we step into a function (not jump to some place) 
-				// do we check if there is glue code and step past it if any
-				// ...........................08/07/11
-				if (dmc.isFunctionCallDestination(newPC))
-					stepPastGlueCode(dmc, newPC, rm);
-				else
-					rm.done();
-			}
-			else
-				rm.done();
-		}
-		else if (r != null)
-			// Still in a code range of the line, keep going by recursive call.
-			stepAddressRange(dmc, stepIn, newPC, r.getEndAddress(), new RequestMonitor(getExecutor(), rm) {
-				@Override
-				protected void handleSuccess() {
-					// recursive
-					handleStepAddressRangeDone(stepIn, dmc, rm);
-				}}); 
-	}
-
-	/**
-	 * If instructions at PC are glue code (e.g. jump table for call to function in DLL),
-	 * step past them. Otherwise just do nothing.
-	 * 
-	 * @param dmc the execution context, usually a thread.
-	 * @param pc program counter.
-	 * @param rm
-	 */
-	private void stepPastGlueCode(ExecutionDMC dmc, IAddress pc,
-			RequestMonitor rm) {
-		// Glue code is totally processor specific. So
-		// let TargetEnvironment service handle it.
-		ITargetEnvironment te = getService(ITargetEnvironment.class);
-		te.stepPastGlueCode(dmc, pc, 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 translateMemoryBytes()
-				}
-
-				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())); }
-
-		int memSize = startAddr.distanceTo(endAddr).intValue();
-		if (memSize < 0) { // endAddr < startAddr
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, 
-					MessageFormat.format(
-							"Invalid arguments for StepAddressRange(): ending address {0} is smaller than start address {1}.",
-							endAddr.toHexAddressString(), startAddr.toHexAddressString())));
-			rm.done();
-			return;
-		}
-
-		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);
-
-		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) // not control-change instruction, ignore.
-						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;
-							}
-							
-							if (!jta.isSubroutineAddress() || stepIn)
-							{
-								// evaluate the address expression
-								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);
-								
-								if (jta.isSubroutineAddress()) // step-in a function
-									dmc.addFunctionCallDestination(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);
-									
-									dmc.addFunctionCallDestination(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...
-						 * 
-						 * TODO: we could solve it by keeping stepping till we are out
-						 * of the range. Do it when really needed in practice (namely
-						 * when the following warning is seen).
-						 */
-						// Log a 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);
-	}
-}
+/*******************************************************************************

+ * 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.EDCLogActionEnabler;

+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.EDCAddressRange;

+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$

+

+	final private boolean DEBUG_STEPPING = false;

+	

+	/*

+	 * 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 Map<String, StateChangeReason> reasons;

+	private static StateChangeReason toDsfStateChangeReason(String tcfReason) {

+		if (tcfReason == null)

+			return StateChangeReason.UNKNOWN;		

+		if (reasons == null)

+			reasons = new HashMap<String, IRunControl.StateChangeReason>();

+		StateChangeReason reason = reasons.get(tcfReason);

+		if (reason == null) {

+	

+			if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_USER_REQUEST))

+				reason = StateChangeReason.USER_REQUEST;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_STEP))

+				reason = StateChangeReason.STEP;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_BREAKPOINT))

+				reason = StateChangeReason.BREAKPOINT;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_EXCEPTION))

+				reason = StateChangeReason.EXCEPTION;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_CONTAINER))

+				reason = StateChangeReason.CONTAINER;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_WATCHPOINT))

+				reason = StateChangeReason.WATCHPOINT;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SIGNAL))

+				reason = StateChangeReason.SIGNAL;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SHAREDLIB))

+				reason = StateChangeReason.SHAREDLIB;

+			else if (tcfReason.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_ERROR))

+				reason = StateChangeReason.ERROR;

+			else 

+				reason = StateChangeReason.UNKNOWN;

+			reasons.put(tcfReason, reason);

+		}

+		return reason;

+	}

+

+	@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 resumeForSteppingRM = 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;

+		

+		/**

+		 * Code ranges to step outside of.

+		 *

+		 * Certain source line may have two separate sections of

+		 * . For instance, the following lines <pre>

+		 * 	 for (i=0; i<3; i++) 

+		 * 	   k *= k;

+		 * </pre>

+		 * will have such code generated by MinGW GCC compiler:

+		 * <pre>

+			184               	for (i=0; i<3; i++)

+			00000000004017f7:   movl      $0x0,-0x8(%ebp)

+			00000000004017fe:   jmp       0x40180d

+			185               		k *= k;

+			0000000000401800:   mov       -0x10(%ebp),%eax

+			0000000000401803:   imul      -0x10(%ebp),%eax

+			0000000000401807:   mov       %eax,-0x10(%ebp)

+			184               	for (i=0; i<3; i++)

+			000000000040180a:   incl      -0x8(%ebp)

+			000000000040180d:   cmpl      $0x2,-0x8(%ebp)

+			0000000000401811:   setle     %al

+			0000000000401814:   test      %al,%al

+			0000000000401816:   jne       0x401800

+		   </pre>

+		 *  To step over the above "for()" statement, we need

+		 *  to make sure stepping does not stop in its second

+		 *  code section.

+		 */

+		private List<EDCAddressRange> stepRanges = Collections.synchronizedList(new ArrayList<EDCAddressRange>());

+		

+		private DMCSuspendedEvent cachedSuspendedEvent = null;

+

+		/**

+		 * All possible function call destination addresses when we perform a

+		 * StepIn.<br>

+		 * This is to help auto-step through glue code in a function call (e.g.

+		 * the jmp instruction in a jump table for calling a Win32 DLL).

+		 */

+		private List<IAddress> functionCallDestinations = Collections.synchronizedList(new ArrayList<IAddress>());

+		

+		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;

+		}

+

+		protected void setStateChangeDetails(String newStateChangeDetails) {

+			stateChangeDetails = newStateChangeDetails;

+		}

+

+		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.

+				

+				// negative values are most likely 32-bit numbers;

+				// don't interpret as long since this will result in unsigned 64-bit values

+				if (pc.length() > 0 && pc.charAt(0) == '-') {

+					try {

+						pc = Integer.toHexString(Integer.parseInt(pc));

+					} catch (NumberFormatException e) {

+						// sent also for out-of-range

+						pc = Long.toHexString(Long.parseLong(pc));

+					}

+				}

+				else

+					pc = Long.toHexString(Long.parseLong(pc));

+			}

+

+			latestPC = pc;

+

+			synchronized (properties) {

+				properties.put(PROP_MESSAGE, reason);

+				properties.put(PROP_SUSPEND_PC, pc);

+			}

+			stateChangeReason = toDsfStateChangeReason(reason);

+

+			if (stateChangeReason == StateChangeReason.SHAREDLIB) {

+				// mark the thread as suspended if we're required to resume it

+				boolean requireResume = true;

+				Object propvalue = params.get(IModuleProperty.PROP_RESUME);

+				if (propvalue != null)

+					if (propvalue instanceof Boolean)

+						requireResume = (Boolean) propvalue;

+				

+				setIsSuspended(requireResume);

+

+				handleModuleEvent(this, params);

+			} else {

+				setIsSuspended(true);

+

+				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());

+							}

+

+							// change the reason to STEP.

+							if (resumeForSteppingRM != null && bp == null 

+									&& stateChangeReason == StateChangeReason.BREAKPOINT) {

+								stateChangeReason = StateChangeReason.STEP;

+								stateChangeDetails = null;

+							}

+

+							/*

+							 * 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) {

+								@Override

+								protected void handleCompleted() {

+									// Mark done of the resumeForStepping RM, if any pending.

+									if (resumeForSteppingRM != null) {

+										resumeForSteppingRM.done();

+										resumeForSteppingRM = null;

+									}

+									

+									/*

+									 * Don't report interim suspendedEvent during stepping to upper layer

+									 * (e.g. the one resulted from prepareToRun()) to avoid unnecessary 

+									 * suspend-handling. Just remember it. We'll fire the last such event

+									 * when the stepping is finished.

+									 */

+									DMCSuspendedEvent e = dmc.createSuspendedEvent(stateChangeReason, params);

+									if (! dmc.isStepping())

+										getSession().dispatchEvent(e, RunControl.this.getProperties());

+									else

+										dmc.cacheSuspendedEvent(e);

+									

+									super.handleCompleted();

+								}});

+							

+						} 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;

+		}

+

+		/**

+		 * 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)); }

+

+			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 resumeForSteppingRM == null;

+				resumeForSteppingRM = rm;

+			} else {

+				msg += " failed.";

+				if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().trace(null, msg); }

+

+				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())); }

+

+			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())); }

+

+			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())); }

+

+			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;

+		}

+

+		private void addStepRange(IAddress lowAddress, IAddress highAddress) {

+			stepRanges.add(new EDCAddressRange(lowAddress, highAddress));

+		}

+

+		/**

+		 * Check if the give address is in current step ranges, if yes, return 

+		 * the range that contains it.

+		 * 

+		 * @param address

+		 * @return null if not found.

+		 */

+		private EDCAddressRange findStepRange(IAddress address) {

+			for (EDCAddressRange r : stepRanges) {

+				if (r.contains(address))

+					return r;

+			}

+			return null;

+		}

+

+		private void clearStepRanges() {

+			stepRanges.clear();

+		}

+

+		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) {

+			if (DEBUG_STEPPING) System.out.println("Cache interim SuspendedEvent: " + 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;

+			if (DEBUG_STEPPING) System.out.println("Get cached SuspendedEvent: " + e);

+			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 EDCLogActionEnabler(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);

+		}

+

+		private void addFunctionCallDestination(IAddress addr) {

+			functionCallDestinations.add(addr);

+		}

+		

+		private void clearFunctionCallDestinations() {

+			functionCallDestinations.clear();

+		}

+		

+		private boolean isFunctionCallDestination(IAddress addr) {

+			return functionCallDestinations.contains(addr);

+		}

+	}

+

+	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);

+			if (this.isSuspended())

+			{

+				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));

+			if (this.isSuspended())

+			{

+				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.snapshotValues(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.

+

+					StateChangeReason stateChangeReason = dmc.getStateChangeReason();

+					if (stateChangeReason != StateChangeReason.BREAKPOINT

+							&& stateChangeReason != StateChangeReason.WATCHPOINT) {

+						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 {

+						if (stateChangeReason == StateChangeReason.BREAKPOINT)

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

+						else {// condition above means this is a StateChangeReason.WATCHPOINT

+							bp = bpService.findUserBreakpoint(new Addr64(dmc.getStateChangeDetails(), 16));

+							if (bp != null)

+								dmc.setStateChangeDetails("[" + bp.getExpression() + "]");

+						}

+					}

+

+					// 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.singleStep(true, new RequestMonitor(getExecutor(), drm) {

+							@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) {

+		if (EDCTrace.RUN_CONTROL_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(MessageFormat.format("{0} context {1}", outerStepType, 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;

+

+		if (DEBUG_STEPPING) 

+			System.out.println("isStepping: " + dmc.isStepping() + " -- Thread: " + Thread.currentThread().getName());

+

+		/*

+		 * This "Step()" method is mostly called by DSF (namely initiated by

+		 * user issuing "Step" command). But it may also be called by EDC as

+		 * part of stepping handling. This is to differentiate the two cases.

+		 */

+		final boolean steppingByUser = ! dmc.isStepping();

+		if (steppingByUser)

+			dmc.setStepping(true);

+

+		/*

+		 * Step from current PC in "context"

+		 */

+		asyncExec(new Runnable() {

+			public void run() {

+				doStep(dmc, outerStepType, new RequestMonitor(getExecutor(), rm) {

+

+					@Override

+					protected void handleSuccess() {

+						if (steppingByUser) {

+							dmc.setStepping(false);

+							DMCSuspendedEvent e = dmc.getCachedSuspendedEvent();

+							if (e != null)

+								getSession().dispatchEvent(e, RunControl.this.getProperties());

+							else {

+								// should not happen

+								assert(false);

+							}

+						}

+						

+						rm.done();

+					}});

+			}

+		}, rm);

+	}

+	

+	private void doStep(final ExecutionDMC dmc, StepType stepType, final RequestMonitor rm) {

+		if (timeStepping())

+			steppingStartTime = System.currentTimeMillis();

+		

+		dmc.clearFunctionCallDestinations();

+

+		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(dmc, 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);

+						

+						dmc.clearStepRanges();

+						

+						// If the line has two or more code ranges, record them

+						// 

+						Collection<ILineEntry> ranges

+						  = lineEntryProvider.getLineEntriesForLines(line.getFilePath(),

+																	 line.getLineNumber(),

+																	 line.getLineNumber());

+						if (ranges.size() > 1)

+						{

+							for (ILineEntry iLineEntry : ranges) {

+								dmc.addStepRange(module.toRuntimeAddress(iLineEntry.getLowAddress()),

+													 module.toRuntimeAddress(iLineEntry.getHighAddress()));

+							}

+						}

+

+						/*

+						 * It's possible that PC is larger than

+						 * startAddr (e.g. user does a few instruction

+						 * level stepping then switch to source level

+						 * stepping). We just parse and step past

+						 * instructions within [pcAddr, endAddr) instead

+						 * of all those within [startAddr, endAddr). One

+						 * possible problem with the solution is when

+						 * control jumps from a point within [pcAddress,

+						 * endAddr) to a point within [startAddr,

+						 * pcAddress), the stepping would stop within

+						 * 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

+						 */

+						final boolean stepIn = stepType == StepType.STEP_INTO;

+						stepAddressRange(dmc, stepIn, pcAddress, endAddr, new RequestMonitor(getExecutor(), rm) {

+							@Override

+							protected void handleSuccess() {

+								handleStepAddressRangeDone(stepIn, dmc, 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)

+			// Note when do StepIn at instruction level, we

+			// don't bother checking and stepping past glue code.

+			//

+			stepIntoOneInstruction(dmc, rm);

+		else if (stepType == StepType.INSTRUCTION_STEP_RETURN)

+			stepOut(dmc, pcAddress, rm);

+

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

+	}

+

+	private void handleStepAddressRangeDone(final boolean stepIn, final ExecutionDMC dmc, final RequestMonitor rm) {

+		IAddress newPC = new Addr64(dmc.getPC(), 16);

+

+		boolean done = false;

+		EDCAddressRange r = dmc.findStepRange(newPC);

+

+		if (r == null)

+			// PC is out of line code ranges, done

+			done = true;

+		else {

+			Breakpoints bpService = getService(Breakpoints.class);

+			if (bpService.findUserBreakpoint(newPC) != null) 

+				// hit a user breakpoint

+				done = true;

+		}

+		

+		if (done) {

+			if (stepIn) {

+				// Only when we step into a function (not jump to some place) 

+				// do we check if there is glue code and step past it if any

+				// ...........................08/07/11

+				if (dmc.isFunctionCallDestination(newPC))

+					stepPastGlueCode(dmc, newPC, rm);

+				else

+					rm.done();

+			}

+			else

+				rm.done();

+		}

+		else if (r != null)

+			// Still in a code range of the line, keep going by recursive call.

+			stepAddressRange(dmc, stepIn, newPC, r.getEndAddress(), new RequestMonitor(getExecutor(), rm) {

+				@Override

+				protected void handleSuccess() {

+					// recursive

+					handleStepAddressRangeDone(stepIn, dmc, rm);

+				}}); 

+	}

+

+	/**

+	 * If instructions at PC are glue code (e.g. jump table for call to function in DLL),

+	 * step past them. Otherwise just do nothing.

+	 * 

+	 * @param dmc the execution context, usually a thread.

+	 * @param pc program counter.

+	 * @param rm

+	 */

+	private void stepPastGlueCode(ExecutionDMC dmc, IAddress pc,

+			RequestMonitor rm) {

+		// Glue code is totally processor specific. So

+		// let TargetEnvironment service handle it.

+		ITargetEnvironment te = getService(ITargetEnvironment.class);

+		te.stepPastGlueCode(dmc, pc, 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().

+					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 translateMemoryBytes()

+				}

+

+				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())); }

+

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

+		if (memSize < 0) { // endAddr < startAddr

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, 

+					MessageFormat.format(

+							"Invalid arguments for StepAddressRange(): ending address {0} is smaller than start address {1}.",

+							endAddr.toHexAddressString(), startAddr.toHexAddressString())));

+			rm.done();

+			return;

+		}

+

+		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);

+

+		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) // not control-change instruction, ignore.

+						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;

+							}

+							

+							if (!jta.isSubroutineAddress() || stepIn)

+							{

+								// evaluate the address expression

+								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);

+								

+								if (jta.isSubroutineAddress()) // step-in a function

+									dmc.addFunctionCallDestination(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);

+									

+									dmc.addFunctionCallDestination(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...

+						 * 

+						 * TODO: we could solve it by keeping stepping till we are out

+						 * of the range. Do it when really needed in practice (namely

+						 * when the following warning is seen).

+						 */

+						// Log a 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().

+								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().

+					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);

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Symbols.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Symbols.java
index c563f11..1e8b6b3 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Symbols.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/services/dsf/Symbols.java
@@ -1,402 +1,420 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 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.lang.ref.WeakReference;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.EDCTrace;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;
-import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.DebugInfoProviderFactory;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.PEFileExecutableSymbolicsReader;
-import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
-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.IFrameRegisterProvider;
-import org.eclipse.cdt.debug.edc.services.IFrameRegisters;
-import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
-import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider;
-import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
-import org.eclipse.cdt.debug.edc.symbols.IExecutableSymbolicsReader;
-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.symbols.IModuleScope;
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-import org.eclipse.cdt.debug.edc.symbols.ISymbol;
-import org.eclipse.cdt.debug.edc.symbols.IType;
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.datamodel.IDMContext;
-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.ISymbols;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.debug.core.model.ISourceLocator;
-
-public class Symbols extends AbstractEDCService implements ISymbols, IEDCSymbols {
-	private static Map<IPath, WeakReference<IEDCSymbolReader>> readerCache = new HashMap<IPath, WeakReference<IEDCSymbolReader>>();
-	private ISourceLocator sourceLocator;
-	
-	public ISourceLocator getSourceLocator() {
-		return sourceLocator;
-	}
-
-	public void setSourceLocator(ISourceLocator sourceLocator) {
-		this.sourceLocator = sourceLocator;
-	}
-
-	public Symbols(DsfSession session) {
-		super(session, new String[] { IEDCSymbols.class.getName(), ISymbols.class.getName(), Symbols.class.getName() });
-	}
-
-	public void getSymbols(ISymbolDMContext symCtx, DataRequestMonitor<Iterable<ISymbolObjectDMContext>> rm) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
-		// TODO Auto-generated method stub
-
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCSymbols#getFunctionAtAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)
-	 */
-	public IFunctionScope getFunctionAtAddress(ISymbolDMContext context, IAddress runtimeAddress) {
-		IEDCModules modulesService = getService(Modules.class);
-		IEDCModuleDMContext module = modulesService.getModuleByAddress(context, runtimeAddress);
-		if (module != null) {
-			IEDCSymbolReader reader = module.getSymbolReader();
-			if (reader != null) {
-				IScope scope = reader.getModuleScope().getScopeAtAddress(module.toLinkAddress(runtimeAddress));
-				while (scope != null && !(scope instanceof IFunctionScope)) {
-					scope = scope.getParent();
-				}
-				return (IFunctionScope) scope;
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCSymbols#getFunctionAtAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)
-	 */
-	public String getSymbolNameAtAddress(ISymbolDMContext context, IAddress runtimeAddress) {
-		IEDCModules modulesService = getService(Modules.class);
-		IEDCModuleDMContext module = modulesService.getModuleByAddress(context, runtimeAddress);
-		if (module != null) {
-			IEDCSymbolReader reader = module.getSymbolReader();
-			if (reader != null) {
-				ISymbol symbol = reader.getSymbolAtAddress(module.toLinkAddress(runtimeAddress));
-				if (symbol != null)
-					return symbol.getName();
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCSymbols#getLineEntryForAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)
-	 */
-	public ILineEntry getLineEntryForAddress(ISymbolDMContext context, IAddress runtimeAddress) {
-		IEDCModules modulesService = getService(Modules.class);
-		IEDCModuleDMContext module = modulesService.getModuleByAddress(context, runtimeAddress);
-		if (module != null) {
-			IEDCSymbolReader reader = module.getSymbolReader();
-			if (reader != null) {
-				IAddress linkAddress = module.toLinkAddress(runtimeAddress);
-				IModuleLineEntryProvider lineEntryProvider = reader.getModuleScope().getModuleLineEntryProvider();
-				return lineEntryProvider.getLineEntryAtAddress(linkAddress);
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCSymbols#getLineEntriesForAddressRange(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress, org.eclipse.cdt.core.IAddress)
-	 */
-	public List<ILineEntry> getLineEntriesForAddressRange(ISymbolDMContext context, IAddress start, IAddress end) {
-		List<ILineEntry> lineEntries = new ArrayList<ILineEntry>();
-
-		IEDCModules modulesService = getService(Modules.class);
-		IEDCModuleDMContext module = modulesService.getModuleByAddress(context, start);
-		if (module == null)
-			return lineEntries;
-
-		IAddress linkStartAddress = module.toLinkAddress(start);
-		IAddress linkEndAddress = module.toLinkAddress(end);
-
-		IEDCSymbolReader reader = module.getSymbolReader();
-		if (reader != null) {
-			if (linkStartAddress == null)
-				linkStartAddress = module.getSymbolReader().getModuleScope().getLowAddress();
-			if (linkEndAddress == null)
-				linkEndAddress = module.getSymbolReader().getModuleScope().getHighAddress();
-
-			IModuleScope moduleScope = reader.getModuleScope();
-			
-			if (linkEndAddress.compareTo(moduleScope.getHighAddress()) > 0) {
-				// end address is out of the module sections.
-				// we'll keep getting source lines until we reach an address
-				// point where no source line is available.
-				linkEndAddress = moduleScope.getHighAddress();
-			}
-
-			IModuleLineEntryProvider lineEntryProvider = moduleScope.getModuleLineEntryProvider();
-
-			ILineEntry entry = lineEntryProvider.getLineEntryAtAddress(linkStartAddress);
-			while (entry != null && entry.getLowAddress().compareTo(linkEndAddress) < 0) {
-				lineEntries.add(entry);
-				// FIXME: this shouldn't happen
-				if (entry.getLowAddress().compareTo(entry.getHighAddress()) >= 0)
-					entry = lineEntryProvider.getLineEntryAtAddress(entry.getHighAddress().add(1));
-				else
-					entry = lineEntryProvider.getLineEntryAtAddress(entry.getHighAddress());
-			}
-		}
-
-		return lineEntries;
-	}
-	
-	/**
-	 * Get an accessor for registers in stack frames other than the current one.
-	 * <p>
-	 * Note: this is not meaningful by itselfis typically used from {@link StackFrameDMC#getFrameRegisters()}.
-	 * @param context
-	 * @param runtimeAddress
-	 * @return {@link IFrameRegisters} or <code>null</code>
-	 */
-	public IFrameRegisterProvider getFrameRegisterProvider(ISymbolDMContext context, IAddress runtimeAddress) {
-		Modules modulesService = getService(Modules.class);
-		IEDCModuleDMContext module = modulesService.getModuleByAddress(context, runtimeAddress);
-		if (module != null) {
-			IEDCSymbolReader reader = module.getSymbolReader();
-			if (reader != null) {
-				IFrameRegisterProvider frameRegisterProvider = reader.getModuleScope().getFrameRegisterProvider();
-				return frameRegisterProvider;
-			}
-		}
-		return null;
-	}
-
-	public static IEDCSymbolReader getSymbolReader(IPath modulePath) {
-
-		IEDCSymbolReader reader = null;
-		WeakReference<IEDCSymbolReader> cacheEntry = readerCache.get(modulePath);
-		
-		if (cacheEntry != null)
-			reader = cacheEntry.get();
-
-		if (reader != null) {
-			if (reader.getSymbolFile() != null
-					&& reader.getSymbolFile().toFile().exists()
-					&& reader.getSymbolFile().toFile().lastModified() == reader.getModificationDate()) {
-				return reader;
-			}
-
-			// it's been deleted or modified. remove it from the cache
-			readerCache.remove(modulePath);
-		}
-
-		IExecutableSymbolicsReader exeReader = ExecutableSymbolicsReaderFactory.createFor(modulePath);
-		if (exeReader != null) {
-			IDebugInfoProvider debugProvider = DebugInfoProviderFactory.createFor(modulePath, exeReader); // may be null
-			if (debugProvider != null) {
-				// if debug info came from a different file, the "executable" may be that symbol file too 
-				if (!exeReader.getSymbolFile().equals(debugProvider.getExecutableSymbolicsReader().getSymbolFile())) {
-					exeReader.dispose();
-					exeReader = debugProvider.getExecutableSymbolicsReader();
-				}
-			}
-			reader = new EDCSymbolReader(exeReader, debugProvider);
-		}
-
-		if (reader != null) {
-			readerCache.put(modulePath, new WeakReference<IEDCSymbolReader>(reader));
-		}
-		
-		return reader;
-	}
-
-	@Override
-	public void shutdown(RequestMonitor rm) {
-		super.shutdown(rm);
-	}
-
-	/**
-	 * This is exposed only for testing.
-	 */
-	public static void releaseReaderCache() {
-		Collection<WeakReference<IEDCSymbolReader>> readers = readerCache.values();
-		for (WeakReference<IEDCSymbolReader> readerRef : readers) {
-			IEDCSymbolReader reader = readerRef.get();
-			if (reader != null)
-				reader.shutDown();
-		}
-		readerCache.clear();
-	}
-
-	/**
-	 * Given an opaque composite type, search the symbol context for definition
-	 * of the type.
-	 * 
-	 * A C/C++ opaque type is usually used in opaque pointer, e.g.
-	 * 
-	 * <pre>
-	 * typedef class PrivateType* OpaquePTR;
-	 * </pre>
-	 * 
-	 * The actual definition of the "PrivateType" is usually in another
-	 * library/DLL with or without debug info.<br>
-	 * <br>
-	 * This method will search all modules loaded in the symbol context (usually
-	 * a process) until it finds a non-opaque type with the same name as the
-	 * given opaque type. If a loaded module has no debug info, it will just be
-	 * skipped.
-	 * 
-	 * @param symCtx
-	 *            the symbol context (usually a process)
-	 * @param type
-	 *            the opaque composite type
-	 * @return a defined type; null if no defined type is found or the given
-	 *         type is not opaque.
-	 */
-	public ICompositeType resolveOpaqueType(ISymbolDMContext symCtx, ICompositeType type) {
-		ICompositeType result = null;
-		if (type == null || ! type.isOpaque()) {
-			return result;
-		}
-	
-		if (EDCTrace.SYMBOL_READER_TRACE_ON) { 
-			EDCTrace.getTrace().traceEntry(null, "Resolve opaque type \"" + type.getName() + "\" in " + EDCTrace.fixArg(symCtx)); 
-		}
-		
-		IModuleDMContext[] moduleList = null;
-
-		Modules modulesService = getService(Modules.class);
-		assert(modulesService != null);
-		
-		if (symCtx instanceof IEDCExecutionDMC) {
-			String symContextID = ((IEDCDMContext) symCtx).getID();
-			moduleList = modulesService.getModulesForContext(symContextID);
-		} else if (symCtx instanceof IModuleDMContext) {
-			moduleList = new IModuleDMContext[1];
-			moduleList[0] = (IModuleDMContext) symCtx;
-		} else {
-			// should not happen
-			Status s = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
-					"Unknown class implementing ISymbolDMContext : {0}", symCtx.getClass().getName()), null);
-			
-			if (EDCTrace.SYMBOL_READER_TRACE_ON)
-				EDCTrace.getTrace().traceExit(null,	s);
-			return result;
-		}
-
-		for (IModuleDMContext module : moduleList) {
-			ModuleDMC mdmc = (ModuleDMC) module;
-			EDCSymbolReader reader = (EDCSymbolReader)mdmc.getSymbolReader();
-
-			if (reader == null || reader.getDebugInfoProvider() == null) // no debug info 
-				continue;
-			
-			Collection<IType> types = reader.getDebugInfoProvider().getTypesByName(type.getName());
-			if (types == null)
-				return result;
-
-			for (IType t : types) {
-				if (t instanceof ICompositeType && ! ((ICompositeType)t).isOpaque()) {
-					result = (ICompositeType)t;
-					break;
-				}
-			}
-			
-		}
-		
-		return result;
-	}
-	
-	/**
-	 * A wrapper method that calls into symbol reader to get runtime address(es)
-	 * for a given function name.
-	 * For executables that are not PE-COFF, this method only uses the symbol table instead of
-	 * also debug info (e.g. Dwarf3) to get function address. See reason in the implementation.
-	 * 
-	 * @param module where the runtime address is.
-	 * @param functionName
-	 * @return list of runtime addresses.
-	 */
-	public List<IAddress> getFunctionAddress(IEDCModuleDMContext module, String functionName) {
-		
-		List<IAddress> ret = new ArrayList<IAddress>(2);
-		
-		IEDCSymbolReader symReader = module.getSymbolReader();
-		if (symReader == null)
-			return ret;
-		
-		// Remove "()" if any
-		int parenIndex = functionName.indexOf('(');
-		if (parenIndex >= 0)
-			functionName = functionName.substring(0, parenIndex);
-
-		// Supposedly we could call this to get what we need, but this may cause full parse of 
-		// debug info and lead to heap overflow for a large symbol file (over one gigabytes of 
-		// memory required in parsing a 180M ELF symbol file) and chokes the debugger.
-		// So before a good solution is available, we resort to symbol table of the executable.
-		// ................04/02/10
-//			Collection<IFunctionScope> functions = symReader.getModuleScope().getFunctionsByName(functionName);
-//			for (IFunctionScope f : functions) {
-//				IAddress breakAddr = f.getLowAddress();
-//		        ...
-
-		// assume it's the human-readable name first
-		Collection<ISymbol> symbols = symReader.findUnmangledSymbols(functionName);
-		if (symbols.isEmpty()) {
-			// else look for a raw symbol
-			symbols = symReader.findSymbols(functionName);
-		}
-
-		if (symbols.isEmpty() && symReader.getSymbolicsReader() instanceof PEFileExecutableSymbolicsReader) {
-			// for PE-COFF files, if the name is not in the symbol list, search the debug info
-			IFunctionScope function = symReader.getModuleScope().getFunctionByName(functionName);
-			if (function != null)
-				ret.add(function.getLowAddress());
-		} else for (ISymbol symbol : symbols) {
-			// don't consider zero sized symbol.
-			if (symbol.getSize() ==  0) 
-				continue;
-
-			IAddress addr = symbol.getAddress();
-			// convert from link to runtime address
-			addr = module.toRuntimeAddress(addr);
-			
-			ret.add(addr);
-		}
-
-		return ret;
-	}
-	
-}
+/*******************************************************************************

+ * Copyright (c) 2009, 2010, 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.lang.ref.WeakReference;

+import java.text.MessageFormat;

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.HashMap;

+import java.util.List;

+import java.util.Map;

+

+import org.eclipse.cdt.core.IAddress;

+import org.eclipse.cdt.debug.edc.internal.EDCDebugger;

+import org.eclipse.cdt.debug.edc.internal.EDCTrace;

+import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;

+import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType;

+import org.eclipse.cdt.debug.edc.internal.symbols.files.DebugInfoProviderFactory;

+import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;

+import org.eclipse.cdt.debug.edc.internal.symbols.files.PEFileExecutableSymbolicsReader;

+import org.eclipse.cdt.debug.edc.services.AbstractEDCService;

+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.IFrameRegisterProvider;

+import org.eclipse.cdt.debug.edc.services.IFrameRegisters;

+import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;

+import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider;

+import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;

+import org.eclipse.cdt.debug.edc.symbols.IExecutableSymbolicsReader;

+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.symbols.IModuleScope;

+import org.eclipse.cdt.debug.edc.symbols.IScope;

+import org.eclipse.cdt.debug.edc.symbols.ISymbol;

+import org.eclipse.cdt.debug.edc.symbols.IType;

+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;

+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;

+import org.eclipse.cdt.dsf.datamodel.IDMContext;

+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.ISymbols;

+import org.eclipse.cdt.dsf.service.DsfSession;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.runtime.IStatus;

+import org.eclipse.core.runtime.Status;

+import org.eclipse.core.runtime.SubMonitor;

+import org.eclipse.debug.core.model.ISourceLocator;

+

+public class Symbols extends AbstractEDCService implements ISymbols, IEDCSymbols {

+	private static Map<IPath, WeakReference<IEDCSymbolReader>> readerCache = new HashMap<IPath, WeakReference<IEDCSymbolReader>>();

+	private ISourceLocator sourceLocator;

+	

+	public ISourceLocator getSourceLocator() {

+		return sourceLocator;

+	}

+

+	public void setSourceLocator(ISourceLocator sourceLocator) {

+		this.sourceLocator = sourceLocator;

+	}

+

+	public Symbols(DsfSession session) {

+		super(session, new String[] { IEDCSymbols.class.getName(), ISymbols.class.getName(), Symbols.class.getName() });

+	}

+

+	public void getSymbols(ISymbolDMContext symCtx, DataRequestMonitor<Iterable<ISymbolObjectDMContext>> rm) {

+		// TODO Auto-generated method stub

+

+	}

+
<