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

+

+	}

+

+	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,

+			IProgressMonitor monitor) {

+		if (type == null || ! type.isOpaque())

+			return null;

+	

+		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 null;

+		}

+

+		SubMonitor searchMonitor = SubMonitor.convert(monitor, moduleList.length);

+		searchMonitor.subTask("Searching modules list: 0/" + String.valueOf(moduleList.length));

+		int count = 0;

+		for (IModuleDMContext module : moduleList) {

+			ModuleDMC mdmc = (ModuleDMC) module;

+

+			searchMonitor.worked(1);

+			searchMonitor.subTask("Searching modules list: " + String.valueOf(++count)

+								  + "/" + String.valueOf(moduleList.length));

+

+			EDCSymbolReader reader = (EDCSymbolReader)mdmc.getSymbolReader();

+			if (reader == null)

+				continue;

+			searchMonitor.subTask("Searching modules list: " + String.valueOf(count)

+								  + "/" + String.valueOf(moduleList.length) + " "

+								  + reader.getSymbolFile().toOSString());

+			IDebugInfoProvider provider = reader.getDebugInfoProvider();

+			if (provider == null)

+				continue;

+

+			searchMonitor.subTask("Searching modules list: " + String.valueOf(count)

+								  + "/" + String.valueOf(moduleList.length) + " "

+								  + provider.getSymbolFile().toOSString());

+

+			Collection<IType> types = provider.getTypesByName(type.getName());				

+

+			if (types == null)

+				continue;

+

+			for (IType t : types)

+				if (t instanceof ICompositeType && ! ((ICompositeType)t).isOpaque())

+					// return immediately as soon as we have something useful

+					return (ICompositeType)t;

+			if (searchMonitor.isCanceled())

+				break;

+		}

+		

+		return null;

+	}

+

+	/**

+	 * 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;

+	}

+	

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Album.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Album.java
index 41bac9e..0c015ab 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Album.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Album.java
@@ -1,1326 +1,1339 @@
-/*******************************************************************************
- * 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.snapshot;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
-
-import org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.PathUtils;
-import org.eclipse.cdt.debug.edc.internal.ZipFileUtils;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
-import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
-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.internal.core.sourcelookup.MapEntrySourceContainer;
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
-import org.eclipse.cdt.dsf.concurrent.Query;
-import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
-import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
-import org.eclipse.cdt.dsf.service.DsfServicesTracker;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.FileLocator;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.PlatformObject;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.sourcelookup.ISourceContainer;
-import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
-import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
-import org.eclipse.debug.internal.core.LaunchManager;
-import org.osgi.framework.Bundle;
-import org.osgi.service.prefs.BackingStoreException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-/**
- * The Album class represents a series of snapshots that record moments in a
- * debug session. An Album manages the collection of snapshots, common resources
- * such as source files, persistence, and association with debug sessions.
- * 
- * An Album is usually created during a debug session, saved at the conclusion
- * of the session, and reopened by a launch delegate for a new snapshot debug
- * session.
- * 
- * When an Album is saved it's data and resources are archived in a snapshot
- * file in a default location. When reopened the contents are expanded into a
- * temporary directory and used to recreate the debug session.
- */
-@SuppressWarnings("restriction")
-public class Album extends PlatformObject implements IAlbum {
-
-	// XML element names
-	public static final String SNAPSHOT = "snapshot";
-	private static final String ALBUM = "album";
-	private static final String LAUNCH = "launch";
-	private static final String RESOURCES = "resources";
-	private static final String FILE = "file";
-	private static final String INFO = "info";
-
-	public static final String METADATA = "snapshotMetaData";
-	public static final String SNAPSHOT_LIST = "snapshots";
-
-	private static final String ALBUM_DATA = "album.xml";
-	private static final String ALBUM_VERSION = "100";
-
-	private static String[] DSA_FILE_EXTENSIONS = new String[] {"dsa"};
-
-	// Preferences
-	public static final String PREF_CREATION_CONTROL = "creation_control";
-	public static final String CREATE_MANUAL = "manual";
-	public static final String CREATE_WHEN_STOPPED = "suspend";
-	public static final String CREATE_AT_BEAKPOINTS = "breakpoints";	
-	
-	public static final String PREF_VARIABLE_CAPTURE_DEPTH = "variable_capture_depth";
-	public static final String PLAY_SNAPSHOT_DELAY_TIME = "play_snapshot_delay_time";
-
-	private static final String CAMERA_CLICK_WAV = "/sounds/camera_click.wav";
-	
-	private Document document;
-	private Element albumRootElement;
-
-	private final List<Snapshot> snapshotList = new ArrayList<Snapshot>();
-	private String sessionID = "";
-	private String recordingSessionID = "";
-	private IPath albumRootDirectory;
-	private boolean launchConfigSaved;
-	private String launchType;
-	private HashMap<String, Object> launchProperties;
-	private String launchName = "";
-	private String name;
-	private boolean loaded;
-	private boolean metaDataLoaded;
-	private final Set<IPath> files = new HashSet<IPath>();
-
-	private int currentSnapshotIndex;
-	private IPath location;
-	private boolean resourceListSaved;
-	private boolean metadataSaved;
-	private boolean albumInfoSaved;
-	private String displayName;
-	private boolean playingSnapshots;
-
-	/**
-     * Listener for state changes on albums
-     */
-	protected static List<ISnapshotAlbumEventListener> listeners = Collections.synchronizedList(new ArrayList<ISnapshotAlbumEventListener>());
-
-	private static Map<String, Album> albumsBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());
-	private static Map<String, Album> albumsRecordingBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());	
-	private static Map<IPath, Album> albumsByLocation = Collections.synchronizedMap(new HashMap<IPath, Album>());
-	private static Map<String, Integer> launchNames = Collections.synchronizedMap(new HashMap<String, Integer>());
-
-	private static boolean sessionEndedListenerAdded;
-	private static SessionEndedListener sessionEndedListener = new SessionEndedListener() {
-
-		public void sessionEnded(DsfSession session) {
-			Album album = albumsRecordingBySessionID.get(session.getId());
-			if (album == null)
-				album = albumsBySessionID.get(session.getId());
-			if (album != null && session.getId().equals(album.getRecordingSessionID())) {
-				album.saveResources(new NullProgressMonitor());
-				album.setRecordingSessionID("");
-			}
-			synchronized (albumsRecordingBySessionID) {
-			albumsRecordingBySessionID.remove(session.getId());
-			}
-			synchronized (albumsBySessionID) {
-			albumsBySessionID.remove(session.getId());
-			}
-
-			if (album != null) {
-				for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
-					l.snapshotSessionEnded(album, session);
-				}
-			}
-		}
-	};
-
-	public interface IAlbumArchiveEntry {
-
-		public String createEntryName(File file);
-
-	}
-
-	public Album() {
-		super();
-		try {
-			setDocument(DebugPlugin.newDocument());
-			if (!sessionEndedListenerAdded)
-				DsfSession.addSessionEndedListener(sessionEndedListener);
-			sessionEndedListenerAdded = true;
-		} catch (CoreException e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getName()
-	 */
-	public String getName() {
-		if (name == null) {
-			name = getDefaultAlbumName();
-		}
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public void setDisplayName(String displayName) {
-		this.displayName = displayName;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getDisplayName()
-	 */
-	public String getDisplayName() {
-		if (displayName == null || displayName.length() == 0) {
-			displayName = getName();
-		}
-		return displayName;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSessionID()
-	 */
-	public String getSessionID() {
-		sessionID = "";
-		if (albumsBySessionID != null) {
-			for (Map.Entry<String, Album> entry : albumsBySessionID.entrySet()){
-				if (entry.getValue().location != null && entry.getValue().location.equals(getLocation())){
-					sessionID = entry.getKey();
-				}
-			}
-		}
-		return sessionID;
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getRecordingSessionID()
-	 */
-	public String getRecordingSessionID() {
-		return recordingSessionID;
-	}
-
-	public void setRecordingSessionID(String sessionID) {
-		this.recordingSessionID = sessionID;
-		if (sessionID.length() > 0)
-			albumsRecordingBySessionID.put(sessionID, this);
-	}
-
-	public void setSessionID(String sessionID) {
-		this.sessionID = sessionID;
-		if (sessionID.length() > 0)
-			albumsBySessionID.put(sessionID, this);
-	}
-	
-	/**
-	 * Is the album currently open for recording
-	 * @param sessionId
-	 * @return true if the album is currently being recording by an active debug session
-	 */
-	public static boolean isSnapshotSession(String sessionId) {
-		EDCLaunch launch = EDCLaunch.getLaunchForSession(sessionId);
-		return launch != null && launch.isSnapshotLaunch();
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#createSnapshot(org.eclipse.cdt.dsf.service.DsfSession, org.eclipse.cdt.debug.edc.internal.services.dsf.Stack.StackFrameDMC, org.eclipse.core.runtime.IProgressMonitor)
-	 */
-	public Snapshot createSnapshot(DsfSession session, StackFrameDMC stackFrame, IProgressMonitor monitor) throws Exception {
-		SubMonitor progress = SubMonitor.convert(monitor, "Creating Snapshot", 10000);
-		configureAlbum();
-		progress.worked(100);
-		
-		if (getLocation() == null || !getLocation().toFile().exists()){
-				createEmptyAlbum(); 
-		}
-		
-		Snapshot snapshot = new Snapshot(this, session, stackFrame);
-		snapshot.writeSnapshotData(progress.newChild(7900));
-
-		snapshotList.add(snapshot);
-		saveAlbum(progress.newChild(1000));
-		
-		monitor.done();
-		return snapshot;
-	}
-
-	private void configureAlbum() {
-		saveAlbumInfo();
-		saveLaunchConfiguration();
-	}
-
-	private void saveAlbumInfo() {
-		if (!albumInfoSaved) {
-			Element infoElement = document.createElement(INFO);
-			infoElement.setAttribute("version", ALBUM_VERSION);
-			Calendar calendar = Calendar.getInstance();
-			infoElement.setAttribute("month", Integer.toString(calendar.get(Calendar.MONTH)));
-			infoElement.setAttribute("day", Integer.toString(calendar.get(Calendar.DATE)));
-			infoElement.setAttribute("year", Integer.toString(calendar.get(Calendar.YEAR)));
-			infoElement.setAttribute("hour", Integer.toString(calendar.get(Calendar.HOUR)));
-			infoElement.setAttribute("minute", Integer.toString(calendar.get(Calendar.MINUTE)));
-			infoElement.setAttribute("second", Integer.toString(calendar.get(Calendar.SECOND)));
-
-			Properties systemProps = System.getProperties();
-			Map<String, Object> infoProps = new HashMap<String, Object>();
-			Set<Object> systemKeys = systemProps.keySet();
-
-			for (Object sysKey : systemKeys) {
-				if (sysKey instanceof String)
-					infoProps.put((String) sysKey, systemProps.get(sysKey));
-			}
-			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, infoProps);
-			infoElement.appendChild(propsElement);
-
-			getAlbumRootElement().appendChild(infoElement);
-			albumInfoSaved = true;
-		}
-	}
-
-	private void saveResourceList() {
-		if (!resourceListSaved) {
-			Element resourcesElement = document.createElement(RESOURCES);
-			for (IPath filePath : files) {
-				Element fileElement = document.createElement(FILE);
-				fileElement.setAttribute("path", filePath.toOSString());
-				resourcesElement.appendChild(fileElement);
-			}
-			getAlbumRootElement().appendChild(resourcesElement);
-			resourceListSaved = true;
-		}
-	}
-
-	private void saveSnapshotMetadata() {
-		if (!metadataSaved || isRecording()) {
-					
-			if (metadataSaved){
-				// If metatdata is saved, it must be a live debug session so
-				// we need to add a new snapshot to the snapshot list
-				NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
-				assert snapMetaDataNode.item(0) != null;
-				document.getDocumentElement().removeChild(snapMetaDataNode.item(0));
-			}
-			
-			Element metadataElement = document.createElement(METADATA);
-
-			Element albumElement = document.createElement(ALBUM);
-			albumElement.setAttribute("albumName", this.getDisplayName());
-			metadataElement.appendChild(albumElement);
-
-			Element snapshotsElement = document.createElement(SNAPSHOT_LIST);
-			metadataElement.appendChild(snapshotsElement);
-
-			for (Snapshot snap : snapshotList) {
-				Element snapshotMetadataElement = document.createElement(SNAPSHOT);
-				if (snap.getSnapshotDisplayName().length() == 0) {
-					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotFileName());
-				} else {
-					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotDisplayName());
-				}
-				if (snap.getCreationDate() != null) {
-					snapshotMetadataElement.setAttribute("date", snap.getCreationDate().toString());
-				} else {
-					snapshotMetadataElement.setAttribute("date", "unknown");
-				}
-
-				snapshotMetadataElement.setAttribute("description", snap.getSnapshotDescription());
-				snapshotMetadataElement.setAttribute("fileName", snap.getSnapshotFileName());				
-				snapshotMetadataElement.setAttribute("referenceLocationSourceFile", snap.getReferenceLocationSourceFile());
-				snapshotMetadataElement.setAttribute("referenceLocationLineNumber", String.valueOf(snap.getReferenceLocationLineNumber()));
-				
-				snapshotsElement.appendChild(snapshotMetadataElement);
-			}
-			getAlbumRootElement().appendChild(metadataElement);
-			metadataSaved = true;
-		}
-	}
-
-	@SuppressWarnings("unchecked")
-	private void saveLaunchConfiguration() {
-		if (!launchConfigSaved) {
-			EDCLaunch launch = EDCLaunch.getLaunchForSession(getRecordingSessionID());
-			try {
-				Map<String, Object> map = launch.getLaunchConfiguration().getAttributes();
-				Element launchElement = document.createElement(LAUNCH);
-				launchType = launch.getLaunchConfiguration().getType().getIdentifier();
-				launchName = launch.getLaunchConfiguration().getName();
-				Integer count = launchNames.get(launchName);
-				if (count == null) {
-					launchNames.put(launchName, new Integer(0));
-				}
-				else {
-					count = new Integer(count.intValue() + 1);
-					launchNames.put(launchName, count);
-					launchName += " (" + count.toString() + ")";
-				}
-				launchElement.setAttribute("type", launchType);
-				launchElement.setAttribute("name", launchName);
-				Element propsElement = SnapshotUtils.makeXMLFromProperties(document, map);
-				launchElement.appendChild(propsElement);
-				getAlbumRootElement().appendChild(launchElement);
-			} catch (CoreException e) {
-				EDCDebugger.getMessageLogger().logError(null, e);
-			}
-			launchConfigSaved = true;
-		}
-	}
-
-	private static void addZipEntry(ZipOutputStream zipOut, IAlbumArchiveEntry entry, File file)
-			throws FileNotFoundException, IOException {
-		if (file.exists()) {
-			if (file.isDirectory()) {
-				for (File child : file.listFiles()) {
-					addZipEntry(zipOut, entry, child);
-				}
-			} else {
-				// Add ZIP entry to output stream.m
-				String path = ""; //$NON-NLS-1$
-
-				if (entry != null) {
-					path = entry.createEntryName(file);
-				} else {
-					path = file.getName();
-				}
-
-				zipOut.putNextEntry(new ZipEntry(path));
-
-				// Create a buffer for reading the files
-				byte[] buf = new byte[1024];
-
-				// Transfer bytes from the file to the ZIP file
-				// and compress the files
-				FileInputStream in = new FileInputStream(file);
-				int len;
-				while ((len = in.read(buf)) > 0) {
-					zipOut.write(buf, 0, len);
-				}
-
-				// Complete the entry
-				zipOut.closeEntry();
-				in.close();
-			}
-		}
-	}
-
-	/**
-	 * Create and write a full snapshot album from scratch
-	 */
-	private void saveAlbum(IProgressMonitor monitor) {
-
-		IPath zipPath = getLocation();
-		ZipOutputStream zipOut = null;
-		try {
-			SubMonitor progress = SubMonitor.convert(monitor, 2000 + (snapshotList.size() * 1000));
-			progress.subTask("Saving album data");
-
-			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));
-
-			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));
-
-			saveResourceList();
-			progress.worked(1000);
-			saveSnapshotMetadata();
-			progress.worked(1000);
-
-			String xml = LaunchManager.serializeDocument(document);
-			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$
-			zipOut.closeEntry();
-
-			for (Snapshot snap : snapshotList) {
-				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));
-				snap.saveSnapshot(zipOut);
-				progress.worked(1000);
-			}
-
-		} catch (Exception e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		} finally {
-			try {
-				if (zipOut != null) {
-					zipOut.close();
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
-	/**
-	 * Create and write a full snapshot album from scratch
-	 */
-	private void saveResources(IProgressMonitor monitor) {
-
-		IPath zipPath = getLocation();
-		ZipOutputStream zipOut = null;
-		try {
-			// TODO: Here's we're just rewriting the entire album again
-			// Need to just add the resources alone using proper utils
-			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));
-
-			for (IPath path : files) {
-
-				IAlbumArchiveEntry entry = new IAlbumArchiveEntry() {
-
-					public String createEntryName(File file) {
-						StringBuffer entryPath = new StringBuffer();
-
-						entryPath.append("Resources/");
-
-						IPath filepath = new Path(file.getAbsolutePath());
-
-						String deviceName = filepath.getDevice();
-						if (deviceName != null) {
-							// Remove the : from the end
-							entryPath.append(deviceName.substring(0, deviceName.length() - 1));
-							entryPath.append("/");
-						}
-						
-						String[] segments = filepath.segments();
-						int numSegments = segments.length - 1;
-
-						for (int i = 0; i < numSegments; i++) {
-							entryPath.append(segments[i]);
-							entryPath.append("/");
-						}
-						entryPath.append(file.getName());
-						return entryPath.toString();
-					}
-				};
-				addZipEntry(zipOut, entry, path.toFile());
-				if (monitor != null) {
-					monitor.worked(1);
-				}
-			}
-			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));
-
-			saveResourceList();
-			saveSnapshotMetadata();
-
-			String xml = LaunchManager.serializeDocument(document);
-			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$
-			zipOut.closeEntry();
-
-			for (Snapshot snap : snapshotList) {
-				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));
-				snap.saveSnapshot(zipOut);
-			}
-
-		} catch (Exception e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		} finally {
-			try {
-				if (zipOut != null) {
-					zipOut.close();
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-	}
-
-	private String getDefaultAlbumName() {
-		return getLaunchName();
-	}
-
-	public void saveAlbum(IPath path) throws TransformerException, IOException {
-		String xml = LaunchManager.serializeDocument(document);
-		File file = path.toFile();
-		if (!file.exists()) {
-			file.createNewFile();
-		}
-		FileOutputStream stream = new FileOutputStream(file);
-		stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$
-		stream.close();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openSnapshot(int)
-	 */
-	public void openSnapshot(final int index) {
-
-		final DsfSession session = DsfSession.getSession(sessionID);
-
-		DsfRunnable openIt = new DsfRunnable() {
-			public void run() {
-				currentSnapshotIndex = index;
-				try {
-					loadAlbum(false);
-				} catch (Exception e) {
-					EDCDebugger.getMessageLogger().logError(null, e);
-				}
-				if (session != null && snapshotList.size() > index) {
-					Snapshot snapshot = snapshotList.get(index);
-					snapshot.open(session);
-					// Fire the event
-					for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
-						l.snapshotOpened(snapshot);
-					}
-				}
-			}
-		};
-
-		if (session != null && session.getExecutor() != null)
-		{
-			if (session.getExecutor().isInExecutorThread())
-				openIt.run();
-			else
-				session.getExecutor().execute(openIt);
-		}
-
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getCurrentSnapshotIndex()
-	 */
-	public int getCurrentSnapshotIndex() {
-		return currentSnapshotIndex;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openNextSnapshot()
-	 */
-	public void openNextSnapshot() throws Exception {
-		int nextIndex = currentSnapshotIndex + 1;
-		if (nextIndex >= snapshotList.size())
-			nextIndex = 0;
-		openSnapshot(nextIndex);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openPreviousSnapshot()
-	 */
-	public void openPreviousSnapshot() throws Exception {
-		int previousIndex = currentSnapshotIndex - 1;
-		if (previousIndex < 0)
-			previousIndex = snapshotList.size() - 1;
-		openSnapshot(previousIndex);
-	}
-
-	public void loadAlbum(boolean force) throws ParserConfigurationException, SAXException, IOException {
-		if (force)
-			loaded = false;
-		if (!loaded) {
-			File albumFile = location.toFile();
-			setName(albumFile.getName());
-			
-			if (!isRecording()){
-				// not creating the snapshot, so must be snapshot play back	
-				try {
-					ZipFileUtils.unzipFiles(albumFile, getAlbumRootDirectory().toOSString(), new NullProgressMonitor());
-				} catch (Exception e) {
-					EDCDebugger.getMessageLogger().logError(null, e);
-				}
-			}
-
-			BufferedInputStream stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-			parser.setErrorHandler(new DefaultHandler());
-			InputSource inputSource = new InputSource(stream);
-			inputSource.setSystemId(albumFile.toURI().toString());	// avoid NPE inside XML parser
-			setDocument(parser.parse(inputSource));
-
-			loadAlbumInfo();
-			loadLaunchConfiguration();
-			loadResourceList();
-			try {
-				loadSnapshotMetadata();
-			} catch (Exception e) {
-				e.printStackTrace();
-			} finally {
-				loaded = true;
-				ZipFileUtils.unmount();
-			}
-		}
-	}
-
-	/**
-	 * A lightwieght parse to get basic album info and what snapshots are
-	 * available.
-	 * 
-	 * @throws ParserConfigurationException
-	 * @throws SAXException
-	 * @throws IOException
-	 */
-	public void loadAlbumMetada(boolean force) throws Exception {
-		if (force)
-			metaDataLoaded = false;
-		if (!metaDataLoaded) {
-			
-			File albumFile = location.toFile();
-			setDisplayName(albumFile.getName());
-
-			BufferedInputStream stream = null;
-			try {
-				stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);
-				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-				parser.setErrorHandler(new DefaultHandler());
-				setDocument(parser.parse(new InputSource(stream)));
-				loadSnapshotMetadata();
-				loadLaunchConfiguration(); // need to load launch config in case we need to delete it
-
-			} catch (Exception e) {
-				EDCDebugger.getMessageLogger().logError("Failed to load album: " + getName(), e);
-			} finally {
-				metaDataLoaded = true;
-				ZipFileUtils.unmount();
-			}
-		}
-	}
-
-	private void loadAlbumInfo() {
-		document.getElementsByTagName(INFO).item(0);
-	}
-
-	private void setDocument(Document newDoc)
-	{
-		document = newDoc;
-		albumRootElement = null;
-	}
-	
-	private Element getAlbumRootElement()
-	{
-		if (albumRootElement == null)
-		{
-			NodeList albumRootElements = document.getElementsByTagName(ALBUM);
-			if (albumRootElements.getLength() == 0)
-			{
-				albumRootElement = document.createElement(ALBUM);
-				document.appendChild(albumRootElement);
-			}
-			else
-			{
-				albumRootElement = (Element) albumRootElements.item(0);
-			}
-		}
-		return albumRootElement;
-	}
-	
-	private void loadResourceList() {
-		NodeList resources = document.getElementsByTagName(RESOURCES);
-		NodeList elementFiles = ((Element) resources.item(0)).getElementsByTagName(FILE);
-		int numFiles = elementFiles.getLength();
-		for (int i = 0; i < numFiles; i++) {
-			Element fileElement = (Element) elementFiles.item(i);
-			String elementPath = fileElement.getAttribute("path");
-			files.add(PathUtils.createPath(elementPath));		// for cross-created snapshot
-		}
-	}
-
-	private void loadSnapshotMetadata() throws Exception {
-		snapshotList.clear();
-		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
-
-		if (snapMetaDataNode.getLength() == 0) {
-			throw new Exception("Invalid or corrupted Album : " + getName());
-		}
-		NodeList albumNameElement = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);
-		Element albumElement = (Element) albumNameElement.item(0);
-		String albumDisplayName = albumElement.getAttribute("albumName");
-
-		setDisplayName(albumDisplayName);
-
-		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);
-		int numSnapshots = elementSnapshots.getLength();
-		for (int i = 0; i < numSnapshots; i++) {
-			Element snapshotElement = (Element) elementSnapshots.item(i);
-			String elementDescription = snapshotElement.getAttribute("description");
-			String elementDate = snapshotElement.getAttribute("date");
-			String elementDispalyName = snapshotElement.getAttribute("displayName");
-			String elementFileName = snapshotElement.getAttribute("fileName");
-			String referenceLocationSourceFile = snapshotElement.getAttribute("referenceLocationSourceFile");
-			String referenceLocationLineNumber = snapshotElement.getAttribute("referenceLocationLineNumber");
-			
-			Snapshot s = new Snapshot(this);
-			s.setCreationDate(elementDate);
-			s.setSnapshotFileName(elementFileName);
-			s.setSnapshotDisplayName(elementDispalyName);
-			s.setSnapshotDescription(elementDescription);
-			if (referenceLocationLineNumber.length() > 0){
-				s.setReferenceLocationLineNumber(Long.parseLong(referenceLocationLineNumber));
-			}
-			s.setReferenceLocationSourceFile(referenceLocationSourceFile);
-			snapshotList.add(s);
-		}
-	}
-
-	private void loadLaunchConfiguration() {
-		NodeList launchElements = document.getElementsByTagName(LAUNCH);
-		Element launchElement = (Element) launchElements.item(0);
-		if (launchElement == null){
-			return;
-		}
-		launchType = launchElement.getAttribute("type");
-		launchName = launchElement.getAttribute("name");
-
-		Element propElement = (Element) launchElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-		launchProperties = new HashMap<String, Object>();
-		try {
-			SnapshotUtils.initializeFromXML(propElement, launchProperties);
-		} catch (Exception e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-
-	}
-
-	@SuppressWarnings("rawtypes")
-	@Override
-	public Object getAdapter(Class adapter) {
-		if (adapter.equals(Document.class))
-			return document;
-
-		return super.getAdapter(adapter);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getAlbumRootDirectory()
-	 */
-	public IPath getAlbumRootDirectory() {
-		if (albumRootDirectory == null) {
-			IPath path = EDCDebugger.getDefault().getStateLocation().append("SnapshotAlbums");
-			String locationName = location.lastSegment();
-			int extension = locationName.lastIndexOf(".");
-			if (extension > 0) {
-				locationName = locationName.substring(0, extension);
-			}
-			path = path.append(locationName);
-			File dir = path.toFile();
-			if (!dir.exists()) {
-				dir.mkdirs();
-			}
-			albumRootDirectory = path;
-		}
-		return albumRootDirectory;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchTypeID()
-	 */
-	public String getLaunchTypeID() {
-		return launchType;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchProperties()
-	 */
-	public HashMap<String, Object> getLaunchProperties() {
-		return launchProperties;
-	}
-
-	public void setLaunchProperties(HashMap<String, Object> launchProperties) {
-		this.launchProperties = launchProperties;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchName()
-	 */
-	public String getLaunchName() {
-		return launchName;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#playSnapshots(org.eclipse.cdt.dsf.service.DsfSession)
-	 */
-	public void playSnapshots() {
-		if (!isPlayingSnapshots())
-		{
-			Job playSnapshotsJob = new Job("Play Snapshots for Album " + getDisplayName()){
-
-				@Override
-				protected IStatus run(IProgressMonitor monitor) {
-					try {
-						monitor.beginTask("Play Snapshots for Album " + getDisplayName(), IProgressMonitor.UNKNOWN);
-						while (isPlayingSnapshots() && !monitor.isCanceled())
-						{
-							Album.this.openNextSnapshot();
-							Thread.sleep(getPlaySnapshotInterval());
-						}
-						setPlayingSnapshots(false);
-						monitor.done();
-					} catch (Exception e) {
-						EDCDebugger.getMessageLogger().logError(null, e);
-						return new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, null, e);
-					}
-					return Status.OK_STATUS;
-				}
-				
-			};
-			setPlayingSnapshots(true);
-			playSnapshotsJob.schedule();
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#addFile(org.eclipse.core.runtime.IPath)
-	 */
-	public void addFile(IPath path) {
-		files.add(path);
-	}
-
-	public static Album getAlbumByLocation(IPath path) {
-		return albumsByLocation.get(path);
-	}
-
-	public static IAlbum getAlbumBySession(String sessionId) {
-		return albumsBySessionID.get(sessionId);
-	}
-
-	public static Album getRecordingForSession(String sessionId) {
-		return albumsRecordingBySessionID.get(sessionId);
-	}
-
-	public void setLocation(IPath albumPath) {
-		this.location = albumPath;
-		albumsByLocation.put(albumPath, this);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLocation()
-	 */
-	public IPath getLocation() {
-		return location;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureSourceLookupDirector(org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector)
-	 */
-	public void configureSourceLookupDirector(ISourceLookupDirector director) {
-		MappingSourceContainer sourceContainer = new MappingSourceContainer(getName());
-		configureMappingSourceContainer(sourceContainer);
-		ArrayList<ISourceContainer> containers = new ArrayList<ISourceContainer>(Arrays.asList(director
-				.getSourceContainers()));
-		containers.add(sourceContainer);
-
-		DirectorySourceContainer directoryContainer = new DirectorySourceContainer(getResourcesDirectory(), true);
-		containers.add(directoryContainer);
-
-		director.setSourceContainers(containers.toArray(new ISourceContainer[containers.size()]));
-	}
-
-	protected IPath getResourcesDirectory()
-	{
-		return getAlbumRootDirectory().append("Resources");
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureMappingSourceContainer(org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer)
-	 */
-	public void configureMappingSourceContainer(MappingSourceContainer mappingContainer) {
-		IPath albumRoot = getResourcesDirectory();
-		List<MapEntrySourceContainer> containers = new ArrayList<MapEntrySourceContainer>();
-		Set<String> devicesAlreadyAdded = new HashSet<String>();
-		String deviceName = null;
-		for (IPath iPath : files) {
-		    	deviceName = iPath.getDevice();
-			if (deviceName != null && !devicesAlreadyAdded.contains(deviceName))
-			{
-				String albumRootSuffix = deviceName;
-                if (albumRootSuffix.endsWith(":"))
-                	albumRootSuffix = albumRootSuffix.substring(0, albumRootSuffix.length() - 1);
-	                        devicesAlreadyAdded.add(deviceName);
-                            MapEntrySourceContainer newContainer = new MapEntrySourceContainer(PathUtils.createPath(deviceName), albumRoot.append(albumRootSuffix));
-                            containers.add(newContainer);
-                                
-			}
-		}
-		mappingContainer.addMapEntries(containers.toArray(new MapEntrySourceContainer[containers.size()]));
-	}
-
-	public static void setVariableCaptureDepth(int newSetting) {
-		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);
-		scope.putInt(PREF_VARIABLE_CAPTURE_DEPTH, newSetting);
-		try {
-			scope.flush();
-		} catch (BackingStoreException e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-	}
-
-	public static int getVariableCaptureDepth() {
-		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,
-				PREF_VARIABLE_CAPTURE_DEPTH, 5, null);
-	}
-
-	public static void setPlaySnapshotInterval(int delayInMilliseconds) {
-		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);
-		scope.putInt(PLAY_SNAPSHOT_DELAY_TIME, delayInMilliseconds);
-		try {
-			scope.flush();
-		} catch (BackingStoreException e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-	}
-
-	public static int getPlaySnapshotInterval() {
-		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,
-				PLAY_SNAPSHOT_DELAY_TIME, 5000, null);
-	}
-
-	public static void setSnapshotCreationControl(String newSetting) {
-		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);
-		scope.put(PREF_CREATION_CONTROL, newSetting);
-		try {
-			scope.flush();
-		} catch (BackingStoreException e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-	}
-
-	public static String getSnapshotCreationControl() {
-		return Platform.getPreferencesService().getString(EDCDebugger.PLUGIN_ID,
-				PREF_CREATION_CONTROL, CREATE_MANUAL, null);
-	}
-
-	protected static void playSnapshotSound() {
-		Bundle bundle = Platform.getBundle(EDCDebugger.getUniqueIdentifier());
-		if (bundle == null)
-			return;
-		
-		URL url = null;
-		try {
-			url = FileLocator.toFileURL(bundle.getEntry(CAMERA_CLICK_WAV));
-		} catch (IOException e) {
-		} catch (RuntimeException e){
-		}
-		finally {
-			if (url != null){
-				File f = new File(url.getFile());
-				SnapshotUtils.playSoundFile(f);
-			}
-		}
-		
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSnapshots()
-	 */
-	public List<Snapshot> getSnapshots() {
-		if (snapshotList == null || snapshotList.size() == 0) {
-			try {
-				loadAlbumMetada(false);
-			} catch (Exception e) {
-				EDCDebugger.getMessageLogger().logError("Failed to load snapshots", e);
-			}
-		}
-
-		return snapshotList;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isLoaded()
-	 */
-	public boolean isLoaded() {
-		return loaded;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getIndexOfSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)
-	 */
-	public int getIndexOfSnapshot(Snapshot snap) {
-		return snapshotList.indexOf(snap);
-	}
-
-	public void setCurrentSnapshotIndex(int index) {
-		if (currentSnapshotIndex >= 0 && currentSnapshotIndex < snapshotList.size()) {
-			currentSnapshotIndex = index;
-		}
-	}
-
-	/**
-	 * Update album.xml within the Album's .dsa file with new Snapshot data
-	 * 
-	 * @param albumName
-	 *            - Name of album to display. Use null if value should not be
-	 *            updated.
-	 * @param snap
-	 *            - Specific snapshot to update. Use null is snapshot should not
-	 *            be updated.
-	 */
-	public void updateSnapshotMetaData(String albumName, Snapshot snap) {
-		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
-		
-		// try to update album display name
-		if (albumName != null) {
-			NodeList albumNameNode = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);
-			((Element) albumNameNode.item(0)).setAttribute("albumName", albumName);
-		}
-
-		// try to update snapshot data
-		if (snap != null) {
-
-			NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);
-
-			int numSnapshots = elementSnapshots.getLength();
-			for (int i = 0; i < numSnapshots; i++) {
-				Element currentSnapshotNode = (Element) elementSnapshots.item(i);
-				String fileName = currentSnapshotNode.getAttribute("fileName");
-				if (fileName.equals(snap.getSnapshotFileName())) {
-
-					currentSnapshotNode.setAttribute("description", snap.getSnapshotDescription());
-					currentSnapshotNode.setAttribute("displayName", snap.getSnapshotDisplayName());
-
-					break;
-				}
-			}
-		}
-
-		saveAlbumData();
-
-		// refresh all data
-		try {
-			loadAlbumMetada(true);
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-
-	}
-
-	private void saveAlbumData() {
-		try {
-			File tempFile = File.createTempFile("album", ".xml");
-			File tempFile2 = new File(tempFile.getParent() + File.separator + ALBUM_DATA);
-			tempFile.delete();
-			if (!tempFile2.exists()) {
-				tempFile2.delete();
-			}
-			tempFile2.createNewFile();
-			saveAlbum(new Path(tempFile2.toString()));
-			File[] fileList = { tempFile2 };
-			ZipFileUtils.addFilesToZip(fileList, getLocation().toFile(), DSA_FILE_EXTENSIONS);
-
-		} catch (IOException e) {
-			e.printStackTrace();
-		} catch (TransformerException e) {
-			e.printStackTrace();
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#deleteSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)
-	 */
-	public void deleteSnapshot(Snapshot snap) {
-
-		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);
-
-		NodeList elementSnapshotList = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT_LIST);
-		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);
-
-		int numSnapshots = elementSnapshots.getLength();
-		for (int i = 0; i < numSnapshots; i++) {
-			Element currentSnapshotNode = (Element) elementSnapshots.item(i);
-			String fileName = currentSnapshotNode.getAttribute("fileName");
-			if (fileName.equals(snap.getSnapshotFileName())) {
-				elementSnapshotList.item(0).removeChild(currentSnapshotNode);
-				break;
-			}
-		}
-
-		snapshotList.remove(snap);
-
-		saveAlbumData();
-
-		// refresh all data
-		try {
-			loadAlbum(true);
-			loadAlbumMetada(true);
-		} catch (Exception e) {
-
-		}
-
-		ZipFileUtils.deleteFileFromZip(snap.getSnapshotFileName(), getLocation().toFile(), DSA_FILE_EXTENSIONS);
-	}
-
-	@Override
-	public String toString() {
-		return "Album [name=" + name + ", launchName=" + launchName + ", sessionID=" + sessionID + "]";
-	}
-	
-	public IPath createEmptyAlbum() {
-		IPath zipPath = null;
-		try {
-			zipPath = SnapshotUtils.getSnapshotsProject().getLocation();
-			zipPath = zipPath.append(getDefaultAlbumName());
-			zipPath = zipPath.addFileExtension("dsa");
-			boolean created =  ZipFileUtils.createNewZip(zipPath.toFile());
-			
-			if (created && zipPath.toFile().exists()){
-				setLocation(zipPath);
-			} else {
-				return null;
-			}
-			SnapshotUtils.getSnapshotsProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
-		} catch (CoreException e) {
-			EDCDebugger.getMessageLogger().logError(e.getLocalizedMessage(), e);
-		}		
-		return zipPath;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isRecording()
-	 */
-	public boolean isRecording() {
-		return recordingSessionID.length() > 0;
-	}
-
-	/**
-	 * @noreference This method is not intended to be referenced by clients.
-	 */
-	public static void addSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {
-		listeners.add(listener);
-	}
-	
-	/**
-	 * @noreference This method is not intended to be referenced by clients.
-	 */
-	public static void removeSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {
-		listeners.remove(listener);
-	}
-
-	public static void captureSnapshotForSession(final DsfSession session) {
-		Job createSnapshotJob = new Job("Creating Debug Snapshot") {
-
-			@Override
-			protected IStatus run(final IProgressMonitor monitor) {
-
-				Query<IFrameDMContext> frameQuery = new Query<IFrameDMContext>() {
-					@Override
-					protected void execute(
-							DataRequestMonitor<IFrameDMContext> rm) {
-						DsfServicesTracker servicesTracker = new DsfServicesTracker(
-								EDCDebugger.getBundleContext(),
-								session.getId());
-						try {
-							RunControl runControl = servicesTracker.getService(RunControl.class);
-							IThreadDMContext[] suspendedThreads = runControl.getSuspendedThreads();
-							if (suspendedThreads.length == 0)
-							{
-								rm.setData(null);
-								rm.done();
-							}
-							else
-							{
-								Stack stackService = servicesTracker.getService(Stack.class);
-								if (stackService != null) {
-									stackService.getTopFrame(suspendedThreads[0], rm);
-								}
-							}
-						} finally {
-							servicesTracker.dispose();
-						}
-					}
-				};
-
-				session.getExecutor().execute(frameQuery);
-
-				IStatus status = Status.OK_STATUS;
-				try {
-					final StackFrameDMC stackFrame = (StackFrameDMC) frameQuery.get();
-
-					String sessionId = session.getId();
-					Album album = Album.getRecordingForSession(sessionId);
-					if (album == null) {
-						album = new Album();
-						album.setRecordingSessionID(sessionId);
-					}
-					final Album finalAlbum = album;
-					playSnapshotSound();
-
-					Query<IStatus> query = new Query<IStatus>() {
-						@Override
-						protected void execute(final DataRequestMonitor<IStatus> drm) {
-							try {
-								Snapshot newSnapshot = finalAlbum.createSnapshot(session, stackFrame, monitor);
-								// Fire the event to anyone listening
-								for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {
-									l.snapshotCreated(finalAlbum, newSnapshot, session, stackFrame);
-								}
-								drm.setData(Status.OK_STATUS);
-							} catch (Exception e) {
-								Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error creating snapshot.", e);
-								EDCDebugger.getMessageLogger().log(s);
-								drm.setStatus(s);
-							}
-							drm.done();
-						}
-					};
-
-					session.getExecutor().execute(query);
-
-					status = query.get();
-				} catch (Exception e) {
-					status = new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, "Error creating snapshot", e);
-				}
-
-				return status;
-			}
-		};
-
-		createSnapshotJob.schedule();
-	}
-
-    public boolean isPlayingSnapshots() {
-		return playingSnapshots;
-	}
-
-	public void setPlayingSnapshots(boolean playingSnapshots) {
-		this.playingSnapshots = playingSnapshots;
-	}
-
-	public void stopPlayingSnapshots() {
-		setPlayingSnapshots(false);
-		openSnapshot(getCurrentSnapshotIndex()); // Reloading the current snapshot will resync the UI.
-	}
-
-}
+/*******************************************************************************

+ * 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.snapshot;

+

+import java.io.BufferedInputStream;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileNotFoundException;

+import java.io.FileOutputStream;

+import java.io.IOException;

+import java.net.URL;

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Calendar;

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.List;

+import java.util.Map;

+import java.util.Properties;

+import java.util.Set;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipOutputStream;

+

+import javax.xml.parsers.DocumentBuilder;

+import javax.xml.parsers.DocumentBuilderFactory;

+import javax.xml.parsers.ParserConfigurationException;

+import javax.xml.transform.TransformerException;

+

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

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

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

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

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

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

+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.internal.core.sourcelookup.MapEntrySourceContainer;

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

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

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

+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;

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

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

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

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

+import org.eclipse.core.resources.IResource;

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

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

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

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

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

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

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

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

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

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

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

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

+import org.eclipse.core.runtime.preferences.IEclipsePreferences;

+import org.eclipse.debug.core.DebugPlugin;

+import org.eclipse.debug.core.sourcelookup.ISourceContainer;

+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;

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

+import org.eclipse.debug.internal.core.LaunchManager;

+import org.osgi.framework.Bundle;

+import org.osgi.service.prefs.BackingStoreException;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.NodeList;

+import org.xml.sax.InputSource;

+import org.xml.sax.SAXException;

+import org.xml.sax.helpers.DefaultHandler;

+

+/**

+ * The Album class represents a series of snapshots that record moments in a

+ * debug session. An Album manages the collection of snapshots, common resources

+ * such as source files, persistence, and association with debug sessions.

+ * 

+ * An Album is usually created during a debug session, saved at the conclusion

+ * of the session, and reopened by a launch delegate for a new snapshot debug

+ * session.

+ * 

+ * When an Album is saved it's data and resources are archived in a snapshot

+ * file in a default location. When reopened the contents are expanded into a

+ * temporary directory and used to recreate the debug session.

+ */

+@SuppressWarnings("restriction")

+public class Album extends PlatformObject implements IAlbum {

+

+	// XML element names

+	public static final String SNAPSHOT = "snapshot";

+	private static final String ALBUM = "album";

+	private static final String LAUNCH = "launch";

+	private static final String RESOURCES = "resources";

+	private static final String FILE = "file";

+	private static final String INFO = "info";

+

+	public static final String METADATA = "snapshotMetaData";

+	public static final String SNAPSHOT_LIST = "snapshots";

+

+	private static final String ALBUM_DATA = "album.xml";

+	private static final String ALBUM_VERSION = "100";

+

+	private static String[] DSA_FILE_EXTENSIONS = new String[] {"dsa"};

+

+	// Preferences

+	public static final String PREF_CREATION_CONTROL = "creation_control";

+	public static final String CREATE_MANUAL = "manual";

+	public static final String CREATE_WHEN_STOPPED = "suspend";

+	public static final String CREATE_AT_BEAKPOINTS = "breakpoints";	

+	

+	public static final String PREF_RESOLVE_OPAQUE_TYPE = "resolve_opaque_type";

+	public static final String PREF_VARIABLE_CAPTURE_DEPTH = "variable_capture_depth";

+	public static final String PLAY_SNAPSHOT_DELAY_TIME = "play_snapshot_delay_time";

+

+	private static final String CAMERA_CLICK_WAV = "/sounds/camera_click.wav";

+	

+	private Document document;

+	private Element albumRootElement;

+

+	private final List<Snapshot> snapshotList = new ArrayList<Snapshot>();

+	private String sessionID = "";

+	private String recordingSessionID = "";

+	private IPath albumRootDirectory;

+	private boolean launchConfigSaved;

+	private String launchType;

+	private HashMap<String, Object> launchProperties;

+	private String launchName = "";

+	private String name;

+	private boolean loaded;

+	private boolean metaDataLoaded;

+	private final Set<IPath> files = new HashSet<IPath>();

+

+	private int currentSnapshotIndex;

+	private IPath location;

+	private boolean resourceListSaved;

+	private boolean metadataSaved;

+	private boolean albumInfoSaved;

+	private String displayName;

+	private boolean playingSnapshots;

+

+	/**

+     * Listener for state changes on albums

+     */

+	protected static List<ISnapshotAlbumEventListener> listeners = Collections.synchronizedList(new ArrayList<ISnapshotAlbumEventListener>());

+

+	private static Map<String, Album> albumsBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());

+	private static Map<String, Album> albumsRecordingBySessionID = Collections.synchronizedMap(new HashMap<String, Album>());	

+	private static Map<IPath, Album> albumsByLocation = Collections.synchronizedMap(new HashMap<IPath, Album>());

+	private static Map<String, Integer> launchNames = Collections.synchronizedMap(new HashMap<String, Integer>());

+

+	private static boolean sessionEndedListenerAdded;

+	private static SessionEndedListener sessionEndedListener = new SessionEndedListener() {

+

+		public void sessionEnded(DsfSession session) {

+			Album album = albumsRecordingBySessionID.get(session.getId());

+			if (album == null)

+				album = albumsBySessionID.get(session.getId());

+			if (album != null && session.getId().equals(album.getRecordingSessionID())) {

+				album.saveResources(new NullProgressMonitor());

+				album.setRecordingSessionID("");

+			}

+			synchronized (albumsRecordingBySessionID) {

+			albumsRecordingBySessionID.remove(session.getId());

+			}

+			synchronized (albumsBySessionID) {

+			albumsBySessionID.remove(session.getId());

+			}

+

+			if (album != null) {

+				for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {

+					l.snapshotSessionEnded(album, session);

+				}

+			}

+		}

+	};

+

+	public interface IAlbumArchiveEntry {

+

+		public String createEntryName(File file);

+

+	}

+

+	public Album() {

+		super();

+		try {

+			setDocument(DebugPlugin.newDocument());

+			if (!sessionEndedListenerAdded)

+				DsfSession.addSessionEndedListener(sessionEndedListener);

+			sessionEndedListenerAdded = true;

+		} catch (CoreException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getName()

+	 */

+	public String getName() {

+		if (name == null) {

+			name = getDefaultAlbumName();

+		}

+		return name;

+	}

+

+	public void setName(String name) {

+		this.name = name;

+	}

+

+	public void setDisplayName(String displayName) {

+		this.displayName = displayName;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getDisplayName()

+	 */

+	public String getDisplayName() {

+		if (displayName == null || displayName.length() == 0) {

+			displayName = getName();

+		}

+		return displayName;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSessionID()

+	 */

+	public String getSessionID() {

+		sessionID = "";

+		if (albumsBySessionID != null) {

+			for (Map.Entry<String, Album> entry : albumsBySessionID.entrySet()){

+				if (entry.getValue().location != null && entry.getValue().location.equals(getLocation())){

+					sessionID = entry.getKey();

+				}

+			}

+		}

+		return sessionID;

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getRecordingSessionID()

+	 */

+	public String getRecordingSessionID() {

+		return recordingSessionID;

+	}

+

+	public void setRecordingSessionID(String sessionID) {

+		this.recordingSessionID = sessionID;

+		if (sessionID.length() > 0)

+			albumsRecordingBySessionID.put(sessionID, this);

+	}

+

+	public void setSessionID(String sessionID) {

+		this.sessionID = sessionID;

+		if (sessionID.length() > 0)

+			albumsBySessionID.put(sessionID, this);

+	}

+	

+	/**

+	 * Is the album currently open for recording

+	 * @param sessionId

+	 * @return true if the album is currently being recording by an active debug session

+	 */

+	public static boolean isSnapshotSession(String sessionId) {

+		EDCLaunch launch = EDCLaunch.getLaunchForSession(sessionId);

+		return launch != null && launch.isSnapshotLaunch();

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#createSnapshot(org.eclipse.cdt.dsf.service.DsfSession, org.eclipse.cdt.debug.edc.internal.services.dsf.Stack.StackFrameDMC, org.eclipse.core.runtime.IProgressMonitor)

+	 */

+	public Snapshot createSnapshot(DsfSession session, StackFrameDMC stackFrame, IProgressMonitor monitor) throws Exception {

+		SubMonitor progress = SubMonitor.convert(monitor, "Creating Snapshot", 10000);

+		configureAlbum();

+		progress.worked(100);

+		

+		if (getLocation() == null || !getLocation().toFile().exists()){

+				createEmptyAlbum(); 

+		}

+		

+		Snapshot snapshot = new Snapshot(this, session, stackFrame);

+		snapshot.writeSnapshotData(progress.newChild(7900));

+

+		snapshotList.add(snapshot);

+		saveAlbum(progress.newChild(1000));

+		

+		monitor.done();

+		return snapshot;

+	}

+

+	private void configureAlbum() {

+		saveAlbumInfo();

+		saveLaunchConfiguration();

+	}

+

+	private void saveAlbumInfo() {

+		if (!albumInfoSaved) {

+			Element infoElement = document.createElement(INFO);

+			infoElement.setAttribute("version", ALBUM_VERSION);

+			Calendar calendar = Calendar.getInstance();

+			infoElement.setAttribute("month", Integer.toString(calendar.get(Calendar.MONTH)));

+			infoElement.setAttribute("day", Integer.toString(calendar.get(Calendar.DATE)));

+			infoElement.setAttribute("year", Integer.toString(calendar.get(Calendar.YEAR)));

+			infoElement.setAttribute("hour", Integer.toString(calendar.get(Calendar.HOUR)));

+			infoElement.setAttribute("minute", Integer.toString(calendar.get(Calendar.MINUTE)));

+			infoElement.setAttribute("second", Integer.toString(calendar.get(Calendar.SECOND)));

+

+			Properties systemProps = System.getProperties();

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

+			Set<Object> systemKeys = systemProps.keySet();

+

+			for (Object sysKey : systemKeys) {

+				if (sysKey instanceof String)

+					infoProps.put((String) sysKey, systemProps.get(sysKey));

+			}

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

+			infoElement.appendChild(propsElement);

+

+			getAlbumRootElement().appendChild(infoElement);

+			albumInfoSaved = true;

+		}

+	}

+

+	private void saveResourceList() {

+		if (!resourceListSaved) {

+			Element resourcesElement = document.createElement(RESOURCES);

+			for (IPath filePath : files) {

+				Element fileElement = document.createElement(FILE);

+				fileElement.setAttribute("path", filePath.toOSString());

+				resourcesElement.appendChild(fileElement);

+			}

+			getAlbumRootElement().appendChild(resourcesElement);

+			resourceListSaved = true;

+		}

+	}

+

+	private void saveSnapshotMetadata() {

+		if (!metadataSaved || isRecording()) {

+					

+			if (metadataSaved){

+				// If metatdata is saved, it must be a live debug session so

+				// we need to add a new snapshot to the snapshot list

+				NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

+				assert snapMetaDataNode.item(0) != null;

+				document.getDocumentElement().removeChild(snapMetaDataNode.item(0));

+			}

+			

+			Element metadataElement = document.createElement(METADATA);

+

+			Element albumElement = document.createElement(ALBUM);

+			albumElement.setAttribute("albumName", this.getDisplayName());

+			metadataElement.appendChild(albumElement);

+

+			Element snapshotsElement = document.createElement(SNAPSHOT_LIST);

+			metadataElement.appendChild(snapshotsElement);

+

+			for (Snapshot snap : snapshotList) {

+				Element snapshotMetadataElement = document.createElement(SNAPSHOT);

+				if (snap.getSnapshotDisplayName().length() == 0) {

+					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotFileName());

+				} else {

+					snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotDisplayName());

+				}

+				if (snap.getCreationDate() != null) {

+					snapshotMetadataElement.setAttribute("date", snap.getCreationDate().toString());

+				} else {

+					snapshotMetadataElement.setAttribute("date", "unknown");

+				}

+

+				snapshotMetadataElement.setAttribute("description", snap.getSnapshotDescription());

+				snapshotMetadataElement.setAttribute("fileName", snap.getSnapshotFileName());				

+				snapshotMetadataElement.setAttribute("referenceLocationSourceFile", snap.getReferenceLocationSourceFile());

+				snapshotMetadataElement.setAttribute("referenceLocationLineNumber", String.valueOf(snap.getReferenceLocationLineNumber()));

+				

+				snapshotsElement.appendChild(snapshotMetadataElement);

+			}

+			getAlbumRootElement().appendChild(metadataElement);

+			metadataSaved = true;

+		}

+	}

+

+	@SuppressWarnings("unchecked")

+	private void saveLaunchConfiguration() {

+		if (!launchConfigSaved) {

+			EDCLaunch launch = EDCLaunch.getLaunchForSession(getRecordingSessionID());

+			try {

+				Map<String, Object> map = launch.getLaunchConfiguration().getAttributes();

+				Element launchElement = document.createElement(LAUNCH);

+				launchType = launch.getLaunchConfiguration().getType().getIdentifier();

+				launchName = launch.getLaunchConfiguration().getName();

+				Integer count = launchNames.get(launchName);

+				if (count == null) {

+					launchNames.put(launchName, new Integer(0));

+				}

+				else {

+					count = new Integer(count.intValue() + 1);

+					launchNames.put(launchName, count);

+					launchName += " (" + count.toString() + ")";

+				}

+				launchElement.setAttribute("type", launchType);

+				launchElement.setAttribute("name", launchName);

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

+				launchElement.appendChild(propsElement);

+				getAlbumRootElement().appendChild(launchElement);

+			} catch (CoreException e) {

+				EDCDebugger.getMessageLogger().logError(null, e);

+			}

+			launchConfigSaved = true;

+		}

+	}

+

+	private static void addZipEntry(ZipOutputStream zipOut, IAlbumArchiveEntry entry, File file)

+			throws FileNotFoundException, IOException {

+		if (file.exists()) {

+			if (file.isDirectory()) {

+				for (File child : file.listFiles()) {

+					addZipEntry(zipOut, entry, child);

+				}

+			} else {

+				// Add ZIP entry to output stream.m

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

+

+				if (entry != null) {

+					path = entry.createEntryName(file);

+				} else {

+					path = file.getName();

+				}

+

+				zipOut.putNextEntry(new ZipEntry(path));

+

+				// Create a buffer for reading the files

+				byte[] buf = new byte[1024];

+

+				// Transfer bytes from the file to the ZIP file

+				// and compress the files

+				FileInputStream in = new FileInputStream(file);

+				int len;

+				while ((len = in.read(buf)) > 0) {

+					zipOut.write(buf, 0, len);

+				}

+

+				// Complete the entry

+				zipOut.closeEntry();

+				in.close();

+			}

+		}

+	}

+

+	/**

+	 * Create and write a full snapshot album from scratch

+	 */

+	private void saveAlbum(IProgressMonitor monitor) {

+

+		IPath zipPath = getLocation();

+		ZipOutputStream zipOut = null;

+		try {

+			SubMonitor progress = SubMonitor.convert(monitor, 2000 + (snapshotList.size() * 1000));

+			progress.subTask("Saving album data");

+

+			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));

+

+			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));

+

+			saveResourceList();

+			progress.worked(1000);

+			saveSnapshotMetadata();

+			progress.worked(1000);

+

+			String xml = LaunchManager.serializeDocument(document);

+			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$

+			zipOut.closeEntry();

+

+			for (Snapshot snap : snapshotList) {

+				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));

+				snap.saveSnapshot(zipOut);

+				progress.worked(1000);

+			}

+

+		} catch (Exception e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		} finally {

+			try {

+				if (zipOut != null) {

+					zipOut.close();

+				}

+			} catch (IOException e) {

+				e.printStackTrace();

+			}

+		}

+	}

+

+	/**

+	 * Create and write a full snapshot album from scratch

+	 */

+	private void saveResources(IProgressMonitor monitor) {

+

+		IPath zipPath = getLocation();

+		ZipOutputStream zipOut = null;

+		try {

+			// TODO: Here's we're just rewriting the entire album again

+			// Need to just add the resources alone using proper utils

+			zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile()));

+

+			for (IPath path : files) {

+

+				IAlbumArchiveEntry entry = new IAlbumArchiveEntry() {

+

+					public String createEntryName(File file) {

+						StringBuffer entryPath = new StringBuffer();

+

+						entryPath.append("Resources/");

+

+						IPath filepath = new Path(file.getAbsolutePath());

+

+						String deviceName = filepath.getDevice();

+						if (deviceName != null) {

+							// Remove the : from the end

+							entryPath.append(deviceName.substring(0, deviceName.length() - 1));

+							entryPath.append("/");

+						}

+						

+						String[] segments = filepath.segments();

+						int numSegments = segments.length - 1;

+

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

+							entryPath.append(segments[i]);

+							entryPath.append("/");

+						}

+						entryPath.append(file.getName());

+						return entryPath.toString();

+					}

+				};

+				addZipEntry(zipOut, entry, path.toFile());

+				if (monitor != null) {

+					monitor.worked(1);

+				}

+			}

+			zipOut.putNextEntry(new ZipEntry(ALBUM_DATA));

+

+			saveResourceList();

+			saveSnapshotMetadata();

+

+			String xml = LaunchManager.serializeDocument(document);

+			zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$

+			zipOut.closeEntry();

+

+			for (Snapshot snap : snapshotList) {

+				zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName()));

+				snap.saveSnapshot(zipOut);

+			}

+

+		} catch (Exception e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		} finally {

+			try {

+				if (zipOut != null) {

+					zipOut.close();

+				}

+			} catch (IOException e) {

+				e.printStackTrace();

+			}

+		}

+	}

+

+	private String getDefaultAlbumName() {

+		return getLaunchName();

+	}

+

+	public void saveAlbum(IPath path) throws TransformerException, IOException {

+		String xml = LaunchManager.serializeDocument(document);

+		File file = path.toFile();

+		if (!file.exists()) {

+			file.createNewFile();

+		}

+		FileOutputStream stream = new FileOutputStream(file);

+		stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$

+		stream.close();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openSnapshot(int)

+	 */

+	public void openSnapshot(final int index) {

+

+		final DsfSession session = DsfSession.getSession(sessionID);

+

+		DsfRunnable openIt = new DsfRunnable() {

+			public void run() {

+				currentSnapshotIndex = index;

+				try {

+					loadAlbum(false);

+				} catch (Exception e) {

+					EDCDebugger.getMessageLogger().logError(null, e);

+				}

+				if (session != null && snapshotList.size() > index) {

+					Snapshot snapshot = snapshotList.get(index);

+					snapshot.open(session);

+					// Fire the event

+					for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {

+						l.snapshotOpened(snapshot);

+					}

+				}

+			}

+		};

+

+		if (session != null && session.getExecutor() != null)

+		{

+			if (session.getExecutor().isInExecutorThread())

+				openIt.run();

+			else

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

+		}

+

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getCurrentSnapshotIndex()

+	 */

+	public int getCurrentSnapshotIndex() {

+		return currentSnapshotIndex;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openNextSnapshot()

+	 */

+	public void openNextSnapshot() throws Exception {

+		int nextIndex = currentSnapshotIndex + 1;

+		if (nextIndex >= snapshotList.size())

+			nextIndex = 0;

+		openSnapshot(nextIndex);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openPreviousSnapshot()

+	 */

+	public void openPreviousSnapshot() throws Exception {

+		int previousIndex = currentSnapshotIndex - 1;

+		if (previousIndex < 0)

+			previousIndex = snapshotList.size() - 1;

+		openSnapshot(previousIndex);

+	}

+

+	public void loadAlbum(boolean force) throws ParserConfigurationException, SAXException, IOException {

+		if (force)

+			loaded = false;

+		if (!loaded) {

+			File albumFile = location.toFile();

+			setName(albumFile.getName());

+			

+			if (!isRecording()){

+				// not creating the snapshot, so must be snapshot play back	

+				try {

+					ZipFileUtils.unzipFiles(albumFile, getAlbumRootDirectory().toOSString(), new NullProgressMonitor());

+				} catch (Exception e) {

+					EDCDebugger.getMessageLogger().logError(null, e);

+				}

+			}

+

+			BufferedInputStream stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);

+			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();

+			parser.setErrorHandler(new DefaultHandler());

+			InputSource inputSource = new InputSource(stream);

+			inputSource.setSystemId(albumFile.toURI().toString());	// avoid NPE inside XML parser

+			setDocument(parser.parse(inputSource));

+

+			loadAlbumInfo();

+			loadLaunchConfiguration();

+			loadResourceList();

+			try {

+				loadSnapshotMetadata();

+			} catch (Exception e) {

+				e.printStackTrace();

+			} finally {

+				loaded = true;

+				ZipFileUtils.unmount();

+			}

+		}

+	}

+

+	/**

+	 * A lightwieght parse to get basic album info and what snapshots are

+	 * available.

+	 * 

+	 * @throws ParserConfigurationException

+	 * @throws SAXException

+	 * @throws IOException

+	 */

+	public void loadAlbumMetada(boolean force) throws Exception {

+		if (force)

+			metaDataLoaded = false;

+		if (!metaDataLoaded) {

+			

+			File albumFile = location.toFile();

+			setDisplayName(albumFile.getName());

+

+			BufferedInputStream stream = null;

+			try {

+				stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS);

+				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();

+				parser.setErrorHandler(new DefaultHandler());

+				setDocument(parser.parse(new InputSource(stream)));

+				loadSnapshotMetadata();

+				loadLaunchConfiguration(); // need to load launch config in case we need to delete it

+

+			} catch (Exception e) {

+				EDCDebugger.getMessageLogger().logError("Failed to load album: " + getName(), e);

+			} finally {

+				metaDataLoaded = true;

+				ZipFileUtils.unmount();

+			}

+		}

+	}

+

+	private void loadAlbumInfo() {

+		document.getElementsByTagName(INFO).item(0);

+	}

+

+	private void setDocument(Document newDoc)

+	{

+		document = newDoc;

+		albumRootElement = null;

+	}

+	

+	private Element getAlbumRootElement()

+	{

+		if (albumRootElement == null)

+		{

+			NodeList albumRootElements = document.getElementsByTagName(ALBUM);

+			if (albumRootElements.getLength() == 0)

+			{

+				albumRootElement = document.createElement(ALBUM);

+				document.appendChild(albumRootElement);

+			}

+			else

+			{

+				albumRootElement = (Element) albumRootElements.item(0);

+			}

+		}

+		return albumRootElement;

+	}

+	

+	private void loadResourceList() {

+		NodeList resources = document.getElementsByTagName(RESOURCES);

+		NodeList elementFiles = ((Element) resources.item(0)).getElementsByTagName(FILE);

+		int numFiles = elementFiles.getLength();

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

+			Element fileElement = (Element) elementFiles.item(i);

+			String elementPath = fileElement.getAttribute("path");

+			files.add(PathUtils.createPath(elementPath));		// for cross-created snapshot

+		}

+	}

+

+	private void loadSnapshotMetadata() throws Exception {

+		snapshotList.clear();

+		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

+

+		if (snapMetaDataNode.getLength() == 0) {

+			throw new Exception("Invalid or corrupted Album : " + getName());

+		}

+		NodeList albumNameElement = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);

+		Element albumElement = (Element) albumNameElement.item(0);

+		String albumDisplayName = albumElement.getAttribute("albumName");

+

+		setDisplayName(albumDisplayName);

+

+		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);

+		int numSnapshots = elementSnapshots.getLength();

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

+			Element snapshotElement = (Element) elementSnapshots.item(i);

+			String elementDescription = snapshotElement.getAttribute("description");

+			String elementDate = snapshotElement.getAttribute("date");

+			String elementDispalyName = snapshotElement.getAttribute("displayName");

+			String elementFileName = snapshotElement.getAttribute("fileName");

+			String referenceLocationSourceFile = snapshotElement.getAttribute("referenceLocationSourceFile");

+			String referenceLocationLineNumber = snapshotElement.getAttribute("referenceLocationLineNumber");

+			

+			Snapshot s = new Snapshot(this);

+			s.setCreationDate(elementDate);

+			s.setSnapshotFileName(elementFileName);

+			s.setSnapshotDisplayName(elementDispalyName);

+			s.setSnapshotDescription(elementDescription);

+			if (referenceLocationLineNumber.length() > 0){

+				s.setReferenceLocationLineNumber(Long.parseLong(referenceLocationLineNumber));

+			}

+			s.setReferenceLocationSourceFile(referenceLocationSourceFile);

+			snapshotList.add(s);

+		}

+	}

+

+	private void loadLaunchConfiguration() {

+		NodeList launchElements = document.getElementsByTagName(LAUNCH);

+		Element launchElement = (Element) launchElements.item(0);

+		if (launchElement == null){

+			return;

+		}

+		launchType = launchElement.getAttribute("type");

+		launchName = launchElement.getAttribute("name");

+

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

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

+		try {

+			SnapshotUtils.initializeFromXML(propElement, launchProperties);

+		} catch (Exception e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+

+	}

+

+	@SuppressWarnings("rawtypes")

+	@Override

+	public Object getAdapter(Class adapter) {

+		if (adapter.equals(Document.class))

+			return document;

+

+		return super.getAdapter(adapter);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getAlbumRootDirectory()

+	 */

+	public IPath getAlbumRootDirectory() {

+		if (albumRootDirectory == null) {

+			IPath path = EDCDebugger.getDefault().getStateLocation().append("SnapshotAlbums");

+			String locationName = location.lastSegment();

+			int extension = locationName.lastIndexOf(".");

+			if (extension > 0) {

+				locationName = locationName.substring(0, extension);

+			}

+			path = path.append(locationName);

+			File dir = path.toFile();

+			if (!dir.exists()) {

+				dir.mkdirs();

+			}

+			albumRootDirectory = path;

+		}

+		return albumRootDirectory;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchTypeID()

+	 */

+	public String getLaunchTypeID() {

+		return launchType;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchProperties()

+	 */

+	public HashMap<String, Object> getLaunchProperties() {

+		return launchProperties;

+	}

+

+	public void setLaunchProperties(HashMap<String, Object> launchProperties) {

+		this.launchProperties = launchProperties;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchName()

+	 */

+	public String getLaunchName() {

+		return launchName;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#playSnapshots(org.eclipse.cdt.dsf.service.DsfSession)

+	 */

+	public void playSnapshots() {

+		if (!isPlayingSnapshots()) {

+			Job playSnapshotsJob = new Job("Play Snapshots for Album " + getDisplayName()){

+

+				@Override

+				protected IStatus run(IProgressMonitor monitor) {

+					try {

+						monitor.beginTask("Play Snapshots for Album " + getDisplayName(), IProgressMonitor.UNKNOWN);

+						while (isPlayingSnapshots() && !monitor.isCanceled())

+						{

+							Album.this.openNextSnapshot();

+							Thread.sleep(getPlaySnapshotInterval());

+						}

+						setPlayingSnapshots(false);

+						monitor.done();

+					} catch (Exception e) {

+						EDCDebugger.getMessageLogger().logError(null, e);

+						return new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, null, e);

+					}

+					return Status.OK_STATUS;

+				}

+				

+			};

+			setPlayingSnapshots(true);

+			playSnapshotsJob.schedule();

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#addFile(org.eclipse.core.runtime.IPath)

+	 */

+	public void addFile(IPath path) {

+		files.add(path);

+	}

+

+	public static Album getAlbumByLocation(IPath path) {

+		return albumsByLocation.get(path);

+	}

+

+	public static IAlbum getAlbumBySession(String sessionId) {

+		return albumsBySessionID.get(sessionId);

+	}

+

+	public static Album getRecordingForSession(String sessionId) {

+		return albumsRecordingBySessionID.get(sessionId);

+	}

+

+	public void setLocation(IPath albumPath) {

+		this.location = albumPath;

+		albumsByLocation.put(albumPath, this);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLocation()

+	 */

+	public IPath getLocation() {

+		return location;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureSourceLookupDirector(org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector)

+	 */

+	public void configureSourceLookupDirector(ISourceLookupDirector director) {

+		MappingSourceContainer sourceContainer = new MappingSourceContainer(getName());

+		configureMappingSourceContainer(sourceContainer);

+		ArrayList<ISourceContainer> containers = new ArrayList<ISourceContainer>(Arrays.asList(director

+				.getSourceContainers()));

+		containers.add(sourceContainer);

+

+		DirectorySourceContainer directoryContainer = new DirectorySourceContainer(getResourcesDirectory(), true);

+		containers.add(directoryContainer);

+

+		director.setSourceContainers(containers.toArray(new ISourceContainer[containers.size()]));

+	}

+

+	protected IPath getResourcesDirectory() {

+		return getAlbumRootDirectory().append("Resources");

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureMappingSourceContainer(org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer)

+	 */

+	public void configureMappingSourceContainer(MappingSourceContainer mappingContainer) {

+		IPath albumRoot = getResourcesDirectory();

+		List<MapEntrySourceContainer> containers = new ArrayList<MapEntrySourceContainer>();

+		Set<String> devicesAlreadyAdded = new HashSet<String>();

+		String deviceName = null;

+		for (IPath iPath : files) {

+			deviceName = iPath.getDevice();

+			if (deviceName != null && !devicesAlreadyAdded.contains(deviceName)) {

+				String albumRootSuffix = deviceName;

+				if (albumRootSuffix.endsWith(":"))

+					albumRootSuffix = albumRootSuffix.substring(0, albumRootSuffix.length() - 1);

+				devicesAlreadyAdded.add(deviceName);

+				MapEntrySourceContainer newContainer = new MapEntrySourceContainer(PathUtils.createPath(deviceName), albumRoot.append(albumRootSuffix));

+				containers.add(newContainer);

+

+			}

+		}

+		mappingContainer.addMapEntries(containers.toArray(new MapEntrySourceContainer[containers.size()]));

+	}

+

+	public static void setResolveOpaqueType(boolean newSetting) {

+		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+		scope.putBoolean(PREF_RESOLVE_OPAQUE_TYPE, newSetting);

+		try {

+			scope.flush();

+		} catch (BackingStoreException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+	}

+

+	public static boolean getResolveOpaqueType() {

+		return Platform.getPreferencesService().getBoolean(EDCDebugger.PLUGIN_ID,

+				PREF_RESOLVE_OPAQUE_TYPE, false, null);

+	}

+

+	public static void setVariableCaptureDepth(int newSetting) {

+		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+		scope.putInt(PREF_VARIABLE_CAPTURE_DEPTH, newSetting);

+		try {

+			scope.flush();

+		} catch (BackingStoreException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+	}

+

+	public static int getVariableCaptureDepth() {

+		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,

+				PREF_VARIABLE_CAPTURE_DEPTH, 5, null);

+	}

+

+	public static void setPlaySnapshotInterval(int delayInMilliseconds) {

+		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+		scope.putInt(PLAY_SNAPSHOT_DELAY_TIME, delayInMilliseconds);

+		try {

+			scope.flush();

+		} catch (BackingStoreException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+	}

+

+	public static int getPlaySnapshotInterval() {

+		return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID,

+				PLAY_SNAPSHOT_DELAY_TIME, 5000, null);

+	}

+

+	public static void setSnapshotCreationControl(String newSetting) {

+		IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+		scope.put(PREF_CREATION_CONTROL, newSetting);

+		try {

+			scope.flush();

+		} catch (BackingStoreException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+	}

+

+	public static String getSnapshotCreationControl() {

+		return Platform.getPreferencesService().getString(EDCDebugger.PLUGIN_ID,

+				PREF_CREATION_CONTROL, CREATE_MANUAL, null);

+	}

+

+	protected static void playSnapshotSound() {

+		Bundle bundle = Platform.getBundle(EDCDebugger.getUniqueIdentifier());

+		if (bundle == null)

+			return;

+		

+		URL url = null;

+		try {

+			url = FileLocator.toFileURL(bundle.getEntry(CAMERA_CLICK_WAV));

+		} catch (IOException e) {

+		} catch (RuntimeException e){

+		}

+		finally {

+			if (url != null){

+				File f = new File(url.getFile());

+				SnapshotUtils.playSoundFile(f);

+			}

+		}

+		

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSnapshots()

+	 */

+	public List<Snapshot> getSnapshots() {

+		if (snapshotList == null || snapshotList.size() == 0) {

+			try {

+				loadAlbumMetada(false);

+			} catch (Exception e) {

+				EDCDebugger.getMessageLogger().logError("Failed to load snapshots", e);

+			}

+		}

+

+		return snapshotList;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isLoaded()

+	 */

+	public boolean isLoaded() {

+		return loaded;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getIndexOfSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)

+	 */

+	public int getIndexOfSnapshot(Snapshot snap) {

+		return snapshotList.indexOf(snap);

+	}

+

+	public void setCurrentSnapshotIndex(int index) {

+		if (currentSnapshotIndex >= 0 && currentSnapshotIndex < snapshotList.size()) {

+			currentSnapshotIndex = index;

+		}

+	}

+

+	/**

+	 * Update album.xml within the Album's .dsa file with new Snapshot data

+	 * 

+	 * @param albumName

+	 *            - Name of album to display. Use null if value should not be

+	 *            updated.

+	 * @param snap

+	 *            - Specific snapshot to update. Use null is snapshot should not

+	 *            be updated.

+	 */

+	public void updateSnapshotMetaData(String albumName, Snapshot snap) {

+		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

+		

+		// try to update album display name

+		if (albumName != null) {

+			NodeList albumNameNode = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM);

+			((Element) albumNameNode.item(0)).setAttribute("albumName", albumName);

+		}

+

+		// try to update snapshot data

+		if (snap != null) {

+

+			NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);

+

+			int numSnapshots = elementSnapshots.getLength();

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

+				Element currentSnapshotNode = (Element) elementSnapshots.item(i);

+				String fileName = currentSnapshotNode.getAttribute("fileName");

+				if (fileName.equals(snap.getSnapshotFileName())) {

+

+					currentSnapshotNode.setAttribute("description", snap.getSnapshotDescription());

+					currentSnapshotNode.setAttribute("displayName", snap.getSnapshotDisplayName());

+

+					break;

+				}

+			}

+		}

+

+		saveAlbumData();

+

+		// refresh all data

+		try {

+			loadAlbumMetada(true);

+		} catch (Exception e) {

+			e.printStackTrace();

+		}

+

+	}

+

+	private void saveAlbumData() {

+		try {

+			File tempFile = File.createTempFile("album", ".xml");

+			File tempFile2 = new File(tempFile.getParent() + File.separator + ALBUM_DATA);

+			tempFile.delete();

+			if (!tempFile2.exists()) {

+				tempFile2.delete();

+			}

+			tempFile2.createNewFile();

+			saveAlbum(new Path(tempFile2.toString()));

+			File[] fileList = { tempFile2 };

+			ZipFileUtils.addFilesToZip(fileList, getLocation().toFile(), DSA_FILE_EXTENSIONS);

+

+		} catch (IOException e) {

+			e.printStackTrace();

+		} catch (TransformerException e) {

+			e.printStackTrace();

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#deleteSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot)

+	 */

+	public void deleteSnapshot(Snapshot snap) {

+

+		NodeList snapMetaDataNode = document.getElementsByTagName(METADATA);

+

+		NodeList elementSnapshotList = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT_LIST);

+		NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT);

+

+		int numSnapshots = elementSnapshots.getLength();

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

+			Element currentSnapshotNode = (Element) elementSnapshots.item(i);

+			String fileName = currentSnapshotNode.getAttribute("fileName");

+			if (fileName.equals(snap.getSnapshotFileName())) {

+				elementSnapshotList.item(0).removeChild(currentSnapshotNode);

+				break;

+			}

+		}

+

+		snapshotList.remove(snap);

+

+		saveAlbumData();

+

+		// refresh all data

+		try {

+			loadAlbum(true);

+			loadAlbumMetada(true);

+		} catch (Exception e) {

+

+		}

+

+		ZipFileUtils.deleteFileFromZip(snap.getSnapshotFileName(), getLocation().toFile(), DSA_FILE_EXTENSIONS);

+	}

+

+	@Override

+	public String toString() {

+		return "Album [name=" + name + ", launchName=" + launchName + ", sessionID=" + sessionID + "]";

+	}

+	

+	public IPath createEmptyAlbum() {

+		IPath zipPath = null;

+		try {

+			zipPath = SnapshotUtils.getSnapshotsProject().getLocation();

+			zipPath = zipPath.append(getDefaultAlbumName());

+			zipPath = zipPath.addFileExtension("dsa");

+			boolean created =  ZipFileUtils.createNewZip(zipPath.toFile());

+			

+			if (created && zipPath.toFile().exists()){

+				setLocation(zipPath);

+			} else {

+				return null;

+			}

+			SnapshotUtils.getSnapshotsProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());

+		} catch (CoreException e) {

+			EDCDebugger.getMessageLogger().logError(e.getLocalizedMessage(), e);

+		}		

+		return zipPath;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isRecording()

+	 */

+	public boolean isRecording() {

+		return recordingSessionID.length() > 0;

+	}

+

+	/**

+	 * @noreference This method is not intended to be referenced by clients.

+	 */

+	public static void addSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {

+		listeners.add(listener);

+	}

+	

+	/**

+	 * @noreference This method is not intended to be referenced by clients.

+	 */

+	public static void removeSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) {

+		listeners.remove(listener);

+	}

+

+	public static void captureSnapshotForSession(final DsfSession session) {

+		Job createSnapshotJob = new Job("Creating Debug Snapshot") {

+

+			@Override

+			protected IStatus run(final IProgressMonitor monitor) {

+

+				Query<IFrameDMContext> frameQuery = new Query<IFrameDMContext>() {

+					@Override

+					protected void execute(

+							DataRequestMonitor<IFrameDMContext> rm) {

+						DsfServicesTracker servicesTracker = new DsfServicesTracker(

+								EDCDebugger.getBundleContext(),

+								session.getId());

+						try {

+							RunControl runControl = servicesTracker.getService(RunControl.class);

+							IThreadDMContext[] suspendedThreads = runControl.getSuspendedThreads();

+							if (suspendedThreads.length == 0)

+							{

+								rm.setData(null);

+								rm.done();

+							}

+							else

+							{

+								Stack stackService = servicesTracker.getService(Stack.class);

+								if (stackService != null) {

+									stackService.getTopFrame(suspendedThreads[0], rm);

+								}

+							}

+						} finally {

+							servicesTracker.dispose();

+						}

+					}

+				};

+

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

+

+				IStatus status = Status.OK_STATUS;

+				try {

+					final StackFrameDMC stackFrame = (StackFrameDMC) frameQuery.get();

+

+					String sessionId = session.getId();

+					Album album = Album.getRecordingForSession(sessionId);

+					if (album == null) {

+						album = new Album();

+						album.setRecordingSessionID(sessionId);

+					}

+					final Album finalAlbum = album;

+					playSnapshotSound();

+

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

+						@Override

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

+							try {

+								Snapshot newSnapshot = finalAlbum.createSnapshot(session, stackFrame, monitor);

+								// Fire the event to anyone listening

+								for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) {

+									l.snapshotCreated(finalAlbum, newSnapshot, session, stackFrame);

+								}

+								drm.setData(Status.OK_STATUS);

+							} catch (Exception e) {

+								Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error creating snapshot.", e);

+								EDCDebugger.getMessageLogger().log(s);

+								drm.setStatus(s);

+							}

+							drm.done();

+						}

+					};

+

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

+

+					status = query.get();

+				} catch (Exception e) {

+					status = new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, "Error creating snapshot", e);

+				}

+

+				return status;

+			}

+		};

+

+		createSnapshotJob.schedule();

+	}

+

+    public boolean isPlayingSnapshots() {

+		return playingSnapshots;

+	}

+

+	public void setPlayingSnapshots(boolean playingSnapshots) {

+		this.playingSnapshots = playingSnapshots;

+	}

+

+	public void stopPlayingSnapshots() {

+		setPlayingSnapshots(false);

+		openSnapshot(getCurrentSnapshotIndex()); // Reloading the current snapshot will resync the UI.

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Snapshot.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Snapshot.java
index 2b44aa4..d73b1c2 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Snapshot.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/snapshot/Snapshot.java
@@ -1,305 +1,303 @@
-/*******************************************************************************
- * 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.internal.snapshot;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.Date;
-import java.util.zip.ZipOutputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.TransformerException;
-
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.ZipFileUtils;
-import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
-import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.dsf.service.IDsfService;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.PlatformObject;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.internal.core.LaunchManager;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.helpers.DefaultHandler;
-
-@SuppressWarnings("restriction")
-public class Snapshot extends PlatformObject {
-	
-	// XML elements
-	public static final String SNAPSHOT = "snapshot";
-	
-	public static final String SNAPSHOT_FILENAME_PREFIX = "snapshot_";
-	
-	private Document document;
-	private Element snapshotRootElement;
-	private DsfSession session;
-	private Album album;
-	private String snapshotFileName;
-	private String snapshotDisplayName;
-
-	private String creationDate;
-
-	private String snapshotDescription;
-	
-	// Reference location information: when a snapshot is created
-	// we record the location in the most recently suspended stack frame.
-	// This is then used to create a default name for the snapshot and
-	// is displayed in the snapshot view.
-	// Of course, when debugging multiple contexts this does not
-	// provide a complete description of the snapshot.
-	
-	private String referenceLocationSourceFile = "";
-	private long referenceLocationLineNumber;
-	
-	/*
-	 * Create a snapshot for reading
-	 */
-	public Snapshot(Album album){
-		try {
-			this.album = album;
-			document = DebugPlugin.newDocument();
-			snapshotRootElement = document.createElement(SNAPSHOT);
-		} catch (CoreException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	/**
-	 * Create a snapshot with prep for writing to file.
-	 * @param album
-	 * @param recentStackFrame - 
-	 */
-	public Snapshot(Album album, DsfSession session, StackFrameDMC recentStackFrame){
-		try {
-			assert session != null;
-			
-			this.album = album;
-			this.session = session;
-			document = DebugPlugin.newDocument();
-			snapshotRootElement = document.createElement(SNAPSHOT);
-			document.appendChild(snapshotRootElement);
-			
-			if (recentStackFrame == null){
-				snapshotDisplayName = snapshotFileName;
-			} else {
-				snapshotDisplayName = createSnapshotNameFromStackFrameDMC(recentStackFrame);
-			}
-			snapshotFileName = SNAPSHOT_FILENAME_PREFIX + System.currentTimeMillis() + ".xml";
-			creationDate = new Date(System.currentTimeMillis()).toString();
-			
-			if (recentStackFrame != null){
-				File f = new File(recentStackFrame.getSourceFile());
-				if (f != null){
-					setReferenceLocationSourceFile(f.getName());
-				} 
-				setReferenceLocationLineNumber(recentStackFrame.getLineNumber());
-			}
-			
-		} catch (CoreException e) {
-			e.printStackTrace();
-		}
-		
-	}
-
-	@SuppressWarnings("rawtypes")
-	@Override
-	public Object getAdapter(Class adapter) {
-		if (adapter.equals(Document.class))
-			return document;
-
-		return super.getAdapter(adapter);
-	}
-	
-	private static String getServiceFilter(String sessionId) {
-		return ("(" + IDsfService.PROP_SESSION_ID + "=" + sessionId + ")").intern(); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
-	}
-
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	public void open(DsfSession session) {
-		ServiceReference[] references;
-		BufferedInputStream stream = null;
-		try {
-			
-			stream = ZipFileUtils.openFile(album.getLocation().toFile(), snapshotFileName, new String[] {"dsa"} );
-			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-			parser.setErrorHandler(new DefaultHandler());
-			
-			document = parser.parse(new InputSource(stream));
-			NodeList snapNode = document.getElementsByTagName(SNAPSHOT);
-			Element snapShotE = (Element)snapNode.item(0);
-			
-			references = EDCDebugger.getBundleContext().getServiceReferences(ISnapshotContributor.class.getName(),
-					getServiceFilter(session.getId()));
-			for (ServiceReference serviceReference : references) {
-				ISnapshotContributor sc = (ISnapshotContributor) EDCDebugger.getBundleContext().getService(
-						serviceReference);
-				sc.loadSnapshot(snapShotE);
-			}
-			
-		} catch (Exception e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		} finally {
-			ZipFileUtils.unmount();
-		}
-	}
-	
-	/**
-	 * Write snapshot data.
-	 *
-	 * @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
-        to call done() on the given monitor. Accepts null, indicating that no progress should be
-        reported and that the operation cannot be canceled.
-	 */
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	public void writeSnapshotData(IProgressMonitor monitor) throws Exception{
-		try {
-			ServiceReference[] references = EDCDebugger.getBundleContext().getServiceReferences(
-					ISnapshotContributor.class.getName(), getServiceFilter(session.getId()));
-			SubMonitor progress = SubMonitor.convert(monitor, references.length * 1000);
-			progress.subTask("Writing snapshot data");
-			for (ServiceReference serviceReference : references) {
-				if (progress.isCanceled())
-					break;
-				ISnapshotContributor sc = (ISnapshotContributor) EDCDebugger.getBundleContext().getService(
-						serviceReference);
-				Element serviceElement = sc.takeSnapshot(album, document, progress.newChild(1000));
-				if (serviceElement != null)
-					snapshotRootElement.appendChild(serviceElement);
-			}
-		} catch (InvalidSyntaxException e) {
-			EDCDebugger.getMessageLogger().logError("Invalid session ID syntax", e); //$NON-NLS-1$
-		} catch (IllegalStateException e) {
-			EDCDebugger.getMessageLogger().logError(null, e);
-		}
-	}
-	
-	public String getSnapshotFileName(){
-		return snapshotFileName;
-	}
-	
-	public void setSnapshotFileName(String snapshotFileName){
-		this.snapshotFileName = snapshotFileName;
-	}
-	
-	public void saveSnapshot(ZipOutputStream zipOut) throws TransformerException, IOException {
-		String xml = LaunchManager.serializeDocument(document);
-		zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$
-		zipOut.closeEntry();
-	}
-	
-	public String getCreationDate(){
-		return creationDate;
-	}
-	
-	public void setCreationDate(String date){
-		this.creationDate = date;
-	}
-
-	/**
-	 * Set the display text for the snapshot
-	 * @param snapshotDisplayName
-	 */
-	public void setSnapshotDisplayName(String snapshotDisplayName) {
-		this.snapshotDisplayName = snapshotDisplayName;
-	}
-
-	/**
-	 * Get the display name of the snapshot. If there is no display name, the XML file containing
-	 * the snapshot data in the DSA archive will be used.
-	 * @return
-	 */
-	public String getSnapshotDisplayName() {
-		if (snapshotDisplayName == null || snapshotDisplayName.length() == 0){
-			snapshotDisplayName = snapshotFileName;
-		}
-		return snapshotDisplayName;
-	}
-	
-	/**
-	 * Additional arbitrary notes to describe a particular snapshot
-	 * @return
-	 */
-	public String getSnapshotDescription() {
-		if (snapshotDescription == null){
-			snapshotDescription = "";
-		}
-		return snapshotDescription;
-	}
-	
-	/**
-	 * Set the snapshot description text.
-	 * @param descr
-	 */
-	public void setSnapshotDescription(String descr) {
-		snapshotDescription = descr;
-	}
-	
-	/**
-	 * Get the album this snapshot belongs to
-	 * @return
-	 */
-	public Album getAlbum(){
-		return album;
-	}
-	
-	/**
-	 * Creates the snapshot name from a stack frame dmc.
-	 * 
-	 * @param frameDMC the frame dmc
-	 * 
-	 * @return the snapshot name
-	 */
-	public String createSnapshotNameFromStackFrameDMC(StackFrameDMC stackFrame)
-	{
-		assert stackFrame != null;
-		StringBuilder name = new StringBuilder();
-		if (stackFrame.getFunctionName() != null && stackFrame.getFunctionName().length() != 0) {
-			name.append(stackFrame.getFunctionName());
-			name.append("() : "); //$NON-NLS-1$
-			name.append(stackFrame.getLineNumber());
-		} else if (stackFrame.getModuleName() != null && stackFrame.getModuleName().length() != 0) {
-			name.append(stackFrame.getModuleName());
-		} else if (stackFrame.getInstructionPtrAddress() != null) {
-			name.append(stackFrame.getInstructionPtrAddress().toHexAddressString());
-		}
-
-		return name.toString();	
-	}
-
-	public void setReferenceLocationSourceFile(String referenceLocationSourceFile) {
-		assert referenceLocationSourceFile != null;
-		this.referenceLocationSourceFile = referenceLocationSourceFile;
-	}
-
-	public String getReferenceLocationSourceFile() {
-		assert referenceLocationSourceFile != null;
-		return referenceLocationSourceFile;
-	}
-
-	public void setReferenceLocationLineNumber(long referenceLocationLineNumber) {
-		this.referenceLocationLineNumber = referenceLocationLineNumber;
-	}
-
-	public long getReferenceLocationLineNumber() {
-		return referenceLocationLineNumber;
-	}
-	
-}
+/*******************************************************************************

+ * 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.internal.snapshot;

+

+import java.io.BufferedInputStream;

+import java.io.File;

+import java.io.IOException;

+import java.util.Date;

+import java.util.zip.ZipOutputStream;

+

+import javax.xml.parsers.DocumentBuilder;

+import javax.xml.parsers.DocumentBuilderFactory;

+import javax.xml.transform.TransformerException;

+

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

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

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

+import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;

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

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

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

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

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

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

+import org.eclipse.debug.core.DebugPlugin;

+import org.eclipse.debug.internal.core.LaunchManager;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceReference;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.NodeList;

+import org.xml.sax.InputSource;

+import org.xml.sax.helpers.DefaultHandler;

+

+@SuppressWarnings({ "restriction", "rawtypes", "unchecked" })

+

+public class Snapshot extends PlatformObject {

+	

+	// XML elements

+	public static final String SNAPSHOT = "snapshot";

+	

+	public static final String SNAPSHOT_FILENAME_PREFIX = "snapshot_";

+	

+	private Document document;

+	private Element snapshotRootElement;

+	private DsfSession session;

+	private Album album;

+	private String snapshotFileName;

+	private String snapshotDisplayName;

+

+	private String creationDate;

+

+	private String snapshotDescription;

+	

+	// Reference location information: when a snapshot is created

+	// we record the location in the most recently suspended stack frame.

+	// This is then used to create a default name for the snapshot and

+	// is displayed in the snapshot view.

+	// Of course, when debugging multiple contexts this does not

+	// provide a complete description of the snapshot.

+	

+	private String referenceLocationSourceFile = "";

+	private long referenceLocationLineNumber;

+	

+	/*

+	 * Create a snapshot for reading

+	 */

+	public Snapshot(Album album){

+		try {

+			this.album = album;

+			document = DebugPlugin.newDocument();

+			snapshotRootElement = document.createElement(SNAPSHOT);

+		} catch (CoreException e) {

+			e.printStackTrace();

+		}

+	}

+	

+	/**

+	 * Create a snapshot with prep for writing to file.

+	 * @param album

+	 * @param recentStackFrame - 

+	 */

+	public Snapshot(Album album, DsfSession session, StackFrameDMC recentStackFrame){

+		try {

+			assert session != null;

+			

+			this.album = album;

+			this.session = session;

+			document = DebugPlugin.newDocument();

+			snapshotRootElement = document.createElement(SNAPSHOT);

+			document.appendChild(snapshotRootElement);

+			

+			if (recentStackFrame == null){

+				snapshotDisplayName = snapshotFileName;

+			} else {

+				snapshotDisplayName = createSnapshotNameFromStackFrameDMC(recentStackFrame);

+			}

+			snapshotFileName = SNAPSHOT_FILENAME_PREFIX + System.currentTimeMillis() + ".xml";

+			creationDate = new Date(System.currentTimeMillis()).toString();

+			

+			if (recentStackFrame != null){

+				File f = new File(recentStackFrame.getSourceFile());

+				if (f != null){

+					setReferenceLocationSourceFile(f.getName());

+				} 

+				setReferenceLocationLineNumber(recentStackFrame.getLineNumber());

+			}

+			

+		} catch (CoreException e) {

+			e.printStackTrace();

+		}

+		

+	}

+

+	@Override

+	public Object getAdapter(Class adapter) {

+		if (adapter.equals(Document.class))

+			return document;

+

+		return super.getAdapter(adapter);

+	}

+	

+	private static String getServiceFilter(String sessionId) {

+		return ("(" + IDsfService.PROP_SESSION_ID + "=" + sessionId + ")").intern(); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$

+	}

+

+	public void open(DsfSession session) {

+		ServiceReference[] references;

+		BufferedInputStream stream = null;

+		try {

+			

+			stream = ZipFileUtils.openFile(album.getLocation().toFile(), snapshotFileName, new String[] {"dsa"} );

+			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();

+			parser.setErrorHandler(new DefaultHandler());

+			

+			document = parser.parse(new InputSource(stream));

+			NodeList snapNode = document.getElementsByTagName(SNAPSHOT);

+			Element snapShotE = (Element)snapNode.item(0);

+			

+			references = EDCDebugger.getBundleContext().getServiceReferences(ISnapshotContributor.class.getName(),

+					getServiceFilter(session.getId()));

+			for (ServiceReference serviceReference : references) {

+				ISnapshotContributor sc = (ISnapshotContributor) EDCDebugger.getBundleContext().getService(

+						serviceReference);

+				sc.loadSnapshot(snapShotE);

+			}

+			

+		} catch (Exception e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		} finally {

+			ZipFileUtils.unmount();

+		}

+	}

+	

+	/**

+	 * Write snapshot data.

+	 *

+	 * @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility

+        to call done() on the given monitor. Accepts null, indicating that no progress should be

+        reported and that the operation cannot be canceled.

+	 */

+	public void writeSnapshotData(IProgressMonitor monitor) throws Exception{

+		try {

+			ServiceReference[] references = EDCDebugger.getBundleContext().getServiceReferences(

+					ISnapshotContributor.class.getName(), getServiceFilter(session.getId()));

+			SubMonitor progress = SubMonitor.convert(monitor, references.length * 1000);

+			progress.subTask("Writing snapshot data");

+			for (ServiceReference serviceReference : references) {

+				if (progress.isCanceled())

+					break;

+				ISnapshotContributor sc = (ISnapshotContributor) EDCDebugger.getBundleContext().getService(

+						serviceReference);

+				Element serviceElement = sc.takeSnapshot(album, document, progress.newChild(1000));

+				if (serviceElement != null)

+					snapshotRootElement.appendChild(serviceElement);

+			}

+		} catch (InvalidSyntaxException e) {

+			EDCDebugger.getMessageLogger().logError("Invalid session ID syntax", e); //$NON-NLS-1$

+		} catch (IllegalStateException e) {

+			EDCDebugger.getMessageLogger().logError(null, e);

+		}

+	}

+	

+	public String getSnapshotFileName(){

+		return snapshotFileName;

+	}

+	

+	public void setSnapshotFileName(String snapshotFileName){

+		this.snapshotFileName = snapshotFileName;

+	}

+	

+	public void saveSnapshot(ZipOutputStream zipOut) throws TransformerException, IOException {

+		String xml = LaunchManager.serializeDocument(document);

+		zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$

+		zipOut.closeEntry();

+	}

+	

+	public String getCreationDate(){

+		return creationDate;

+	}

+	

+	public void setCreationDate(String date){

+		this.creationDate = date;

+	}

+

+	/**

+	 * Set the display text for the snapshot

+	 * @param snapshotDisplayName

+	 */

+	public void setSnapshotDisplayName(String snapshotDisplayName) {

+		this.snapshotDisplayName = snapshotDisplayName;

+	}

+

+	/**

+	 * Get the display name of the snapshot. If there is no display name, the XML file containing

+	 * the snapshot data in the DSA archive will be used.

+	 * @return

+	 */

+	public String getSnapshotDisplayName() {

+		if (snapshotDisplayName == null || snapshotDisplayName.length() == 0){

+			snapshotDisplayName = snapshotFileName;

+		}

+		return snapshotDisplayName;

+	}

+	

+	/**

+	 * Additional arbitrary notes to describe a particular snapshot

+	 * @return

+	 */

+	public String getSnapshotDescription() {

+		if (snapshotDescription == null){

+			snapshotDescription = "";

+		}

+		return snapshotDescription;

+	}

+	

+	/**

+	 * Set the snapshot description text.

+	 * @param descr

+	 */

+	public void setSnapshotDescription(String descr) {

+		snapshotDescription = descr;

+	}

+	

+	/**

+	 * Get the album this snapshot belongs to

+	 * @return

+	 */

+	public Album getAlbum(){

+		return album;

+	}

+	

+	/**

+	 * Creates the snapshot name from a stack frame dmc.

+	 * 

+	 * @param frameDMC the frame dmc

+	 * 

+	 * @return the snapshot name

+	 */

+	public String createSnapshotNameFromStackFrameDMC(StackFrameDMC stackFrame)

+	{

+		assert stackFrame != null;

+		StringBuilder name = new StringBuilder();

+		if (stackFrame.getFunctionName() != null && stackFrame.getFunctionName().length() != 0) {

+			name.append(stackFrame.getFunctionName());

+			name.append("() : "); //$NON-NLS-1$

+			name.append(stackFrame.getLineNumber());

+		} else if (stackFrame.getModuleName() != null && stackFrame.getModuleName().length() != 0) {

+			name.append(stackFrame.getModuleName());

+		} else if (stackFrame.getInstructionPtrAddress() != null) {

+			name.append(stackFrame.getInstructionPtrAddress().toHexAddressString());

+		}

+

+		return name.toString();	

+	}

+

+	public void setReferenceLocationSourceFile(String referenceLocationSourceFile) {

+		assert referenceLocationSourceFile != null;

+		this.referenceLocationSourceFile = referenceLocationSourceFile;

+	}

+

+	public String getReferenceLocationSourceFile() {

+		assert referenceLocationSourceFile != null;

+		return referenceLocationSourceFile;

+	}

+

+	public void setReferenceLocationLineNumber(long referenceLocationLineNumber) {

+		this.referenceLocationLineNumber = referenceLocationLineNumber;

+	}

+

+	public long getReferenceLocationLineNumber() {

+		return referenceLocationLineNumber;

+	}

+	

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/CompositeType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/CompositeType.java
index 739390f..f4d28a4 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/CompositeType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/CompositeType.java
@@ -1,453 +1,473 @@
-/*******************************************************************************
- * 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.symbols;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import java.util.Comparator;
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-
-public class CompositeType extends MayBeQualifiedType implements ICompositeType {
-	
-	// kind of composite (class, struct, union)
-	private final int key;
-	
-	// composite name without "class ", "struct " or "union " prefix
-	private String baseName;
-
-	// fields in the composite 
-	protected ArrayList<IField> fields = new ArrayList<IField>();
-	private boolean fieldsSorted = false;
-	
-	// classes inherited from
-	protected ArrayList<IInheritance> inheritances = null;
-	private boolean inheritancesSorted = false;
-	
-	// template parameters
-	protected ArrayList<ITemplateParam> templateParams = null;
-	boolean nameIncludesTemplateParams;
-
-	/**
-	 * fields of anonymous union types, with unknown offsets
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfInfoReader#processUnionType()
-	 */
-	protected ArrayList<IField> unknownOffsetFields = null;
-
-	protected static class OffsetAndLength {
-		public long offset;
-		public long length;
-	}
-
-	public CompositeType(String name, IScope scope, int key, int byteSize, Map<Object, Object> properties, String prefix) {
-		super(name, scope, byteSize, properties);
-		this.baseName = name;
-		this.name = prefix + " " + name; //$NON-NLS-1$
-		this.key = key;
-		nameIncludesTemplateParams = name.contains("<"); //$NON-NLS-1$
-	}
-
-	public int getKey() {
-		return this.key;
-	}
-
-	public int fieldCount() {
-		if (unknownOffsetFields != null)
-			setAnonymousUnionOffsets();
-		return fields.size();
-	}
-
-	public void addField(IField field) {
-		if (field.getFieldOffset() < 0) {
-			if (unknownOffsetFields == null)
-				unknownOffsetFields = new ArrayList<IField>();
-			unknownOffsetFields.add(field);
-		} else
-			fields.add(field);
-	}
-
-	public IField[] getFields() {
-		if (unknownOffsetFields != null)
-			setAnonymousUnionOffsets();
-		if (fields.size() > 1 && !fieldsSorted) {
-			Collections.sort(fields, new Comparator<IField>() {
-	            public int compare(IField f1, IField f2) {
-	                return (int)(f1.getFieldOffset() - f2.getFieldOffset());
-	            }
-			});
-			fieldsSorted = true;
-		}
-		
-		ArrayList<IField> fieldList = new ArrayList<IField>(fields);
-		
-		return fieldList.toArray(new IField[fields.size()]);
-	}
-
-	public void addTemplateParam(ITemplateParam templateParam) {
-		if (templateParams == null) {
-			templateParams = new ArrayList<ITemplateParam>(2);
-		}
-		templateParams.add(templateParam);
-	}
-
-	public ITemplateParam[] getTemplateParams() {
-		if (templateParams == null)
-			return new ITemplateParam[0];
-
-		ArrayList<ITemplateParam> templateParamList = new ArrayList<ITemplateParam>(templateParams);
-
-		return templateParamList.toArray(new ITemplateParam[templateParams.size()]);
-	}
-
-	@Override
-	public String getName() {
-		if (templateParams != null && !nameIncludesTemplateParams)
-			addTemplateStringToNames();
-		return name;
-	}
-	
-	public String getBaseName() {
-		if (templateParams != null && !nameIncludesTemplateParams)
-			addTemplateStringToNames();
-		return baseName;
-	}
-
-	// add template parameters (e.g. "<Long>") to name and base name
-	private void addTemplateStringToNames() {
-		nameIncludesTemplateParams = true;
-		String templateName = "<"; //$NON-NLS-1$
-		for (int i = 0; i < templateParams.size(); i++) {
-			templateName += templateParams.get(i).getName();
-			if (i + 1 < templateParams.size())
-				templateName += ","; //$NON-NLS-1$
-		}
-		templateName += ">"; //$NON-NLS-1$
-		// remove composite type names (e.g., "class")
-		templateName = templateName.replaceAll("class ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-		templateName = templateName.replaceAll("struct ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-		templateName = templateName.replaceAll("union ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-		name += templateName;
-		baseName += templateName;
-	}
-
-	public int inheritanceCount() {
-		return inheritances == null ? 0 : inheritances.size();
-	}
-
-	public void addInheritance(IInheritance inheritance) {
-		if (inheritances == null)
-			inheritances = new ArrayList<IInheritance>();
-		inheritances.add(inheritance);
-	}
-
-	public IInheritance[] getInheritances() {
-		if (inheritances == null)
-			return new IInheritance[0];
-
-		if (inheritances.size() > 1 && !inheritancesSorted) {
-			Collections.sort(inheritances, new Comparator<IInheritance>() {
-	            public int compare(IInheritance i1, IInheritance i2) {
-	                return (int)(i1.getFieldsOffset() - i2.getFieldsOffset());
-	            }
-			});
-			inheritancesSorted = true;
-		}
-
-		return inheritances.toArray(new IInheritance[inheritances.size()]);
-	}	
-
-	public IField[] findFields(String name) {
-		// For a qualified name containing "::", save the qualifiers to match against
-		String baseFieldName = name;
-		ArrayList<String> nameQualifiers = new ArrayList<String>();
-		
-		if (name.contains("::")) { //$NON-NLS-1$
-			StringTokenizer st = new StringTokenizer(name, "::", false); //$NON-NLS-1$
-			while (st.hasMoreTokens()) {
-				baseFieldName = st.nextToken();
-				nameQualifiers.add(baseFieldName);
-			}
-			
-			// last token in the array is the base field name
-			nameQualifiers.remove(nameQualifiers.size() - 1);
-
-			// if the first nameQualifier is the composite's name, remove it
-			// E.g., if we're in class foo, change "foo::x" to "x".
-			if ((nameQualifiers.size() >= 0) && nameQualifiers.get(0).equals(this.baseName))
-				nameQualifiers.remove(0);
-		}
-
-		// try for a fast exit: match against the non-inherited fields and names of
-		// composites we're inheriting from
-		if (nameQualifiers.size() == 0) {
-			if (unknownOffsetFields != null)
-				setAnonymousUnionOffsets();
-			for (int i = 0; i < fields.size(); i++) {
-				if (((FieldType) fields.get(i)).getName().equals(baseFieldName)) {
-					IField[] foundFields = new IField[1];
-					foundFields[0] = fields.get(i);
-					return foundFields;
-				}
-			}
-			
-			if (inheritances != null) {
-				for (IInheritance inheritance : inheritances) {
-					String inheritanceName = inheritance.getName();
-					// for templates, remove composite type names (e.g., "class")
-					if (inheritanceName.indexOf('<') != -1) {
-						inheritanceName = inheritanceName.replaceAll("class ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-						inheritanceName = inheritanceName.replaceAll("struct ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-						inheritanceName = inheritanceName.replaceAll("union ", ""); //$NON-NLS-1$ //$NON-NLS-2$
-					}
-
-					if (inheritanceName.equals(baseFieldName)) {
-						IField[] foundFields = new IField[1];
-						
-						// treat the inherited type as a field
-						FieldType newField = new FieldType(inheritanceName, scope, this,
-								inheritance.getFieldsOffset(), 0 /* bitSize */, 0 /* bitOffset */,
-								inheritance.getType().getByteSize(), inheritance.getAccessibility(),
-								inheritance.getProperties());
-						newField.setType(inheritance.getType());
-
-						foundFields[0] = newField;
-						return foundFields;
-					}
-				}
-			}
-		}
-		
-		// check the inherited types
-		if (inheritances == null)
-			return null;
-
-		ArrayList<IField> matches = new ArrayList<IField>();
-		
-		for (IInheritance inheritance : inheritances) {
-			if (inheritance.getType() instanceof ICompositeType) {
-				ICompositeType inheritComposite = (ICompositeType)inheritance.getType();
-				matches = findInheritedByName(baseFieldName, inheritComposite, inheritComposite.getBaseName(), inheritance.getFieldsOffset(), matches);
-			}
-		}
-		
-		// eliminate partial matches
-		matches = pruneMatches(nameQualifiers, matches);
-
-		// create the list of all inherited fields
-		IField[] foundFields = null;
-		
-		// gather the names and offsets of the inherited fields
-		if (matches.size() > 0) {
-			foundFields = new IField[matches.size()];
-			for (int i = 0; i < matches.size(); i++) {
-				foundFields[i] = matches.get(i);
-			}
-		}
-		
-		return foundFields;
-	}
-	
-	/**
-	 * From a list of fields whose name matches the one we're looking for, remove those
-	 * whose "::" qualifiers do not match. E.g., "foo::x" would match "bar::foo::x", but
-	 * it would not match "bar::x" - so "bar::x" would be pruned.
-	 *  
-	 * @param nameQualifiers qualifiers of the field we're matching against
-	 * @param matches list of fields whose base name matches, but whose qualifiers may not match
-	 * @return list of fields whose base name and qualifiers match the field we're looking for
-	 */
-	private ArrayList<IField> pruneMatches(ArrayList<String> nameQualifiers, ArrayList<IField> matches) {
-		if (nameQualifiers.size() == 0)
-			return matches;
-
-		for (int i = 0; i < matches.size(); i++) {
-			ArrayList<String> matchQualifiers = new ArrayList<String>();
-			String matchName = matches.get(i).getName();
-			
-			if (!matchName.contains("::")) //$NON-NLS-1$
-				continue;
-			
-			// tokenize the match's name
-			StringTokenizer st = new StringTokenizer(matchName, "::", false); //$NON-NLS-1$
-			while (st.hasMoreTokens()) {
-				matchQualifiers.add(st.nextToken());
-			}
-			
-			// last token in the array is the base name, which we already know matches
-			matchQualifiers.remove(matchQualifiers.size() - 1);
-
-			for (int nameIndex = 0, matchIndex = 0;
-					nameIndex < nameQualifiers.size() && matchIndex < matchQualifiers.size();
-					nameIndex++) {
-				// match against each name qualifier, in order
-				boolean found = false;
-				while (!found && matchIndex < matchQualifiers.size()) {
-					found = nameQualifiers.get(nameIndex).equals(matchQualifiers.get(matchIndex));
-					matchIndex++;
-				}
-				
-				// if did not find a qualifier, remove the match
-				if (!found) {
-					matches.remove(i);
-					break;
-				}
-			}
-		}
-		
-		return matches;
-	}
-
-	/**
-	 * Find all inherited fields whose base name, ignoring "::" qualifiers, match the search name
-	 * 
-	 * @param name name to match
-	 * @param composite composite type whose fields or inherited fields may match 
-	 * @param prefix string of "::" qualifiers so far
-	 * @param offset byte offset of the composite from the composite that inherits from it
-	 * @param matches list of matches found so far
-	 * @return list of matches 
-	 */
-	private ArrayList<IField> findInheritedByName(String name, ICompositeType composite, String prefix, long offset, ArrayList<IField> matches) {
-		IField[] fields = composite.getFields();
-		if (fields != null) {
-			for (IField field : fields) {
-				String fieldName = field.getName();
-				
-				if (fieldName.equals(name)) {
-					// create a field with the prefixed name
-					FieldType newField = new FieldType(prefix + "::" + field.getName(), scope, //$NON-NLS-1$
-							composite, offset + field.getFieldOffset(), 0 /* bitSize */, 0 /* bitOffset */,
-							field.getType().getByteSize(), field.getAccessibility(),
-							field.getProperties());
-					newField.setType(field.getType());
-					matches.add(newField);
-					break;
-				}
-			}
-		}
-
-		IInheritance[] compositeInheritances = composite.getInheritances(); 
-		if (compositeInheritances.length == 0)
-			return matches;
-
-		for (IInheritance inheritance : compositeInheritances) {
-			if (inheritance.getName().equals(name)) {
-				// treat the inherited type as a field
-				FieldType newField = new FieldType(inheritance.getName(), scope, this,
-						offset + inheritance.getFieldsOffset(), 0 /* bitSize */, 0 /* bitOffset */,
-						inheritance.getType().getByteSize(), inheritance.getAccessibility(),
-						inheritance.getProperties());
-				newField.setType(inheritance.getType());
-			}
-
-			if (inheritance.getType() instanceof ICompositeType) {
-				ICompositeType inheritComposite = (ICompositeType)inheritance.getType();
-				matches = findInheritedByName(name, inheritComposite, prefix + "::" + inheritComposite.getBaseName(), //$NON-NLS-1$
-								offset + inheritance.getFieldsOffset(), matches);
-			}
-		}
-
-		return matches;
-	}
-
-	/**
-	 * Fields with unknown offsets may be between other members or at the end
-	 */
-	private void setAnonymousUnionOffsets() {
-		OffsetAndLength[] offsetSizes = new OffsetAndLength[fields.size() + inheritanceCount()];
-		int count = 0;
-		if (fields.size() > 0) {
-			for ( ; count < fields.size(); count++) {
-				offsetSizes[count] = new OffsetAndLength();
-				offsetSizes[count].offset = fields.get(count).getFieldOffset();
-				offsetSizes[count].length = fields.get(count).getByteSize();
-			}
-		}
-		
-		if (inheritances != null) {
-			for (IInheritance inheritance : inheritances) {
-				offsetSizes[count] = new OffsetAndLength();
-				offsetSizes[count].offset = inheritance.getFieldsOffset();
-				offsetSizes[count].length = inheritance.getType().getByteSize();
-				count++;
-			}
-		}
-
-		// sort by offsets
-		if (offsetSizes.length > 1) {
-			boolean sorted;
-			int passCnt = 1;
-			do {
-				sorted = true;
-				for (int i = 0; i < offsetSizes.length - passCnt; i++) {
-					if (offsetSizes[i].offset > offsetSizes[i + 1].offset) {
-						OffsetAndLength temp = offsetSizes[i];
-						offsetSizes[i] = offsetSizes[i + 1];
-						offsetSizes[i + 1] = temp;
-						sorted = false;
-					}
-				}
-				passCnt++;
-			} while (!sorted && passCnt < offsetSizes.length);
-		}
-
-		// find the offset for each anonymous union's data - between other members or at the end
-		int i = 0;
-		long fieldOffset = 0;
-		for (IField unknownOffsetField : unknownOffsetFields) {
-			for ( ; i < offsetSizes.length; i++) {
-				if (fieldOffset < offsetSizes[i].offset)
-					break;
-				fieldOffset = offsetSizes[i].offset + offsetSizes[i].length;
-			}
-			unknownOffsetField.setFieldOffset(fieldOffset);
-			if (i >= offsetSizes.length)
-				fieldOffset += unknownOffsetField.getByteSize();
-			fields.add(unknownOffsetField);
-		}
-
-		unknownOffsetFields = null;
-	}
-
-	public boolean isOpaque() {
-		/*
-		 * Opaque pointer:
-		 * - Source:
-				struct PrivateStruct* struct_op;
-		 * -- Dwarf from GNU C++ 3.4.5 (mingw-vista special r3):
-				 <1><654>: Abbrev Number: 6 (DW_TAG_structure_type)
-				    <655>   DW_AT_name        : PrivateStruct	
-				    <663>   DW_AT_declaration : 1	
-		 * RVCT Dwarf for an opaque type:
-			  454f6b:   62  = 0x13 (DW_TAG_structure_type)
-			  454f6c:     DW_AT_name PrivateStruct
-		 
-		 * 
-		 * Intentional empty structure/class:
-		 * Source:
-				class EmptyClass {
-				};
-		 * -- Dwarf from GNU C++ 3.4.5 (mingw-vista special r3):
-		 *    Note the non-zero bype_size:
-				 <1><172>: Abbrev Number: 13 (DW_TAG_structure_type)
-				    <173>   DW_AT_sibling     : <0x1da>	
-				    <177>   DW_AT_name        : (indirect string, offset: 0x23): EmptyStruct	
-				    <17b>   DW_AT_byte_size   : 1	
-				    <17c>   DW_AT_decl_file   : 1	
-				    <17d>   DW_AT_decl_line   : 22
-				    ...	
-		 * 
-		 */
-		return getByteSize() <= 0;
-	}
-}
+/*******************************************************************************

+ * 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.symbols;

+

+import java.util.ArrayList;

+import java.util.Collections;

+import java.util.Comparator;

+import java.util.Map;

+import java.util.StringTokenizer;

+

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

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

+

+public class CompositeType extends MayBeQualifiedType implements ICompositeType {

+	

+	// kind of composite (class, struct, union)

+	private final int key;

+	

+	// composite name without "class ", "struct " or "union " prefix

+	private String baseName;

+

+	// fields in the composite 

+	protected ArrayList<IField> fields = new ArrayList<IField>();

+	private boolean fieldsSorted = false;

+	

+	// classes inherited from

+	protected ArrayList<IInheritance> inheritances = null;

+	private boolean inheritancesSorted = false;

+	

+	// template parameters

+	protected ArrayList<ITemplateParam> templateParams = null;

+	boolean nameIncludesTemplateParams;

+

+	// runtime type info offset - non-negative offset means RTTI may be possible

+	protected long runtimeTypeOffset = -1;

+

+	/**

+	 * fields of anonymous union types, with unknown offsets

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfInfoReader#processUnionType()

+	 */

+	protected ArrayList<IField> unknownOffsetFields = null;

+

+	protected static class OffsetAndLength {

+		public long offset;

+		public long length;

+	}

+

+	public CompositeType(String name, IScope scope, int key, int byteSize, Map<Object, Object> properties, String prefix) {

+		super(name, scope, byteSize, properties);

+		this.baseName = name;

+		this.name = prefix + " " + name; //$NON-NLS-1$

+		this.key = key;

+		nameIncludesTemplateParams = name.contains("<"); //$NON-NLS-1$

+	}

+

+	public int getKey() {

+		return this.key;

+	}

+

+	public int fieldCount() {

+		if (unknownOffsetFields != null)

+			setAnonymousUnionOffsets();

+		return fields.size();

+	}

+

+	public void addField(IField field) {

+		if (field.getFieldOffset() < 0) {

+			if (unknownOffsetFields == null)

+				unknownOffsetFields = new ArrayList<IField>();

+			unknownOffsetFields.add(field);

+		} else

+			fields.add(field);

+	}

+

+	public IField[] getFields() {

+		if (unknownOffsetFields != null)

+			setAnonymousUnionOffsets();

+		if (fields.size() > 1 && !fieldsSorted) {

+			Collections.sort(fields, new Comparator<IField>() {

+	            public int compare(IField f1, IField f2) {

+	                return (int)(f1.getFieldOffset() - f2.getFieldOffset());

+	            }

+			});

+			fieldsSorted = true;

+		}

+		

+		ArrayList<IField> fieldList = new ArrayList<IField>(fields);

+		

+		return fieldList.toArray(new IField[fields.size()]);

+	}

+

+	public void addTemplateParam(ITemplateParam templateParam) {

+		if (templateParams == null) {

+			templateParams = new ArrayList<ITemplateParam>(2);

+		}

+		templateParams.add(templateParam);

+	}

+

+	public ITemplateParam[] getTemplateParams() {

+		if (templateParams == null)

+			return new ITemplateParam[0];

+

+		ArrayList<ITemplateParam> templateParamList = new ArrayList<ITemplateParam>(templateParams);

+

+		return templateParamList.toArray(new ITemplateParam[templateParams.size()]);

+	}

+

+	@Override

+	public String getName() {

+		if (templateParams != null && !nameIncludesTemplateParams)

+			addTemplateStringToNames();

+		return name;

+	}

+	

+	public String getBaseName() {

+		if (templateParams != null && !nameIncludesTemplateParams)

+			addTemplateStringToNames();

+		return baseName;

+	}

+

+	// add template parameters (e.g. "<Long>") to name and base name

+	private void addTemplateStringToNames() {

+		nameIncludesTemplateParams = true;

+		String templateName = "<"; //$NON-NLS-1$

+		for (int i = 0; i < templateParams.size(); i++) {

+			templateName += templateParams.get(i).getName();

+			if (i + 1 < templateParams.size())

+				templateName += ","; //$NON-NLS-1$

+		}

+		templateName += ">"; //$NON-NLS-1$

+		// remove composite type names (e.g., "class")

+		templateName = templateName.replaceAll("class ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+		templateName = templateName.replaceAll("struct ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+		templateName = templateName.replaceAll("union ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+		name += templateName;

+		baseName += templateName;

+	}

+

+	public int inheritanceCount() {

+		return inheritances == null ? 0 : inheritances.size();

+	}

+

+	public void addInheritance(IInheritance inheritance) {

+		if (inheritances == null)

+			inheritances = new ArrayList<IInheritance>();

+		inheritances.add(inheritance);

+	}

+

+	public IInheritance[] getInheritances() {

+		if (inheritances == null)

+			return new IInheritance[0];

+

+		if (inheritances.size() > 1 && !inheritancesSorted) {

+			Collections.sort(inheritances, new Comparator<IInheritance>() {

+	            public int compare(IInheritance i1, IInheritance i2) {

+	                return (int)(i1.getFieldsOffset() - i2.getFieldsOffset());

+	            }

+			});

+			inheritancesSorted = true;

+		}

+

+		return inheritances.toArray(new IInheritance[inheritances.size()]);

+	}	

+

+	public IField[] findFields(String name) {

+		// For a qualified name containing "::", save the qualifiers to match against

+		String baseFieldName = name;

+		ArrayList<String> nameQualifiers = new ArrayList<String>();

+		

+		if (name.contains("::")) { //$NON-NLS-1$

+			StringTokenizer st = new StringTokenizer(name, "::", false); //$NON-NLS-1$

+			while (st.hasMoreTokens()) {

+				baseFieldName = st.nextToken();

+				nameQualifiers.add(baseFieldName);

+			}

+			

+			// last token in the array is the base field name

+			nameQualifiers.remove(nameQualifiers.size() - 1);

+

+			// if the first nameQualifier is the composite's name, remove it

+			// E.g., if we're in class foo, change "foo::x" to "x".

+			if ((nameQualifiers.size() >= 0) && nameQualifiers.get(0).equals(this.baseName))

+				nameQualifiers.remove(0);

+		}

+

+		// try for a fast exit: match against the non-inherited fields and names of

+		// composites we're inheriting from

+		if (nameQualifiers.size() == 0) {

+			if (unknownOffsetFields != null)

+				setAnonymousUnionOffsets();

+			for (int i = 0; i < fields.size(); i++) {

+				if (((FieldType) fields.get(i)).getName().equals(baseFieldName)) {

+					IField[] foundFields = new IField[1];

+					foundFields[0] = fields.get(i);

+					return foundFields;

+				}

+			}

+			

+			if (inheritances != null) {

+				for (IInheritance inheritance : inheritances) {

+					String inheritanceName = inheritance.getName();

+					// for templates, remove composite type names (e.g., "class")

+					if (inheritanceName.indexOf('<') != -1) {

+						inheritanceName = inheritanceName.replaceAll("class ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+						inheritanceName = inheritanceName.replaceAll("struct ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+						inheritanceName = inheritanceName.replaceAll("union ", ""); //$NON-NLS-1$ //$NON-NLS-2$

+					}

+

+					if (inheritanceName.equals(baseFieldName)) {

+						IField[] foundFields = new IField[1];

+						

+						// treat the inherited type as a field

+						FieldType newField = new FieldType(inheritanceName, scope, this,

+								inheritance.getFieldsOffset(), 0 /* bitSize */, 0 /* bitOffset */,

+								inheritance.getType().getByteSize(), inheritance.getAccessibility(),

+								inheritance.getProperties());

+						newField.setType(inheritance.getType());

+

+						foundFields[0] = newField;

+						return foundFields;

+					}

+				}

+			}

+		}

+		

+		// check the inherited types

+		if (inheritances == null)

+			return null;

+

+		ArrayList<IField> matches = new ArrayList<IField>();

+		

+		for (IInheritance inheritance : inheritances) {

+			if (inheritance.getType() instanceof ICompositeType) {

+				ICompositeType inheritComposite = (ICompositeType)inheritance.getType();

+				matches = findInheritedByName(baseFieldName, inheritComposite, inheritComposite.getBaseName(), inheritance.getFieldsOffset(), matches);

+			}

+		}

+		

+		// eliminate partial matches

+		matches = pruneMatches(nameQualifiers, matches);

+

+		// create the list of all inherited fields

+		IField[] foundFields = null;

+		

+		// gather the names and offsets of the inherited fields

+		if (matches.size() > 0) {

+			foundFields = new IField[matches.size()];

+			for (int i = 0; i < matches.size(); i++) {

+				foundFields[i] = matches.get(i);

+			}

+		}

+		

+		return foundFields;

+	}

+	

+	/**

+	 * From a list of fields whose name matches the one we're looking for, remove those

+	 * whose "::" qualifiers do not match. E.g., "foo::x" would match "bar::foo::x", but

+	 * it would not match "bar::x" - so "bar::x" would be pruned.

+	 *  

+	 * @param nameQualifiers qualifiers of the field we're matching against

+	 * @param matches list of fields whose base name matches, but whose qualifiers may not match

+	 * @return list of fields whose base name and qualifiers match the field we're looking for

+	 */

+	private ArrayList<IField> pruneMatches(ArrayList<String> nameQualifiers, ArrayList<IField> matches) {

+		if (nameQualifiers.size() == 0)

+			return matches;

+

+		for (int i = 0; i < matches.size(); i++) {

+			ArrayList<String> matchQualifiers = new ArrayList<String>();

+			String matchName = matches.get(i).getName();

+			

+			if (!matchName.contains("::")) //$NON-NLS-1$

+				continue;

+			

+			// tokenize the match's name

+			StringTokenizer st = new StringTokenizer(matchName, "::", false); //$NON-NLS-1$

+			while (st.hasMoreTokens()) {

+				matchQualifiers.add(st.nextToken());

+			}

+			

+			// last token in the array is the base name, which we already know matches

+			matchQualifiers.remove(matchQualifiers.size() - 1);

+

+			for (int nameIndex = 0, matchIndex = 0;

+					nameIndex < nameQualifiers.size() && matchIndex < matchQualifiers.size();

+					nameIndex++) {

+				// match against each name qualifier, in order

+				boolean found = false;

+				while (!found && matchIndex < matchQualifiers.size()) {

+					found = nameQualifiers.get(nameIndex).equals(matchQualifiers.get(matchIndex));

+					matchIndex++;

+				}

+				

+				// if did not find a qualifier, remove the match

+				if (!found) {

+					matches.remove(i);

+					break;

+				}

+			}

+		}

+		

+		return matches;

+	}

+

+	/**

+	 * Find all inherited fields whose base name, ignoring "::" qualifiers, match the search name

+	 * 

+	 * @param name name to match

+	 * @param composite composite type whose fields or inherited fields may match 

+	 * @param prefix string of "::" qualifiers so far

+	 * @param offset byte offset of the composite from the composite that inherits from it

+	 * @param matches list of matches found so far

+	 * @return list of matches 

+	 */

+	private ArrayList<IField> findInheritedByName(String name, ICompositeType composite, String prefix, long offset, ArrayList<IField> matches) {

+		IField[] fields = composite.getFields();

+		if (fields != null) {

+			for (IField field : fields) {

+				String fieldName = field.getName();

+				

+				if (fieldName.equals(name)) {

+					// create a field with the prefixed name

+					FieldType newField = new FieldType(prefix + "::" + field.getName(), scope, //$NON-NLS-1$

+							composite, offset + field.getFieldOffset(), 0 /* bitSize */, 0 /* bitOffset */,

+							field.getType().getByteSize(), field.getAccessibility(),

+							field.getProperties());

+					newField.setType(field.getType());

+					matches.add(newField);

+					break;

+				}

+			}

+		}

+

+		IInheritance[] compositeInheritances = composite.getInheritances(); 

+		if (compositeInheritances.length == 0)

+			return matches;

+

+		for (IInheritance inheritance : compositeInheritances) {

+			if (inheritance.getName().equals(name)) {

+				// treat the inherited type as a field

+				FieldType newField = new FieldType(inheritance.getName(), scope, this,

+						offset + inheritance.getFieldsOffset(), 0 /* bitSize */, 0 /* bitOffset */,

+						inheritance.getType().getByteSize(), inheritance.getAccessibility(),

+						inheritance.getProperties());

+				newField.setType(inheritance.getType());

+			}

+

+			if (inheritance.getType() instanceof ICompositeType) {

+				ICompositeType inheritComposite = (ICompositeType)inheritance.getType();

+				matches = findInheritedByName(name, inheritComposite, prefix + "::" + inheritComposite.getBaseName(), //$NON-NLS-1$

+								offset + inheritance.getFieldsOffset(), matches);

+			}

+		}

+

+		return matches;

+	}

+

+	/**

+	 * Fields with unknown offsets may be between other members or at the end

+	 */

+	private void setAnonymousUnionOffsets() {

+		OffsetAndLength[] offsetSizes = new OffsetAndLength[fields.size() + inheritanceCount()];

+		int count = 0;

+		if (fields.size() > 0) {

+			for ( ; count < fields.size(); count++) {

+				offsetSizes[count] = new OffsetAndLength();

+				offsetSizes[count].offset = fields.get(count).getFieldOffset();

+				offsetSizes[count].length = fields.get(count).getByteSize();

+			}

+		}

+		

+		if (inheritances != null) {

+			for (IInheritance inheritance : inheritances) {

+				offsetSizes[count] = new OffsetAndLength();

+				offsetSizes[count].offset = inheritance.getFieldsOffset();

+				offsetSizes[count].length = inheritance.getType().getByteSize();

+				count++;

+			}

+		}

+

+		// sort by offsets

+		if (offsetSizes.length > 1) {

+			boolean sorted;

+			int passCnt = 1;

+			do {

+				sorted = true;

+				for (int i = 0; i < offsetSizes.length - passCnt; i++) {

+					if (offsetSizes[i].offset > offsetSizes[i + 1].offset) {

+						OffsetAndLength temp = offsetSizes[i];

+						offsetSizes[i] = offsetSizes[i + 1];

+						offsetSizes[i + 1] = temp;

+						sorted = false;

+					}

+				}

+				passCnt++;

+			} while (!sorted && passCnt < offsetSizes.length);

+		}

+

+		// find the offset for each anonymous union's data - between other members or at the end

+		int i = 0;

+		long fieldOffset = 0;

+		for (IField unknownOffsetField : unknownOffsetFields) {

+			for ( ; i < offsetSizes.length; i++) {

+				if (fieldOffset < offsetSizes[i].offset)

+					break;

+				fieldOffset = offsetSizes[i].offset + offsetSizes[i].length;

+			}

+			unknownOffsetField.setFieldOffset(fieldOffset);

+			if (i >= offsetSizes.length)

+				fieldOffset += unknownOffsetField.getByteSize();

+			fields.add(unknownOffsetField);

+		}

+

+		unknownOffsetFields = null;

+	}

+

+	public boolean isOpaque() {

+		/*

+		 * Opaque pointer:

+		 * - Source:

+				struct PrivateStruct* struct_op;

+		 * -- Dwarf from GNU C++ 3.4.5 (mingw-vista special r3):

+				 <1><654>: Abbrev Number: 6 (DW_TAG_structure_type)

+				    <655>   DW_AT_name        : PrivateStruct	

+				    <663>   DW_AT_declaration : 1	

+		 * RVCT Dwarf for an opaque type:

+			  454f6b:   62  = 0x13 (DW_TAG_structure_type)

+			  454f6c:     DW_AT_name PrivateStruct

+		 

+		 * 

+		 * Intentional empty structure/class:

+		 * Source:

+				class EmptyClass {

+				};

+		 * -- Dwarf from GNU C++ 3.4.5 (mingw-vista special r3):

+		 *    Note the non-zero byte_size:

+				 <1><172>: Abbrev Number: 13 (DW_TAG_structure_type)

+				    <173>   DW_AT_sibling     : <0x1da>	

+				    <177>   DW_AT_name        : (indirect string, offset: 0x23): EmptyStruct	

+				    <17b>   DW_AT_byte_size   : 1	

+				    <17c>   DW_AT_decl_file   : 1	

+				    <17d>   DW_AT_decl_line   : 22

+				    ...	

+		 * 

+		 */

+		return getByteSize() <= 0;

+	}

+

+	public boolean hasRuntimeTypeInfo() {

+		return false;

+	}

+

+	public void setRuntimeTypeOffset(long runtimeTypeOffset) {

+		this.runtimeTypeOffset = runtimeTypeOffset;

+	}

+

+	public long getRuntimeTypeOffset() {

+		return runtimeTypeOffset;

+	}

+

+	public IType getRuntimeType(MemoryVariableLocation address) {

+		return getType();

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ICompositeType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ICompositeType.java
index 9cdfe3b..60e13a0 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ICompositeType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ICompositeType.java
@@ -1,122 +1,147 @@
-/*******************************************************************************
- * 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.symbols;
-
-import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
-import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
-import org.eclipse.cdt.debug.edc.symbols.IType;
-
-public interface ICompositeType extends IType, IAggregate {
-	
-	// accessibility of an inherited class or of a composite's field
-	public static int ACCESS_PUBLIC    = 0;
-	public static int ACCESS_PROTECTED = 1;
-	public static int ACCESS_PRIVATE   = 2;
-
-	public static final int k_class  = ICPPASTCompositeTypeSpecifier.k_class;
-	public static final int k_struct = IASTCompositeTypeSpecifier.k_struct;
-	public static final int k_union  = IASTCompositeTypeSpecifier.k_union;
-
-	/**
-	 * Kind of composite (class, struct, union)
-	 * 
-	 * @return kind
-	 */
-	public int getKey();
-
-	/**
-	 * Number of fields/enumerators in composite
-	 * 
-	 * @return count
-	 */
-	public int fieldCount();
-
-	/**
-	 * Add a field/member to the end of the list of fields or enumerators
-	 * Intended for use by a debug information parser.
-	 * 
-	 * @param field
-	 *            field to add
-	 */
-	public void addField(IField field);
-
-	/**
-	 * Get an array of fields/enumerators in composite
-	 * 
-	 * @return array of fields/enumerators, or IField.EMPTY_FIELD_ARRAY if no
-	 *         fields/enumerators
-	 */
-	public IField[] getFields();
-
-	/**
-	 * Add a template parameter to the end of the list of template parameters
-	 * Intended for use by a debug information parser.
-	 * 
-	 * @param templateParam
-	 *            template parameter to add
-	 */
-	public void addTemplateParam(ITemplateParam templateParam);
-
-	/**
-	 * Get an array of template parameters in composite
-	 * 
-	 * @return array of template parameters, or empty array if no
-	 *         template parameters
-	 */
-	public ITemplateParam[] getTemplateParams();
-
-	/**
-	 * Find the composite fields/members with the given name
-	 * 
-	 * @param name field name, which may contain "::" separators
-	 * @return array of matching fields if any exist, or null otherwise
-	 */
-	public IField[] findFields(String name);
-
-	/**
-	 * Number of classes and structs from which the composite inherits
-	 * 
-	 * @return count
-	 */
-	public int inheritanceCount();
-
-	/**
-	 * Add an inherited-from class or struct to the end of the list
-	 * of inherited-from classes and structs
-	 * Intended for use by a debug information parser.
-	 * 
-	 * @param inheritance
-	 *            information about class/struct from which this
-	 *            composite inherits
-	 */
-	public void addInheritance(IInheritance inheritance);
-	
-	/**
-	 * Get an array of inherited-from classes/structs for composite
-	 * 
-	 * @return array of information about classes and structs from which this
-	 * composite inherits, or an empty array if nothing is inherited
-	 */
-	public IInheritance[] getInheritances();
-	
-	/**
-	 * Get the name without a type prefix (e.g., "foo" instead of "class foo")
-	 * 
-	 * @return composite name without a type 
-	 */
-	public String getBaseName();
-
-	/**
-	 * Is this an opaque type  ?
-	 * @return true or false
-	 */
-	public boolean isOpaque();
-}
+/*******************************************************************************

+ * 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.symbols;

+

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

+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;

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

+

+public interface ICompositeType extends IType, IAggregate {

+	

+	// accessibility of an inherited class or of a composite's field

+	public static int ACCESS_PUBLIC    = 0;

+	public static int ACCESS_PROTECTED = 1;

+	public static int ACCESS_PRIVATE   = 2;

+

+	public static final int k_class  = ICPPASTCompositeTypeSpecifier.k_class;

+	public static final int k_struct = IASTCompositeTypeSpecifier.k_struct;

+	public static final int k_union  = IASTCompositeTypeSpecifier.k_union;

+

+	/**

+	 * Kind of composite (class, struct, union)

+	 * 

+	 * @return kind

+	 */

+	public int getKey();

+

+	/**

+	 * Number of fields/enumerators in composite

+	 * 

+	 * @return count

+	 */

+	public int fieldCount();

+

+	/**

+	 * Add a field/member to the end of the list of fields or enumerators

+	 * Intended for use by a debug information parser.

+	 * 

+	 * @param field

+	 *            field to add

+	 */

+	public void addField(IField field);

+

+	/**

+	 * Get an array of fields/enumerators in composite

+	 * 

+	 * @return array of fields/enumerators, or IField.EMPTY_FIELD_ARRAY if no

+	 *         fields/enumerators

+	 */

+	public IField[] getFields();

+

+	/**

+	 * Add a template parameter to the end of the list of template parameters

+	 * Intended for use by a debug information parser.

+	 * 

+	 * @param templateParam

+	 *            template parameter to add

+	 */

+	public void addTemplateParam(ITemplateParam templateParam);

+

+	/**

+	 * Get an array of template parameters in composite

+	 * 

+	 * @return array of template parameters, or empty array if no

+	 *         template parameters

+	 */

+	public ITemplateParam[] getTemplateParams();

+

+	/**

+	 * Find the composite fields/members with the given name

+	 * 

+	 * @param name field name, which may contain "::" separators

+	 * @return array of matching fields if any exist, or null otherwise

+	 */

+	public IField[] findFields(String name);

+

+	/**

+	 * Number of classes and structs from which the composite inherits

+	 * 

+	 * @return count

+	 */

+	public int inheritanceCount();

+

+	/**

+	 * Add an inherited-from class or struct to the end of the list

+	 * of inherited-from classes and structs

+	 * Intended for use by a debug information parser.

+	 * 

+	 * @param inheritance

+	 *            information about class/struct from which this

+	 *            composite inherits

+	 */

+	public void addInheritance(IInheritance inheritance);

+	

+	/**

+	 * Get an array of inherited-from classes/structs for composite

+	 * 

+	 * @return array of information about classes and structs from which this

+	 * composite inherits, or an empty array if nothing is inherited

+	 */

+	public IInheritance[] getInheritances();

+	

+	/**

+	 * Get the name without a type prefix (e.g., "foo" instead of "class foo")

+	 * 

+	 * @return composite name without a type 

+	 */

+	public String getBaseName();

+

+	/**

+	 * Is this an opaque type?

+	 * @return true or false

+	 */

+	public boolean isOpaque();

+

+	/**

+	 * Does this composite type have runtime type info? 

+	 * @return true or false

+	 */

+	public boolean hasRuntimeTypeInfo();

+

+	/**

+	 * Set the offset to info that can be used to determine the runtime type (-1 if no info)

+	 * @param runtimeTypeOffset

+	 */

+	public void setRuntimeTypeOffset(long runtimeTypeOffset);

+

+	/**

+	 * Get the offset to info that can be used to determine the runtime type (-1 if no info)

+	 * @return runtime type info offset 

+	 */

+	public long getRuntimeTypeOffset();

+

+	/**

+	 * Get runtime type

+	 * @param address of start of runtime type info

+	 * @return runtime type

+	 */

+	public IType getRuntimeType(MemoryVariableLocation address);

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IPointerType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IPointerType.java
index 119982f..a15b5b0 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IPointerType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IPointerType.java
@@ -1,20 +1,18 @@
-/*******************************************************************************
- * 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.symbols;
-
-import org.eclipse.cdt.debug.edc.symbols.IType;
-
-/**
- * Interface for pointer types
- */
-public interface IPointerType extends IType {
-
-}
+/*******************************************************************************

+ * 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.symbols;

+

+/**

+ * Interface for pointer types

+ */

+public interface IPointerType extends IRuntimeType {

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IReferenceType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IReferenceType.java
index beea795..96ba494 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IReferenceType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IReferenceType.java
@@ -1,17 +1,18 @@
-/*******************************************************************************
- * 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.symbols;
-
-import org.eclipse.cdt.debug.edc.symbols.IType;
-
-public interface IReferenceType extends IType {
-
-}
+/*******************************************************************************

+ * 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.symbols;

+

+/**

+ * Interface for reference types

+ */

+public interface IReferenceType extends IRuntimeType {

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IRuntimeType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IRuntimeType.java
new file mode 100644
index 0000000..9a1866e
--- /dev/null
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/IRuntimeType.java
@@ -0,0 +1,32 @@
+/*******************************************************************************

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

+

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

+

+/**

+ * For a pointer or reference type, allow access to RTTI-determined offset

+ */

+public interface IRuntimeType extends IType {

+

+	/**

+	 * Get offset from variable's apparent address in memory to its real address when

+	 * using RTTI

+	 */

+	public long getRuntimeOffset();

+

+	/**

+	 * Set offset from variable's apparent address in memory to its real address when

+	 * using RTTI

+	 * @param runtimeOffset offset from apparent object address to real address when using RTTI

+	 */

+	public void setRuntimeOffset(long runtimeOffset); 

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/LineEntry.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/LineEntry.java
index efdc4b2..1dca869 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/LineEntry.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/LineEntry.java
@@ -1,83 +1,83 @@
-/*******************************************************************************
- * 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.symbols;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.symbols.ILineEntry;
-import org.eclipse.core.runtime.IPath;
-
-public class LineEntry implements ILineEntry {
-
-	protected IPath filePath;
-	protected int lineNumber;
-	protected int columnNumber;
-	protected IAddress lowAddress;
-	protected IAddress highAddress;
-
-	public LineEntry(IPath filePath, int lineNumber, int columnNumber, IAddress lowAddress, IAddress highAddress) {
-		this.filePath = filePath;
-		this.lineNumber = lineNumber;
-		this.columnNumber = columnNumber;
-		this.lowAddress = lowAddress;
-		this.highAddress = highAddress;
-	}
-
-	public IPath getFilePath() {
-		return filePath;
-	}
-
-	public int getLineNumber() {
-		return lineNumber;
-	}
-
-	public int getColumnNumber() {
-		return columnNumber;
-	}
-
-	public IAddress getLowAddress() {
-		return lowAddress;
-	}
-
-	public IAddress getHighAddress() {
-		return highAddress;
-	}
-
-	public void setHighAddress(IAddress highAddress) {
-		this.highAddress = highAddress;
-	}
-
-	public int compareTo(Object o) {
-		if (o instanceof ILineEntry) {
-			// some entries have low==high
-			int diff = lowAddress.compareTo(((ILineEntry) o).getLowAddress());
-			if (diff != 0)
-				return diff;
-			if (highAddress != null && ((ILineEntry) o).getHighAddress() != null)
-				return highAddress.compareTo(((ILineEntry) o).getHighAddress());
-			return 0;
-		} else if (o instanceof IAddress) {
-			return lowAddress.compareTo(o);
-		}
-
-		return 0;
-	}
-
-	@Override
-	public String toString() {
-		return "LineEntry [lowAddress="
-				+ (lowAddress != null ? lowAddress.toHexAddressString() : "null")
-				+ ", highAddress="
-				+ (highAddress != null ? highAddress.toHexAddressString() : "null")
-				+ ((filePath != null) ? ", path=" + filePath.toOSString() + ", " : ", ")
-				+ "line=" + lineNumber + ", column=" + columnNumber
-				+ "]" ; //$NON-NLS-1$
-	}
-}
+/*******************************************************************************

+ * 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.symbols;

+

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

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

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

+

+public class LineEntry implements ILineEntry {

+

+	protected IPath filePath;

+	protected int lineNumber;

+	protected int columnNumber;

+	protected IAddress lowAddress;

+	protected IAddress highAddress;

+

+	public LineEntry(IPath filePath, int lineNumber, int columnNumber, IAddress lowAddress, IAddress highAddress) {

+		this.filePath = filePath;

+		this.lineNumber = lineNumber;

+		this.columnNumber = columnNumber;

+		this.lowAddress = lowAddress;

+		this.highAddress = highAddress;

+	}

+

+	public IPath getFilePath() {

+		return filePath;

+	}

+

+	public int getLineNumber() {

+		return lineNumber;

+	}

+

+	public int getColumnNumber() {

+		return columnNumber;

+	}

+

+	public IAddress getLowAddress() {

+		return lowAddress;

+	}

+

+	public IAddress getHighAddress() {

+		return highAddress;

+	}

+

+	public void setHighAddress(IAddress highAddress) {

+		this.highAddress = highAddress;

+	}

+

+	public int compareTo(Object o) {

+		if (o instanceof ILineEntry) {

+			// some entries have low==high

+			int diff = lowAddress.compareTo(((ILineEntry) o).getLowAddress());

+			if (diff != 0)

+				return diff;

+			if (highAddress != null && ((ILineEntry) o).getHighAddress() != null)

+				return highAddress.compareTo(((ILineEntry) o).getHighAddress());

+			return 0;

+		} else if (o instanceof IAddress) {

+			return lowAddress.compareTo(o);

+		}

+

+		return 0;

+	}

+

+	@Override

+	public String toString() {

+		return "LineEntry [lowAddress=" //$NON-NLS-1$

+				+ (lowAddress != null ? lowAddress.toHexAddressString() : "null") //$NON-NLS-1$

+				+ ", highAddress=" //$NON-NLS-1$

+				+ (highAddress != null ? highAddress.toHexAddressString() : "null") //$NON-NLS-1$

+				+ ((filePath != null) ? ", path=" + filePath.toOSString() : "") //$NON-NLS-1$//$NON-NLS-2$

+				+ ", line=" + lineNumber + ", column=" + columnNumber //$NON-NLS-1$//$NON-NLS-2$

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

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/MemoryVariableLocation.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/MemoryVariableLocation.java
index 0418415..88310f6 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/MemoryVariableLocation.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/MemoryVariableLocation.java
@@ -1,217 +1,227 @@
-/*******************************************************************************
- * 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.symbols;
-
-import java.math.BigInteger;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.MemoryUtils;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.Memory;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
-import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
-import org.eclipse.cdt.debug.edc.services.ITargetEnvironment;
-import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC;
-import org.eclipse.cdt.debug.edc.symbols.IMemoryVariableLocation;
-import org.eclipse.cdt.debug.edc.symbols.IVariableLocation;
-import org.eclipse.cdt.dsf.datamodel.DMContexts;
-import org.eclipse.cdt.dsf.datamodel.IDMContext;
-import org.eclipse.cdt.utils.Addr64;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.debug.core.model.MemoryByte;
-
-public class MemoryVariableLocation implements IMemoryVariableLocation {
-
-	protected IAddress address;
-	protected boolean isRuntimeAddress;
-	protected EDCServicesTracker tracker;
-	private IDMContext context;
-
-	public MemoryVariableLocation(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,
-			boolean isRuntimeAddress) {
-		initialize(tracker,context,addressValue,isRuntimeAddress, false);
-	}
-
-	public MemoryVariableLocation(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,
-			boolean isRuntimeAddress, boolean checkNonLocalConstVariable) {
-		// checkConstVariableAddress should only be true for global or static (non-local) constant variables
-		initialize(tracker,context,addressValue,isRuntimeAddress, checkNonLocalConstVariable);
-	}
-
-	private void initialize(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,
-			boolean isRuntimeAddress, boolean checkNonLocalConstVariable)  {
-		this.tracker = tracker;
-		this.context = context;
-		BigInteger MAXADDR = BigInteger.valueOf(0xffffffffL);
-		ITargetEnvironment targetEnvironment = tracker.getService(ITargetEnvironment.class);
-		if (targetEnvironment != null && targetEnvironment.getPointerSize() == 8) {
-			MAXADDR = BigInteger.valueOf(0xffffffffffffffffL);
-		}
-		this.address = new Addr64(addressValue.and(MAXADDR));
-		this.isRuntimeAddress = isRuntimeAddress;
-
-		if (checkNonLocalConstVariable)
-			checkNonLocalConstVariableAddr();
-	}
-	
-	/**
-	 * Since a global or static constant variable may be either at a fixed ROM address or at a runtime address,
-	 * and a compiler may not know which is correct when generating debug info, check the address   
-	 */
-	private void checkNonLocalConstVariableAddr() {
-		// TODO: Instead of this, query whether the constant variable's address is a fixed or runtime address
-
-		// Try reading a byte at the supposed address, and, if that fails, switch the sense of this.isRuntimeAddress
-		IAddress theAddress = address;
-		if (!isRuntimeAddress) {
-			StackFrameDMC frame = DMContexts.getAncestorOfType(context, StackFrameDMC.class);
-			if (frame == null) {
-				isRuntimeAddress = !isRuntimeAddress;
-				return;
-			}
-			theAddress = frame.getModule().toRuntimeAddress(theAddress);
-		}
-		
-		ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);
-		
-		Memory memoryService = tracker.getService(Memory.class);
-		ArrayList<MemoryByte> memBuffer = new ArrayList<MemoryByte>(1);
-		IStatus memGetStatus = memoryService.getMemory(exeDMC, theAddress, memBuffer, 1, 1);
-		if (!memGetStatus.isOK()) {
-			isRuntimeAddress = !isRuntimeAddress;
-			return;
-		}
-
-		if (!memBuffer.get(0).isReadable()) {
-			isRuntimeAddress = !isRuntimeAddress;
-			return;
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see java.lang.Object#toString()
-	 */
-	@Override
-	public String toString() {
-		return "0x" + Long.toHexString(address.getValue().longValue()) + //$NON-NLS-1$
-				(isRuntimeAddress ? "" : " (link address)"); //$NON-NLS-1$ //$NON-NLS-2$
-	}
-	
-	public IAddress getAddress() {
-		try {
-			return getRealAddress();
-		} catch (CoreException e) {
-			return null;
-		}
-	}
-
-	public boolean isRuntimeAddress() {
-		return isRuntimeAddress;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.symbols.IVariableLocation#readValue()
-	 */
-	public BigInteger readValue(int varSize) throws CoreException {
-		IAddress theAddress = address;
-		if (!isRuntimeAddress) {
-			theAddress = getRealAddress();
-		}
-		
-		ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);
-		
-		Memory memoryService = tracker.getService(Memory.class);
-		ArrayList<MemoryByte> memBuffer = new ArrayList<MemoryByte>();
-		IStatus memGetStatus = memoryService.getMemory(exeDMC, theAddress, memBuffer, varSize, 1);
-		if (!memGetStatus.isOK()) {
-			throw EDCDebugger.newCoreException(MessageFormat.format(
-					SymbolsMessages.MemoryVariableLocation_CannotReadAddrFormat, theAddress.toHexAddressString()));
-		}
-
-		// check each byte
-		for (int i = 0; i < memBuffer.size(); i++) {
-			if (!memBuffer.get(i).isReadable())
-				throw EDCDebugger.newCoreException(MessageFormat.format(
-					SymbolsMessages.MemoryVariableLocation_CannotReadAddrFormat, theAddress.add(i).getValue().toString(16)));
-		}
-
-		MemoryByte[] memArray = memBuffer.toArray(new MemoryByte[varSize]);
-		
-		return MemoryUtils.convertByteArrayToUnsignedLong(
-				memArray, getEndian());
-	}
-
-	private int getEndian() {
-		ITargetEnvironment targetEnvironment = tracker.getService(ITargetEnvironment.class);
-		int endian = MemoryUtils.LITTLE_ENDIAN;
-		if (targetEnvironment != null)
-			endian = targetEnvironment.isLittleEndian(context) ? MemoryUtils.LITTLE_ENDIAN : MemoryUtils.BIG_ENDIAN;
-		return endian;
-	}
-
-	/**
-	 * @return
-	 * @throws CoreException
-	 */
-	private IAddress getRealAddress() throws CoreException {
-		IAddress theAddress = address;
-		if (!isRuntimeAddress) {
-			StackFrameDMC frame = DMContexts.getAncestorOfType(context, StackFrameDMC.class);
-			if (frame == null) 
-				throw EDCDebugger.newCoreException(SymbolsMessages.MemoryVariableLocation_CannotFindFrame);
-			theAddress = frame.getModule().toRuntimeAddress(theAddress);
-		}
-		return theAddress;
-	}
-	
-	public IVariableLocation addOffset(long offset) {
-		return new MemoryVariableLocation(tracker, context, 
-				address.getValue().add(BigInteger.valueOf(offset)), isRuntimeAddress);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.symbols.IVariableLocation#getLocationName(org.eclipse.cdt.dsf.service.DsfServicesTracker)
-	 */
-	public String getLocationName() {
-		if (!isRuntimeAddress) {
-			try {
-				return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(getRealAddress().getValue().longValue());
-			} catch (CoreException e) {
-				return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(address.getValue().longValue()) + SymbolsMessages.MemoryVariableLocation_LinkTime; // should not happen
-			}
-		} else {
-			return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(address.getValue().longValue());
-		}
-	}
-
-	public void writeValue(final int bytes, BigInteger value) throws CoreException {
-		final byte[] buffer = MemoryUtils.convertSignedBigIntToByteArray(value, getEndian(), bytes);
-		final IAddress theAddress = !isRuntimeAddress ? getRealAddress() : address;
-		final ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);
-	    final Memory memory = tracker.getService(Memory.class);
-		IStatus status = memory.setMemory(exeDMC, theAddress, 1, bytes, buffer);
-		if (!status.isOK()) {
-			throw EDCDebugger.newCoreException(MessageFormat.format(
-					SymbolsMessages.MemoryVariableLocation_CannotWriteAddrFormat, theAddress.toHexAddressString()), status.getException());
-		}
-	}
-
-	public IDMContext getContext() {
-		return context;
-	}
-
-	public EDCServicesTracker getServicesTracker() {
-		return tracker;
-	}
-}
+/*******************************************************************************

+ * 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.symbols;

+

+import java.math.BigInteger;

+import java.text.MessageFormat;

+import java.util.ArrayList;

+

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+

+public class MemoryVariableLocation implements IMemoryVariableLocation {

+

+	protected IAddress address;

+	protected boolean isRuntimeAddress;

+	protected EDCServicesTracker tracker;

+	private IDMContext context;

+

+	public MemoryVariableLocation(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,

+			boolean isRuntimeAddress) {

+		initialize(tracker,context,addressValue,isRuntimeAddress, false);

+	}

+

+	public MemoryVariableLocation(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,

+			boolean isRuntimeAddress, boolean checkNonLocalConstVariable) {

+		// checkConstVariableAddress should only be true for global or static (non-local) constant variables

+		initialize(tracker,context,addressValue,isRuntimeAddress, checkNonLocalConstVariable);

+	}

+

+	private void initialize(EDCServicesTracker tracker, IDMContext context, BigInteger addressValue,

+			boolean isRuntimeAddress, boolean checkNonLocalConstVariable)  {

+		this.tracker = tracker;

+		this.context = context;

+		BigInteger MAXADDR = BigInteger.valueOf(0xffffffffL);

+		ITargetEnvironment targetEnvironment = tracker.getService(ITargetEnvironment.class);

+		if (targetEnvironment != null && targetEnvironment.getPointerSize() == 8) {

+			MAXADDR = BigInteger.valueOf(0xffffffffffffffffL);

+		}

+		this.address = new Addr64(addressValue.and(MAXADDR));

+		this.isRuntimeAddress = isRuntimeAddress;

+

+		if (checkNonLocalConstVariable)

+			checkNonLocalConstVariableAddr();

+	}

+	

+	/**

+	 * Since a global or static constant variable may be either at a fixed ROM address or at a runtime address,

+	 * and a compiler may not know which is correct when generating debug info, check the address   

+	 */

+	private void checkNonLocalConstVariableAddr() {

+		// TODO: Instead of this, query whether the constant variable's address is a fixed or runtime address

+

+		// Try reading a byte at the supposed address, and, if that fails, switch the sense of this.isRuntimeAddress

+		IAddress theAddress = address;

+		if (!isRuntimeAddress) {

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

+			if (frame == null) {

+				isRuntimeAddress = !isRuntimeAddress;

+				return;

+			}

+			theAddress = frame.getModule().toRuntimeAddress(theAddress);

+		}

+		

+		ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);

+		

+		Memory memoryService = tracker.getService(Memory.class);

+		ArrayList<MemoryByte> memBuffer = new ArrayList<MemoryByte>(1);

+		IStatus memGetStatus = memoryService.getMemory(exeDMC, theAddress, memBuffer, 1, 1);

+		if (!memGetStatus.isOK()) {

+			isRuntimeAddress = !isRuntimeAddress;

+			return;

+		}

+

+		if (!memBuffer.get(0).isReadable()) {

+			isRuntimeAddress = !isRuntimeAddress;

+			return;

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see java.lang.Object#toString()

+	 */

+	@Override

+	public String toString() {

+		return "0x" + Long.toHexString(address.getValue().longValue()) + //$NON-NLS-1$

+				(isRuntimeAddress ? "" : " (link address)"); //$NON-NLS-1$ //$NON-NLS-2$

+	}

+	

+	public IAddress getAddress() {

+		try {

+			return getRealAddress();

+		} catch (CoreException e) {

+			return null;

+		}

+	}

+

+	public boolean isRuntimeAddress() {

+		return isRuntimeAddress;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.symbols.IVariableLocation#readValue()

+	 */

+	public BigInteger readValue(int varSize) throws CoreException {

+		IAddress theAddress = address;

+		if (!isRuntimeAddress) {

+			theAddress = getRealAddress();

+		}

+		

+		ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);

+		

+		Memory memoryService = tracker.getService(Memory.class);

+		ArrayList<MemoryByte> memBuffer = new ArrayList<MemoryByte>();

+		IStatus memGetStatus = memoryService.getMemory(exeDMC, theAddress, memBuffer, varSize, 1);

+		if (!memGetStatus.isOK()) {

+			throw EDCDebugger.newCoreException(MessageFormat.format(

+					SymbolsMessages.MemoryVariableLocation_CannotReadAddrFormat, theAddress.toHexAddressString()));

+		}

+

+		// check each byte

+		for (int i = 0; i < memBuffer.size(); i++) {

+			if (!memBuffer.get(i).isReadable())

+				throw EDCDebugger.newCoreException(MessageFormat.format(

+					SymbolsMessages.MemoryVariableLocation_CannotReadAddrFormat, theAddress.add(i).getValue().toString(16)));

+		}

+

+		MemoryByte[] memArray = memBuffer.toArray(new MemoryByte[varSize]);

+		

+		return MemoryUtils.convertByteArrayToUnsignedLong(

+				memArray, getEndian());

+	}

+

+	private int getEndian() {

+		ITargetEnvironment targetEnvironment = tracker.getService(ITargetEnvironment.class);

+		int endian = MemoryUtils.LITTLE_ENDIAN;

+		if (targetEnvironment != null)

+			endian = targetEnvironment.isLittleEndian(context) ? MemoryUtils.LITTLE_ENDIAN : MemoryUtils.BIG_ENDIAN;

+		return endian;

+	}

+

+	/**

+	 * @return

+	 * @throws CoreException

+	 */

+	private IAddress getRealAddress() throws CoreException {

+		IAddress theAddress = address;

+		if (!isRuntimeAddress) {

+			IEDCModuleDMContext module

+			  = DMContexts.getAncestorOfType(context, IEDCModuleDMContext.class);

+			if (module == null) {

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

+				if (frame == null) 

+					throw EDCDebugger.newCoreException(SymbolsMessages.MemoryVariableLocation_CannotFindFrame);

+				module = frame.getModule();

+			}

+			theAddress = module.toRuntimeAddress(theAddress);

+		}

+		return theAddress;

+	}

+

+	public IVariableLocation addOffset(long offset) {

+		return new MemoryVariableLocation(tracker, context, 

+				address.getValue().add(BigInteger.valueOf(offset)), isRuntimeAddress);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.symbols.IVariableLocation#getLocationName(org.eclipse.cdt.dsf.service.DsfServicesTracker)

+	 */

+	public String getLocationName() {

+		if (!isRuntimeAddress) {

+			try {

+				return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(getRealAddress().getValue().longValue());

+			} catch (CoreException e) {

+				return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(address.getValue().longValue()) + SymbolsMessages.MemoryVariableLocation_LinkTime; // should not happen

+			}

+		} else {

+			return SymbolsMessages.MemoryVariableLocation_Hex + Long.toHexString(address.getValue().longValue());

+		}

+	}

+

+	public void writeValue(final int bytes, BigInteger value) throws CoreException {

+		final byte[] buffer = MemoryUtils.convertSignedBigIntToByteArray(value, getEndian(), bytes);

+		final IAddress theAddress = !isRuntimeAddress ? getRealAddress() : address;

+		final ExecutionDMC exeDMC = DMContexts.getAncestorOfType(context, ExecutionDMC.class);

+	    final Memory memory = tracker.getService(Memory.class);

+		IStatus status = memory.setMemory(exeDMC, theAddress, 1, bytes, buffer);

+		if (!status.isOK()) {

+			throw EDCDebugger.newCoreException(MessageFormat.format(

+					SymbolsMessages.MemoryVariableLocation_CannotWriteAddrFormat, theAddress.toHexAddressString()), status.getException());

+		}

+	}

+

+	public IDMContext getContext() {

+		return context;

+	}

+

+	public void setModuleContext(IEDCModuleDMContext ctx) {

+		context = ctx;

+	}

+

+	public EDCServicesTracker getServicesTracker() {

+		return tracker;

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ModuleLineEntryProvider.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ModuleLineEntryProvider.java
index a8c94a4..34bd5dc 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ModuleLineEntryProvider.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ModuleLineEntryProvider.java
@@ -1,434 +1,433 @@
-/**
- * Copyright (c) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * This component and the accompanying materials are made available
- * under the terms of the License "Eclipse Public License v1.0"
- * which accompanies this distribution, and is available
- * at the URL "http://www.eclipse.org/legal/epl-v10.html".
- *
- * Initial Contributors:
- * Nokia Corporation - initial contribution
- * 					   refactoring of FileLineEntryProvider to separate class
- *
- * Contributors:
- * Broadcom - convert private class extensions to final
- *
- */
-
-package org.eclipse.cdt.debug.edc.internal.symbols;
-
-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.edc.internal.PathUtils;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.EDCLineAddresses;
-import org.eclipse.cdt.debug.edc.symbols.ICompileUnitScope;
-import org.eclipse.cdt.debug.edc.symbols.IFunctionScope;
-import org.eclipse.cdt.debug.edc.symbols.ILineEntry;
-import org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider;
-import org.eclipse.cdt.debug.edc.symbols.IModuleLineEntryProvider;
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-import org.eclipse.core.runtime.IPath;
-
-/**
- * This class holds a conglomeration of line entry data for an entire
- * module.  
- */
-public class ModuleLineEntryProvider implements IModuleLineEntryProvider {
-	
-	/**
-	 *	basically, a typedef of {@link ArrayList}&lt;{@link FileLineEntryProvider}&gt;
-	 */
-	private static final class FileLineEntryProviders extends ArrayList<FileLineEntryProvider> {
-		private static final long serialVersionUID = -2157263701372708990L;		
-	}
-
-	/**
-	 *	basically, a typedef of {@link HashMap}&lt;{@link IPath},{@link FileLineEntryProvider}&gt;
-	 */
-	private static final class PathToLineEntryMap extends HashMap<IPath, FileLineEntryProviders> {
-		private static final long serialVersionUID = 7064789571684986782L;
-	}
-
-	// CUs we've already considered
-	private Set<ICompileUnitScope> parsedCUs = new HashSet<ICompileUnitScope>();
-	// mapping to find info for a given path
-	private PathToLineEntryMap pathToLineEntryMap = new PathToLineEntryMap();
-	// all known providers
-	private FileLineEntryProviders fileProviders = new FileLineEntryProviders();
-	// cached array of providers
-	private FileLineEntryProvider[] fileProviderArray;
-
-	public ModuleLineEntryProvider() {
-
-	}
-
-	
-	/**
-	 * Add the line entries from a compilation unit to the mapper.
-	 * @param scope
-	 */
-	public void addCompileUnit(ICompileUnitScope cu) {
-		if (parsedCUs.contains(cu))
-			return;
-		
-		parsedCUs.add(cu);
-		
-		Collection<ILineEntry> lineEntries = cu.getLineEntries();
-		
-		if (lineEntries.size() > 0) {
-			// files created for this compile unit scope (union of all CUs in this.lineEntryMap)
-			// (kept because we visit the same file a lot in this function)
-			Map<IPath, FileLineEntryProvider> fileProviders = new HashMap<IPath, FileLineEntryProvider>(4);
-			
-			// go through each entry and extract entries for each file.
-			//
-			// allocate one FileLineEntryProvider per CU
-			//
-			for (ILineEntry entry : lineEntries) {
-				IPath path = entry.getFilePath();
-				
-				FileLineEntryProvider provider = fileProviders.get(path);
-				if (provider == null) {
-					// This will look for an existing one and create a 
-					// new one if none exits.
-					provider = getFileLineProviderForCU(cu,	path);
-					provider.setCULineEntries(lineEntries);
-					fileProviders.put(path, provider);
-				}
-	
-				provider.addLineEntry(entry);
-			}
-		}
-		
-		// then, look for lines provided by decl file/line/column entries
-		for (IScope child : cu.getChildren()) {
-			addCompileUnitChild(cu, child);
-		}
-	}
-
-
-
-	/**
-	 * Add (or update) a compile unit child entry (function) by adding a
-	 * line entry for its declaration location, which may differ from the
-	 * first line inside the function to which the low PC refers. 
-	 * @param cu
-	 * @param child
-	 */
-	public void addCompileUnitChild(ICompileUnitScope cu, IScope child) {
-		if (child instanceof IFunctionScope) {
-			IFunctionScope func = (IFunctionScope) child;
-			IPath declFile = func.getDeclFile();
-			
-			if (declFile != null) {
-				// this is the slow path for dynamic parsing
-				FileLineEntryProvider provider
-				  = getFileLineProviderForCU(cu, declFile);
-				
-				int declLine = func.getDeclLine();
-				int declColumn = func.getDeclColumn();
-				
-				// is there already an entry at this line?
-				Collection<ILineEntry> curEntries
-				  = provider.getLineEntriesForLines(declFile, declLine, declLine);
-				if (curEntries.isEmpty()) {
-					// no, add one, and make it range from our start to the first actual line
-					
-					LineEntry entry
-					  = new LineEntry(declFile, declLine, declColumn,
-									  func.getLowAddress(), func.getLowAddress());
-					provider.addLineEntry(entry);
-				}
-			}
-		}	
-	}
-
-
-	private FileLineEntryProvider getFileLineProviderForCU(
-			ICompileUnitScope cu, IPath declFile) {
-		FileLineEntryProviders providers = pathToLineEntryMap.get(declFile);
-		if (providers != null) {
-			for (FileLineEntryProvider p : providers) {
-				if (p.getCU().equals(cu)) {
-					return p;
-				}
-			}
-		}
-		FileLineEntryProvider provider = new FileLineEntryProvider(cu, declFile);
-		registerFileLineEntryProvider(declFile, provider);
-		return provider;
-	}
-
-
-
-	private void registerFileLineEntryProvider(IPath path,
-			FileLineEntryProvider provider) {
-		FileLineEntryProviders fileEntries = pathToLineEntryMap.get(path);
-		if (fileEntries == null) {
-			fileEntries = new FileLineEntryProviders();
-			pathToLineEntryMap.put(path, fileEntries);
-		}
-		fileEntries.add(provider);
-		fileProviders.add(provider);
-		fileProviderArray = null;
-	}
-	
-	/**
-	 * Get the line entry providers for the given source file.  
-	 * @path sourceFile the absolute path to the source file
-	 * @return the unmodifiable list of providers for the file, possibly empty.
-	 */
-	public Collection<ILineEntryProvider> getLineEntryProvidersForFile(IPath sourceFile) {
-		List<? extends ILineEntryProvider> cus = pathToLineEntryMap.get(sourceFile);
-		if (cus != null)
-			return Collections.unmodifiableCollection(cus);
-		
-		for (Map.Entry<IPath, FileLineEntryProviders> entry : pathToLineEntryMap.entrySet()) {
-			if (!PathUtils.isCaseSensitive() && entry.getKey().toOSString().compareToIgnoreCase(sourceFile.toOSString()) == 0) {
-				cus = entry.getValue();
-				pathToLineEntryMap.put(sourceFile, entry.getValue());
-				return Collections.unmodifiableCollection(cus);
-			}
-		}
-		
-		for (Map.Entry<IPath, FileLineEntryProviders> entry : pathToLineEntryMap.entrySet()) {
-			if (entry.getKey().equals(sourceFile)) {
-				cus = entry.getValue();
-				return Collections.unmodifiableCollection(cus);
-			}
-		}
-		
-		return Collections.emptyList();
-	}
-
-
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getLineEntriesForLines(org.eclipse.core.runtime.IPath, int, int)
-	 */
-	public Collection<ILineEntry> getLineEntriesForLines(IPath file,
-			int startLineNumber, int endLineNumber) {
-		FileLineEntryProviders matches = pathToLineEntryMap.get(file);
-		if (matches == null)
-			return Collections.emptyList();
-		
-		List<ILineEntry> ret = null;
-		for (FileLineEntryProvider provider : matches) {
-			Collection<ILineEntry> entries
-			  = provider.getLineEntriesForLines(file, startLineNumber, endLineNumber);
-			if (!entries.isEmpty()) {
-				if (ret == null)
-					ret = new ArrayList<ILineEntry>(entries);
-				else
-					ret.addAll(entries);
-			}
-		}
-		if (ret == null)
-			return Collections.emptyList();
-		
-		return ret;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getLineEntryAtAddress(org.eclipse.cdt.core.IAddress)
-	 */
-	public ILineEntry getLineEntryAtAddress(IAddress linkAddress) {
-		// scanning files can introduce new file providers; avoid ConcurrentModificationException
-		if (fileProviderArray == null) {
-			fileProviderArray = fileProviders.toArray(new FileLineEntryProvider[fileProviders.size()]);
-		}
-		for (FileLineEntryProvider provider : fileProviderArray) {
-			// Narrow down the search to avoid iterating potentially hundreds
-			// of duplicates of the same file 
-			// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).
-			// (Don't use #getScopeAtAddress() since this preparses too much.)
-			if (provider.getCU().getLowAddress().compareTo(linkAddress) <= 0
-					&& provider.getCU().getHighAddress().compareTo(linkAddress) > 0) {
-				ILineEntry entry = provider.getLineEntryAtAddress(linkAddress);
-				if (entry != null
-
-					/*	FIXME: sigh ...
-					 *
-					 *	yet another RVCT DWARF inlined LNT entry generation bug ...
-					 *
-					 *	we just can't have entry.highAddr == entry.lowAddr!
-					 *
-					 *	that just TOTALLY ruins the illusion of stepping.
-					 *
-					 *	see, if we pass back the address we're on,
-					 *	no step-over range will get created,
-					 *	and the debugger will just run ...
-					 *		
-					 *	... and that's just NotGood-TM .
-					 */
-						&& !entry.getLowAddress().equals(entry.getHighAddress())
-
-						) {
-					return entry;
-				}
-			}
-		}
-		return null;
-	}
-
-
-	public ILineEntry getLineEntryInFunction(IAddress linkAddress, IFunctionScope parentFunction) {
-		ILineEntry functionEntry = getLineEntryAtAddress(parentFunction.getLowAddress());
-		if (functionEntry == null)
-			return null;
-		Collection<ILineEntryProvider> parentProviders
-		  = getLineEntryProvidersForFile(functionEntry.getFilePath());
-		for (ILineEntryProvider iLineEntryProvider : parentProviders) {
-			if (iLineEntryProvider instanceof FileLineEntryProvider) {
-				ILineEntry entry
-				  = ((FileLineEntryProvider)iLineEntryProvider).getLineEntryInFunction(linkAddress, parentFunction);
-				if (entry != null)
-					return entry;
-			}
-		}
-		return null;
-	}
-
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getNextLineEntry(org.eclipse.cdt.debug.edc.internal.symbols.ILineEntry)
-	 */
-	public ILineEntry getNextLineEntry(final ILineEntry entry, final boolean collapseInlineFunctions) {
-		if (entry == null)
-			return null;
-
-		final IAddress entryLowAddr = entry.getLowAddress();
-		final IAddress entryHighAddr = entry.getHighAddress();
-		final IPath entryPath = entry.getFilePath();
-		FileLineEntryProviders matches = pathToLineEntryMap.get(entryPath);
-		if (matches == null)
-			return null;
-
-		// avoid possible concurrent access if we read new files while searching
-		FileLineEntryProvider[] matchArray = matches.toArray(new FileLineEntryProvider[matches.size()]);
-
-		for (FileLineEntryProvider provider : matchArray) {
-			ICompileUnitScope cuScope = provider.getCU();
-			// Narrow down the search to avoid iterating potentially hundreds of duplicates of the same file 
-			// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).
-			// (Don't use #getScopeAtAddress() since this preparses too much.).
-			if (cuScope.getLowAddress().compareTo(entryLowAddr) <= 0
-					// NOTE: high addrs for both scope & line entries are inclusive: thus >= 0
-					&& cuScope.getHighAddress().compareTo(entryHighAddr) >= 0) {
-
-				// provider.getNextLineEntry() returns null for only 1 reason:
-				// 1) there are no more entries at all for the compileUnitScope
-				//
-				// so there's no need to continue looking in other providers
-				return provider.getNextLineEntry(entry, collapseInlineFunctions);
-			}
-		}
-
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getPreviousLineEntry
-	 */
-	public ILineEntry getPreviousLineEntry(ILineEntry entry,
-			boolean collapseInlineFunctions) {
-		if (entry == null)
-			return null;
-
-		FileLineEntryProviders matches = pathToLineEntryMap.get(entry.getFilePath());
-		if (matches != null) {
-			final IAddress entryLowAddr  = entry.getLowAddress();
-			final IAddress entryHighAddr = entry.getHighAddress();
-			boolean entryIsInline = false, inlineEstablished = false;
-
-			// avoid possible concurrent access if we read new files while searching
-			FileLineEntryProvider[] matchArray = matches.toArray(new FileLineEntryProvider[matches.size()]);
-
-			for (FileLineEntryProvider provider : matchArray) {
-				ICompileUnitScope cuScope = provider.getCU();
-				// Narrow down the search to avoid iterating potentially hundreds of duplicates of the same file 
-				// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).
-				// (Don't use #getScopeAtAddress() since this preparses too much.).
-				//
-				// 
-				if (cuScope.getLowAddress().compareTo(entryLowAddr) <= 0
-						// NOTE: high addrs for both scope & line entries are inclusive: thus >= 0
-						&& cuScope.getHighAddress().compareTo(entryHighAddr) >= 0) {
-					if (!inlineEstablished) {
-						entryIsInline = FileLineEntryProvider.isInlinedFunction(cuScope.getFunctionAtAddress(entryLowAddr));
-						inlineEstablished = true;
-					}
-					ILineEntry prev = provider.getPreviousLineEntry(entry, collapseInlineFunctions);
-					if (prev == null && collapseInlineFunctions && entryIsInline) {
-						// retry with the provider mapped from the compileUnitScope.filePath
-						return provider.getPreviousLineEntryInCU(entry);
-					}
-
-					if (prev != null) {	// in case there's another provider
-						return prev;
-					}
-				}
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#findClosestLineWithCode(org.eclipse.core.runtime.IPath, int, int)
-	 */
-	public List<ILineAddresses> findClosestLineWithCode(IPath sourceFile,
-			int anchorLine, int neighbor_limit) {
-		List<ILineAddresses> ret = new ArrayList<ILineAddresses>(1);
-
-		/* Check all compile units in the module for code line.
-		  */ 
-		Collection<? extends ILineEntryProvider> fileProviders = 
-			getLineEntryProvidersForFile(sourceFile);
-		if (fileProviders.isEmpty())
-			return ret;
-
-		for (ILineEntryProvider fileProvider : fileProviders) {
-			
-			// Find code line in one CU using the source file
-			List<ILineAddresses> la = fileProvider.findClosestLineWithCode(sourceFile, anchorLine, neighbor_limit);
-			if (la.isEmpty())
-				continue;
-			assert (la.size() == 1);
-			ILineAddresses newCodeLine = la.get(0);
-			
-			if (ret.isEmpty())
-				ret.add(newCodeLine);
-			else {
-				boolean merged = false;
-				for (ILineAddresses e : ret)
-					if (newCodeLine.getLineNumber() == e.getLineNumber()) {
-						((EDCLineAddresses)e).addAddress(newCodeLine.getAddress());
-						merged = true;
-						break;
-					}
-			
-				if (!merged)
-					ret.add(newCodeLine);
-			}
-		}
-		
-		return ret;
-	}
-
-
-	public boolean hasSourceFile(IPath sourceFile) {
-		Collection<? extends ILineEntryProvider> fileProviders = 
-			getLineEntryProvidersForFile(sourceFile);
-		return fileProviders != null && ! fileProviders.isEmpty();
-	}
-	
-}
+/**

+ * Copyright (c) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).

+ * All rights reserved.

+ * This component and the accompanying materials are made available

+ * under the terms of the License "Eclipse Public License v1.0"

+ * which accompanies this distribution, and is available

+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".

+ *

+ * Initial Contributors:

+ * Nokia Corporation - initial contribution

+ * 					   refactoring of FileLineEntryProvider to separate class

+ *

+ * Contributors:

+ * Broadcom - convert private class extensions to final

+ *

+ */

+

+package org.eclipse.cdt.debug.edc.internal.symbols;

+

+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.edc.internal.PathUtils;

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

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

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

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

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

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

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

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

+

+/**

+ * This class holds a conglomeration of line entry data for an entire

+ * module.  

+ */

+public class ModuleLineEntryProvider implements IModuleLineEntryProvider {

+	

+	/**

+	 *	basically, a typedef of {@link ArrayList}&lt;{@link FileLineEntryProvider}&gt;

+	 */

+	private static final class FileLineEntryProviders extends ArrayList<FileLineEntryProvider> {

+		private static final long serialVersionUID = -2157263701372708990L;		

+	}

+

+	/**

+	 *	basically, a typedef of {@link HashMap}&lt;{@link IPath},{@link FileLineEntryProvider}&gt;

+	 */

+	private static final class PathToLineEntryMap extends HashMap<IPath, FileLineEntryProviders> {

+		private static final long serialVersionUID = 7064789571684986782L;

+	}

+

+	// CUs we've already considered

+	private Set<ICompileUnitScope> parsedCUs = new HashSet<ICompileUnitScope>();

+	// mapping to find info for a given path

+	private PathToLineEntryMap pathToLineEntryMap = new PathToLineEntryMap();

+	// all known providers

+	private FileLineEntryProviders fileProviders = new FileLineEntryProviders();

+	// cached array of providers

+	private FileLineEntryProvider[] fileProviderArray;

+

+	public ModuleLineEntryProvider() {

+

+	}

+	

+	/**

+	 * Add the line entries from a compilation unit to the mapper.

+	 * @param scope

+	 */

+	public void addCompileUnit(ICompileUnitScope cu) {

+		if (parsedCUs.contains(cu))

+			return;

+		

+		parsedCUs.add(cu);

+		

+		Collection<ILineEntry> lineEntries = cu.getLineEntries();

+		

+		if (lineEntries.size() > 0) {

+			// files created for this compile unit scope (union of all CUs in this.lineEntryMap)

+			// (kept because we visit the same file a lot in this function)

+			Map<IPath, FileLineEntryProvider> fileProviders = new HashMap<IPath, FileLineEntryProvider>(4);

+			

+			// go through each entry and extract entries for each file.

+			//

+			// allocate one FileLineEntryProvider per CU

+			//

+			for (ILineEntry entry : lineEntries) {

+				IPath path = entry.getFilePath();

+				

+				FileLineEntryProvider provider = fileProviders.get(path);

+				if (provider == null) {

+					// This will look for an existing one and create a 

+					// new one if none exits.

+					provider = getFileLineProviderForCU(cu,	path);

+					provider.setCULineEntries(lineEntries);

+					fileProviders.put(path, provider);

+				}

+	

+				provider.addLineEntry(entry);

+			}

+		}

+		

+		// then, look for lines provided by decl file/line/column entries

+		for (IScope child : cu.getChildren()) {

+			addCompileUnitChild(cu, child);

+		}

+	}

+

+

+

+	/**

+	 * Add (or update) a compile unit child entry (function) by adding a

+	 * line entry for its declaration location, which may differ from the

+	 * first line inside the function to which the low PC refers. 

+	 * @param cu

+	 * @param child

+	 */

+	public void addCompileUnitChild(ICompileUnitScope cu, IScope child) {

+		if (child instanceof IFunctionScope) {

+			IFunctionScope func = (IFunctionScope) child;

+			IPath declFile = func.getDeclFile();

+			

+			if (declFile != null) {

+				// this is the slow path for dynamic parsing

+				FileLineEntryProvider provider

+				  = getFileLineProviderForCU(cu, declFile);

+				

+				int declLine = func.getDeclLine();

+				int declColumn = func.getDeclColumn();

+				

+				// is there already an entry at this line?

+				Collection<ILineEntry> curEntries

+				  = provider.getLineEntriesForLines(declFile, declLine, declLine);

+				if (curEntries.isEmpty()) {

+					// no, add one, and make it range from our start to the first actual line

+					

+					LineEntry entry

+					  = new LineEntry(declFile, declLine, declColumn,

+									  func.getLowAddress(), func.getLowAddress());

+					provider.addLineEntry(entry);

+				}

+			}

+		}	

+	}

+

+

+	private FileLineEntryProvider getFileLineProviderForCU(

+			ICompileUnitScope cu, IPath declFile) {

+		FileLineEntryProviders providers = pathToLineEntryMap.get(declFile);

+		if (providers != null) {

+			for (FileLineEntryProvider p : providers) {

+				if (p.getCU().equals(cu)) {

+					return p;

+				}

+			}

+		}

+		FileLineEntryProvider provider = new FileLineEntryProvider(cu, declFile);

+		registerFileLineEntryProvider(declFile, provider);

+		return provider;

+	}

+

+

+

+	private void registerFileLineEntryProvider(IPath path,

+			FileLineEntryProvider provider) {

+		FileLineEntryProviders fileEntries = pathToLineEntryMap.get(path);

+		if (fileEntries == null) {

+			fileEntries = new FileLineEntryProviders();

+			pathToLineEntryMap.put(path, fileEntries);

+		}

+		fileEntries.add(provider);

+		fileProviders.add(provider);

+		fileProviderArray = null;

+	}

+	

+	/**

+	 * Get the line entry providers for the given source file.  

+	 * @path sourceFile the absolute path to the source file

+	 * @return the unmodifiable list of providers for the file, possibly empty.

+	 */

+	public Collection<ILineEntryProvider> getLineEntryProvidersForFile(IPath sourceFile) {

+		List<? extends ILineEntryProvider> cus = pathToLineEntryMap.get(sourceFile);

+		if (cus != null)

+			return Collections.unmodifiableCollection(cus);

+		

+		for (Map.Entry<IPath, FileLineEntryProviders> entry : pathToLineEntryMap.entrySet()) {

+			if (!PathUtils.isCaseSensitive() && entry.getKey().toOSString().compareToIgnoreCase(sourceFile.toOSString()) == 0) {

+				cus = entry.getValue();

+				pathToLineEntryMap.put(sourceFile, entry.getValue());

+				return Collections.unmodifiableCollection(cus);

+			}

+		}

+		

+		for (Map.Entry<IPath, FileLineEntryProviders> entry : pathToLineEntryMap.entrySet()) {

+			if (entry.getKey().equals(sourceFile)) {

+				cus = entry.getValue();

+				return Collections.unmodifiableCollection(cus);

+			}

+		}

+		

+		return Collections.emptyList();

+	}

+

+

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getLineEntriesForLines(org.eclipse.core.runtime.IPath, int, int)

+	 */

+	public Collection<ILineEntry> getLineEntriesForLines(IPath file,

+			int startLineNumber, int endLineNumber) {

+		FileLineEntryProviders matches = pathToLineEntryMap.get(file);

+		if (matches == null)

+			return Collections.emptyList();

+		

+		List<ILineEntry> ret = null;

+		for (FileLineEntryProvider provider : matches) {

+			Collection<ILineEntry> entries

+			  = provider.getLineEntriesForLines(file, startLineNumber, endLineNumber);

+			if (!entries.isEmpty()) {

+				if (ret == null)

+					ret = new ArrayList<ILineEntry>(entries);

+				else

+					ret.addAll(entries);

+			}

+		}

+		if (ret == null)

+			return Collections.emptyList();

+		

+		return ret;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getLineEntryAtAddress(org.eclipse.cdt.core.IAddress)

+	 */

+	public ILineEntry getLineEntryAtAddress(IAddress linkAddress) {

+		// scanning files can introduce new file providers; avoid ConcurrentModificationException

+		if (fileProviderArray == null) {

+			fileProviderArray = fileProviders.toArray(new FileLineEntryProvider[fileProviders.size()]);

+		}

+		for (FileLineEntryProvider provider : fileProviderArray) {

+			// Narrow down the search to avoid iterating potentially hundreds

+			// of duplicates of the same file 

+			// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).

+			// (Don't use #getScopeAtAddress() since this preparses too much.)

+			if (provider.getCU().getLowAddress().compareTo(linkAddress) <= 0

+					&& provider.getCU().getHighAddress().compareTo(linkAddress) > 0) {

+				ILineEntry entry = provider.getLineEntryAtAddress(linkAddress);

+				if (entry != null

+

+					/*	FIXME: sigh ...

+					 *

+					 *	yet another RVCT DWARF inlined LNT entry generation bug ...

+					 *

+					 *	we just can't have entry.highAddr == entry.lowAddr!

+					 *

+					 *	that just TOTALLY ruins the illusion of stepping.

+					 *

+					 *	see, if we pass back the address we're on,

+					 *	no step-over range will get created,

+					 *	and the debugger will just run ...

+					 *		

+					 *	... and that's just NotGood-TM .

+					 */

+						&& !entry.getLowAddress().equals(entry.getHighAddress())

+

+						) {

+					return entry;

+				}

+			}

+		}

+		return null;

+	}

+

+

+	public ILineEntry getLineEntryInFunction(IAddress linkAddress, IFunctionScope parentFunction) {

+		ILineEntry functionEntry = getLineEntryAtAddress(parentFunction.getLowAddress());

+		if (functionEntry == null)

+			return null;

+		Collection<ILineEntryProvider> parentProviders

+		  = getLineEntryProvidersForFile(functionEntry.getFilePath());

+		for (ILineEntryProvider iLineEntryProvider : parentProviders) {

+			if (iLineEntryProvider instanceof FileLineEntryProvider) {

+				ILineEntry entry

+				  = ((FileLineEntryProvider)iLineEntryProvider).getLineEntryInFunction(linkAddress, parentFunction);

+				if (entry != null)

+					return entry;

+			}

+		}

+		return null;

+	}

+

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getNextLineEntry(org.eclipse.cdt.debug.edc.internal.symbols.ILineEntry)

+	 */

+	public ILineEntry getNextLineEntry(final ILineEntry entry, final boolean collapseInlineFunctions) {

+		if (entry == null)

+			return null;

+

+		final IAddress entryLowAddr = entry.getLowAddress();

+		final IAddress entryHighAddr = entry.getHighAddress();

+		final IPath entryPath = entry.getFilePath();

+		FileLineEntryProviders matches = pathToLineEntryMap.get(entryPath);

+		if (matches == null)

+			return null;

+

+		// avoid possible concurrent access if we read new files while searching

+		FileLineEntryProvider[] matchArray = matches.toArray(new FileLineEntryProvider[matches.size()]);

+

+		for (FileLineEntryProvider provider : matchArray) {

+			ICompileUnitScope cuScope = provider.getCU();

+			// Narrow down the search to avoid iterating potentially hundreds of duplicates of the same file 

+			// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).

+			// (Don't use #getScopeAtAddress() since this preparses too much.).

+			if (cuScope.getLowAddress().compareTo(entryLowAddr) <= 0

+					// NOTE: high addrs for both scope & line entries are inclusive: thus >= 0

+					&& cuScope.getHighAddress().compareTo(entryHighAddr) >= 0) {

+

+				// provider.getNextLineEntry() returns null for only 1 reason:

+				// 1) there are no more entries at all for the compileUnitScope

+				//

+				// so there's no need to continue looking in other providers

+				return provider.getNextLineEntry(entry, collapseInlineFunctions);

+			}

+		}

+

+		return null;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.ILineEntryProvider#getPreviousLineEntry

+	 */

+	public ILineEntry getPreviousLineEntry(ILineEntry entry,

+			boolean collapseInlineFunctions) {

+		if (entry == null)

+			return null;

+

+		FileLineEntryProviders matches = pathToLineEntryMap.get(entry.getFilePath());

+		if (matches != null) {

+			final IAddress entryLowAddr  = entry.getLowAddress();

+			final IAddress entryHighAddr = entry.getHighAddress();

+			boolean entryIsInline = false, inlineEstablished = false;

+

+			// avoid possible concurrent access if we read new files while searching

+			FileLineEntryProvider[] matchArray = matches.toArray(new FileLineEntryProvider[matches.size()]);

+

+			for (FileLineEntryProvider provider : matchArray) {

+				ICompileUnitScope cuScope = provider.getCU();

+				// Narrow down the search to avoid iterating potentially hundreds of duplicates of the same file 

+				// (e.g. for stl_vector.h, expanded N times for N std::vector<T> uses).

+				// (Don't use #getScopeAtAddress() since this preparses too much.).

+				//

+				// 

+				if (cuScope.getLowAddress().compareTo(entryLowAddr) <= 0

+						// NOTE: high addrs for both scope & line entries are inclusive: thus >= 0

+						&& cuScope.getHighAddress().compareTo(entryHighAddr) >= 0) {

+					if (!inlineEstablished) {

+						entryIsInline = FileLineEntryProvider.isInlinedFunction(cuScope.getFunctionAtAddress(entryLowAddr));

+						inlineEstablished = true;

+					}

+					ILineEntry prev = provider.getPreviousLineEntry(entry, collapseInlineFunctions);

+					if (prev == null && collapseInlineFunctions && entryIsInline) {

+						// retry with the provider mapped from the compileUnitScope.filePath

+						return provider.getPreviousLineEntryInCU(entry);

+					}

+

+					if (prev != null) {	// in case there's another provider

+						return prev;

+					}

+				}

+			}

+		}

+		return null;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#findClosestLineWithCode(org.eclipse.core.runtime.IPath, int, int)

+	 */

+	public List<ILineAddresses> findClosestLineWithCode(IPath sourceFile,

+			int anchorLine, int neighbor_limit) {

+		List<ILineAddresses> ret = new ArrayList<ILineAddresses>(1);

+

+		/* Check all compile units in the module for code line.

+		  */ 

+		Collection<? extends ILineEntryProvider> fileProviders = 

+			getLineEntryProvidersForFile(sourceFile);

+		if (fileProviders.isEmpty())

+			return ret;

+

+		for (ILineEntryProvider fileProvider : fileProviders) {

+			

+			// Find code line in one CU using the source file

+			List<ILineAddresses> la = fileProvider.findClosestLineWithCode(sourceFile, anchorLine, neighbor_limit);

+			if (la.isEmpty())

+				continue;

+			assert (la.size() == 1);

+			ILineAddresses newCodeLine = la.get(0);

+			

+			if (ret.isEmpty())

+				ret.add(newCodeLine);

+			else {

+				boolean merged = false;

+				for (ILineAddresses e : ret)

+					if (newCodeLine.getLineNumber() == e.getLineNumber()) {

+						((EDCLineAddresses)e).addAddress(newCodeLine.getAddress());

+						merged = true;

+						break;

+					}

+			

+				if (!merged)

+					ret.add(newCodeLine);

+			}

+		}

+		

+		return ret;

+	}

+

+

+	public boolean hasSourceFile(IPath sourceFile) {

+		Collection<? extends ILineEntryProvider> fileProviders = 

+			getLineEntryProvidersForFile(sourceFile);

+		return fileProviders != null && ! fileProviders.isEmpty();

+	}

+	

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/PointerType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/PointerType.java
index 4ba1294..5c952dc 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/PointerType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/PointerType.java
@@ -1,28 +1,37 @@
-/*******************************************************************************
- * 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.symbols;
-
-import java.util.Map;
-
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-
-public class PointerType extends MayBeQualifiedType implements IPointerType {
-
-	public PointerType(String name, IScope scope, int byteSize, Map<Object, Object> properties) {
-		super(name, scope, byteSize, properties);
-	}
-
-	// create an internal pointer for expression evaluation
-	public PointerType() {
-		super("", null, 0, null); //$NON-NLS-1$
-	}
-
-}
+/*******************************************************************************

+ * 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.symbols;

+

+import java.util.Map;

+

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

+

+public class PointerType extends MayBeQualifiedType implements IPointerType {

+	protected long runtimeOffset = 0;

+

+	public PointerType(String name, IScope scope, int byteSize, Map<Object, Object> properties) {

+		super(name, scope, byteSize, properties);

+	}

+

+	// create an internal pointer for expression evaluation

+	public PointerType() {

+		super("", null, 0, null); //$NON-NLS-1$

+	}

+

+	public long getRuntimeOffset() {

+		return runtimeOffset;

+	}

+

+	public void setRuntimeOffset(long runtimeOffset) {

+		this.runtimeOffset = runtimeOffset;

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ReferenceType.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ReferenceType.java
index ce308d5..cbe9cc7 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ReferenceType.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/ReferenceType.java
@@ -1,22 +1,32 @@
-/*******************************************************************************
- * 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.symbols;
-
-import java.util.Map;
-
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-
-public class ReferenceType extends Type implements IReferenceType {
-	
-	public ReferenceType(String name, IScope scope, int byteSize, Map<Object, Object> properties) {
-		super(name, scope, byteSize, properties);
-	}
-}
+/*******************************************************************************

+ * 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.symbols;

+

+import java.util.Map;

+

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

+

+public class ReferenceType extends Type implements IReferenceType {

+	protected long runtimeOffset = 0;

+	

+	public ReferenceType(String name, IScope scope, int byteSize, Map<Object, Object> properties) {

+		super(name, scope, byteSize, properties);

+	}

+

+	public long getRuntimeOffset() {

+		return runtimeOffset;

+	}

+

+	public void setRuntimeOffset(long runtimeOffset) {

+		this.runtimeOffset = runtimeOffset;

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Scope.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Scope.java
index 2b030fa..cc207f1 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Scope.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Scope.java
@@ -1,435 +1,437 @@
-/*******************************************************************************
- * 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.symbols;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.RangeList;
-import org.eclipse.cdt.debug.edc.symbols.ICompileUnitScope;
-import org.eclipse.cdt.debug.edc.symbols.IEnumerator;
-import org.eclipse.cdt.debug.edc.symbols.IModuleScope;
-import org.eclipse.cdt.debug.edc.symbols.IRangeList;
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-import org.eclipse.cdt.debug.edc.symbols.IVariable;
-import org.eclipse.cdt.debug.edc.symbols.IRangeList.Entry;
-import org.eclipse.cdt.utils.Addr32;
-import org.eclipse.cdt.utils.Addr64;
-
-/**
- * abstract implementation of {@link IScope},
- * optionally containing a name, low & high addresses, IScope parent,
- * children, variables, enumerators, et al
- *
- */
-public abstract class Scope implements IScope {
-
-	protected String name;
-	protected IAddress lowAddress;
-	protected IAddress highAddress;
-	protected IScope parent;
-	protected List<IScope> children = new ArrayList<IScope>();
-	protected List<IVariable> variables = new ArrayList<IVariable>();
-	protected List<IEnumerator> enumerators = new ArrayList<IEnumerator>();
-	private TreeMap<IRangeList.Entry, IScope> addressToScopeMap;
-	
-	protected IRangeList rangeList;
-
-	public Scope(String name, IAddress lowAddress, IAddress highAddress, IScope parent) {
-		this.name = name;
-		this.lowAddress = lowAddress;
-		this.highAddress = highAddress;
-		this.parent = parent;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public IAddress getLowAddress() {
-		return lowAddress;
-	}
-
-	public IAddress getHighAddress() {
-		return highAddress;
-	}
-
-	/**
-	 * Tell whether the address range for the scope is empty.
-	 * @return flag
-	 */
-	public boolean hasEmptyRange() {
-		return (lowAddress == null || highAddress == null)
-		|| (lowAddress.isZero() && highAddress.isZero())
-		|| (lowAddress.getValue().longValue() == -1 && highAddress.isZero()) // TODO: remove this case
-		|| lowAddress.equals(highAddress);
-	}
-
-	/**
-	 * Return the list of non-contiguous ranges for this scope.
-	 * @return list or <code>null</code>
-	 */
-	public IRangeList getRangeList() {
-		return rangeList;
-	}
-
-	public void setLowAddress(IAddress lowAddress) {
-		this.lowAddress = lowAddress;
-	}
-
-	public void setHighAddress(IAddress highAddress) {
-		this.highAddress = highAddress;
-	}
-
-	public void setRangeList(IRangeList ranges) {
-		this.rangeList = ranges;
-		setLowAddress(new Addr32(rangeList.getLowAddress()));
-		setHighAddress(new Addr32(rangeList.getHighAddress()));
-	}
-	
-	public IScope getParent() {
-		return parent;
-	}
-
-	public Collection<IScope> getChildren() {
-		return Collections.unmodifiableCollection(children);
-	}
-
-	public Collection<IVariable> getVariables() {
-		return Collections.unmodifiableCollection(variables);
-	}
-
-	public Collection<IEnumerator> getEnumerators() {
-		return Collections.unmodifiableCollection(enumerators);
-	}
-
-	public IScope getScopeAtAddress(IAddress linkAddress) {
-		// see if it's in this scope
-		if (linkAddress.compareTo(lowAddress) >= 0 && linkAddress.compareTo(highAddress) < 0) {
-			
-			ensureScopeRangeLookup();
-			
-			long addr = linkAddress.getValue().longValue();
-			IRangeList.Entry addressEntry = new IRangeList.Entry(addr, addr);
-			SortedMap<Entry,IScope> tailMap = addressToScopeMap.tailMap(addressEntry);
-			
-			if (tailMap.isEmpty())
-				return this;
-			
-			IScope child = tailMap.values().iterator().next();
-			if (linkAddress.compareTo(child.getLowAddress()) >= 0 
-					&& linkAddress.compareTo(child.getHighAddress()) < 0) {
-				return child.getScopeAtAddress(linkAddress);
-			}
-			
-			return this;
-		}
-
-		return null;
-	}
-
-	/**
-	 * Make sure our mapping of address range to scope is valid. 
-	 */
-	private void ensureScopeRangeLookup() {
-		if (addressToScopeMap == null) {
-			addressToScopeMap = new TreeMap<Entry, IScope>();
-			
-			for (IScope scope : children) {
-				addScopeRange(scope);
-			}
-			//System.out.println("Mapping for " + getName()+ ": "+ addressToScopeMap.size() + " entries");
-		}
-	}
-
-	/**
-	 * @param scope
-	 */
-	private void addScopeRange(IScope scope) {
-		IRangeList ranges = scope.getRangeList();
-		if (ranges != null) {
-			for (IRangeList.Entry entry : ranges) {
-				addressToScopeMap.put(entry, scope);
-			}
-		} else {
-			addressToScopeMap.put(new IRangeList.Entry(
-						scope.getLowAddress().getValue().longValue(), 
-						scope.getHighAddress().getValue().longValue()),
-					scope);
-		}
-	}
-
-	/**
-	 * Adds the given scope as a child of this scope
-	 * 
-	 * @param scope
-	 */
-	public void addChild(IScope scope) {
-		children.add(scope);
-		if (addressToScopeMap == null)
-			addressToScopeMap = new TreeMap<Entry, IScope>();
-		addScopeRange(scope);
-	}
-
-	/**
-	 * Adds the given variable to this scope
-	 * 
-	 * @param variable
-	 */
-	public void addVariable(IVariable variable) {
-		variables.add(variable);
-	}
-
-	/**
-	 * Adds the given variable to this scope
-	 * 
-	 * @param variable
-	 */
-	public void addEnumerator(IEnumerator enumerator) {
-		enumerators.add(enumerator);
-	}
-
-	/** Scope specific compareTo() based upon<br>
-	 * 1) if object to compare is IScope, comparison of lowAddress, then highAddress<br>
-	 * 2) if object to compare is IAddress, compare address to this lowAddress<br>
-	 * @see java.lang.Comparable#compareTo(java.lang.Object)
-	 */
-	public int compareTo(Object o) {
-		if (o instanceof IScope) {
-			IScope io = (IScope) o;
-			int comparison = lowAddress.compareTo(io.getLowAddress());
-			if (comparison == 0) {
-				comparison = highAddress.compareTo(io.getHighAddress());
-			}
-			return comparison;
-		} else if (o instanceof IAddress) {
-			return lowAddress.compareTo(o);
-		}
-		return 0;
-	}
-
-	/**
-	 * Scope specific version of toString():<br>
-	 * <code>
-	 * [ranges=, lowAddress=, highAddress=, name=]
-	 * </code>
-	 * @see java.lang.Object#toString()
-	 */
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Scope ["); //$NON-NLS-1$
-		if (rangeList != null) {
-			builder.append("ranges="); //$NON-NLS-1$
-			builder.append(rangeList);
-		} else {
-			builder.append("lowAddress="); //$NON-NLS-1$
-			builder.append(lowAddress != null ? lowAddress.toHexAddressString() : "null");
-			builder.append(", highAddress="); //$NON-NLS-1$
-			builder.append(highAddress != null ? highAddress.toHexAddressString() : "null");
-		}
-		builder.append(", "); //$NON-NLS-1$
-		if (name != null) {
-			builder.append("name="); //$NON-NLS-1$
-			builder.append(name);
-			builder.append(", "); //$NON-NLS-1$
-		}
-		builder.append("]"); //$NON-NLS-1$
-		return builder.toString();
-	}
-
-	/**
-	 * deal with incorrectly generated ranges by the compiler
-	 * that may not work together properly with ranges of children
-	 * @param baseAddress
-	 */
-	public void fixupRanges(IAddress baseAddress) {
-		// compile unit scopes not generated by the compiler so
-		// figure it out from the functions
-		IAddress newLowAddress = Addr64.MAX;
-		IAddress newHighAddress = Addr64.ZERO;
-		IRangeList newRangeList = new RangeList();
-		boolean any = false;
-		
-		for (IScope kid : getChildren()) {
-			// the compiler may generate (bad) low/high pc's which are not
-			// in the actual module space for some functions. to work
-			// around this, only honor addresses that are above the
-			// actual link address
-			if (kid.hasEmptyRange()) {
-				continue;
-			}
-
-			if (kid.getLowAddress().compareTo(baseAddress) > 0) {
-				IRangeList kidRanges = kid.getRangeList();
-				if (kidRanges == null){// If it didn't have ranges it still has one range
-					kidRanges = new RangeList();
-					((RangeList)kidRanges).addRange(kid.getLowAddress().getValue().longValue(),kid.getHighAddress().getValue().longValue());
-				}
-				newRangeList = RangeList.mergeRangeLists(newRangeList,kidRanges);
-
-				if (kid.getLowAddress().compareTo(newLowAddress) < 0) {
-					newLowAddress = kid.getLowAddress();
-					any = true;
-				}
-
-				if (kid.getHighAddress().compareTo(newHighAddress) > 0) {
-					newHighAddress = kid.getHighAddress();
-					any = true;
-				}
-			}
-		}
-
-		if (any) {
-			//System.out.println("Needed to fix up ranges for " + getName());
-			lowAddress = newLowAddress; 
-			highAddress = newHighAddress;
-			int entryCount = 0;
-			for (@SuppressWarnings("unused") IRangeList.Entry entry : newRangeList){
-				++entryCount;
-			}
-			rangeList = (entryCount > 1) ? newRangeList : null;
-		} else {
-			if (lowAddress == null) {
-				lowAddress = highAddress = Addr32.ZERO;
-			}
-		}
-	}
-	
-	/**
-	 * Merge the code range(s) from the given scope into this one.
-	 * @param scope
-	 */
-	protected void mergeScopeRange(IScope scope) {
-		if (hasEmptyRange()) {
-			// copy range
-			if (scope.getRangeList() != null) {
-				setRangeList(scope.getRangeList());
-			} else {
-				setLowAddress(scope.getLowAddress());
-				setHighAddress(scope.getHighAddress());
-			}
-		} else {
-			if (scope.getLowAddress() != null && scope.getLowAddress().compareTo(lowAddress) < 0
-					&& !scope.getLowAddress().isZero()) 		// ignore random 0 entries 
-			{
-				if (rangeList != null) {
-					if (scope.getRangeList() != null) {
-						rangeList = RangeList.mergeRangeLists(rangeList,scope.getRangeList());
-					} else {
-						((RangeList)rangeList).addLowRange(scope.getLowAddress().getValue().longValue());
-					}
-				}
-				lowAddress = scope.getLowAddress();
-			}
-			if (scope.getHighAddress() != null && scope.getHighAddress().compareTo(highAddress) > 0) {
-				if (rangeList != null) {
-					if (scope.getRangeList() != null) {
-						rangeList = RangeList.mergeRangeLists(rangeList,scope.getRangeList());
-					} else {
-						((RangeList)rangeList).addHighRange(scope.getHighAddress().getValue().longValue());
-					}
-				}
-				highAddress = scope.getHighAddress();
-			}	
-		}
-	}
-
-	/**
-	 * @param scope
-	 */
-	protected void addLineInfoToParent(IScope scope) {
-		IScope cu = parent;
-		while (cu != null) {
-			if (cu instanceof ICompileUnitScope && cu.getParent() instanceof IModuleScope) {
-				IModuleScope module = (IModuleScope) cu.getParent();
-				ModuleLineEntryProvider provider = (ModuleLineEntryProvider) module.getModuleLineEntryProvider();
-				provider.addCompileUnitChild((ICompileUnitScope) cu, scope);
-				break;
-			}
-			cu = cu.getParent();
-		}
-	}
-
-	/**
-	 * 
-	 */
-	public void dispose() {
-		for (IScope scope : children)
-			scope.dispose();
-		children.clear();
-		for (IVariable var : variables)
-			var.dispose();
-		variables.clear();
-		enumerators.clear();
-		if (addressToScopeMap != null)
-			addressToScopeMap.clear();
-		rangeList = null;
-	}
-
-	/** 
-	 * there are not enough non-mutable members with which
-	 * to provide a proper hashCode() for Scope, and we
-	 * cannot provide equals() if we cannot guarantee
-	 * hashCode() ... but at least we can make comparison
-	 * of different Scope objects a little easier for
-	 * situations where we want to claim to Scope objects
-	 * have the same contents.
-	 * <br>
-	 * in this case, content equality is based upon the
-	 * following criteria<br>
-	 * 1) same children<br>
-	 * 2) same highAddress<br>
-	 * 3) same lowAddress<br>
-	 * 4) same name<br>
-	 * 5) same rangeList<br>
-	 */
-	public boolean contentsEquals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		Scope other = (Scope) obj;
-		if (children == null) {
-			if (other.children != null)
-				return false;
-		} else if (!children.equals(other.children))
-			return false;
-		if (highAddress == null) {
-			if (other.highAddress != null)
-				return false;
-		} else if (!highAddress.equals(other.highAddress))
-			return false;
-		if (lowAddress == null) {
-			if (other.lowAddress != null)
-				return false;
-		} else if (!lowAddress.equals(other.lowAddress))
-			return false;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (rangeList == null) {
-			if (other.rangeList != null)
-				return false;
-		} else if (!rangeList.equals(other.rangeList))
-			return false;
-		return true;
-	}
-}
+/*******************************************************************************

+ * 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.symbols;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.Collections;

+import java.util.LinkedHashMap;

+import java.util.List;

+import java.util.Map;

+import java.util.SortedMap;

+import java.util.TreeMap;

+

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

+import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.RangeList;

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

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

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

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

+import org.eclipse.cdt.debug.edc.symbols.IRangeList.Entry;

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

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

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

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

+

+/**

+ * abstract implementation of {@link IScope},

+ * optionally containing a name, low & high addresses, IScope parent,

+ * children, variables, enumerators, et al

+ *

+ */

+public abstract class Scope implements IScope {

+

+	protected String name;

+	protected IAddress lowAddress;

+	protected IAddress highAddress;

+	protected IScope parent;

+	protected List<IScope> children = new ArrayList<IScope>();

+	protected Map<String, IVariable> variables = new LinkedHashMap<String, IVariable>();

+	protected List<IEnumerator> enumerators = new ArrayList<IEnumerator>();

+	private TreeMap<IRangeList.Entry, IScope> addressToScopeMap;

+	

+	protected IRangeList rangeList;

+

+	public Scope(String name, IAddress lowAddress, IAddress highAddress, IScope parent) {

+		this.name = name;

+		this.lowAddress = lowAddress;

+		this.highAddress = highAddress;

+		this.parent = parent;

+	}

+

+	public String getName() {

+		return name;

+	}

+

+	public IAddress getLowAddress() {

+		return lowAddress;

+	}

+

+	public IAddress getHighAddress() {

+		return highAddress;

+	}

+

+	/**

+	 * Tell whether the address range for the scope is empty.

+	 * @return flag

+	 */

+	public boolean hasEmptyRange() {

+		return (lowAddress == null || highAddress == null)

+		|| (lowAddress.isZero() && highAddress.isZero())

+		|| (lowAddress.getValue().longValue() == -1 && highAddress.isZero()) // TODO: remove this case

+		|| lowAddress.equals(highAddress);

+	}

+

+	/**

+	 * Return the list of non-contiguous ranges for this scope.

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

+	 */

+	public IRangeList getRangeList() {

+		return rangeList;

+	}

+

+	public void setLowAddress(IAddress lowAddress) {

+		this.lowAddress = lowAddress;

+	}

+

+	public void setHighAddress(IAddress highAddress) {

+		this.highAddress = highAddress;

+	}

+

+	public void setRangeList(IRangeList ranges) {

+		this.rangeList = ranges;

+		setLowAddress(new Addr32(rangeList.getLowAddress()));

+		setHighAddress(new Addr32(rangeList.getHighAddress()));

+	}

+	

+	public IScope getParent() {

+		return parent;

+	}

+

+	public Collection<IScope> getChildren() {

+		return Collections.unmodifiableCollection(children);

+	}

+

+	public Collection<IVariable> getVariables() {

+		return Collections.unmodifiableCollection(variables.values());

+	}

+

+	public Collection<IEnumerator> getEnumerators() {

+		return Collections.unmodifiableCollection(enumerators);

+	}

+

+	public IScope getScopeAtAddress(IAddress linkAddress) {

+		// see if it's in this scope

+		if (linkAddress.compareTo(lowAddress) >= 0 && linkAddress.compareTo(highAddress) < 0) {

+			

+			ensureScopeRangeLookup();

+			

+			long addr = linkAddress.getValue().longValue();

+			IRangeList.Entry addressEntry = new IRangeList.Entry(addr, addr);

+			SortedMap<Entry,IScope> tailMap = addressToScopeMap.tailMap(addressEntry);

+			

+			if (tailMap.isEmpty())

+				return this;

+			

+			IScope child = tailMap.values().iterator().next();

+			if (linkAddress.compareTo(child.getLowAddress()) >= 0 

+					&& linkAddress.compareTo(child.getHighAddress()) < 0) {

+				return child.getScopeAtAddress(linkAddress);

+			}

+			

+			return this;

+		}

+

+		return null;

+	}

+

+	/**

+	 * Make sure our mapping of address range to scope is valid. 

+	 */

+	private void ensureScopeRangeLookup() {

+		if (addressToScopeMap == null) {

+			addressToScopeMap = new TreeMap<Entry, IScope>();

+			

+			for (IScope scope : children) {

+				addScopeRange(scope);

+			}

+			//System.out.println("Mapping for " + getName()+ ": "+ addressToScopeMap.size() + " entries");

+		}

+	}

+

+	/**

+	 * @param scope

+	 */

+	private void addScopeRange(IScope scope) {

+		IRangeList ranges = scope.getRangeList();

+		if (ranges != null) {

+			for (IRangeList.Entry entry : ranges) {

+				addressToScopeMap.put(entry, scope);

+			}

+		} else {

+			addressToScopeMap.put(new IRangeList.Entry(

+						scope.getLowAddress().getValue().longValue(), 

+						scope.getHighAddress().getValue().longValue()),

+					scope);

+		}

+	}

+

+	/**

+	 * Adds the given scope as a child of this scope

+	 * 

+	 * @param scope

+	 */

+	public void addChild(IScope scope) {

+		children.add(scope);

+		if (addressToScopeMap == null)

+			addressToScopeMap = new TreeMap<Entry, IScope>();

+		addScopeRange(scope);

+	}

+

+	/**

+	 * Adds the given variable to this scope

+	 * 

+	 * @param variable

+	 */

+	public void addVariable(IVariable variable) {

+		variables.put(variable.getName(), variable);

+	}

+

+	/**

+	 * Adds the given variable to this scope

+	 * 

+	 * @param variable

+	 */

+	public void addEnumerator(IEnumerator enumerator) {

+		enumerators.add(enumerator);

+	}

+

+	/** Scope specific compareTo() based upon<br>

+	 * 1) if object to compare is IScope, comparison of lowAddress, then highAddress<br>

+	 * 2) if object to compare is IAddress, compare address to this lowAddress<br>

+	 * @see java.lang.Comparable#compareTo(java.lang.Object)

+	 */

+	public int compareTo(Object o) {

+		if (o instanceof IScope) {

+			IScope io = (IScope) o;

+			int comparison = lowAddress.compareTo(io.getLowAddress());

+			if (comparison == 0) {

+				comparison = highAddress.compareTo(io.getHighAddress());

+			}

+			return comparison;

+		} else if (o instanceof IAddress) {

+			return lowAddress.compareTo(o);

+		}

+		return 0;

+	}

+

+	/**

+	 * Scope specific version of toString():<br>

+	 * <code>

+	 * [ranges=, lowAddress=, highAddress=, name=]

+	 * </code>

+	 * @see java.lang.Object#toString()

+	 */

+	@Override

+	public String toString() {

+		StringBuilder builder = new StringBuilder();

+		builder.append("Scope ["); //$NON-NLS-1$

+		if (rangeList != null) {

+			builder.append("ranges="); //$NON-NLS-1$

+			builder.append(rangeList);

+		} else {

+			builder.append("lowAddress="); //$NON-NLS-1$

+			builder.append(lowAddress != null ? lowAddress.toHexAddressString() : "null");

+			builder.append(", highAddress="); //$NON-NLS-1$

+			builder.append(highAddress != null ? highAddress.toHexAddressString() : "null");

+		}

+		builder.append(", "); //$NON-NLS-1$

+		if (name != null) {

+			builder.append("name="); //$NON-NLS-1$

+			builder.append(name);

+			builder.append(", "); //$NON-NLS-1$

+		}

+		builder.append("]"); //$NON-NLS-1$

+		return builder.toString();

+	}

+

+	/**

+	 * deal with incorrectly generated ranges by the compiler

+	 * that may not work together properly with ranges of children

+	 * @param baseAddress

+	 */

+	public void fixupRanges(IAddress baseAddress) {

+		// compile unit scopes not generated by the compiler so

+		// figure it out from the functions

+		IAddress newLowAddress = Addr64.MAX;

+		IAddress newHighAddress = Addr64.ZERO;

+		IRangeList newRangeList = new RangeList();

+		boolean any = false;

+		

+		for (IScope kid : getChildren()) {

+			// the compiler may generate (bad) low/high pc's which are not

+			// in the actual module space for some functions. to work

+			// around this, only honor addresses that are above the

+			// actual link address

+			if (kid.hasEmptyRange()) {

+				continue;

+			}

+

+			if (kid.getLowAddress().compareTo(baseAddress) > 0) {

+				IRangeList kidRanges = kid.getRangeList();

+				if (kidRanges == null){// If it didn't have ranges it still has one range

+					kidRanges = new RangeList();

+					((RangeList)kidRanges).addRange(kid.getLowAddress().getValue().longValue(),kid.getHighAddress().getValue().longValue());

+				}

+				newRangeList = RangeList.mergeRangeLists(newRangeList,kidRanges);

+

+				if (kid.getLowAddress().compareTo(newLowAddress) < 0) {

+					newLowAddress = kid.getLowAddress();

+					any = true;

+				}

+

+				if (kid.getHighAddress().compareTo(newHighAddress) > 0) {

+					newHighAddress = kid.getHighAddress();

+					any = true;

+				}

+			}

+		}

+

+		if (any) {

+			//System.out.println("Needed to fix up ranges for " + getName());

+			lowAddress = newLowAddress; 

+			highAddress = newHighAddress;

+			int entryCount = 0;

+			for (@SuppressWarnings("unused") IRangeList.Entry entry : newRangeList){

+				++entryCount;

+			}

+			rangeList = (entryCount > 1) ? newRangeList : null;

+		} else {

+			if (lowAddress == null) {

+				lowAddress = highAddress = Addr32.ZERO;

+			}

+		}

+	}

+	

+	/**

+	 * Merge the code range(s) from the given scope into this one.

+	 * @param scope

+	 */

+	protected void mergeScopeRange(IScope scope) {

+		if (hasEmptyRange()) {

+			// copy range

+			if (scope.getRangeList() != null) {

+				setRangeList(scope.getRangeList());

+			} else {

+				setLowAddress(scope.getLowAddress());

+				setHighAddress(scope.getHighAddress());

+			}

+		} else {

+			if (scope.getLowAddress() != null && scope.getLowAddress().compareTo(lowAddress) < 0

+					&& !scope.getLowAddress().isZero()) 		// ignore random 0 entries 

+			{

+				if (rangeList != null) {

+					if (scope.getRangeList() != null) {

+						rangeList = RangeList.mergeRangeLists(rangeList,scope.getRangeList());

+					} else {

+						((RangeList)rangeList).addLowRange(scope.getLowAddress().getValue().longValue());

+					}

+				}

+				lowAddress = scope.getLowAddress();

+			}

+			if (scope.getHighAddress() != null && scope.getHighAddress().compareTo(highAddress) > 0) {

+				if (rangeList != null) {

+					if (scope.getRangeList() != null) {

+						rangeList = RangeList.mergeRangeLists(rangeList,scope.getRangeList());

+					} else {

+						((RangeList)rangeList).addHighRange(scope.getHighAddress().getValue().longValue());

+					}

+				}

+				highAddress = scope.getHighAddress();

+			}	

+		}

+	}

+

+	/**

+	 * @param scope

+	 */

+	protected void addLineInfoToParent(IScope scope) {

+		IScope cu = parent;

+		while (cu != null) {

+			if (cu instanceof ICompileUnitScope && cu.getParent() instanceof IModuleScope) {

+				IModuleScope module = (IModuleScope) cu.getParent();

+				ModuleLineEntryProvider provider = (ModuleLineEntryProvider) module.getModuleLineEntryProvider();

+				provider.addCompileUnitChild((ICompileUnitScope) cu, scope);

+				break;

+			}

+			cu = cu.getParent();

+		}

+	}

+

+	/**

+	 * 

+	 */

+	public void dispose() {

+		for (IScope scope : children)

+			scope.dispose();

+		children.clear();

+		for (IVariable var : variables.values())

+			var.dispose();

+		variables.clear();

+		enumerators.clear();

+		if (addressToScopeMap != null)

+			addressToScopeMap.clear();

+		rangeList = null;

+	}

+

+	/** 

+	 * there are not enough non-mutable members with which

+	 * to provide a proper hashCode() for Scope, and we

+	 * cannot provide equals() if we cannot guarantee

+	 * hashCode() ... but at least we can make comparison

+	 * of different Scope objects a little easier for

+	 * situations where we want to claim to Scope objects

+	 * have the same contents.

+	 * <br>

+	 * in this case, content equality is based upon the

+	 * following criteria<br>

+	 * 1) same children<br>

+	 * 2) same highAddress<br>

+	 * 3) same lowAddress<br>

+	 * 4) same name<br>

+	 * 5) same rangeList<br>

+	 */

+	public boolean contentsEquals(Object obj) {

+		if (this == obj)

+			return true;

+		if (obj == null)

+			return false;

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

+			return false;

+		Scope other = (Scope) obj;

+		if (children == null) {

+			if (other.children != null)

+				return false;

+		} else if (!children.equals(other.children))

+			return false;

+		if (highAddress == null) {

+			if (other.highAddress != null)

+				return false;

+		} else if (!highAddress.equals(other.highAddress))

+			return false;

+		if (lowAddress == null) {

+			if (other.lowAddress != null)

+				return false;

+		} else if (!lowAddress.equals(other.lowAddress))

+			return false;

+		if (name == null) {

+			if (other.name != null)

+				return false;

+		} else if (!name.equals(other.name))

+			return false;

+		if (rangeList == null) {

+			if (other.rangeList != null)

+				return false;

+		} else if (!rangeList.equals(other.rangeList))

+			return false;

+		return true;

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Variable.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Variable.java
index a2faabd..902aaf4 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Variable.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/Variable.java
@@ -1,184 +1,190 @@
-/*******************************************************************************
- * 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
- * Broadcom - added hashCode() and equals() implementations
- *******************************************************************************/
-package org.eclipse.cdt.debug.edc.internal.symbols;
-
-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.core.runtime.IPath;
-
-
-public class Variable implements IVariable {
-
-	protected String name;
-	protected IScope scope;
-	protected IType type;
-	protected ILocationProvider locationProvider;
-	protected long startScope;
-	protected boolean isDeclared;
-	protected IPath definingFile;
-
-	
-	public Variable(String name, IScope scope, IType type, ILocationProvider locationProvider, boolean isDeclared, IPath definingFile) {
-		this.name = name;
-		this.scope = scope;
-		this.type = type;
-		this.locationProvider = locationProvider;
-		this.isDeclared = isDeclared;
-		this.definingFile = definingFile;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#dispose()
-	 */
-	public void dispose() {
-		type = null;
-		locationProvider = null;
-		scope = null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getName()
-	 */
-	public String getName() {
-		return name;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getScope()
-	 */
-	public IScope getScope() {
-		return scope;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getType()
-	 */
-	public IType getType() {
-		if (type instanceof IForwardTypeReference)
-			type = ((IForwardTypeReference) type).getReferencedType();
-		
-		return type;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getLocationProvider()
-	 */
-	public ILocationProvider getLocationProvider() {
-		return locationProvider;
-	}
-
-	public void setStartScope(long start) {
-		this.startScope = start;
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getStartScope()
-	 */
-	public long getStartScope() {
-		return startScope;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#isDeclared()
-	 */
-	public boolean isDeclared() {
-		return isDeclared;
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.symbols.IVariable#getDefiningFile()
-	 */
-	public IPath getDefiningFile() {
-		return definingFile;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Var ["); //$NON-NLS-1$
-		if (name != null) {
-			builder.append(name);
-		}
-		if (scope != null) {
-			builder.append(", "); //$NON-NLS-1$
-			builder.append("scope="); //$NON-NLS-1$
-			String sname = scope.getName();
-			if (sname.length() == 0) {
-				for (IScope parent = scope.getParent()
-						; parent != null
-						; parent = parent.getParent())
-					if ((sname = parent.getName()).length() != 0)
-						break;
-				if (sname.length() != 0) {
-					sname += "()"; //$NON-NLS-1$
-					if (scope instanceof LexicalBlockScope)
-						sname += "{.lexBlk.}"; //$NON-NLS-1$
-				} else
-					sname = "{." + scope.getClass().getSimpleName() + ".}";
-			}
-			builder.append(sname);
-		}
-		builder.append("]"); //$NON-NLS-1$
-		return builder.toString();
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((definingFile == null) ? 0 : definingFile.hashCode());
-		result = prime * result + (isDeclared ? 1231 : 1237);
-		result = prime * result + ((name == null) ? 0 : name.hashCode());
-		result = prime * result + ((scope == null) ? 0 : scope.hashCode());
-		result = prime * result + (int) (startScope ^ (startScope >>> 32));
-		result = prime * result + ((type == null) ? 0 : type.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;
-		Variable other = (Variable) obj;
-		if (definingFile == null) {
-			if (other.definingFile != null)
-				return false;
-		} else if (!definingFile.equals(other.definingFile))
-			return false;
-		if (isDeclared != other.isDeclared)
-			return false;
-		if (name == null) {
-			if (other.name != null)
-				return false;
-		} else if (!name.equals(other.name))
-			return false;
-		if (scope == null) {
-			if (other.scope != null)
-				return false;
-		} else if (!scope.equals(other.scope))
-			return false;
-		if (startScope != other.startScope)
-			return false;
-		if (type == null) {
-			if (other.type != null)
-				return false;
-		} else if (!type.equals(other.type))
-			return false;
-		return true;
-	}
-}
+/*******************************************************************************

+ * 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

+ * Broadcom - added hashCode() and equals() implementations

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

+package org.eclipse.cdt.debug.edc.internal.symbols;

+

+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.core.runtime.IPath;

+

+

+public class Variable implements IVariable {

+

+	protected String name;

+	protected IScope scope;

+	protected IType type;

+	protected ILocationProvider locationProvider;

+	protected long startScope;

+	protected boolean isDeclared;

+	protected IPath definingFile;

+

+	

+	public Variable(String name, IScope scope, IType type, ILocationProvider locationProvider, boolean isDeclared, IPath definingFile) {

+		this.name = name;

+		this.scope = scope;

+		this.type = type;

+		this.locationProvider = locationProvider;

+		this.isDeclared = isDeclared;

+		this.definingFile = definingFile;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#dispose()

+	 */

+	public void dispose() {

+		type = null;

+		locationProvider = null;

+		scope = null;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getName()

+	 */

+	public String getName() {

+		return name;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getScope()

+	 */

+	public IScope getScope() {

+		return scope;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getType()

+	 */

+	public IType getType() {

+		if (type instanceof IForwardTypeReference)

+			type = ((IForwardTypeReference) type).getReferencedType();

+		

+		return type;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getLocationProvider()

+	 */

+	public ILocationProvider getLocationProvider() {

+		return locationProvider;

+	}

+

+	public void setStartScope(long start) {

+		this.startScope = start;

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#getStartScope()

+	 */

+	public long getStartScope() {

+		return startScope;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.IVariable#isDeclared()

+	 */

+	public boolean isDeclared() {

+		return isDeclared;

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.symbols.IVariable#getDefiningFile()

+	 */

+	public IPath getDefiningFile() {

+		return definingFile;

+	}

+

+	@Override

+	public String toString() {

+		StringBuilder builder = new StringBuilder();

+		builder.append("Var ["); //$NON-NLS-1$

+		if (name != null) {

+			builder.append(name);

+		}

+		if (scope != null) {

+			builder.append(", "); //$NON-NLS-1$

+			builder.append("scope="); //$NON-NLS-1$

+			String sname = scope.getName();

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

+				for (IScope parent = scope.getParent()

+						; parent != null

+						; parent = parent.getParent())

+					if ((sname = parent.getName()).length() != 0)

+						break;

+				if (sname.length() != 0) {

+					sname += "()"; //$NON-NLS-1$

+					if (scope instanceof LexicalBlockScope)

+						sname += "{.lexBlk.}"; //$NON-NLS-1$

+				} else

+					sname = "{." + scope.getClass().getSimpleName() + ".}";

+			}

+			builder.append(sname);

+		}

+		builder.append("]"); //$NON-NLS-1$

+		return builder.toString();

+	}

+

+	@Override

+	public int hashCode() {

+		final int prime = 31;

+		int result = 1;

+		result = prime * result + ((definingFile == null) ? 0 : definingFile.hashCode());

+		result = prime * result + (isDeclared ? 1231 : 1237);

+		result = prime * result + ((name == null) ? 0 : name.hashCode());

+		result = prime * result + ((scope == null) ? 0 : scope.hashCode());

+		result = prime * result + (int) (startScope ^ (startScope >>> 32));

+		result = prime * result + ((type == null) ? 0 : type.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;

+		Variable other = (Variable) obj;

+		if (definingFile == null) {

+			if (other.definingFile != null)

+				return false;

+		} else if (!definingFile.equals(other.definingFile))

+			return false;

+		if (isDeclared != other.isDeclared)

+			return false;

+		if (name == null) {

+			if (other.name != null)

+				return false;

+		} else if (!name.equals(other.name))

+			return false;

+		if (scope == null) {

+			if (other.scope != null)

+				return false;

+		} else if (!scope.equals(other.scope))

+			return false;

+		if (startScope != other.startScope)

+			return false;

+		if (type == null) {

+			if (other.type != null)

+				return false;

+		} else if (!type.equals(other.type))

+			return false;

+		return true;

+	}

+

+	public IVariable copyWithNewType(IType newType) {

+		Variable variable = new Variable(name, scope, newType, locationProvider, isDeclared, definingFile);

+		variable.startScope = startScope;

+		return variable;

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfCompileUnit.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfCompileUnit.java
index 6409810..0dd95f5 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfCompileUnit.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfCompileUnit.java
@@ -1,337 +1,336 @@
-/*******************************************************************************
- * 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 - remove duplicate child methods (repeating super methods from Scope)
- *******************************************************************************/
-package org.eclipse.cdt.debug.edc.internal.symbols.dwarf;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope;
-import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.AttributeList;
-import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.CompilationUnitHeader;
-import org.eclipse.cdt.debug.edc.symbols.IFunctionScope;
-import org.eclipse.cdt.debug.edc.symbols.ILineEntry;
-import org.eclipse.cdt.debug.edc.symbols.IModuleScope;
-import org.eclipse.cdt.debug.edc.symbols.IScope;
-import org.eclipse.cdt.debug.edc.symbols.IVariable;
-import org.eclipse.core.runtime.IPath;
-
-/**
- * extension of CompileUnitScope that holds<br>
- * 1) DWARF specific debug info provider<br>
- * 2) DWARF specific attributes<br>
- * 3) DWARF sepcific compile unit header<br>
- * 4) cache flags for previously parsed variables, addresses & types
- *
- */
-public class DwarfCompileUnit extends CompileUnitScope {
-
-	protected DwarfDebugInfoProvider provider;
-	protected AttributeList attributes;
-	private List<IPath> fileList;
-	private boolean rangesDirty;
-
-	/** computation unit header */
-	protected final CompilationUnitHeader header;
-	
-	/** whether the computation unit has been parsed to find variables and children with address ranges */
-	protected boolean parsedForVarsAndAddresses = false;
-	
-	/** whether the computation unit has been parsed to find types */
-	protected boolean parsedForTypes = false;
-
-	
-	/**
-	 * DwarfCompileUnit holds the provider, attributes and DWARF header
-	 * in addition to other member variables of its super, 
-	 * {@link CompileUnitScope#CompileUnitScope(IPath, IModuleScope, IAddress, IAddress)}
-	 * @param provider
-	 * @param parent
-	 * @param filePath
-	 * @param lowAddress
-	 * @param highAddress
-	 * @param header
-	 * @param hasChildren
-	 * @param attributes
-	 */
-	public DwarfCompileUnit(DwarfDebugInfoProvider provider, IModuleScope parent, IPath filePath,
-			IAddress lowAddress, IAddress highAddress, CompilationUnitHeader header, boolean hasChildren,
-			AttributeList attributes) {
-		super(filePath, parent, lowAddress, highAddress);
-
-		this.provider = provider;
-		this.attributes = attributes;
-		this.header = header;
-		
-		// if there are no children, say the children have been parsed
-		if (!hasChildren) {
-			this.parsedForVarsAndAddresses = true;
-			this.parsedForTypes = true;
-		}
-	}
-
-	/**
-	 * called by {@link CompileUnitScope#hashCode()}.
-	 * this implementation further distinguishes the hash-code
-	 * by adding the following to the caller hashCode as follows:
-	 * <br><code>
-	 * (prime+header.debugInfoOffset)*prime+provider.symbolfFile.hashCode()
-	 * </code>
-	 * @see CompileUnitScope#cuScopeHashCode()
-	 */
-	protected int cuScopeHashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + header.debugInfoOffset;
-		result = prime * result + provider.getSymbolFile().hashCode();
-		return result;
-	}
-
-	/**
-	 * called by {@link CompileUnitScope#equals(Object)}.
-	 * caller will guarantee objects are not identical, non-null,
-	 * of same class, with the same scope name.
-	 * This implementation further guarantees equality:
-	 * <br>(1) if and only if debugInfoOffset values are equal
-	 * <br>(2) if and only if provider symbol file values are equal
-	 * @see CompileUnitScope#cuScopeEquals(java.lang.Object)
-	 */
-	protected boolean cuScopeEquals(Object obj) {
-		DwarfCompileUnit other = (DwarfCompileUnit) obj;
-		if (header.debugInfoOffset != other.header.debugInfoOffset)
-			return false;
-		if (!provider.getSymbolFile().equals(other.provider.getSymbolFile()))
-			return false;
-		return true;
-	}
-
-	/**
-	 * @return attributes of this DwarfCompileUnit
-	 */
-	public AttributeList getAttributeList() {
-		return attributes;
-	}
-	
-	/**
-	 * utilize DwarfInfoReader to implement abstract declaration in
-	 * {@link CompileUnitScope#parseLineTable()}
-	 */
-	protected Collection<ILineEntry> parseLineTable() {
-		DwarfInfoReader reader = new DwarfInfoReader(provider);
-		fileList = new ArrayList<IPath>();
-		return reader.parseLineTable(this, attributes, fileList);
-	}
-	
-	/** fixup ranges and ensure parsed for addresses before calling
-	 * super.getFunctionAtAddress()
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#getFunctionAtAddress(org.eclipse.cdt.core.IAddress)
-	 */
-	@Override
-	public IFunctionScope getFunctionAtAddress(IAddress linkAddress) {
-		if (rangesDirty) {
-			fixupRanges();
-		}
-		ensureParsedForAddresses();
-		return super.getFunctionAtAddress(linkAddress);
-	}
-	
-	/** ensure parsed for addresses before calling super.getChildren
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#getFunctions()
-	 */
-	@Override
-	public Collection<IFunctionScope> getFunctions() {
-		ensureParsedForAddresses();
-		return super.getFunctions();
-	}
-	
-	/**
-	 * For compilers that don't generate compile unit scopes, e.g. GCCE with
-	 * dlls, this fixes up the low and high addresses of the compile unit based
-	 * on the function scopes
-	 */
-	protected void fixupRanges() {
-		
-		// fix up scope addresses in case compiler doesn't generate them.
-		if (hasEmptyRange() && parsedForVarsAndAddresses) {
-			fixupRanges(provider.getBaseLinkAddress());
-		}
-
-		rangesDirty = false;
-	}
-	
-	/** ensure parsed for addresses before calling super.getChildren()
-	 * @return children of this compile unit after it has been parsed for addresses
-	 */
-	@Override
-	public Collection<IScope> getChildren() {
-		ensureParsedForAddresses();
-		return super.getChildren();
-	}
-
-	/**
-	 * allow the caller to establish an attribute list
-	 */
-	public void setAttributes(AttributeList attributes) {
-		this.attributes = attributes;
-	}
-
-	/**
-	 * @return whether or not this DwarfCompileUnit has been parsed for addresses
-	 */
-	public boolean isParsedForAddresses() {
-		return parsedForVarsAndAddresses;
-	}
-
-	/**
-	 * @return whether or not this DwarfCompileUnit has been parsed for variables
-	 */
-	public boolean isParsedForVariables() {
-		return parsedForVarsAndAddresses;
-	}
-
-	/**
-	 * @return whether or not this DwarfCompileUnit has been parsed for types
-	 */
-	public boolean isParsedForTypes() {
-		return parsedForTypes;
-	}
-
-	/** ensure first parsed for variables before calling
-	 * {@link CompileUnitScope#getVariables()}
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#getVariables()
-	 */
-	@Override
-	public Collection<IVariable> getVariables() {
-		ensureParsedForVariables();
-		return super.getVariables();
-	}
-
-	/**
-	 * allow caller to set this DwarfCompileUnit's parsedForVarsAndAddresses flag true
-	 * @param parsedForAddresses
-	 */
-	public void setParsedForAddresses(boolean parsedForAddresses) {
-		this.parsedForVarsAndAddresses = parsedForAddresses;
-	}
-
-	/**
-	 * allow caller to set this DwarfCompileUnit's parsedForVarsAndAddresses flag true
-	 * @param parsedForVariables
-	 */
-	public void setParsedForVariables(boolean parsedForVariables) {
-		this.parsedForVarsAndAddresses = parsedForVariables;
-	}
-
-	/**
-	 * allow caller to set this DwarfCompileUnit's parsedForTypes flag true
-	 * @param parsedForTypes
-	 */
-	public void setParsedForTypes(boolean parsedForTypes) {
-		this.parsedForTypes = parsedForTypes;
-	}
-
-	private void ensureParsedForAddresses() {
-		if (!parsedForVarsAndAddresses) {
-			DwarfInfoReader reader = new DwarfInfoReader(provider);
-			reader.parseCompilationUnitForAddresses(this);
-			fixupRanges();
-		}
-	}
-	
-	/**
-	 * Get the file path for a file number
-	 * @param declFileNum
-	 * @return IPath for the file, or <code>null</code>
-	 */
-	public IPath getFileEntry(int declFileNum) {
-		if (fileList == null)
-			parseLineTable();
-		if (declFileNum <= 0 || declFileNum > fileList.size())
-			return null;
-		return fileList.get(declFileNum - 1);
-	}
-	
-	private void ensureParsedForVariables() {
-		if (!parsedForVarsAndAddresses) {
-			DwarfInfoReader reader = new DwarfInfoReader(provider);
-			reader.parseCompilationUnitForAddresses(this);
-		}
-	}
-	
-	/** ensure parsed for addresses before calling super.getScopeAtAddress()
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#getScopeAtAddress(org.eclipse.cdt.core.IAddress)
-	 */
-	@Override
-	public IScope getScopeAtAddress(IAddress linkAddress) {
-		ensureParsedForAddresses();
-		return super.getScopeAtAddress(linkAddress);
-	}
-
-	/**
-	 * DwarfCompileUnit specific version of toString():<br>
-	 * <code>
-	 * [SymFile=, SectionOffset=, lowAddr=, highAddr=, path=, parsedForVarsAndAddress=, parsedForTypes=]
-	 * </code>
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#toString()
-	 */
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("DwarfCompileUnit [");
-		
-		builder.append("SymFile=");
-		builder.append(provider.getSymbolFile().lastSegment());
-		
-		builder.append(", SectionOffset=0x");
-		builder.append(Integer.toHexString(header.debugInfoOffset));
-		
-		builder.append(", lowAddr=");
-		builder.append(lowAddress != null ? lowAddress.toHexAddressString() : null);
-		
-		builder.append(", highAddr=");
-		builder.append(highAddress != null ? highAddress.toHexAddressString() : null);
-		if (filePath != null) {
-			builder.append(", path=");
-			builder.append(filePath.toOSString());
-		}
-		builder.append(", parsedForVarsAndAddresses=");
-		builder.append(parsedForVarsAndAddresses);
-		builder.append(", parsedForTypes=");
-		builder.append(parsedForTypes);
-		builder.append("]\n");
-		return builder.toString();
-	}
-	
-
-	/**
-	 * 1) calls super.addChild() first<br>
-	 * 2) checks whether this has an empty range and merges range with passed child scope if not.<br>
-	 * 3) adds line info to the passed child scope
-	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#addChild(org.eclipse.cdt.debug.edc.symbols.IScope)
-	 */
-	@Override
-	public void addChild(IScope scope) {
-		super.addChild(scope);
-		
-		// if we don't know our scope yet...
-		if (hasEmptyRange()) {
-			rangesDirty = true;
-		} else {
-			// the CU may have an incomplete idea of its scope; fit the new scope in
-			mergeScopeRange(scope);
-		}
-
-		addLineInfoToParent(scope);
-	}
-
-}
+/*******************************************************************************

+ * 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 - remove duplicate child methods (repeating super methods from Scope)

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

+package org.eclipse.cdt.debug.edc.internal.symbols.dwarf;

+

+import java.util.ArrayList;

+import java.util.Collection;

+import java.util.List;

+

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

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

+import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.AttributeList;

+import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider.CompilationUnitHeader;

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

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

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

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

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

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

+

+/**

+ * extension of CompileUnitScope that holds<br>

+ * 1) DWARF specific debug info provider<br>

+ * 2) DWARF specific attributes<br>

+ * 3) DWARF sepcific compile unit header<br>

+ * 4) cache flags for previously parsed variables, addresses & types

+ *

+ */

+public class DwarfCompileUnit extends CompileUnitScope {

+

+	protected DwarfDebugInfoProvider provider;

+	protected AttributeList attributes;

+	private List<IPath> fileList;

+	private boolean rangesDirty;

+

+	/** computation unit header */

+	protected final CompilationUnitHeader header;

+	

+	/** whether the computation unit has been parsed to find variables and children with address ranges */

+	protected boolean parsedForVarsAndAddresses = false;

+	

+	/** whether the computation unit has been parsed to find types */

+	protected boolean parsedForTypes = false;

+

+	

+	/**

+	 * DwarfCompileUnit holds the provider, attributes and DWARF header

+	 * in addition to other member variables of its super, 

+	 * {@link CompileUnitScope#CompileUnitScope(IPath, IModuleScope, IAddress, IAddress)}

+	 * @param provider

+	 * @param parent

+	 * @param filePath

+	 * @param lowAddress

+	 * @param highAddress

+	 * @param header

+	 * @param hasChildren

+	 * @param attributes

+	 */

+	public DwarfCompileUnit(DwarfDebugInfoProvider provider, IModuleScope parent, IPath filePath,

+			IAddress lowAddress, IAddress highAddress, CompilationUnitHeader header, boolean hasChildren,

+			AttributeList attributes) {

+		super(filePath, parent, lowAddress, highAddress);

+

+		this.provider = provider;

+		this.attributes = attributes;

+		this.header = header;

+		

+		// if there are no children, say the children have been parsed

+		if (!hasChildren) {

+			this.parsedForVarsAndAddresses = true;

+			this.parsedForTypes = true;

+		}

+	}

+

+	/**

+	 * called by {@link CompileUnitScope#hashCode()}.

+	 * this implementation further distinguishes the hash-code

+	 * by adding the following to the caller hashCode as follows:

+	 * <br><code>

+	 * (prime+header.debugInfoOffset)*prime+provider.symbolfFile.hashCode()

+	 * </code>

+	 * @see CompileUnitScope#cuScopeHashCode()

+	 */

+	protected int cuScopeHashCode() {

+		final int prime = 31;

+		int result = 1;

+		result = prime * result + header.debugInfoOffset;

+		result = prime * result + provider.getSymbolFile().hashCode();

+		return result;

+	}

+

+	/**

+	 * called by {@link CompileUnitScope#equals(Object)}.

+	 * caller will guarantee objects are not identical, non-null,

+	 * of same class, with the same scope name.

+	 * This implementation further guarantees equality:

+	 * <br>(1) if and only if debugInfoOffset values are equal

+	 * <br>(2) if and only if provider symbol file values are equal

+	 * @see CompileUnitScope#cuScopeEquals(java.lang.Object)

+	 */

+	protected boolean cuScopeEquals(Object obj) {

+		DwarfCompileUnit other = (DwarfCompileUnit) obj;

+		if (header.debugInfoOffset != other.header.debugInfoOffset)

+			return false;

+		if (!provider.getSymbolFile().equals(other.provider.getSymbolFile()))

+			return false;

+		return true;

+	}

+

+	/**

+	 * @return attributes of this DwarfCompileUnit

+	 */

+	public AttributeList getAttributeList() {

+		return attributes;

+	}

+	

+	/**

+	 * utilize DwarfInfoReader to implement abstract declaration in

+	 * {@link CompileUnitScope#parseLineTable()}

+	 */

+	protected Collection<ILineEntry> parseLineTable() {

+		DwarfInfoReader reader = new DwarfInfoReader(provider);

+		fileList = new ArrayList<IPath>();

+		return reader.parseLineTable(this, attributes, fileList);

+	}

+	

+	/** fixup ranges and ensure parsed for addresses before calling

+	 * super.getFunctionAtAddress()

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#getFunctionAtAddress(org.eclipse.cdt.core.IAddress)

+	 */

+	@Override

+	public IFunctionScope getFunctionAtAddress(IAddress linkAddress) {

+		if (rangesDirty) {

+			fixupRanges();

+		}

+		ensureParsedForAddresses();

+		return super.getFunctionAtAddress(linkAddress);

+	}

+	

+	/** ensure parsed for addresses before calling super.getFunctions

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#getFunctions()

+	 */

+	@Override

+	public Collection<IFunctionScope> getFunctions() {

+		ensureParsedForAddresses();

+		return super.getFunctions();

+	}

+	

+	/**

+	 * For compilers that don't generate compile unit scopes, e.g. GCCE with

+	 * dlls, this fixes up the low and high addresses of the compile unit based

+	 * on the function scopes

+	 */

+	protected void fixupRanges() {

+		

+		// fix up scope addresses in case compiler doesn't generate them.

+		if (hasEmptyRange() && parsedForVarsAndAddresses) {

+			fixupRanges(provider.getBaseLinkAddress());

+		}

+

+		rangesDirty = false;

+	}

+	

+// Don't override this here. It causes unnecessary parsing 

+// wasting memory & time.

+//	@Override

+//	public Collection<IScope> getChildren() {

+//		ensureParsedForAddresses();

+//		return super.getChildren();

+//	}

+

+	/**

+	 * allow the caller to establish an attribute list

+	 */

+	public void setAttributes(AttributeList attributes) {

+		this.attributes = attributes;

+	}

+

+	/**

+	 * @return whether or not this DwarfCompileUnit has been parsed for addresses

+	 */

+	public boolean isParsedForAddresses() {

+		return parsedForVarsAndAddresses;

+	}

+

+	/**

+	 * @return whether or not this DwarfCompileUnit has been parsed for variables

+	 */

+	public boolean isParsedForVariables() {

+		return parsedForVarsAndAddresses;

+	}

+

+	/**

+	 * @return whether or not this DwarfCompileUnit has been parsed for types

+	 */

+	public boolean isParsedForTypes() {

+		return parsedForTypes;

+	}

+

+	/** ensure first parsed for variables before calling

+	 * {@link CompileUnitScope#getVariables()}

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#getVariables()

+	 */

+	@Override

+	public Collection<IVariable> getVariables() {

+		ensureParsedForVariables();

+		return super.getVariables();

+	}

+

+	/**

+	 * allow caller to set this DwarfCompileUnit's parsedForVarsAndAddresses flag true

+	 * @param parsedForAddresses

+	 */

+	public void setParsedForAddresses(boolean parsedForAddresses) {

+		this.parsedForVarsAndAddresses = parsedForAddresses;

+	}

+

+	/**

+	 * allow caller to set this DwarfCompileUnit's parsedForVarsAndAddresses flag true

+	 * @param parsedForVariables

+	 */

+	public void setParsedForVariables(boolean parsedForVariables) {

+		this.parsedForVarsAndAddresses = parsedForVariables;

+	}

+

+	/**

+	 * allow caller to set this DwarfCompileUnit's parsedForTypes flag true

+	 * @param parsedForTypes

+	 */

+	public void setParsedForTypes(boolean parsedForTypes) {

+		this.parsedForTypes = parsedForTypes;

+	}

+

+	private void ensureParsedForAddresses() {

+		if (!parsedForVarsAndAddresses) {

+			DwarfInfoReader reader = new DwarfInfoReader(provider);

+			reader.parseCompilationUnitForAddresses(this);

+			fixupRanges();

+		}

+	}

+	

+	/**

+	 * Get the file path for a file number

+	 * @param declFileNum

+	 * @return IPath for the file, or <code>null</code>

+	 */

+	public IPath getFileEntry(int declFileNum) {

+		if (fileList == null)

+			parseLineTable();

+		if (declFileNum <= 0 || declFileNum > fileList.size())

+			return null;

+		return fileList.get(declFileNum - 1);

+	}

+	

+	private void ensureParsedForVariables() {

+		if (!parsedForVarsAndAddresses) {

+			DwarfInfoReader reader = new DwarfInfoReader(provider);

+			reader.parseCompilationUnitForAddresses(this);

+		}

+	}

+	

+	/** ensure parsed for addresses before calling super.getScopeAtAddress()

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#getScopeAtAddress(org.eclipse.cdt.core.IAddress)

+	 */

+	@Override

+	public IScope getScopeAtAddress(IAddress linkAddress) {

+		ensureParsedForAddresses();

+		return super.getScopeAtAddress(linkAddress);

+	}

+

+	/**

+	 * DwarfCompileUnit specific version of toString():<br>

+	 * <code>

+	 * [SymFile=, SectionOffset=, lowAddr=, highAddr=, path=, parsedForVarsAndAddress=, parsedForTypes=]

+	 * </code>

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.CompileUnitScope#toString()

+	 */

+	@Override

+	public String toString() {

+		StringBuilder builder = new StringBuilder();

+		builder.append("DwarfCompileUnit [");

+		

+		builder.append("SymFile=");

+		builder.append(provider.getSymbolFile().lastSegment());

+		

+		builder.append(", SectionOffset=0x");

+		builder.append(Integer.toHexString(header.debugInfoOffset));

+		

+		builder.append(", lowAddr=");

+		builder.append(lowAddress != null ? lowAddress.toHexAddressString() : null);

+		

+		builder.append(", highAddr=");

+		builder.append(highAddress != null ? highAddress.toHexAddressString() : null);

+		if (filePath != null) {

+			builder.append(", path=");

+			builder.append(filePath.toOSString());

+		}

+		builder.append(", parsedForVarsAndAddresses=");

+		builder.append(parsedForVarsAndAddresses);

+		builder.append(", parsedForTypes=");

+		builder.append(parsedForTypes);

+		builder.append("]\n");

+		return builder.toString();

+	}

+	

+

+	/**

+	 * 1) calls super.addChild() first<br>

+	 * 2) checks whether this has an empty range and merges range with passed child scope if not.<br>

+	 * 3) adds line info to the passed child scope

+	 * @see org.eclipse.cdt.debug.edc.internal.symbols.Scope#addChild(org.eclipse.cdt.debug.edc.symbols.IScope)

+	 */

+	@Override

+	public void addChild(IScope scope) {

+		super.addChild(scope);

+		

+		// if we don't know our scope yet...

+		if (hasEmptyRange()) {

+			rangesDirty = true;

+		} else {

+			// the CU may have an incomplete idea of its scope; fit the new scope in

+			mergeScopeRange(scope);

+		}

+

+		addLineInfoToParent(scope);

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfDebugInfoProvider.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfDebugInfoProvider.java
index ffbbbc6..a5bf841 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfDebugInfoProvider.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfDebugInfoProvider.java
@@ -735,6 +735,7 @@
 		functionsByOffset.clear();

 		typesByOffset.clear();

 		referenceTypesByOffset.clear();

+		typesByName.clear();

 		scopesByOffset.clear();

 		debugOffsetsToCompileUnits.clear();

 		functionsByName.clear();

@@ -742,6 +743,8 @@
 		publicFunctions.clear();

 		publicVariables.clear();

 		abbreviationMaps.clear();

+		frameDescEntries.clear();

+		commonInfoEntries.clear();

 		referencedFiles.clear();

 		parsedInitially = false;

 		parsedForTypes = false;

@@ -988,7 +991,8 @@
 	private void filterOutLocalVariables(List<IVariable> variables) {

 		List<IVariable> allVariables = new ArrayList<IVariable>(variables);

 		for (IVariable var : allVariables) {

-			if (!(var.getScope() instanceof ICompileUnitScope)) {

+			if (!(var.getScope() instanceof ICompileUnitScope)

+				&& !(var.getScope() instanceof IModuleScope)) {

 				variables.remove(var);

 			}

 		}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfInfoReader.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfInfoReader.java
index 674f4c5..3ace41d 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfInfoReader.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/dwarf/DwarfInfoReader.java
@@ -98,6 +98,8 @@
 import org.eclipse.core.runtime.Status;

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

 

+@SuppressWarnings("unused")

+

 /**

  * Handle restartable parsing of Dwarf information from a single module.  

  * This class may be instantiated multiple times to parse specific subsets 

@@ -247,19 +249,7 @@
  	 * compilation units.  

 	 */

 	public void parseInitial() {

-			Job parseInitialJob = new Job(DwarfMessages.DwarfInfoReader_ReadingSymbolInfo + symbolFilePath) {

-		

-				@Override

-				protected IStatus run(IProgressMonitor monitor) {

-					if (EDCTrace.SYMBOL_READER_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(DwarfMessages.DwarfInfoReader_TraceInitialParseFor + symbolFilePath)); }

-					synchronized (provider) {

-						parseCUDebugInfo(monitor);

-						parsePublicNames();

-					}

-					if (EDCTrace.SYMBOL_READER_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(DwarfMessages.DwarfInfoReader_TraceFinishedInitialParse)); }

-					return Status.OK_STATUS;

-				}

-			};

+			Job parseInitialJob = new ParseJob(DwarfMessages.DwarfInfoReader_ReadingSymbolInfo + symbolFilePath, provider, this, symbolFilePath);

 			

 			try {

 				parseInitialJob.schedule();

@@ -270,6 +260,42 @@
 	}

 

 	/**

+	 * Must be static and a separate class so that its pointer to this

+	 * DwarfInfoReader can be broken as Jobs get held onto by the

+	 * ProgressViewUpdater and so this prevents GC from occurring on everything.

+	 * 

+	 * @author Daniel Thomas

+	 * 

+	 */

+	private static class ParseJob extends Job{

+

+		private DwarfDebugInfoProvider provider;

+		private DwarfInfoReader reader;

+		private IPath symbolFilePath;

+

+		public ParseJob(String string, DwarfDebugInfoProvider provider, DwarfInfoReader reader, IPath symbolFilePath) {

+			super(string);

+			this.provider = provider;

+			this.reader = reader;

+			this.symbolFilePath = symbolFilePath;

+		}

+

+		@Override

+		protected IStatus run(IProgressMonitor monitor) {

+			if (EDCTrace.SYMBOL_READER_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(DwarfMessages.DwarfInfoReader_TraceInitialParseFor + symbolFilePath)); }

+			synchronized (provider) {

+				reader.parseCUDebugInfo(monitor);

+				reader.parsePublicNames();

+			}

+			provider = null;

+			reader = null;

+			symbolFilePath = null;

+			if (EDCTrace.SYMBOL_READER_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(DwarfMessages.DwarfInfoReader_TraceFinishedInitialParse)); }

+			return Status.OK_STATUS;

+		}

+	}

+

+	/**

 	 * Parse all compilation units for addresses

 	 * 

 	 * @param includeCUWithoutCode

@@ -1114,9 +1140,7 @@
 					int length = data.getInt() + 4;

 	

 					// Skip the following till "opcode_base"

-					@SuppressWarnings("unused")

 					int version = data.getShort();

-					@SuppressWarnings("unused")

 					int prologue_length = data.getInt();

 					int minimum_instruction_length = data.get() & 0xff;

 					boolean default_is_stmt = data.get() > 0;

@@ -1180,9 +1204,7 @@
 					int info_line = 1;

 					int info_column = 0;

 					boolean is_stmt = default_is_stmt;

-					@SuppressWarnings("unused")

 					int info_flags = 0;

-					@SuppressWarnings("unused")

 					long info_ISA = 0;

 	

 					long lineInfoEnd = stmtList + length;

@@ -1208,9 +1230,7 @@
 							case DwarfConstants.DW_LNE_define_file: {

 								fileName = readString(data);

 								long dir = read_unsigned_leb128(data);

-								@SuppressWarnings("unused")

 								long modTime = read_unsigned_leb128(data);

-								@SuppressWarnings("unused")

 								long fileSize = read_unsigned_leb128(data);

 								IPath fullPath = fileHelper.normalizeFilePath(dirList.get((int) dir), fileName);

 								if (fullPath != null) {

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/files/ElfExecutableSymbolicsReader.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/files/ElfExecutableSymbolicsReader.java
index 94164a7..c63656b 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/files/ElfExecutableSymbolicsReader.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/internal/symbols/files/ElfExecutableSymbolicsReader.java
@@ -142,7 +142,8 @@
 	protected ISection getSegmentForExecutableSection(Elf.Section section){

 		for (ISection segment : sections){

 			if (segment.getLowAddress().compareTo(section.sh_addr) <= 0

-					&& segment.getHighAddress().compareTo(section.sh_addr.add(section.sh_size)) > 0){

+				&& (segment.getHighAddress().compareTo(section.sh_addr.add(section.sh_size)) > 0

+					|| segment.getLowAddress().equals(segment.getHighAddress()))) {

 				return segment;

 			}

 		}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/EDCServicesTracker.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/EDCServicesTracker.java
index b7d2320..bfe0805 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/EDCServicesTracker.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/EDCServicesTracker.java
@@ -1,242 +1,239 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 Wind River Systems 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:
- *     Wind River Systems - initial API and implementation
- *******************************************************************************/
-package org.eclipse.cdt.debug.edc.services;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.dsf.service.IDsfService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Convenience class to help track DSF services that a given
- * client needs to use.  This class is based on the DsfServicesTracker
- * but is designed to be thread safe so clients can use it to get
- * a service reference from any thread. This is important for EDC
- * services because they are not restricted to the Dsf thread.
- * 
- * @since 2.0
- */
-public class EDCServicesTracker {
-	
-    private static String getServiceFilter(String sessionId) {
-        return ("(" + IDsfService.PROP_SESSION_ID + "=" + sessionId + ")").intern();   //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
-    }
-
-    final private static class ServiceKey 
-    {
-        private final String fClassName;
-        private final String fFilter;
-        private final int fHashCode;
-        private final String fHashString;
-        
-        
-        public ServiceKey(Class<?> clazz, String filter) {
-            fClassName = clazz != null ? clazz.getName() : null;
-            fFilter = filter;
-            fHashString =  'C' + (fClassName == null ? "" : fClassName) + //$NON-NLS-1$
-        				   'F' + (fFilter == null ? "" : fFilter); //$NON-NLS-1$
-            fHashCode = fHashString.hashCode();
-        }
-        
-        @Override
-        public boolean equals(Object other) {
-        	// hashcodes are not guaranteed to be unique, but objects that are equal must have the same hashcode
-        	// thus we can optimize by first comparing hashcodes
-            return other instanceof ServiceKey &&
-            	((((ServiceKey)other).fHashCode == this.fHashCode) && (((ServiceKey)other).fHashString.equals(this.fHashString))); 
-        }
-        
-        @Override
-        public int hashCode() {
-        	return fHashCode;
-        }
-    }
-    
-    private final String fSessionId;    
-    private volatile boolean fDisposed = false;
-    private final BundleContext fBundleContext;
-
-    @SuppressWarnings("rawtypes")
-	private final Map<ServiceKey,ServiceReference> fServiceReferences = Collections.synchronizedMap(new HashMap<ServiceKey,ServiceReference>());
-    @SuppressWarnings("rawtypes")
-	private final Map<ServiceReference,Object> fServices = Collections.synchronizedMap(new HashMap<ServiceReference,Object>());
-    private final String fServiceFilter;
-
-    private final ServiceListener fListner = new ServiceListener() {
-        public void serviceChanged(final ServiceEvent event) {
-            // Only listen to unregister events.
-            if (event.getType() != ServiceEvent.UNREGISTERING) {
-                return;
-            }
-            
-            // If session is not active anymore, just exit.  The tracker should 
-            // soon be disposed.
-            DsfSession session = DsfSession.getSession(fSessionId);
-            if (session == null) {
-                return;
-            }
-            
-            handleUnregisterEvent(event);
-        }
-    };
-    
-    @SuppressWarnings("rawtypes")
-	private void handleUnregisterEvent(ServiceEvent event) {
-    	synchronized (fServiceReferences)
-    	{
-            for (Iterator<Map.Entry<ServiceKey, ServiceReference>> itr = fServiceReferences.entrySet().iterator(); itr.hasNext();) {
-                Map.Entry<ServiceKey, ServiceReference> entry = itr.next();
-                if ( entry.getValue().equals(event.getServiceReference()) ) {
-                    itr.remove();
-                }
-            }
-            if (fServices.remove(event.getServiceReference()) != null) {
-                fBundleContext.ungetService(event.getServiceReference());
-            }
-    	}
-    }
-    
-    /** 
-     * Only constructor.
-     * @param bundleContext Context of the plugin that the client lives in. 
-     * @param sessionId The DSF session that this tracker will be used for. 
-     */
-    public EDCServicesTracker(BundleContext bundleContext, String sessionId) {
-        fSessionId = sessionId;
-        fBundleContext = bundleContext;
-        fServiceFilter = getServiceFilter(sessionId); 
-        try {
-            fBundleContext.addServiceListener(fListner, fServiceFilter);
-        } catch (InvalidSyntaxException e) {
-            assert false : "Invalid session ID syntax"; //$NON-NLS-1$
-        }
-    }
-    
-    /**
-     * Retrieves a service reference for given service class and optional filter.  
-     * Filter should be used if there are multiple instances of the desired service
-     * running within the same session. 
-     * @param serviceClass class of the desired service
-     * @param custom filter to use when searching for the service, this filter will 
-     * be used instead of the standard filter so it should also specify the desired 
-     * session-ID 
-     * @return OSGI service reference object to the desired service, null if not found
-     */
-    @SuppressWarnings("rawtypes")
-    public ServiceReference getServiceReference(Class serviceClass, String filter) {
-        if (fDisposed) {
-            return null;
-        }
-        
-        // If the session is not active, all of its services are gone.
-        DsfSession session = DsfSession.getSession(fSessionId);
-        if (session == null) {
-            return null;
-        }
-        
-        ServiceKey key = new ServiceKey(serviceClass, filter != null ? filter : fServiceFilter);
-        if (fServiceReferences.containsKey(key)) {
-            return fServiceReferences.get(key);
-        }
-        
-        try {
-            ServiceReference[] references = fBundleContext.getServiceReferences(key.fClassName, key.fFilter);
-            assert references == null || references.length <= 1;
-            if (references == null || references.length == 0) {
-                return null;
-            } else {
-                fServiceReferences.put(key, references[0]);
-                return references[0];
-            }
-        } catch(InvalidSyntaxException e) {
-            assert false : "Invalid session ID syntax"; //$NON-NLS-1$
-        } catch(IllegalStateException e) {
-            // Can occur when plugin is shutting down.
-        }
-        return null;
-    }
-    
-    /**
-     * Convenience class to retrieve a service based on class name only.
-     * @param serviceClass class of the desired service
-     * @return instance of the desired service, null if not found
-     */
-    public <V> V getService(Class<V> serviceClass) {
-        return getService(serviceClass, null);
-    }
-    
-    /** 
-     * Retrieves the service given service class and optional filter.
-     * Filter should be used if there are multiple instances of the desired service
-     * running within the same session. 
-     * @param serviceClass class of the desired service
-     * @param custom filter to use when searching for the service, this filter will 
-     * be used instead of the standard filter so it should also specify the desired 
-     * session-ID 
-     * @return instance of the desired service, null if not found
-     */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <V> V getService(Class<V> serviceClass, String filter) {
-        ServiceReference serviceRef = getServiceReference(serviceClass, filter);
-        if (serviceRef == null) {
-            return null;
-        } else {
-            if (fServices.containsKey(serviceRef)) {
-                return (V)fServices.get(serviceRef);
-            } else {
-                V service = (V)fBundleContext.getService(serviceRef);
-                fServices.put(serviceRef, service);
-                return service;
-            }
-        }
-    }
-    
-    /**
-     * Un-gets all the references held by this tracker.  Must be called
-     * to avoid leaking OSGI service references.
-     */
-    public void dispose() {
-        assert !fDisposed;
-        fDisposed = true;
-        doDispose();
-    }
-
-    @SuppressWarnings("rawtypes")
-	private void doDispose() {
-    	synchronized (fServices)
-    	{
-            try {
-                fBundleContext.removeServiceListener(fListner);
-                for (Iterator<ServiceReference> itr = fServices.keySet().iterator(); itr.hasNext();) {
-                    fBundleContext.ungetService(itr.next());
-                }
-            } catch (IllegalStateException e) {
-                // May be thrown during shutdown (bug 293049).
-            }
-    	}
-        fServices.clear();
-        fServiceReferences.clear();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        assert fDisposed;
-        super.finalize();
-    }
-}
+/*******************************************************************************

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

+ *     Wind River Systems - initial API and implementation

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

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

+

+import java.util.Collections;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+

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

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

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceEvent;

+import org.osgi.framework.ServiceListener;

+import org.osgi.framework.ServiceReference;

+

+@SuppressWarnings("rawtypes")

+

+/**

+ * Convenience class to help track DSF services that a given

+ * client needs to use.  This class is based on the DsfServicesTracker

+ * but is designed to be thread safe so clients can use it to get

+ * a service reference from any thread. This is important for EDC

+ * services because they are not restricted to the Dsf thread.

+ * 

+ * @since 2.0

+ */

+public class EDCServicesTracker {

+	

+    private static String getServiceFilter(String sessionId) {

+        return ("(" + IDsfService.PROP_SESSION_ID + "=" + sessionId + ")").intern();   //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$

+    }

+

+    final private static class ServiceKey 

+    {

+        private final String fClassName;

+        private final String fFilter;

+        private final int fHashCode;

+        private final String fHashString;

+        

+        

+        public ServiceKey(Class<?> clazz, String filter) {

+            fClassName = clazz != null ? clazz.getName() : null;

+            fFilter = filter;

+            fHashString =  'C' + (fClassName == null ? "" : fClassName) + //$NON-NLS-1$

+        				   'F' + (fFilter == null ? "" : fFilter); //$NON-NLS-1$

+            fHashCode = fHashString.hashCode();

+        }

+        

+        @Override

+        public boolean equals(Object other) {

+        	// hashcodes are not guaranteed to be unique, but objects that are equal must have the same hashcode

+        	// thus we can optimize by first comparing hashcodes

+            return other instanceof ServiceKey &&

+            	((((ServiceKey)other).fHashCode == this.fHashCode) && (((ServiceKey)other).fHashString.equals(this.fHashString))); 

+        }

+        

+        @Override

+        public int hashCode() {

+        	return fHashCode;

+        }

+    }

+    

+    private final String fSessionId;    

+    private volatile boolean fDisposed = false;

+    private final BundleContext fBundleContext;

+

+	private final Map<ServiceKey,ServiceReference> fServiceReferences = Collections.synchronizedMap(new HashMap<ServiceKey,ServiceReference>());

+	private final Map<ServiceReference,Object> fServices = Collections.synchronizedMap(new HashMap<ServiceReference,Object>());

+    private final String fServiceFilter;

+

+    private final ServiceListener fListner = new ServiceListener() {

+        public void serviceChanged(final ServiceEvent event) {

+            // Only listen to unregister events.

+            if (event.getType() != ServiceEvent.UNREGISTERING) {

+                return;

+            }

+            

+            // If session is not active anymore, just exit.  The tracker should 

+            // soon be disposed.

+            DsfSession session = DsfSession.getSession(fSessionId);

+            if (session == null) {

+                return;

+            }

+            

+            handleUnregisterEvent(event);

+        }

+    };

+    

+	private void handleUnregisterEvent(ServiceEvent event) {

+    	synchronized (fServiceReferences)

+    	{

+            for (Iterator<Map.Entry<ServiceKey, ServiceReference>> itr = fServiceReferences.entrySet().iterator(); itr.hasNext();) {

+                Map.Entry<ServiceKey, ServiceReference> entry = itr.next();

+                if ( entry.getValue().equals(event.getServiceReference()) ) {

+                    itr.remove();

+                }

+            }

+            if (fServices.remove(event.getServiceReference()) != null) {

+                fBundleContext.ungetService(event.getServiceReference());

+            }

+    	}

+    }

+    

+    /** 

+     * Only constructor.

+     * @param bundleContext Context of the plugin that the client lives in. 

+     * @param sessionId The DSF session that this tracker will be used for. 

+     */

+    public EDCServicesTracker(BundleContext bundleContext, String sessionId) {

+        fSessionId = sessionId;

+        fBundleContext = bundleContext;

+        fServiceFilter = getServiceFilter(sessionId); 

+        try {

+            fBundleContext.addServiceListener(fListner, fServiceFilter);

+        } catch (InvalidSyntaxException e) {

+            assert false : "Invalid session ID syntax"; //$NON-NLS-1$

+        }

+    }

+    

+    /**

+     * Retrieves a service reference for given service class and optional filter.  

+     * Filter should be used if there are multiple instances of the desired service

+     * running within the same session. 

+     * @param serviceClass class of the desired service

+     * @param custom filter to use when searching for the service, this filter will 

+     * be used instead of the standard filter so it should also specify the desired 

+     * session-ID 

+     * @return OSGI service reference object to the desired service, null if not found

+     */

+    public ServiceReference getServiceReference(Class serviceClass, String filter) {

+        if (fDisposed) {

+            return null;

+        }

+        

+        // If the session is not active, all of its services are gone.

+        DsfSession session = DsfSession.getSession(fSessionId);

+        if (session == null) {

+            return null;

+        }

+        

+        ServiceKey key = new ServiceKey(serviceClass, filter != null ? filter : fServiceFilter);

+        if (fServiceReferences.containsKey(key)) {

+            return fServiceReferences.get(key);

+        }

+        

+        try {

+            ServiceReference[] references = fBundleContext.getServiceReferences(key.fClassName, key.fFilter);

+            assert references == null || references.length <= 1;

+            if (references == null || references.length == 0) {

+                return null;

+            } else {

+                fServiceReferences.put(key, references[0]);

+                return references[0];

+            }

+        } catch(InvalidSyntaxException e) {

+            assert false : "Invalid session ID syntax"; //$NON-NLS-1$

+        } catch(IllegalStateException e) {

+            // Can occur when plugin is shutting down.

+        }

+        return null;

+    }

+    

+    /**

+     * Convenience class to retrieve a service based on class name only.

+     * @param serviceClass class of the desired service

+     * @return instance of the desired service, null if not found

+     */

+    public <V> V getService(Class<V> serviceClass) {

+        return getService(serviceClass, null);

+    }

+    

+    /** 

+     * Retrieves the service given service class and optional filter.

+     * Filter should be used if there are multiple instances of the desired service

+     * running within the same session. 

+     * @param serviceClass class of the desired service

+     * @param custom filter to use when searching for the service, this filter will 

+     * be used instead of the standard filter so it should also specify the desired 

+     * session-ID 

+     * @return instance of the desired service, null if not found

+     */

+    @SuppressWarnings("unchecked")

+	public <V> V getService(Class<V> serviceClass, String filter) {

+        ServiceReference serviceRef = getServiceReference(serviceClass, filter);

+        if (serviceRef == null) {

+            return null;

+        } else {

+            if (fServices.containsKey(serviceRef)) {

+                return (V)fServices.get(serviceRef);

+            } else {

+                V service = (V)fBundleContext.getService(serviceRef);

+                fServices.put(serviceRef, service);

+                return service;

+            }

+        }

+    }

+    

+    /**

+     * Un-gets all the references held by this tracker.  Must be called

+     * to avoid leaking OSGI service references.

+     */

+    public void dispose() {

+        assert !fDisposed;

+        fDisposed = true;

+        doDispose();

+    }

+

+	private void doDispose() {

+    	synchronized (fServices)

+    	{

+            try {

+                fBundleContext.removeServiceListener(fListner);

+                for (Iterator<ServiceReference> itr = fServices.keySet().iterator(); itr.hasNext();) {

+                    fBundleContext.ungetService(itr.next());

+                }

+            } catch (IllegalStateException e) {

+                // May be thrown during shutdown (bug 293049).

+            }

+    	}

+        fServices.clear();

+        fServiceReferences.clear();

+    }

+

+    @Override

+    protected void finalize() throws Throwable {

+        assert fDisposed;

+        super.finalize();

+    }

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/IEDCModuleDMContext.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/IEDCModuleDMContext.java
index 9d7785a..20b8d61 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/IEDCModuleDMContext.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/IEDCModuleDMContext.java
@@ -1,42 +1,52 @@
-/*******************************************************************************
- * 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.services;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
-import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext;
-
-public interface IEDCModuleDMContext extends IModuleDMContext, IEDCDMContext {
-
-	/**
-	 * Convert link address to runtime address.
-	 * 
-	 * @param linkAddress
-	 * @return null if the given link address is not in the module.
-	 */
-	public IAddress toRuntimeAddress(IAddress linkAddress);
-
-	/**
-	 * Convert runtime address to link address.
-	 * 
-	 * @param runtimeAddress
-	 * @return null if the given runtime address is not in the module.
-	 */
-	public IAddress toLinkAddress(IAddress runtimeAddress);
-
-	/**
-	 * Gets the symbol reader used to read symbols for this module.
-	 * 
-	 * @return the symbol reader
-	 */
-	public IEDCSymbolReader getSymbolReader();
-
+/*******************************************************************************

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

+

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

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

+import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext;

+

+public interface IEDCModuleDMContext extends IModuleDMContext, IEDCDMContext {

+

+	/**

+	 * Convert link address to runtime address.

+	 * 

+	 * @param linkAddress

+	 * @return null if the given link address is not in the module.

+	 */

+	public IAddress toRuntimeAddress(IAddress linkAddress);

+

+	/**

+	 * Convert runtime address to link address.

+	 * 

+	 * @param runtimeAddress

+	 * @return null if the given runtime address is not in the module.

+	 */

+	public IAddress toLinkAddress(IAddress runtimeAddress);

+

+	/**

+	 * Gets the symbol reader used to read symbols for this module.

+	 * 

+	 * @return the symbol reader

+	 */

+	public IEDCSymbolReader getSymbolReader();

+

+	/**

+	 * Gets the symbol reader used to read symbols for this module.  The caller

+	 * can force the reader to be created if not done so already.

+	 * 

+	 * @param create try to create the reader if not done so already

+	 * @return the symbol reader, or null if none

+	 * @since 3.0

+	 */

+	public IEDCSymbolReader getSymbolReader(boolean create);

+

 }
\ No newline at end of file
diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Registers.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Registers.java
index 3158061..5876d49 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Registers.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Registers.java
@@ -1,1237 +1,1241 @@
-/*******************************************************************************
- * 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.services;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-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.debug.edc.MemoryUtils;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.NumberFormatUtils;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.SuspendedEvent;
-import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
-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.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.datamodel.DMContexts;
-import org.eclipse.cdt.dsf.datamodel.IDMContext;
-import org.eclipse.cdt.dsf.debug.service.ICachingService;
-import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
-import org.eclipse.cdt.dsf.debug.service.IRegisters;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
-import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
-import org.eclipse.cdt.dsf.service.DsfSession;
-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.SubMonitor;
-import org.eclipse.tm.tcf.protocol.IService;
-import org.eclipse.tm.tcf.protocol.IToken;
-import org.eclipse.tm.tcf.services.IRegisters.RegistersContext;
-import org.eclipse.tm.tcf.util.TCFTask;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-/**
- * The Registers service provides information about the target processor
- * registers.
- */
-public abstract class Registers extends AbstractEDCService implements IRegisters, ICachingService, IDSFServiceUsingTCF {
-
-	/**
-	 * Cache register groups per context.
-	 * Keyed on context ID.
-	 */
-	private Map<String, List<RegisterGroupDMC>> registerGroupsPerContext = 
-		Collections.synchronizedMap(new HashMap<String, List<RegisterGroupDMC>>());
-
-	/** The TCF registers service. */
-	protected org.eclipse.tm.tcf.services.IRegisters		tcfRegistersService = null;
-	
-	/**
-	 * Register value cache per execution context.
-	 * Keyed on context ID.
-	 */
-	private Map<String, Map<String, BigInteger>> registerValueCache = 
-		Collections.synchronizedMap(new HashMap<String, Map<String, BigInteger>>());
-
-	/** Iimeout value in milliseconds when waiting for a response from the TCF service. */
-	private long tcfTimeout;
-
-	/**
-	 * A hex string indicating error in register read.
-	 * See where this is used for more.
-	 */
-	protected static final String REGISTER_VALUE_ERROR = "badbadba";
-	
-	public static final String PROP_EXECUTION_CONTEXT_ID = "Context_ID";
-
-	private static final String REGISTER = "register";
-
-	/**
-	 * Represents a group of registers.
-	 */
-	public class RegisterGroupDMC extends DMContext implements IRegisterGroupDMContext, ISnapshotContributor {
-
-		private static final String REGISTER_GROUP = "register_group";
-
-		/** The registers in this group. */
-		private List<RegisterDMC> registers = Collections.synchronizedList(new ArrayList<RegisterDMC>());
-
-		/** The executable context. */
-		private final IEDCExecutionDMC exeContext;
-
-		/**
-		 * Instantiates a new register group dmc.
-		 *
-		 * @param service the service
-		 * @param executionDMC the execution context
-		 * @param groupName the group name
-		 * @param groupDescription the group description
-		 * @param groupID the group id
-		 */
-		public RegisterGroupDMC(Registers service, IEDCExecutionDMC executionDMC, String groupName, String groupDescription,
-				String groupID) {
-			super(service, new IDMContext[] { executionDMC }, groupName, groupID);
-			exeContext = executionDMC;
-			properties.put(PROP_DESCRIPTION, groupDescription);
-			properties.put(PROP_EXECUTION_CONTEXT_ID, executionDMC.getID());
-		}
-
-		/**
-		 * Instantiates a new register group dmc.
-		 *
-		 * @param service the service
-		 * @param executionDmc the execution dmc
-		 * @param props the props
-		 */
-		public RegisterGroupDMC(Registers service, IEDCExecutionDMC executionDmc,
-								Map<String, Object> props) {
-			super(service, new IDMContext[] { executionDmc }, props);
-			exeContext = executionDmc;
-			properties.put(PROP_EXECUTION_CONTEXT_ID, exeContext.getID());
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.DMContext#toString()
-		 */
-		@Override
-		public String toString() {
-			return baseToString() + ".group[" + getName() + "]";} //$NON-NLS-1$ //$NON-NLS-2$
-
-		/**
-		 * Gets the registers for this group.
-		 *
-		 * @return array of register contexts for this group
-		 * @throws CoreException the core exception
-		 */
-		public RegisterDMC[] getRegisters() throws CoreException {
-			RegisterDMC[] result = new RegisterDMC[0];
-			synchronized (registers) {
-				if (registers.size() == 0) {
-					registers = Registers.this.createRegistersForGroup(this);
-				}
-				result = registers.toArray(new RegisterDMC[registers.size()]);
-			}
-			return result;
-		}
-
-		/**
-		 * Take a snapshot of this group of registers.
-		 *
-		 * @param album the snapshot album
-		 * @param document the XML document
-		 * @param monitor the progress monitor
-		 * @return the XML element
-		 * @throws Exception the exception if anything goes wrong
-		 * @since 2.0
-		 */
-		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor)throws Exception {
-			Element contextElement = document.createElement(REGISTER_GROUP);
-			contextElement.setAttribute(PROP_ID, this.getID());
-
-			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
-			contextElement.appendChild(propsElement);
-
-			RegisterDMC[] allRegisters = getRegisters();
-			SubMonitor progress = SubMonitor.convert(monitor, allRegisters.length * 1000);
-			progress.subTask("Registers");
-			for (RegisterDMC registerDMC : allRegisters) {
-				Element dmcElement = registerDMC.takeSnapshot(album, document, progress.newChild(1000));
-				contextElement.appendChild(dmcElement);
-			}
-			return contextElement;
-		}
-
-		/**
-		 * Gets the execution dmc.
-		 *
-		 * @return the execution dmc
-		 */
-		public IEDCExecutionDMC getExecutionDMC() {
-			return exeContext;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor#loadSnapshot(org.w3c.dom.Element)
-		 */
-		public void loadSnapshot(Element element) throws Exception {
-			NodeList registerElement = element.getElementsByTagName(REGISTER);
-
-			int numRegisters = registerElement.getLength();
-			for (int i = 0; i < numRegisters; i++) {
-				Element regElement = (Element) registerElement.item(i);
-				Element propElement = (Element) regElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-				HashMap<String, Object> properties = new HashMap<String, Object>();
-				SnapshotUtils.initializeFromXML(propElement, properties);
-
-				RegisterDMC regdmc = new RegisterDMC(this, exeContext, properties);
-				regdmc.loadSnapshot(regElement);
-				registers.add(regdmc);
-			}
-
-		}
-
-	}
-
-	/**
-	 * Represents the context for a single register.
-	 */
-	public class RegisterDMC extends DMContext implements IRegisterDMContext, ISnapshotContributor {
-
-		/** The context used by the TCF agent. */
-		private org.eclipse.tm.tcf.services.IRegisters.RegistersContext tcfContext = null;
-		
-		/**
-		 * Instantiates a new register dmc.
-		 *
-		 * @param executableDMC the executable context
-		 * @param name the register name
-		 * @param description the register description
-		 * @param id the register id
-		 */
-		public RegisterDMC(IEDCExecutionDMC executableDMC, String name, String description, String id) {
-			super(Registers.this, new IDMContext[] { executableDMC }, name, id);
-			properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());
-		}
-
-		/**
-		 * Instantiates a new register dmc.
-		 *
-		 * @param registerGroupDmc the register group dmc
-		 * @param executableDMC the executable context
-		 * @param properties the properties
-		 */
-		public RegisterDMC(RegisterGroupDMC registerGroupDmc, IEDCExecutionDMC executableDMC,
-							Map<String, Object> properties) {
-			super(Registers.this, new IDMContext[] { executableDMC }, properties);
-			this.properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());
-		}
-
-		/**
-		 * Construct based on underlying context from TCF IRegisters service.
-		 *
-		 * @param registerGroupDMC the register group dmc
-		 * @param executableDMC the executable context
-		 * @param tcfContext the tcf context
-		 */
-		public RegisterDMC(RegisterGroupDMC registerGroupDMC, IEDCExecutionDMC executableDMC, RegistersContext tcfContext) {
-			super(Registers.this, new IDMContext[] { registerGroupDMC }, tcfContext.getProperties());
-			this.properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());
-			
-			this.tcfContext = tcfContext;
-		}
-
-		/**
-		 * Get the underlying TCF context.
-		 * @return may be null.
-		 */
-		public RegistersContext getTCFContext() {
-			return tcfContext;
-		}
-		
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.services.DMContext#toString()
-		 */
-		@Override
-		public String toString() {
-			return baseToString() + ".register[" + getName() + "]";} //$NON-NLS-1$ //$NON-NLS-2$
-
-		/**
-		 * Take a snapshot of this register.
-		 *
-		 * @param album the snapshot album
-		 * @param document the XML document
-		 * @param monitor the progress monitor
-		 * @return the XML element
-		 * @throws Exception the exception if anything goes wrong
-		 * @since 2.0
-		 */
-		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor) throws Exception {
-			Element registerElement = document.createElement(REGISTER);
-			registerElement.setAttribute(PROP_ID, this.getID());
-			registerElement.setAttribute(PROP_VALUE, getRegisterValueAsHexString(this));
-			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
-			registerElement.appendChild(propsElement);
-			return registerElement;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor#loadSnapshot(org.w3c.dom.Element)
-		 */
-		public void loadSnapshot(Element element) throws Exception {
-			String registerValue = element.getAttribute(PROP_VALUE);
-			String contextID = (String) getProperties().get(PROP_EXECUTION_CONTEXT_ID);
-
-			synchronized (registerValueCache) {
-				Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(contextID);
-				if (exeDMCRegisters == null) {
-					exeDMCRegisters = new HashMap<String, BigInteger>();
-					registerValueCache.put(contextID, exeDMCRegisters);
-				}
-				exeDMCRegisters.put(getID(), new BigInteger(registerValue, 16));
-			}
-		}
-	}
-
-	class RegisterData implements IRegisterDMData {
-
-		private final HashMap<String, Object> properties = new HashMap<String, Object>();
-
-		public RegisterData(Map<String, Object> properties) {
-			this.properties.putAll(properties);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isReadable()
-		 */
-		public boolean isReadable() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_READBLE);
-            if (n == null) 
-            	return true;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isReadOnce()
-		 */
-		public boolean isReadOnce() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_READ_ONCE);
-            if (n == null) 
-            	return false;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isWriteable()
-		 */
-		public boolean isWriteable() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_WRITEABLE);
-            if (n == null) 
-            	return true;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isWriteOnce()
-		 */
-		public boolean isWriteOnce() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_WRITE_ONCE);
-            if (n == null) 
-            	return false;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#hasSideEffects()
-		 */
-		public boolean hasSideEffects() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_SIDE_EFFECTS);
-            if (n == null) 
-            	return false;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isVolatile()
-		 */
-		public boolean isVolatile() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_VOLATILE);
-            if (n == null) 
-            	return false;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isFloat()
-		 */
-		public boolean isFloat() {
-            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_FLOAT);
-            if (n == null) 
-            	return false;
-            return n.booleanValue();
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#getName()
-		 */
-		public String getName() {
-			return (String) properties.get(IEDCDMContext.PROP_NAME);
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#getDescription()
-		 */
-		public String getDescription() {
-			return (String) properties.get(IEDCDMContext.PROP_DESCRIPTION);
-		}
-
-	}
-
-	/**
-	 * Event class to notify register value is changed
-	 */
-	public static class RegisterChangedDMEvent implements IRegisters.IRegisterChangedDMEvent {
-
-		/** The register dmc. */
-		private final IRegisterDMContext fRegisterDMC;
-
-		/**
-		 * Instantiates a new register changed dm event.
-		 *
-		 * @param registerDMC the register dmc
-		 */
-		RegisterChangedDMEvent(IRegisterDMContext registerDMC) {
-			fRegisterDMC = registerDMC;
-		}
-
-		/* (non-Javadoc)
-		 * @see org.eclipse.cdt.dsf.datamodel.IDMEvent#getDMContext()
-		 */
-		public IRegisterDMContext getDMContext() {
-			return fRegisterDMC;
-		}
-	}
-
-	/**
-	 * Instantiates a new Registers service.
-	 *
-	 * @param session the session
-	 * @param classNames the type names the service will be registered under. See
-	 * AbstractDsfService#register for details. We tack on base DSF's
-	 * IRegisters and this class to the list if missing.
-	 */
-	public Registers(DsfSession session, String[] classNames) {
-		super(session, 
-				massageClassNames(classNames,
-						new String[] {IRegisters.class.getName(), Registers.class.getName()}));
-		setTCFTimeout(15 * 1000); // Fifteen seconds
-	}
-
-	/**
-	 * Find register DMC by register name. <br>
-	 * 
-	 * It's required the register name be known/recognizable to TCF agent,
-	 * meaning host debugger still cannot be totally target neutral on register
-	 * access. TCF IRegisters service allows us to access common registers such
-	 * as PC, LP and SP in a target-independent way (using Role property). But
-	 * debugger need to access other registers (e.g. R0, R1, CPSR on ARM) for
-	 * stack crawl and variable evaluation.
-	 *
-	 * @param exeDMC the exe dmc
-	 * @param name the name
-	 * @return the register dmc
-	 * @throws CoreException the core exception
-	 * @since 2.0
-	 */
-	public RegisterDMC findRegisterDMCByName(IEDCExecutionDMC exeDMC, String name) throws CoreException {
-		assert RunControl.isNonContainer(exeDMC);
-		
-		// this will create the reg groups for the exeDMC if not yet. 
-		IRegisterGroupDMContext[] regGroups = getGroupsForContext(exeDMC);
-		
-		for (IRegisterGroupDMContext g : regGroups) {
-			// Note the getRegisters() will create registerDMCs for the group if not yet. 
-			for (RegisterDMC reg : ((RegisterGroupDMC)g).getRegisters()) {
-				String n = (String)reg.getProperties().get(org.eclipse.tm.tcf.services.IRegisters.PROP_NAME);
-				if (name.equals(n))
-					return reg;
-			}
-		}
-		
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.services.AbstractEDCService#doInitialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
-	 */
-	@Override
-	protected void doInitialize(RequestMonitor requestMonitor) {
-		super.doInitialize(requestMonitor);
-		getSession().addServiceEventListener(this, null);
-	}
-
-	/**
-	 * Gets the groups for context.
-	 *
-	 * @param executableContext the executable context
-	 * @return the groups for context
-	 * @throws CoreException the core exception
-	 */
-	public IRegisterGroupDMContext[] getGroupsForContext(IEDCExecutionDMC executableContext) throws CoreException {
-		String contextID = executableContext.getID();
-		List<RegisterGroupDMC> groupsForContext = registerGroupsPerContext.get(contextID);
-		if (groupsForContext == null) {
-			groupsForContext = createGroupsForContext(executableContext);
-			synchronized (registerGroupsPerContext) {
-				registerGroupsPerContext.put(contextID, groupsForContext);
-			}
-		}
-		return groupsForContext.toArray(new IRegisterGroupDMContext[groupsForContext.size()]);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeBitField(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, java.lang.String, java.lang.String, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
-	 */
-	public void writeBitField(IBitFieldDMContext bitFieldCtx, String bitFieldValue, String formatId, RequestMonitor rm) {
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeBitField(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, org.eclipse.cdt.dsf.debug.service.IRegisters.IMnemonic, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
-	 */
-	public void writeBitField(IBitFieldDMContext bitFieldCtx, IMnemonic mnemonic, RequestMonitor rm) {
-		rm.done();
-	}
-
-	/**
-	 * Writes a value to a register.
-	 *
-	 * @param context the context
-	 * @param regID register name.
-	 * @param regValue big-endian hex string representation of the value to write.
-	 * @throws CoreException the core exception
-	 */
-	public void writeRegister(IEDCExecutionDMC context, String regID, String regValue) throws CoreException {
-		RegisterDMC regDMC;
-		
-		regDMC = findRegisterDMCByName(context, regID);
-		assert regDMC != null;
-		
-		writeRegister(regDMC, regValue, IFormattedValues.HEX_FORMAT,
-				new RequestMonitor(getExecutor(), null));
-	}
-
-	/**
-	 * Writes a value to a register
-	 * @throws CoreException 
-	 * @since 2.0
-	 */
-	public void writeRegister(IRegisterDMContext regCtx, String regValue, String formatID) throws CoreException {
-		assert (regCtx instanceof RegisterDMC);
-
-		final RegisterDMC regDMC = (RegisterDMC) regCtx;
-		IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(regDMC, IExecutionDMContext.class);
-		if (exeDMC == null || !(exeDMC instanceof IEDCDMContext)) {
-			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),
-					"No valid execution context for finding the register ID"));
-		}
-
-		final String exeDMCID = ((IEDCDMContext) exeDMC).getID();
-		
-		// Put the incoming value into hex
-		if (formatID.equals(IFormattedValues.OCTAL_FORMAT) || formatID.equals(IFormattedValues.BINARY_FORMAT) ||
-				formatID.equals(IFormattedValues.DECIMAL_FORMAT))
-		{
-			BigInteger bigRegValue = null;
-			
-			try {
-				bigRegValue = NumberFormatUtils.parseIntegerByFormat(regValue, formatID);
-			} catch (NumberFormatException e) {
-				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),
-						"Cannot change register to invalid value \"" + regValue + "\""));
-			}
-			// if bigRegValue is negative, using bigRegValue.toString(16) directly gives values such as '-af'
-			regValue = Long.toHexString(bigRegValue.longValue());
-		}
-
-		// if register value string is too long, truncate to register size (2 hex chars per byte)
-		if (tcfRegistersService != null) {	// TCF IRegisters service available)
-			int regSize = regDMC.getTCFContext().getSize();
-			if (regValue.length() > regSize * 2)
-				regValue = regValue.substring(regValue.length() - regSize * 2);
-		}
-
-		if (tcfRegistersService != null) {	// TCF IRegisters service available
-			final RegistersContext tcfReg = regDMC.getTCFContext();
-			byte[] bv = null;
-			try {
-				bv = MemoryUtils.convertHexStringToByteArray(regValue, tcfReg.getSize(), 2);
-			} catch (NumberFormatException e) {
-				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),
-						"Cannot change register to invalid value \"" + regValue + "\""));
-			}
-			
-			final byte[] byteVal = bv;
-			
-			TCFTask<Object> tcfTask = new TCFTask<Object>() {
-				public void run() {
-					tcfReg.set(byteVal, new org.eclipse.tm.tcf.services.IRegisters.DoneSet() {
-						public void doneSet(IToken token, Exception error) {
-							if (error == null) {
-								generateRegisterChangedEvent(regDMC);
-								done(null);
-							} else {
-								done(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INTERNAL_ERROR,
-										"Error writing register.", error));
-							}
-						}
-					});
-				}
-			};
-
-			try {
-				Object result = tcfTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);
-				if (result != null && result instanceof IStatus)
-					throw new CoreException((IStatus) result);
-			} catch (Exception e) {
-				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INTERNAL_ERROR,
-						"Error writing register.", e));
-			}
-		}
-
-		// Update cached register values if register write succeeds
-		Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);
-		if (exeDMCRegisters != null) {
-			exeDMCRegisters.put(regDMC.getID(), new BigInteger(regValue, 16));
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getAvailableFormats(org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
-        rm.setData(new String[] { HEX_FORMAT, DECIMAL_FORMAT, OCTAL_FORMAT, BINARY_FORMAT, NATURAL_FORMAT });
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getFormattedExpressionValue(org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {
-		if (dmc.getParents().length == 1 && dmc.getParents()[0] instanceof RegisterDMC) {
-			getRegisterDataValue((RegisterDMC) dmc.getParents()[0], dmc.getFormatID(), rm);
-		} else {
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
-			rm.done();
-		}
-	}
-
-	/**
-	 * Read register with given ID, usually a name that's recognizable by TCF agent.
-	 *
-	 * @param context the context
-	 * @param id the id
-	 * @return a hex string on success, and {@link #REGISTER_VALUE_ERROR} on error.
-	 * @throws CoreException the core exception
-	 */
-	public String getRegisterValue(IExecutionDMContext context, String id) throws CoreException {
-		RegisterDMC regDMC;
-		
-		regDMC = findRegisterDMCByName((IEDCExecutionDMC) context, id);
-		assert regDMC != null;
-		
-		return getRegisterValueAsHexString(regDMC);
-	}
-
-	/**
-	 * Gets the register value as hex string.
-	 *
-	 * @param registerDMC the register dmc
-	 * @return the register value as hex string
-	 * @throws CoreException the core exception
-	 * @since 2.0
-	 */
-	public String getRegisterValueAsHexString(RegisterDMC registerDMC) throws CoreException {
-		return getRegisterValue(registerDMC).toString(16);
-	}
-	
-	/**
-	 * Gets the register value as a big integer.
-	 *
-	 * @param registerDMC the register dmc
-	 * @return the register value
-	 * @throws CoreException the core exception
-	 * @since 2.0
-	 */
-	public BigInteger getRegisterValue(RegisterDMC registerDMC) throws CoreException {
-
-		IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(registerDMC, IExecutionDMContext.class);
-		if (exeDMC == null || !(exeDMC instanceof IEDCDMContext)) {
-			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "No valid executionDMC for the register."));
-		}
-
-		final String exeDMCID = ((IEDCDMContext) exeDMC).getID();
-		final String registerDMCID = registerDMC.getID();
-
-		synchronized (registerValueCache) {
-	
-			Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);
-			if (exeDMCRegisters != null) {
-				BigInteger cachedValue = exeDMCRegisters.get(registerDMC.getID());
-				if (cachedValue != null) {
-					return cachedValue;
-				}
-			}
-		}
-	
-		if (tcfRegistersService != null) {	// TCF IRegisters service available
-			final RegistersContext tcfReg = registerDMC.getTCFContext();
-			
-            if (tcfReg == null) {
-    			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "RegisterDMC " + registerDMC.getID() + " has no underlying TCF register context."));
-            }
-
-            TCFTask<byte[]> tcfTask = new TCFTask<byte[]>() {
-		
-				public void run() {
-					tcfReg.get(new org.eclipse.tm.tcf.services.IRegisters.DoneGet() {
-		
-						public void doneGet(IToken token, Exception error, byte[] value) {
-							done(value);
-						}
-					});
-				}
-			};
-			
-			try {
-				byte[] value = tcfTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);	// ignore the return
-				String strVal = MemoryUtils.convertByteArrayToHexString(value);
-				BigInteger biValue = new BigInteger(strVal, 16);
-				synchronized (registerValueCache) {
-					Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);
-					if (exeDMCRegisters == null) {
-						exeDMCRegisters = new HashMap<String, BigInteger>();
-						registerValueCache.put(exeDMCID, exeDMCRegisters);
-					}
-					exeDMCRegisters.put(registerDMCID, biValue);
-				}
-				return biValue;
-			} catch (Throwable e) {
-    			throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Exception reading register " + registerDMC.getName(), e));
-			}
-		}
-		throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "No data for register " + registerDMC.getName()));
-	}
-
-	/**
-	 * Generate a register changed event.
-	 *
-	 * @param dmc the register dmc
-	 */
-	private void generateRegisterChangedEvent(IRegisterDMContext dmc) {
-		getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());
-
-		// need to notify listeners via suspended event if the PC has changed
-		RegisterDMC regdmc = (RegisterDMC) dmc;
-		if (regdmc.getName().equals(getTargetEnvironmentService().getPCRegisterID())) {
-			IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(dmc, IExecutionDMContext.class);
-			getSession().dispatchEvent(new SuspendedEvent(exeDMC, StateChangeReason.USER_REQUEST, new HashMap<String, Object>()), getProperties());
-		}
-	}
-
-	/**
-	 * Gets the register data value.
-	 *
-	 * @param registerDMC the register dmc
-	 * @param formatID the format id
-	 * @param rm the request monitor
-	 * @return the register data value
-	 */
-	private void getRegisterDataValue(RegisterDMC registerDMC, final String formatID,
-			final DataRequestMonitor<FormattedValueDMData> rm) {
-		try {
-			BigInteger bigIntValue = getRegisterValue(registerDMC);
-
-			String formattedValue = bigIntValue.toString(16);
-
-			if (formatID.equals(IFormattedValues.OCTAL_FORMAT))
-				formattedValue = NumberFormatUtils.toOctalString(bigIntValue);
-			if (formatID.equals(IFormattedValues.BINARY_FORMAT))
-				formattedValue = NumberFormatUtils.asBinary(bigIntValue);
-			if (formatID.equals(IFormattedValues.DECIMAL_FORMAT))
-				formattedValue = bigIntValue.toString();
-			
-			rm.setData(new FormattedValueDMData(formattedValue));
-
-		} catch (CoreException e) {
-			Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error in getRegisterDataValue.", e);
-			EDCDebugger.getMessageLogger().log(s);
-			rm.setStatus(s);
-		}
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getFormattedValueContext(org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext, java.lang.String)
-	 */
-	public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String formatId) {
-		if (dmc instanceof RegisterDMC) {
-			return new FormattedValueDMContext(Registers.this, dmc, formatId);
-		}
-		return null;
-	}
-
-	/**
-	 * Gets the model data for a register.
-	 *
-	 * @param dmc the dmc
-	 * @param rm the request monitor
-	 * @return the model data
-	 */
-	@SuppressWarnings("unchecked")
-	public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
-
-		if (dmc instanceof RegisterGroupDMC)
-			getRegisterGroupData((IRegisterGroupDMContext) dmc, (DataRequestMonitor<IRegisterGroupDMData>) rm);
-		else if (dmc instanceof RegisterDMC)
-			getRegisterData((IRegisterDMContext) dmc, (DataRequestMonitor<IRegisterDMData>) rm);
-		else if (dmc instanceof FormattedValueDMContext)
-			getFormattedExpressionValue((FormattedValueDMContext) dmc, (DataRequestMonitor<FormattedValueDMData>) rm);
-		else
-			rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.ICachingService#flushCache(org.eclipse.cdt.dsf.datamodel.IDMContext)
-	 */
-	public void flushCache(IDMContext context) {
-		if (isSnapshot())
-			return;
-		// Why flush this static info ?
-		// registerGroupsPerThread.clear();
-		
-		registerValueCache.clear();
-	}
-
-	/**
-	 * Load register groups for an executable context.
-	 *
-	 * @param executionDmc the execution dmc
-	 * @param element the element
-	 * @throws Exception the exception
-	 */
-	public void loadGroupsForContext(IEDCExecutionDMC executionDmc, Element element) throws Exception {
-		// Can't call flushCache here because it does nothing for snapshot
-		// services.
-		String cxtID = ((IEDCDMContext)executionDmc).getID();
-		// It does not hurt if the context is not in the caches.
-		registerGroupsPerContext.remove(cxtID);
-		registerValueCache.remove(cxtID);
-
-		NodeList registerGroups = element.getElementsByTagName(RegisterGroupDMC.REGISTER_GROUP);
-
-		List<RegisterGroupDMC> regGroups = Collections.synchronizedList(new ArrayList<RegisterGroupDMC>());
-
-		int numGroups = registerGroups.getLength();
-		for (int i = 0; i < numGroups; i++) {
-			Element groupElement = (Element) registerGroups.item(i);
-			Element propElement = (Element) groupElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-			HashMap<String, Object> properties = new HashMap<String, Object>();
-			SnapshotUtils.initializeFromXML(propElement, properties);
-
-			RegisterGroupDMC regdmc = new RegisterGroupDMC(this, executionDmc, properties);
-			regdmc.loadSnapshot(groupElement);
-			regGroups.add(regdmc);
-		}
-		registerGroupsPerContext.put(((IEDCDMContext) executionDmc).getID(), regGroups);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.debug.edc.services.IDSFServiceUsingTCF#tcfServiceReady(org.eclipse.tm.tcf.protocol.IService)
-	 */
-	public void tcfServiceReady(IService service) {
-		tcfRegistersService = (org.eclipse.tm.tcf.services.IRegisters)service;
-	}
-
-	/**
-	 * Gets the register value.
-	 *
-	 * @param executionDMC the execution dmc
-	 * @param id the register id
-	 * @return the register value
-	 * @throws CoreException the core exception
-	 */
-	public String getRegisterValue(IEDCExecutionDMC executionDMC, int id) throws CoreException {
-		String name = getRegisterNameFromCommonID(id);
-		if (name != null) {
-			return getRegisterValue(executionDMC, name);
-		}
-		return null;
-	}
-
-	/**
-	 * Get TCF child registers contexts for the given parent.
-	 * If parent is a thread, the registers contexts are register groups.
-	 * If parent is a register group, the contexts returned are registers.
-	 *
-	 * @param parentID thread ID or register group ID.
-	 * @return the tCF registers contexts
-	 * @throws CoreException the core exception
-	 */
-	protected List<RegistersContext>	getTCFRegistersContexts(final String parentID) throws CoreException {
-		List<RegistersContext> tcfRegContexts = new ArrayList<RegistersContext>();
-		
-		TCFTask<String[]> getChildIDTask = new TCFTask<String[]>() {
-			public void run() {
-				tcfRegistersService.getChildren(parentID, new org.eclipse.tm.tcf.services.IRegisters.DoneGetChildren() {
-
-					public void doneGetChildren(IToken token, Exception error, String[] contextIds) {
-						if (error == null)
-							done(contextIds);
-						else
-							error(error);
-					}});
-			}
-		};
-		
-		String[] childIDs;
-		try {
-			childIDs = getChildIDTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);
-		} catch (Throwable e) {
-			throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Fail to get TCF context for: " + parentID, e));
-		}
-		
-		for (String gid: childIDs) {
-			final String id = gid;
-			TCFTask<RegistersContext> getGroupContextTask = new TCFTask<RegistersContext>() {
-				public void run() {
-					tcfRegistersService.getContext(id, new org.eclipse.tm.tcf.services.IRegisters.DoneGetContext(){
-						public void doneGetContext(IToken token, Exception error, RegistersContext context) {
-							if (error == null)
-								done(context);
-							else
-								error(error);
-						}});
-				}
-			};
-		
-			RegistersContext rgc = null;
-			try {
-				rgc = getGroupContextTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);
-			} catch (Throwable e) {
-				throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Fail to get TCF context for: " + parentID, e));
-			}
-			
-			if (rgc != null)
-				tcfRegContexts.add(rgc);
-		}
-
-		return tcfRegContexts;
-	}
-	
-	/**
-	 * Handle a suspended event by flushing the cache.
-	 *
-	 * @param e the event
-	 */
-	@DsfServiceEventHandler
-	public void eventDispatched(ISuspendedDMEvent e) {
-		flushCache(null);
-	}
-
-	/**
-	 * Handle a resumed event by flushing the cache.
-	 *
-	 * @param e the event
-	 */
-	@DsfServiceEventHandler
-	public void eventDispatched(IResumedDMEvent e) {
-		flushCache(null);
-	}
-
-	/**
-	 * When a context (e.g. a thread) is killed/detached, we should forget
-	 * cached register info & values for it so that we can properly access
-	 * registers when we re-attach to it.
-	 *
-	 * @param e the event
-	 * @since 2.0
-	 */
-	@DsfServiceEventHandler
-	public void eventDispatched(IExitedDMEvent e) {
-		IExecutionDMContext cxt = e.getDMContext();
-		if (cxt != null && cxt instanceof IEDCDMContext) {
-			String cxtID = ((IEDCDMContext)cxt).getID();
-			// It does not hurt if the context is not in the caches.
-			registerGroupsPerContext.remove(cxtID);
-			registerValueCache.remove(cxtID);
-		}
-	}
-
-	/**
-	 * Creates the registers for group.
-	 *
-	 * @param registerGroupDMC the register group dmc
-	 * @return the list
-	 * @throws CoreException the core exception
-	 */
-	protected List<RegisterDMC> createRegistersForGroup(RegisterGroupDMC registerGroupDMC) throws CoreException {
-		ArrayList<RegisterDMC> registers = new ArrayList<RegisterDMC>();
-	
-		if (tcfRegistersService != null) {
-			List<RegistersContext> tcfRegs = getTCFRegistersContexts(registerGroupDMC.getID());
-			
-			for (RegistersContext rg: tcfRegs) {
-				registers.add(new RegisterDMC(registerGroupDMC, registerGroupDMC.getExecutionDMC(), rg));
-			}
-		}
-		
-		return registers;
-	}
-	
-	/**
-	 * Creates the groups for context.
-	 *
-	 * @param ctx the ctx
-	 * @return the list
-	 * @throws CoreException the core exception
-	 */
-	protected List<RegisterGroupDMC> createGroupsForContext(IEDCExecutionDMC ctx) throws CoreException {
-
-		List<RegisterGroupDMC> groups = Collections.synchronizedList(new ArrayList<RegisterGroupDMC>());
-
-		if (RunControl.isNonContainer(ctx)) {
-			if (tcfRegistersService != null) {
-				List<RegistersContext> tcfRegGroups = getTCFRegistersContexts(ctx.getID());
-				
-				for (RegistersContext rg: tcfRegGroups) {
-					groups.add(new RegisterGroupDMC(this, ctx, rg.getProperties()));
-				}
-			}
-		}
-
-		return groups;
-	}
-
-	/**
-	 * Given a common general purpose register id (e.g. from symbolics), get the
-	 * corresponding register name.
-	 * 
-	 * @param id
-	 *            the common general purpose register id (0-31)
-	 * @return the corresponding register name, or null of n/a
-	 */
-	public abstract String getRegisterNameFromCommonID(int id);
-	
-	/**
-	 * Sets the TCF timeout.
-	 *
-	 * @param msecs the new TCF timeout
-	 * @since 2.0
-	 */
-	public void setTCFTimeout(long msecs) {
-		tcfTimeout = msecs;
-	}
-
-	/**
-	 * Gets the TCF timeout.
-	 *
-	 * @return the TCF timeout
-	 * @since 2.0
-	 */
-	public long getTCFTimeout() {
-		return tcfTimeout;
-	}
-
-	// Implementation of org.eclipse.cdt.dsf.debug.service.IRegisters
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterGroups(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getRegisterGroups(final IDMContext ctx, final DataRequestMonitor<IRegisterGroupDMContext[]> rm) {
-		
-		asyncExec(new Runnable() {
-			
-			public void run() {
-				IEDCExecutionDMC execDmc = DMContexts.getAncestorOfType(ctx, IEDCExecutionDMC.class);
-				if (execDmc != null && RunControl.isNonContainer(execDmc)) {
-					try {
-						rm.setData(getGroupsForContext(execDmc));
-					} catch (CoreException e) {
-						EDCDebugger.getMessageLogger().log(e.getStatus());
-						rm.setStatus(e.getStatus());
-					}
-					rm.done();
-					return;
-				}
-
-				StackFrameDMC frameDmc = DMContexts.getAncestorOfType(ctx, StackFrameDMC.class);
-				if (frameDmc != null) {
-					try {
-						rm.setData(getGroupsForContext(frameDmc.getExecutionDMC()));
-					} catch (CoreException e) {
-						EDCDebugger.getMessageLogger().log(e.getStatus());
-						rm.setStatus(e.getStatus());
-					}
-					rm.done();
-					return;
-				}
-				
-				rm.setData(new IRegisterGroupDMContext[0]);
-				rm.done();
-			}
-		}, rm);
-		
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisters(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getRegisters(final IDMContext ctx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
-
-		asyncExec(new Runnable() {
-			
-			public void run() {
-				RegisterGroupDMC groupContext = DMContexts.getAncestorOfType(ctx, RegisterGroupDMC.class);
-				IEDCExecutionDMC executionContext = DMContexts.getAncestorOfType(ctx, IEDCExecutionDMC.class);
-				RegisterDMC[] allRegisters;
-				try {
-					if (groupContext != null && executionContext != null) {
-						allRegisters = groupContext.getRegisters();
-					}
-					else {
-						allRegisters = new RegisterDMC[0];
-					}
-					rm.setData(allRegisters);
-				} catch (CoreException e) {
-					EDCDebugger.getMessageLogger().log(e.getStatus());
-					rm.setStatus(e.getStatus());
-				}
-				rm.done();
-			}
-		}, rm);
-		
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getBitFields(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getBitFields(IDMContext ctx, DataRequestMonitor<IBitFieldDMContext[]> rm) {
-		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "BitField not supported", null)); //$NON-NLS-1$
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findRegisterGroup(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void findRegisterGroup(IDMContext ctx, String name, DataRequestMonitor<IRegisterGroupDMContext> rm) {
-		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findRegisterGroup not supported", null)); //$NON-NLS-1$
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findRegister(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void findRegister(IDMContext ctx, String name, DataRequestMonitor<IRegisterDMContext> rm) {
-		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findRegister not supported", null)); //$NON-NLS-1$
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findBitField(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void findBitField(IDMContext ctx, String name, DataRequestMonitor<IBitFieldDMContext> rm) {
-		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findBitField not supported", null)); //$NON-NLS-1$
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterGroupData(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getRegisterGroupData(IRegisterGroupDMContext dmc, DataRequestMonitor<IRegisterGroupDMData> rm) {
-
-		class RegisterGroupData implements IRegisterGroupDMData {
-			private final String name;
-			private final String description;
-
-			public RegisterGroupData(RegisterGroupDMC dmc) {
-				this.name = dmc.getName();
-				this.description = (String) dmc.getProperty(IEDCDMContext.PROP_DESCRIPTION);
-			}
-
-			public String getName() {
-				return name;
-			}
-
-			public String getDescription() {
-				return description;
-			}
-		}
-
-		rm.setData(new RegisterGroupData((RegisterGroupDMC) dmc));
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterData(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getRegisterData(IRegisterDMContext dmc, DataRequestMonitor<IRegisterDMData> rm) {
-		RegisterDMC regdmc = (RegisterDMC) dmc;
-		rm.setData(new RegisterData(regdmc.getProperties()));
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getBitFieldData(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getBitFieldData(IBitFieldDMContext dmc, DataRequestMonitor<IBitFieldDMData> rm) {
-		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED,
-				"Bit fields not yet supported", null)); //$NON-NLS-1$
-		rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeRegister(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, java.lang.String, java.lang.String, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
-	 */
-	public void writeRegister(final IRegisterDMContext regCtx, final String regValue, final String formatID, final RequestMonitor rm) {
-
-		asyncExec(new Runnable() {
-			
-			public void run() {
-				try{
-				writeRegister(regCtx, regValue, formatID);
-				} catch (CoreException e) {
-					EDCDebugger.getMessageLogger().log(e.getStatus());
-					rm.setStatus(e.getStatus());
-				}
-				rm.done();
-			}
-		}, rm);
-		
-	}
-
-}
+/*******************************************************************************

+ * 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.services;

+

+import java.math.BigInteger;

+import java.util.ArrayList;

+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.debug.edc.MemoryUtils;

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

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

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

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

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

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

+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.dsf.concurrent.DataRequestMonitor;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+import org.eclipse.tm.tcf.protocol.IService;

+import org.eclipse.tm.tcf.protocol.IToken;

+import org.eclipse.tm.tcf.services.IRegisters.RegistersContext;

+import org.eclipse.tm.tcf.util.TCFTask;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.NodeList;

+

+/**

+ * The Registers service provides information about the target processor

+ * registers.

+ */

+public abstract class Registers extends AbstractEDCService implements IRegisters, ICachingService, IDSFServiceUsingTCF {

+

+	/**

+	 * Cache register groups per context.

+	 * Keyed on context ID.

+	 */

+	private Map<String, List<RegisterGroupDMC>> registerGroupsPerContext = 

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

+

+	/** The TCF registers service. */

+	protected org.eclipse.tm.tcf.services.IRegisters		tcfRegistersService = null;

+	

+	/**

+	 * Register value cache per execution context.

+	 * Keyed on context ID.

+	 */

+	private Map<String, Map<String, BigInteger>> registerValueCache = 

+		Collections.synchronizedMap(new HashMap<String, Map<String, BigInteger>>());

+

+	/** Iimeout value in milliseconds when waiting for a response from the TCF service. */

+	private long tcfTimeout;

+

+	/**

+	 * A hex string indicating error in register read.

+	 * See where this is used for more.

+	 */

+	protected static final String REGISTER_VALUE_ERROR = "badbadba";

+	

+	public static final String PROP_EXECUTION_CONTEXT_ID = "Context_ID";

+

+	private static final String REGISTER = "register";

+

+	/**

+	 * Represents a group of registers.

+	 */

+	public class RegisterGroupDMC extends DMContext implements IRegisterGroupDMContext, ISnapshotContributor {

+

+		private static final String REGISTER_GROUP = "register_group";

+

+		/** The registers in this group. */

+		private List<RegisterDMC> registers = Collections.synchronizedList(new ArrayList<RegisterDMC>());

+

+		/** The executable context. */

+		private final IEDCExecutionDMC exeContext;

+

+		/**

+		 * Instantiates a new register group dmc.

+		 *

+		 * @param service the service

+		 * @param executionDMC the execution context

+		 * @param groupName the group name

+		 * @param groupDescription the group description

+		 * @param groupID the group id

+		 */

+		public RegisterGroupDMC(Registers service, IEDCExecutionDMC executionDMC, String groupName, String groupDescription,

+				String groupID) {

+			super(service, new IDMContext[] { executionDMC }, groupName, groupID);

+			exeContext = executionDMC;

+			properties.put(PROP_DESCRIPTION, groupDescription);

+			properties.put(PROP_EXECUTION_CONTEXT_ID, executionDMC.getID());

+		}

+

+		/**

+		 * Instantiates a new register group dmc.

+		 *

+		 * @param service the service

+		 * @param executionDmc the execution dmc

+		 * @param props the props

+		 */

+		public RegisterGroupDMC(Registers service, IEDCExecutionDMC executionDmc,

+								Map<String, Object> props) {

+			super(service, new IDMContext[] { executionDmc }, props);

+			exeContext = executionDmc;

+			properties.put(PROP_EXECUTION_CONTEXT_ID, exeContext.getID());

+		}

+

+		/* (non-Javadoc)

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

+		 */

+		@Override

+		public String toString() {

+			return baseToString() + ".group[" + getName() + "]";} //$NON-NLS-1$ //$NON-NLS-2$

+

+		/**

+		 * Gets the registers for this group.

+		 *

+		 * @return array of register contexts for this group

+		 * @throws CoreException the core exception

+		 */

+		public RegisterDMC[] getRegisters() throws CoreException {

+			RegisterDMC[] result = new RegisterDMC[0];

+			synchronized (registers) {

+				if (registers.size() == 0) {

+					registers = Registers.this.createRegistersForGroup(this);

+				}

+				result = registers.toArray(new RegisterDMC[registers.size()]);

+			}

+			return result;

+		}

+

+		/**

+		 * Take a snapshot of this group of registers.

+		 *

+		 * @param album the snapshot album

+		 * @param document the XML document

+		 * @param monitor the progress monitor

+		 * @return the XML element

+		 * @throws Exception the exception if anything goes wrong

+		 * @since 2.0

+		 */

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

+			Element contextElement = document.createElement(REGISTER_GROUP);

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

+

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

+			contextElement.appendChild(propsElement);

+

+			RegisterDMC[] allRegisters = getRegisters();

+			SubMonitor progress = SubMonitor.convert(monitor, allRegisters.length * 1000);

+			progress.subTask("Registers");

+			for (RegisterDMC registerDMC : allRegisters) {

+				Element dmcElement = registerDMC.takeSnapshot(album, document, progress.newChild(1000));

+				contextElement.appendChild(dmcElement);

+			}

+			return contextElement;

+		}

+

+		/**

+		 * Gets the execution dmc.

+		 *

+		 * @return the execution dmc

+		 */

+		public IEDCExecutionDMC getExecutionDMC() {

+			return exeContext;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor#loadSnapshot(org.w3c.dom.Element)

+		 */

+		public void loadSnapshot(Element element) throws Exception {

+			NodeList registerElement = element.getElementsByTagName(REGISTER);

+

+			int numRegisters = registerElement.getLength();

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

+				Element regElement = (Element) registerElement.item(i);

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

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

+				SnapshotUtils.initializeFromXML(propElement, properties);

+

+				RegisterDMC regdmc = new RegisterDMC(this, exeContext, properties);

+				regdmc.loadSnapshot(regElement);

+				registers.add(regdmc);

+			}

+

+		}

+

+	}

+

+	/**

+	 * Represents the context for a single register.

+	 */

+	public class RegisterDMC extends DMContext implements IRegisterDMContext, ISnapshotContributor {

+

+		/** The context used by the TCF agent. */

+		private org.eclipse.tm.tcf.services.IRegisters.RegistersContext tcfContext = null;

+		

+		/**

+		 * Instantiates a new register dmc.

+		 *

+		 * @param executableDMC the executable context

+		 * @param name the register name

+		 * @param description the register description

+		 * @param id the register id

+		 */

+		public RegisterDMC(IEDCExecutionDMC executableDMC, String name, String description, String id) {

+			super(Registers.this, new IDMContext[] { executableDMC }, name, id);

+			properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());

+		}

+

+		/**

+		 * Instantiates a new register dmc.

+		 *

+		 * @param registerGroupDmc the register group dmc

+		 * @param executableDMC the executable context

+		 * @param properties the properties

+		 */

+		public RegisterDMC(RegisterGroupDMC registerGroupDmc, IEDCExecutionDMC executableDMC,

+							Map<String, Object> properties) {

+			super(Registers.this, new IDMContext[] { executableDMC }, properties);

+			this.properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());

+		}

+

+		/**

+		 * Construct based on underlying context from TCF IRegisters service.

+		 *

+		 * @param registerGroupDMC the register group dmc

+		 * @param executableDMC the executable context

+		 * @param tcfContext the tcf context

+		 */

+		public RegisterDMC(RegisterGroupDMC registerGroupDMC, IEDCExecutionDMC executableDMC, RegistersContext tcfContext) {

+			super(Registers.this, new IDMContext[] { registerGroupDMC }, tcfContext.getProperties());

+			this.properties.put(PROP_EXECUTION_CONTEXT_ID, executableDMC.getID());

+			

+			this.tcfContext = tcfContext;

+		}

+

+		/**

+		 * Get the underlying TCF context.

+		 * @return may be null.

+		 */

+		public RegistersContext getTCFContext() {

+			return tcfContext;

+		}

+		

+		/* (non-Javadoc)

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

+		 */

+		@Override

+		public String toString() {

+			return baseToString() + ".register[" + getName() + "]";} //$NON-NLS-1$ //$NON-NLS-2$

+

+		/**

+		 * Take a snapshot of this register.

+		 *

+		 * @param album the snapshot album

+		 * @param document the XML document

+		 * @param monitor the progress monitor

+		 * @return the XML element

+		 * @throws Exception the exception if anything goes wrong

+		 * @since 2.0

+		 */

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

+			Element registerElement = document.createElement(REGISTER);

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

+			registerElement.setAttribute(PROP_VALUE, getRegisterValueAsHexString(this));

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

+			registerElement.appendChild(propsElement);

+			return registerElement;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor#loadSnapshot(org.w3c.dom.Element)

+		 */

+		public void loadSnapshot(Element element) throws Exception {

+			String registerValue = element.getAttribute(PROP_VALUE);

+			String contextID = (String) getProperties().get(PROP_EXECUTION_CONTEXT_ID);

+

+			synchronized (registerValueCache) {

+				Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(contextID);

+				if (exeDMCRegisters == null) {

+					exeDMCRegisters = new HashMap<String, BigInteger>();

+					registerValueCache.put(contextID, exeDMCRegisters);

+				}

+				exeDMCRegisters.put(getID(), new BigInteger(registerValue, 16));

+			}

+		}

+	}

+

+	class RegisterData implements IRegisterDMData {

+

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

+

+		public RegisterData(Map<String, Object> properties) {

+			this.properties.putAll(properties);

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isReadable()

+		 */

+		public boolean isReadable() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_READBLE);

+            if (n == null) 

+            	return true;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isReadOnce()

+		 */

+		public boolean isReadOnce() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_READ_ONCE);

+            if (n == null) 

+            	return false;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isWriteable()

+		 */

+		public boolean isWriteable() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_WRITEABLE);

+            if (n == null) 

+            	return true;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isWriteOnce()

+		 */

+		public boolean isWriteOnce() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_WRITE_ONCE);

+            if (n == null) 

+            	return false;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#hasSideEffects()

+		 */

+		public boolean hasSideEffects() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_SIDE_EFFECTS);

+            if (n == null) 

+            	return false;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isVolatile()

+		 */

+		public boolean isVolatile() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_VOLATILE);

+            if (n == null) 

+            	return false;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#isFloat()

+		 */

+		public boolean isFloat() {

+            Boolean n = (Boolean)properties.get(org.eclipse.tm.tcf.services.IRegisters.PROP_FLOAT);

+            if (n == null) 

+            	return false;

+            return n.booleanValue();

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#getName()

+		 */

+		public String getName() {

+			return (String) properties.get(IEDCDMContext.PROP_NAME);

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData#getDescription()

+		 */

+		public String getDescription() {

+			return (String) properties.get(IEDCDMContext.PROP_DESCRIPTION);

+		}

+

+	}

+

+	/**

+	 * Event class to notify register value is changed

+	 */

+	public static class RegisterChangedDMEvent implements IRegisters.IRegisterChangedDMEvent {

+

+		/** The register dmc. */

+		private final IRegisterDMContext fRegisterDMC;

+

+		/**

+		 * Instantiates a new register changed dm event.

+		 *

+		 * @param registerDMC the register dmc

+		 */

+		RegisterChangedDMEvent(IRegisterDMContext registerDMC) {

+			fRegisterDMC = registerDMC;

+		}

+

+		/* (non-Javadoc)

+		 * @see org.eclipse.cdt.dsf.datamodel.IDMEvent#getDMContext()

+		 */

+		public IRegisterDMContext getDMContext() {

+			return fRegisterDMC;

+		}

+	}

+

+	/**

+	 * Instantiates a new Registers service.

+	 *

+	 * @param session the session

+	 * @param classNames the type names the service will be registered under. See

+	 * AbstractDsfService#register for details. We tack on base DSF's

+	 * IRegisters and this class to the list if missing.

+	 */

+	public Registers(DsfSession session, String[] classNames) {

+		super(session, 

+				massageClassNames(classNames,

+						new String[] {IRegisters.class.getName(), Registers.class.getName()}));

+		setTCFTimeout(15 * 1000); // Fifteen seconds

+	}

+

+	/**

+	 * Find register DMC by register name. <br>

+	 * 

+	 * It's required the register name be known/recognizable to TCF agent,

+	 * meaning host debugger still cannot be totally target neutral on register

+	 * access. TCF IRegisters service allows us to access common registers such

+	 * as PC, LP and SP in a target-independent way (using Role property). But

+	 * debugger need to access other registers (e.g. R0, R1, CPSR on ARM) for

+	 * stack crawl and variable evaluation.

+	 *

+	 * @param exeDMC the exe dmc

+	 * @param name the name

+	 * @return the register dmc

+	 * @throws CoreException the core exception

+	 * @since 2.0

+	 */

+	public RegisterDMC findRegisterDMCByName(IEDCExecutionDMC exeDMC, String name) throws CoreException {

+		assert RunControl.isNonContainer(exeDMC);

+		

+		// this will create the reg groups for the exeDMC if not yet. 

+		IRegisterGroupDMContext[] regGroups = getGroupsForContext(exeDMC);

+		

+		for (IRegisterGroupDMContext g : regGroups) {

+			// Note the getRegisters() will create registerDMCs for the group if not yet. 

+			for (RegisterDMC reg : ((RegisterGroupDMC)g).getRegisters()) {

+				String n = (String)reg.getProperties().get(org.eclipse.tm.tcf.services.IRegisters.PROP_NAME);

+				if (name.equals(n))

+					return reg;

+			}

+		}

+		

+		return null;

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.services.AbstractEDCService#doInitialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)

+	 */

+	@Override

+	protected void doInitialize(RequestMonitor requestMonitor) {

+		super.doInitialize(requestMonitor);

+		getSession().addServiceEventListener(this, null);

+	}

+

+	/**

+	 * Gets the groups for context.

+	 *

+	 * @param executableContext the executable context

+	 * @return the groups for context

+	 * @throws CoreException the core exception

+	 */

+	public IRegisterGroupDMContext[] getGroupsForContext(IEDCExecutionDMC executableContext) throws CoreException {

+		String contextID = executableContext.getID();

+		List<RegisterGroupDMC> groupsForContext = registerGroupsPerContext.get(contextID);

+		if (groupsForContext == null) {

+			groupsForContext = createGroupsForContext(executableContext);

+			synchronized (registerGroupsPerContext) {

+				registerGroupsPerContext.put(contextID, groupsForContext);

+			}

+		}

+		return groupsForContext.toArray(new IRegisterGroupDMContext[groupsForContext.size()]);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeBitField(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, java.lang.String, java.lang.String, org.eclipse.cdt.dsf.concurrent.RequestMonitor)

+	 */

+	public void writeBitField(IBitFieldDMContext bitFieldCtx, String bitFieldValue, String formatId, RequestMonitor rm) {

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeBitField(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, org.eclipse.cdt.dsf.debug.service.IRegisters.IMnemonic, org.eclipse.cdt.dsf.concurrent.RequestMonitor)

+	 */

+	public void writeBitField(IBitFieldDMContext bitFieldCtx, IMnemonic mnemonic, RequestMonitor rm) {

+		rm.done();

+	}

+

+	/**

+	 * Writes a value to a register.

+	 *

+	 * @param context the context

+	 * @param regID register name.

+	 * @param regValue big-endian hex string representation of the value to write.

+	 * @throws CoreException the core exception

+	 */

+	public void writeRegister(IEDCExecutionDMC context, String regID, String regValue) throws CoreException {

+		RegisterDMC regDMC;

+		

+		regDMC = findRegisterDMCByName(context, regID);

+		assert regDMC != null;

+		

+		writeRegister(regDMC, regValue, IFormattedValues.HEX_FORMAT,

+				new RequestMonitor(getExecutor(), null));

+	}

+

+	/**

+	 * Writes a value to a register

+	 * @throws CoreException 

+	 * @since 2.0

+	 */

+	public void writeRegister(IRegisterDMContext regCtx, String regValue, String formatID) throws CoreException {

+		assert (regCtx instanceof RegisterDMC);

+

+		final RegisterDMC regDMC = (RegisterDMC) regCtx;

+		IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(regDMC, IExecutionDMContext.class);

+		if (exeDMC == null || !(exeDMC instanceof IEDCDMContext)) {

+			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),

+					"No valid execution context for finding the register ID"));

+		}

+

+		final String exeDMCID = ((IEDCDMContext) exeDMC).getID();

+		

+		// Put the incoming value into hex

+		if (formatID.equals(IFormattedValues.OCTAL_FORMAT) || formatID.equals(IFormattedValues.BINARY_FORMAT) ||

+				formatID.equals(IFormattedValues.DECIMAL_FORMAT))

+		{

+			BigInteger bigRegValue = null;

+			

+			try {

+				bigRegValue = NumberFormatUtils.parseIntegerByFormat(regValue, formatID);

+			} catch (NumberFormatException e) {

+				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),

+						"Cannot change register to invalid value \"" + regValue + "\""));

+			}

+			// if bigRegValue is negative, using bigRegValue.toString(16) directly gives values such as '-af'

+			regValue = Long.toHexString(bigRegValue.longValue());

+		}

+

+		// if register value string is too long, truncate to register size (2 hex chars per byte)

+		if (tcfRegistersService != null) {	// TCF IRegisters service available)

+			int regSize = regDMC.getTCFContext().getSize();

+			if (regValue.length() > regSize * 2)

+				regValue = regValue.substring(regValue.length() - regSize * 2);

+		}

+

+		if (tcfRegistersService != null) {	// TCF IRegisters service available

+			final RegistersContext tcfReg = regDMC.getTCFContext();

+			byte[] bv = null;

+			try {

+				bv = MemoryUtils.convertHexStringToByteArray(regValue, tcfReg.getSize(), 2);

+			} catch (NumberFormatException e) {

+				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(),

+						"Cannot change register to invalid value \"" + regValue + "\""));

+			}

+			

+			final byte[] byteVal = bv;

+			

+			TCFTask<Object> tcfTask = new TCFTask<Object>() {

+				public void run() {

+					tcfReg.set(byteVal, new org.eclipse.tm.tcf.services.IRegisters.DoneSet() {

+						public void doneSet(IToken token, Exception error) {

+							if (error == null) {

+								generateRegisterChangedEvent(regDMC);

+								done(null);

+							} else {

+								done(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INTERNAL_ERROR,

+										"Error writing register.", error));

+							}

+						}

+					});

+				}

+			};

+

+			try {

+				Object result = tcfTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);

+				if (result != null && result instanceof IStatus)

+					throw new CoreException((IStatus) result);

+			} catch (Exception e) {

+				throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INTERNAL_ERROR,

+						"Error writing register.", e));

+			}

+		}

+

+		// Update cached register values if register write succeeds

+		Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);

+		if (exeDMCRegisters != null) {

+			exeDMCRegisters.put(regDMC.getID(), new BigInteger(regValue, 16));

+		}

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getAvailableFormats(org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

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

+        rm.setData(new String[] { HEX_FORMAT, DECIMAL_FORMAT, OCTAL_FORMAT, BINARY_FORMAT, NATURAL_FORMAT });

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getFormattedExpressionValue(org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {

+		if (dmc.getParents().length == 1 && dmc.getParents()[0] instanceof RegisterDMC) {

+			getRegisterDataValue((RegisterDMC) dmc.getParents()[0], dmc.getFormatID(), rm);

+		} else {

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$

+			rm.done();

+		}

+	}

+

+	/**

+	 * Read register with given ID, usually a name that's recognizable by TCF agent.

+	 *

+	 * @param context the context

+	 * @param id the id

+	 * @return a hex string on success, and {@link #REGISTER_VALUE_ERROR} on error.

+	 * @throws CoreException the core exception

+	 */

+	public String getRegisterValue(IExecutionDMContext context, String id) throws CoreException {

+		RegisterDMC regDMC;

+		

+		regDMC = findRegisterDMCByName((IEDCExecutionDMC) context, id);

+		assert regDMC != null;

+		

+		return getRegisterValueAsHexString(regDMC);

+	}

+

+	/**

+	 * Gets the register value as hex string.

+	 *

+	 * @param registerDMC the register dmc

+	 * @return the register value as hex string

+	 * @throws CoreException the core exception

+	 * @since 2.0

+	 */

+	public String getRegisterValueAsHexString(RegisterDMC registerDMC) throws CoreException {

+		return getRegisterValue(registerDMC).toString(16);

+	}

+	

+	/**

+	 * Gets the register value as a big integer.

+	 *

+	 * @param registerDMC the register dmc

+	 * @return the register value

+	 * @throws CoreException the core exception

+	 * @since 2.0

+	 */

+	public BigInteger getRegisterValue(RegisterDMC registerDMC) throws CoreException {

+

+		IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(registerDMC, IExecutionDMContext.class);

+		if (exeDMC == null || !(exeDMC instanceof IEDCDMContext)) {

+			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "No valid executionDMC for the register."));

+		}

+

+		final String exeDMCID = ((IEDCDMContext) exeDMC).getID();

+		final String registerDMCID = registerDMC.getID();

+

+		synchronized (registerValueCache) {

+	

+			Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);

+			if (exeDMCRegisters != null) {

+				BigInteger cachedValue = exeDMCRegisters.get(registerDMC.getID());

+				if (cachedValue != null) {

+					return cachedValue;

+				}

+			}

+		}

+	

+		if (tcfRegistersService != null) {	// TCF IRegisters service available

+			final RegistersContext tcfReg = registerDMC.getTCFContext();

+			

+            if (tcfReg == null) {

+    			throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "RegisterDMC " + registerDMC.getID() + " has no underlying TCF register context."));

+            }

+

+            TCFTask<byte[]> tcfTask = new TCFTask<byte[]>() {

+		

+				public void run() {

+					tcfReg.get(new org.eclipse.tm.tcf.services.IRegisters.DoneGet() {

+		

+						public void doneGet(IToken token, Exception error, byte[] value) {

+							if (error == null)

+								done(value);

+							else {

+								error(error);

+							}

+						}

+					});

+				}

+			};

+			

+			try {

+				byte[] value = tcfTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);	// ignore the return

+				String strVal = MemoryUtils.convertByteArrayToHexString(value);

+				BigInteger biValue = new BigInteger(strVal, 16);

+				synchronized (registerValueCache) {

+					Map<String, BigInteger> exeDMCRegisters = registerValueCache.get(exeDMCID);

+					if (exeDMCRegisters == null) {

+						exeDMCRegisters = new HashMap<String, BigInteger>();

+						registerValueCache.put(exeDMCID, exeDMCRegisters);

+					}

+					exeDMCRegisters.put(registerDMCID, biValue);

+				}

+				return biValue;

+			} catch (Throwable e) {

+    			throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Exception reading register " + registerDMC.getName(), e));

+			}

+		}

+		throw new CoreException(new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "No data for register " + registerDMC.getName()));

+	}

+

+	/**

+	 * Generate a register changed event.

+	 *

+	 * @param dmc the register dmc

+	 */

+	private void generateRegisterChangedEvent(IRegisterDMContext dmc) {

+		getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());

+

+		// need to notify listeners via suspended event if the PC has changed

+		RegisterDMC regdmc = (RegisterDMC) dmc;

+		if (regdmc.getName().equals(getTargetEnvironmentService().getPCRegisterID())) {

+			IExecutionDMContext exeDMC = DMContexts.getAncestorOfType(dmc, IExecutionDMContext.class);

+			getSession().dispatchEvent(new SuspendedEvent(exeDMC, StateChangeReason.USER_REQUEST, new HashMap<String, Object>()), getProperties());

+		}

+	}

+

+	/**

+	 * Gets the register data value.

+	 *

+	 * @param registerDMC the register dmc

+	 * @param formatID the format id

+	 * @param rm the request monitor

+	 * @return the register data value

+	 */

+	private void getRegisterDataValue(RegisterDMC registerDMC, final String formatID,

+			final DataRequestMonitor<FormattedValueDMData> rm) {

+		try {

+			BigInteger bigIntValue = getRegisterValue(registerDMC);

+

+			String formattedValue = bigIntValue.toString(16);

+

+			if (formatID.equals(IFormattedValues.OCTAL_FORMAT))

+				formattedValue = NumberFormatUtils.toOctalString(bigIntValue);

+			if (formatID.equals(IFormattedValues.BINARY_FORMAT))

+				formattedValue = NumberFormatUtils.asBinary(bigIntValue);

+			if (formatID.equals(IFormattedValues.DECIMAL_FORMAT))

+				formattedValue = bigIntValue.toString();

+			

+			rm.setData(new FormattedValueDMData(formattedValue));

+

+		} catch (CoreException e) {

+			Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error in getRegisterDataValue.", e);

+			EDCDebugger.getMessageLogger().log(s);

+			rm.setStatus(s);

+		}

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IFormattedValues#getFormattedValueContext(org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext, java.lang.String)

+	 */

+	public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String formatId) {

+		if (dmc instanceof RegisterDMC) {

+			return new FormattedValueDMContext(Registers.this, dmc, formatId);

+		}

+		return null;

+	}

+

+	/**

+	 * Gets the model data for a register.

+	 *

+	 * @param dmc the dmc

+	 * @param rm the request monitor

+	 * @return the model data

+	 */

+	@SuppressWarnings("unchecked")

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

+

+		if (dmc instanceof RegisterGroupDMC)

+			getRegisterGroupData((IRegisterGroupDMContext) dmc, (DataRequestMonitor<IRegisterGroupDMData>) rm);

+		else if (dmc instanceof RegisterDMC)

+			getRegisterData((IRegisterDMContext) dmc, (DataRequestMonitor<IRegisterDMData>) rm);

+		else if (dmc instanceof FormattedValueDMContext)

+			getFormattedExpressionValue((FormattedValueDMContext) dmc, (DataRequestMonitor<FormattedValueDMData>) rm);

+		else

+			rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.ICachingService#flushCache(org.eclipse.cdt.dsf.datamodel.IDMContext)

+	 */

+	public void flushCache(IDMContext context) {

+		if (isSnapshot())

+			return;

+		// Why flush this static info ?

+		// registerGroupsPerThread.clear();

+		

+		registerValueCache.clear();

+	}

+

+	/**

+	 * Load register groups for an executable context.

+	 *

+	 * @param executionDmc the execution dmc

+	 * @param element the element

+	 * @throws Exception the exception

+	 */

+	public void loadGroupsForContext(IEDCExecutionDMC executionDmc, Element element) throws Exception {

+		// Can't call flushCache here because it does nothing for snapshot

+		// services.

+		String cxtID = ((IEDCDMContext)executionDmc).getID();

+		// It does not hurt if the context is not in the caches.

+		registerGroupsPerContext.remove(cxtID);

+		registerValueCache.remove(cxtID);

+

+		NodeList registerGroups = element.getElementsByTagName(RegisterGroupDMC.REGISTER_GROUP);

+

+		List<RegisterGroupDMC> regGroups = Collections.synchronizedList(new ArrayList<RegisterGroupDMC>());

+

+		int numGroups = registerGroups.getLength();

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

+			Element groupElement = (Element) registerGroups.item(i);

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

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

+			SnapshotUtils.initializeFromXML(propElement, properties);

+

+			RegisterGroupDMC regdmc = new RegisterGroupDMC(this, executionDmc, properties);

+			regdmc.loadSnapshot(groupElement);

+			regGroups.add(regdmc);

+		}

+		registerGroupsPerContext.put(((IEDCDMContext) executionDmc).getID(), regGroups);

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.debug.edc.services.IDSFServiceUsingTCF#tcfServiceReady(org.eclipse.tm.tcf.protocol.IService)

+	 */

+	public void tcfServiceReady(IService service) {

+		tcfRegistersService = (org.eclipse.tm.tcf.services.IRegisters)service;

+	}

+

+	/**

+	 * Gets the register value.

+	 *

+	 * @param executionDMC the execution dmc

+	 * @param id the register id

+	 * @return the register value

+	 * @throws CoreException the core exception

+	 */

+	public String getRegisterValue(IEDCExecutionDMC executionDMC, int id) throws CoreException {

+		String name = getRegisterNameFromCommonID(id);

+		if (name != null) {

+			return getRegisterValue(executionDMC, name);

+		}

+		return null;

+	}

+

+	/**

+	 * Get TCF child registers contexts for the given parent.

+	 * If parent is a thread, the registers contexts are register groups.

+	 * If parent is a register group, the contexts returned are registers.

+	 *

+	 * @param parentID thread ID or register group ID.

+	 * @return the tCF registers contexts

+	 * @throws CoreException the core exception

+	 */

+	protected List<RegistersContext>	getTCFRegistersContexts(final String parentID) throws CoreException {

+		List<RegistersContext> tcfRegContexts = new ArrayList<RegistersContext>();

+		

+		TCFTask<String[]> getChildIDTask = new TCFTask<String[]>() {

+			public void run() {

+				tcfRegistersService.getChildren(parentID, new org.eclipse.tm.tcf.services.IRegisters.DoneGetChildren() {

+

+					public void doneGetChildren(IToken token, Exception error, String[] contextIds) {

+						if (error == null)

+							done(contextIds);

+						else

+							error(error);

+					}});

+			}

+		};

+		

+		String[] childIDs;

+		try {

+			childIDs = getChildIDTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);

+		} catch (Throwable e) {

+			throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Fail to get TCF context for: " + parentID, e));

+		}

+		

+		for (String gid: childIDs) {

+			final String id = gid;

+			TCFTask<RegistersContext> getGroupContextTask = new TCFTask<RegistersContext>() {

+				public void run() {

+					tcfRegistersService.getContext(id, new org.eclipse.tm.tcf.services.IRegisters.DoneGetContext(){

+						public void doneGetContext(IToken token, Exception error, RegistersContext context) {

+							if (error == null)

+								done(context);

+							else

+								error(error);

+						}});

+				}

+			};

+		

+			RegistersContext rgc = null;

+			try {

+				rgc = getGroupContextTask.get(getTCFTimeout(), TimeUnit.MILLISECONDS);

+			} catch (Throwable e) {

+				throw new CoreException(EDCDebugger.dsfRequestFailedStatus("Fail to get TCF context for: " + parentID, e));

+			}

+			

+			if (rgc != null)

+				tcfRegContexts.add(rgc);

+		}

+

+		return tcfRegContexts;

+	}

+	

+	/**

+	 * Handle a suspended event by flushing the cache.

+	 *

+	 * @param e the event

+	 */

+	@DsfServiceEventHandler

+	public void eventDispatched(ISuspendedDMEvent e) {

+		flushCache(null);

+	}

+

+	/**

+	 * Handle a resumed event by flushing the cache.

+	 *

+	 * @param e the event

+	 */

+	@DsfServiceEventHandler

+	public void eventDispatched(IResumedDMEvent e) {

+		flushCache(null);

+	}

+

+	/**

+	 * When a context (e.g. a thread) is killed/detached, we should forget

+	 * cached register info & values for it so that we can properly access

+	 * registers when we re-attach to it.

+	 *

+	 * @param e the event

+	 * @since 2.0

+	 */

+	@DsfServiceEventHandler

+	public void eventDispatched(IExitedDMEvent e) {

+		IExecutionDMContext cxt = e.getDMContext();

+		if (cxt != null && cxt instanceof IEDCDMContext) {

+			String cxtID = ((IEDCDMContext)cxt).getID();

+			// It does not hurt if the context is not in the caches.

+			registerGroupsPerContext.remove(cxtID);

+			registerValueCache.remove(cxtID);

+		}

+	}

+

+	/**

+	 * Creates the registers for group.

+	 *

+	 * @param registerGroupDMC the register group dmc

+	 * @return the list

+	 * @throws CoreException the core exception

+	 */

+	protected List<RegisterDMC> createRegistersForGroup(RegisterGroupDMC registerGroupDMC) throws CoreException {

+		ArrayList<RegisterDMC> registers = new ArrayList<RegisterDMC>();

+	

+		if (tcfRegistersService != null) {

+			List<RegistersContext> tcfRegs = getTCFRegistersContexts(registerGroupDMC.getID());

+			

+			for (RegistersContext rg: tcfRegs) {

+				registers.add(new RegisterDMC(registerGroupDMC, registerGroupDMC.getExecutionDMC(), rg));

+			}

+		}

+		

+		return registers;

+	}

+	

+	/**

+	 * Creates the groups for context.

+	 *

+	 * @param ctx the ctx

+	 * @return the list

+	 * @throws CoreException the core exception

+	 */

+	protected List<RegisterGroupDMC> createGroupsForContext(IEDCExecutionDMC ctx) throws CoreException {

+

+		List<RegisterGroupDMC> groups = Collections.synchronizedList(new ArrayList<RegisterGroupDMC>());

+

+		if (RunControl.isNonContainer(ctx)) {

+			if (tcfRegistersService != null) {

+				List<RegistersContext> tcfRegGroups = getTCFRegistersContexts(ctx.getID());

+				

+				for (RegistersContext rg: tcfRegGroups) {

+					groups.add(new RegisterGroupDMC(this, ctx, rg.getProperties()));

+				}

+			}

+		}

+

+		return groups;

+	}

+

+	/**

+	 * Given a common general purpose register id (e.g. from symbolics), get the

+	 * corresponding register name.

+	 * 

+	 * @param id

+	 *            the common general purpose register id (0-31)

+	 * @return the corresponding register name, or null of n/a

+	 */

+	public abstract String getRegisterNameFromCommonID(int id);

+	

+	/**

+	 * Sets the TCF timeout.

+	 *

+	 * @param msecs the new TCF timeout

+	 * @since 2.0

+	 */

+	public void setTCFTimeout(long msecs) {

+		tcfTimeout = msecs;

+	}

+

+	/**

+	 * Gets the TCF timeout.

+	 *

+	 * @return the TCF timeout

+	 * @since 2.0

+	 */

+	public long getTCFTimeout() {

+		return tcfTimeout;

+	}

+

+	// Implementation of org.eclipse.cdt.dsf.debug.service.IRegisters

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterGroups(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getRegisterGroups(final IDMContext ctx, final DataRequestMonitor<IRegisterGroupDMContext[]> rm) {

+		

+		asyncExec(new Runnable() {

+			

+			public void run() {

+				IEDCExecutionDMC execDmc = DMContexts.getAncestorOfType(ctx, IEDCExecutionDMC.class);

+				if (execDmc != null && RunControl.isNonContainer(execDmc)) {

+					try {

+						rm.setData(getGroupsForContext(execDmc));

+					} catch (CoreException e) {

+						EDCDebugger.getMessageLogger().log(e.getStatus());

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

+					}

+					rm.done();

+					return;

+				}

+

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

+				if (frameDmc != null) {

+					try {

+						rm.setData(getGroupsForContext(frameDmc.getExecutionDMC()));

+					} catch (CoreException e) {

+						EDCDebugger.getMessageLogger().log(e.getStatus());

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

+					}

+					rm.done();

+					return;

+				}

+				

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

+				rm.done();

+			}

+		}, rm);

+		

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisters(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getRegisters(final IDMContext ctx, final DataRequestMonitor<IRegisterDMContext[]> rm) {

+

+		asyncExec(new Runnable() {

+			

+			public void run() {

+				RegisterGroupDMC groupContext = DMContexts.getAncestorOfType(ctx, RegisterGroupDMC.class);

+				IEDCExecutionDMC executionContext = DMContexts.getAncestorOfType(ctx, IEDCExecutionDMC.class);

+				RegisterDMC[] allRegisters;

+				try {

+					if (groupContext != null && executionContext != null) {

+						allRegisters = groupContext.getRegisters();

+					}

+					else {

+						allRegisters = new RegisterDMC[0];

+					}

+					rm.setData(allRegisters);

+				} catch (CoreException e) {

+					EDCDebugger.getMessageLogger().log(e.getStatus());

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

+				}

+				rm.done();

+			}

+		}, rm);

+		

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getBitFields(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getBitFields(IDMContext ctx, DataRequestMonitor<IBitFieldDMContext[]> rm) {

+		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "BitField not supported", null)); //$NON-NLS-1$

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findRegisterGroup(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void findRegisterGroup(IDMContext ctx, String name, DataRequestMonitor<IRegisterGroupDMContext> rm) {

+		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findRegisterGroup not supported", null)); //$NON-NLS-1$

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findRegister(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void findRegister(IDMContext ctx, String name, DataRequestMonitor<IRegisterDMContext> rm) {

+		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findRegister not supported", null)); //$NON-NLS-1$

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#findBitField(org.eclipse.cdt.dsf.datamodel.IDMContext, java.lang.String, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void findBitField(IDMContext ctx, String name, DataRequestMonitor<IBitFieldDMContext> rm) {

+		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED, "findBitField not supported", null)); //$NON-NLS-1$

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterGroupData(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getRegisterGroupData(IRegisterGroupDMContext dmc, DataRequestMonitor<IRegisterGroupDMData> rm) {

+

+		class RegisterGroupData implements IRegisterGroupDMData {

+			private final String name;

+			private final String description;

+

+			public RegisterGroupData(RegisterGroupDMC dmc) {

+				this.name = dmc.getName();

+				this.description = (String) dmc.getProperty(IEDCDMContext.PROP_DESCRIPTION);

+			}

+

+			public String getName() {

+				return name;

+			}

+

+			public String getDescription() {

+				return description;

+			}

+		}

+

+		rm.setData(new RegisterGroupData((RegisterGroupDMC) dmc));

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisterData(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getRegisterData(IRegisterDMContext dmc, DataRequestMonitor<IRegisterDMData> rm) {

+		RegisterDMC regdmc = (RegisterDMC) dmc;

+		rm.setData(new RegisterData(regdmc.getProperties()));

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getBitFieldData(org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getBitFieldData(IBitFieldDMContext dmc, DataRequestMonitor<IBitFieldDMData> rm) {

+		rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, NOT_SUPPORTED,

+				"Bit fields not yet supported", null)); //$NON-NLS-1$

+		rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IRegisters#writeRegister(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, java.lang.String, java.lang.String, org.eclipse.cdt.dsf.concurrent.RequestMonitor)

+	 */

+	public void writeRegister(final IRegisterDMContext regCtx, final String regValue, final String formatID, final RequestMonitor rm) {

+

+		asyncExec(new Runnable() {

+			

+			public void run() {

+				try{

+				writeRegister(regCtx, regValue, formatID);

+				} catch (CoreException e) {

+					EDCDebugger.getMessageLogger().log(e.getStatus());

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

+				}

+				rm.done();

+			}

+		}, rm);

+		

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Stack.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Stack.java
index b1b0f76..d5b361e 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Stack.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/services/Stack.java
@@ -1,1653 +1,1739 @@
-/*******************************************************************************
- * 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.services;
-
-import java.io.File;
-import java.io.IOException;
-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.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.cdt.core.IAddress;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
-import org.eclipse.cdt.debug.edc.internal.EDCTrace;
-import org.eclipse.cdt.debug.edc.internal.launch.CSourceLookup;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.EDCSymbolReader;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
-import org.eclipse.cdt.debug.edc.internal.services.dsf.Symbols;
-import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
-import org.eclipse.cdt.debug.edc.internal.symbols.MemoryVariableLocation;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.UnmanglerEABI;
-import org.eclipse.cdt.debug.edc.internal.symbols.files.UnmanglingException;
-import org.eclipse.cdt.debug.edc.snapshot.IAlbum;
-import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;
-import org.eclipse.cdt.debug.edc.symbols.ICompileUnitScope;
-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.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.IUnmangler;
-import org.eclipse.cdt.debug.edc.symbols.IVariable;
-import org.eclipse.cdt.debug.edc.symbols.TypeEngine;
-import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.datamodel.DMContexts;
-import org.eclipse.cdt.dsf.datamodel.IDMContext;
-import org.eclipse.cdt.dsf.debug.service.ICachingService;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
-import org.eclipse.cdt.dsf.debug.service.IStack;
-import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.cdt.dsf.service.IDsfService;
-import org.eclipse.cdt.utils.Addr64;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IStorage;
-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.preferences.IEclipsePreferences;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-public abstract class Stack extends AbstractEDCService implements IStack, ICachingService {
-
-	public static final String STACK_FRAME = "stack_frame";
-	
-	public Boolean showAllVariablesEnabled = null;
-
-	private final Map<String, List<StackFrameDMC>> stackFrames = Collections
-			.synchronizedMap(new HashMap<String, List<StackFrameDMC>>());
-	private final Map<String, Boolean> allFramesCached = Collections
-	.synchronizedMap(new HashMap<String, Boolean>());
-
-	
-	
-	public static class StackFrameData implements IFrameDMData {
-
-		public final IAddress address;
-		public final int level;
-		public final String function;
-		public final String module;
-		private final String file;
-		private final int lineNumber;
-
-		StackFrameData(StackFrameDMC dmc) {
-			level = dmc.getLevel();
-			address = dmc.getInstructionPtrAddress();
-			module = dmc.getModuleName();
-			file = dmc.getSourceFile(); // "" instead of null if no file.
-			lineNumber = dmc.getLineNumber();
-			function = dmc.getFunctionName();
-		}
-
-		public IAddress getAddress() {
-			return address;
-		}
-
-		public String getFunction() {
-			return function;
-		}
-
-		public int getLevel() {
-			return level;
-		}
-
-		// DSF requires non-null return value.
-		public String getFile() {
-			return file;
-		}
-
-		public int getLine() {
-			return lineNumber;
-		}
-
-		public int getColumn() {
-			return 0;
-		}
-
-		public String getModule() {
-			return module;
-		}
-
-		private boolean equals(final IAddress right, final IAddress left) {
-			return right == left || right != null && right.equals(left);
-		}
-
-		private boolean equals(final String right, final String left) {
-			return right == left || right != null && right.equals(left);
-		}
-
-		@Override
-		public boolean equals(Object other) {
-			return
-				this == other
-				|| (other != null && other instanceof StackFrameData
-					&& equals(getAddress(), ((StackFrameData)other).getAddress())
-					&& equals(getFunction(), ((StackFrameData)other).getFunction())
-					&& getLevel() == ((StackFrameData)other).getLevel()
-					&& equals(getFile(), ((StackFrameData)other).getFile())
-					&& getLine() == ((StackFrameData)other).getLine()
-					&& getColumn() == ((StackFrameData)other).getColumn()
-					&& equals(getModule(), ((StackFrameData)other).getModule()));
-		}
-	}
-
-    /**
-     * Variable or enumerator context.  This interface provides a wrapper
-     * for treating variables and enumerators the same when needed.
-     **/
-    public interface IVariableEnumeratorContext {}
-
-    /**
-     * Enumerator context.
-     **/
-    public interface IEnumeratorDMContext {}
-
-    public static final class CurrentFrameRegisters implements IFrameRegisters {
-    	private final Registers registers;
-		private final IEDCExecutionDMC executionDMC;
-    	
-    	public CurrentFrameRegisters(IEDCExecutionDMC executionDMC, Registers registers) {
-    		this.executionDMC = executionDMC;
-			this.registers = registers;
-    	}
-    	
-    	public BigInteger getRegister(int regnum, int bytes) throws CoreException {
-    		String value = registers.getRegisterValue(executionDMC, regnum);
-    		if (value == null || value.equals(Registers.REGISTER_VALUE_ERROR))
-    			throw EDCDebugger.newCoreException("failed to read register");
-    		return new BigInteger(value, 16);
-    	}
-
-		public void writeRegister(int regnum, int bytes, BigInteger value) throws CoreException {
-			String id = registers.getRegisterNameFromCommonID(regnum);
-			if (id != null) {
-				// if value is negative, using value.toString(16) directly gives values such as '-af'
-				registers.writeRegister(executionDMC, id, Long.toHexString(value.longValue()));
-			} else
-				throw EDCDebugger.newCoreException(MessageFormat.format("could not find register number {0}", regnum));
-		}
-    }
-    
-    /**
-	 * Frame registers read from preserved registers on the stack frame.
-	 */
-	public static class PreservedFrameRegisters implements IFrameRegisters {
-		private final Map<Integer, BigInteger> preservedRegisters;
-		private final EDCServicesTracker dsfServicesTracker;
-		private final StackFrameDMC context;
-
-		/**
-		 * @param preservedRegisters map of register number to the address
-		 * where the register is saved
-		 * @since 2.0
-		 */
-		public PreservedFrameRegisters(EDCServicesTracker dsfServicesTracker,
-				StackFrameDMC context,
-				Map<Integer, BigInteger> preservedRegisters) {
-			this.dsfServicesTracker = dsfServicesTracker;
-			this.context = context;
-			this.preservedRegisters = preservedRegisters;
-		}
-
-		public BigInteger getRegister(int regnum, int bytes) throws CoreException {
-			BigInteger addrVal = preservedRegisters.get(regnum);
-			if (addrVal != null) {
-				MemoryVariableLocation location = new MemoryVariableLocation(
-						dsfServicesTracker, context, 
-						addrVal, true);
-				return location.readValue(bytes);
-			}
-			throw EDCDebugger.newCoreException("cannot read $R" + regnum + " from frame");
-		}
-
-		public void writeRegister(int regnum, int bytes, BigInteger value) throws CoreException {
-			BigInteger addrVal = preservedRegisters.get(regnum);
-			if (addrVal != null) {
-				MemoryVariableLocation location = new MemoryVariableLocation(
-						dsfServicesTracker, context, 
-						addrVal, true);
-				location.writeValue(bytes, value);
-			}
-		}
-	}
-
-	/**
-	 * Frame registers which always throws an exception.
-	 */
-	public static class AlwaysFailingFrameRegisters implements IFrameRegisters {
-		private final CoreException e;
-
-		public AlwaysFailingFrameRegisters(CoreException e) {
-			this.e = e;
-		}
-
-		public BigInteger getRegister(int regnum, int bytes) throws CoreException {
-			throw e;
-		}
-
-		public void writeRegister(int regnum, int bytes, BigInteger value)
-				throws CoreException {
-			throw e;
-		}
-	}
-
-	public class StackFrameDMC extends DMContext implements IFrameDMContext, Comparable<StackFrameDMC>,
-			ISnapshotContributor {
-
-		/** 
-		 * Stack frame level.  Zero is used for the first frame, where the PC is.
-		 */
-		public static final String LEVEL_INDEX = "Level";
-		/**
-		 * If set and True, tells that this frame is the topmost that we can fetch.
-		 */
-		public static final String ROOT_FRAME = "root_frame";
-		public static final String BASE_ADDR = "Base_address";
-		/**
-		 * @since 2.0 - previously "IP_ADDR"
-		 */
-		public static final String INSTRUCTION_PTR_ADDR = "Instruction_address";
-		public static final String MODULE_NAME = "module_name";
-		public static final String SOURCE_FILE = "source_file";
-		public static final String FUNCTION_NAME = "function_name";
-		public static final String LINE_NUMBER = "line_number";
-		/** 
-		 * For LEVEL_INDEX == 0, if set and True, this tells us that this frame
-		 * is not "authentic" yet, e.g., that the frame still represents the caller's
-		 * state.  This means we cannot trust the parameters and locals,
-		 * and must resolve variables from other frames differently.
-		 */
-		public static final String IN_PROLOGUE = "in_prologue"; // Boolean
-		/**
-		 * Provides a Map<Integer, BigInteger> instance which can yield addresses of
-		 * registers pushed into the stack frame if debug info does not provide it.
-		 */
-		public static final String PRESERVED_REGISTERS = "preserved_registers";
-		private static final String FRAME_PROPERTY_CACHE = "_frame_properties";
-		/**
-		 * @since 2.0 The id of the owning execution dmc
-		 */
-		public static final String EXECUTION_DMC_ID = "execution_dmc_id";
-
-		private final EDCServicesTracker dsfServicesTracker = Stack.this.getEDCServicesTracker();
-		private final IEDCExecutionDMC executionDMC;
-		private final int level;
-		private IAddress baseAddress;
-		private IAddress instructionPtrAddress;
-
-		private String moduleName = "";
-		private String sourceFile = "";
-		private String functionName = "";
-		private int lineNumber;
-		private IScope variableScope = null;
-		private List<VariableDMC> locals;
-		private List<EnumeratorDMC> enumerators;
-		private final Map<String, VariableDMC> localsByName = Collections
-				.synchronizedMap(new HashMap<String, VariableDMC>());
-		private final Map<String, EnumeratorDMC> enumeratorsByName = Collections
-				.synchronizedMap(new HashMap<String, EnumeratorDMC>());
-		private final Map<String, IVariable> thisPtrs = Collections
-				.synchronizedMap(new LinkedHashMap<String, IVariable>());
-		private IFunctionScope functionScope;
-		private IFrameRegisters frameRegisters;
-		public StackFrameDMC calledFrame;
-		private TypeEngine typeEngine;
-		private IEDCModuleDMContext module;
-
-		// additional items may be null but are usually set early and used repeatedly
-		private IAddress instrPtrLinkAddr = null;
-		private IEDCSymbolReader reader = null;
-		private IModuleLineEntryProvider provider = null;
-		private IDebugInfoProvider debugInfoProvider = null;
-		private IPath symbolFile = null;
-
-		/**
-		 * @since 2.0
-		 */
-		@SuppressWarnings("unchecked")
-		public StackFrameDMC(final IEDCExecutionDMC executionDMC, EdcStackFrame edcFrame) {
-			super(Stack.this, new IDMContext[] { executionDMC }, createFrameID(executionDMC, edcFrame), edcFrame.props);
-			
-			Map<String, Object> frameProperties = edcFrame.props;
-			
-			this.executionDMC = executionDMC;
-			frameProperties.put(EXECUTION_DMC_ID, executionDMC.getID());
-
-			this.level = (Integer) frameProperties.get(LEVEL_INDEX);
-			this.moduleName = (String) frameProperties.get(MODULE_NAME);
-			this.baseAddress = address(frameProperties.get(BASE_ADDR));
-			this.instructionPtrAddress = address(frameProperties.get(INSTRUCTION_PTR_ADDR));
-
-			// compute the source location
-			IEDCSymbols symbolsService = getService(Symbols.class);
-			functionScope = symbolsService.getFunctionAtAddress(executionDMC.getSymbolDMContext(),
-																instructionPtrAddress);
-
-			boolean usingCachedProperties = false;
-			IEDCModules modules = dsfServicesTracker.getService(IEDCModules.class);
-			Map<IAddress, Map<String, Object>> cachedFrameProperties
-			  = new HashMap<IAddress, Map<String, Object>>();
-			if (modules != null) {
-				module = modules.getModuleByAddress(executionDMC.getSymbolDMContext(), instructionPtrAddress);
-				if (module != null) {
-					instrPtrLinkAddr = module.toLinkAddress(instructionPtrAddress);
-					reader = module.getSymbolReader();
-					if (reader != null) {
-						symbolFile = this.reader.getSymbolFile();
-						if (symbolFile != null) {
-							// Check the persistent cache
-							String cacheKey = reader.getSymbolFile().toOSString() + FRAME_PROPERTY_CACHE;
-							Map<IAddress, Map<String, Object>> cachedData
-							  = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class,
-									  											  reader.getModificationDate());
-							if (cachedData != null) {
-								cachedFrameProperties = cachedData;
-								Map<String, Object> cachedProperties
-								  = cachedFrameProperties.get(instrPtrLinkAddr);
-								if (cachedProperties != null) {
-									if (cachedProperties.containsKey(SOURCE_FILE))
-										frameProperties.put(SOURCE_FILE, cachedProperties.get(SOURCE_FILE));
-
-									boolean cachedPropertiesHasFunctionName = false;
- 									if (cachedProperties.containsKey(FUNCTION_NAME)) {
-										Object fnObj = cachedProperties.get(FUNCTION_NAME);
-										if (fnObj != null 
-											&& fnObj instanceof String
-											&& ((String)fnObj).length() != 0) {
-											frameProperties.put(FUNCTION_NAME, fnObj);
-											cachedPropertiesHasFunctionName = true;
-									}	}
-
-									if (!cachedPropertiesHasFunctionName) {
-										setFunctionName(executionDMC, frameProperties, symbolsService);
-										cachedProperties.put(FUNCTION_NAME, functionName);
-									}
-
-									if (cachedProperties.containsKey(LINE_NUMBER))
-										frameProperties.put(LINE_NUMBER, cachedProperties.get(LINE_NUMBER));
-									usingCachedProperties = true;								
-			}	}	}	}	}	}	// null-checks on cachedProperties <= cachedData <= symbolFile
-
-			if (frameProperties.containsKey(SOURCE_FILE)) {
-				sourceFile   = (String) frameProperties.get(SOURCE_FILE);
-				functionName = (String) frameProperties.get(FUNCTION_NAME);
-				lineNumber   = (Integer) frameProperties.get(LINE_NUMBER);
-			} else if (frameProperties.containsKey(FUNCTION_NAME)) {
-				functionName = (String) frameProperties.get(FUNCTION_NAME);
-			} else if (!usingCachedProperties) {
-				ILineEntry line
-				  = symbolsService.getLineEntryForAddress(executionDMC.getSymbolDMContext(),
-														  instructionPtrAddress);
-				if (line != null)
-					setSourceProperties(frameProperties, line);
-
-				setFunctionName(executionDMC, frameProperties, symbolsService);
-			}
-			properties.putAll(frameProperties);
-
-			if (symbolFile != null) {
-				String cacheKey = symbolFile.toOSString() + FRAME_PROPERTY_CACHE;
-				cachedFrameProperties.put(this.instrPtrLinkAddr, frameProperties);
-				EDCDebugger.getDefault().getCache().putCachedData(cacheKey,
-																  (Serializable)cachedFrameProperties,
-																  this.reader.getModificationDate());
-			}
-
-			if (reader instanceof EDCSymbolReader)
-				debugInfoProvider = ((EDCSymbolReader)reader).getDebugInfoProvider();
-			typeEngine = new TypeEngine(getTargetEnvironmentService(), debugInfoProvider);
-		}
-
-		private void setFunctionName(final IEDCExecutionDMC executionDMC,
-				Map<String, Object> frameProperties, IEDCSymbols symbolsService) {
-			if (functionScope != null) {
-				// ignore inlined functions
-				IFunctionScope containerScope = functionScope;
-				while (containerScope.getParent() instanceof IFunctionScope) {
-					containerScope = (IFunctionScope) containerScope.getParent();
-				}
-				functionName = unmangle(containerScope.getName());
-				adjustFunctionSourceInfo(containerScope, frameProperties);
-			} else {
-				functionName
-				  = unmangle(symbolsService.getSymbolNameAtAddress(executionDMC.getSymbolDMContext(),
-						  										   instructionPtrAddress));
-			}
-
-			frameProperties.put(FUNCTION_NAME, functionName);
-		}
-
-		/**
-		 * Modify the name to refer to the inline function within the parent function.
-		 * <p>
-		 * However, ignore the inline function name if the pointer is on the first
-		 * line of the inline function and the "previous" line is
-		 * <br> (a) in the parent function; or
-		 * <br> (b) not in the original inline (meaning it was part of a prior inline); or 
-		 * <br> (c) is nested in another inline
-		 * @param container the ultimate function containing the inline(s)
-		 * @param frameProperties so source-file and line-number can also be adjusted
-		 */
-		private void adjustFunctionSourceInfo(IFunctionScope container,
-				Map<String, Object> frameProperties) {
-			if (functionScope.equals(container)) {
-				ILineEntry funcFirstEntry = this.getLineEntryInFunction(functionScope);
-				if (funcFirstEntry != null
-						&& !instrPtrLinkAddr.equals(funcFirstEntry.getLowAddress())) {
-					// this case covers the compiler having inline LNT entries
-					// whose bounds are outside the DWARF function scope boundaries
-					// for the inlines
-					setSourceProperties(frameProperties, funcFirstEntry);
-				}
-				return;		// i.e. never fall through to "inline" re-naming below
-			}
-
-			ILineEntry containerEntry = this.getLineEntryInFunction(container);
-			if (containerEntry != null && isInlineShouldBeHidden(containerEntry)) {
-				setSourceProperties(frameProperties, containerEntry);
-				return;
-			}
-
-			this.functionName
-			  = unmangle(functionScope.getName()) + " inlined in " + this.functionName;
-		}
-		
-		/**
-		 * Attempt to determine if the frame's instruction pointer is
-		 * <br>(a) at the first instruction of an inlined function; and
-		 * <br>(b) coincidentally at the first instruction of the line
-		 * entry corresponding to the line that caused the inline to
-		 * be generated.<p>
-		 * @param entry if null, will be calculated based on established
-		 * 			frame instruction pointer and function scope; can be passed
-		 * 			in if caller needs line entry for other usage
-		 * @return true if it can be determined that the instruction pointer is
-		 * 			the first instruction of an inline function and coincidentally the
-		 * 			first instruction of the line entry for which the inline was generated
-		 * @since 2.0
-		 */
-		public boolean isInlineShouldBeHidden(ILineEntry entry) {
-			if (functionScope == null
-					|| !(functionScope.getParent() instanceof IFunctionScope)
-					|| !instrPtrLinkAddr.equals(functionScope.getLowAddress()))
-				return false;
-
-			if (entry == null) {
-				entry = getLineEntryInFunction(functionScope);
-				if (entry == null)
-					return false;
-			}
-
-			if (instrPtrLinkAddr.equals(entry.getLowAddress())) {
-				ILineEntry prevEntry = getPreviousLineEntry(entry, true);
-				if (prevEntry != null) {
-					ILineEntry testEntry = getNextLineEntry(prevEntry, true);
-					if (entry.equals(testEntry)) {
-						return true;
-					}
-					return false;
-				}
-				return true;
-			}
-			return false;
-		}
-
-		/**
-		 * Private utility function to call the module's reader's provider's interfaces
-		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getLineEntryInFunction
-		 * @see IModuleScope#getModuleLineEntryProvider
-		 */
-		private ILineEntry getLineEntryInFunction(IFunctionScope func) {
-			return getModuleLineEntryProvider().getLineEntryInFunction(instrPtrLinkAddr, func);
-		}
-
-		/**
-		 * Private utility function to call the module's reader's provider's interfaces
-		 * @see IModuleScope#getModuleLineEntryProvider
-		 * @return {@link IModuleLineEntryProvider} never <code>null</code>
-		 */
-		private IModuleLineEntryProvider getModuleLineEntryProvider() {
-			if (provider == null && reader != null) {
-				IModuleScope moduleScope = reader.getModuleScope();
-				if (moduleScope != null)
-					provider = moduleScope.getModuleLineEntryProvider();			
-			}
-			return provider;
-		}
-
-		/**
-		 * Private utility function to call the module's reader's provider's interfaces
-		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getNextLineEntry
-		 * @see IModuleScope#getModuleLineEntryProvider
-		 */
-		private ILineEntry getNextLineEntry(ILineEntry entry, boolean collapseInlineFunctions) {
-			return getModuleLineEntryProvider().getNextLineEntry(entry, collapseInlineFunctions);
-		}					
-
-		/**
-		 * Private utility function to call the module's reader's provider's interfaces
-		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getPreviousLineEntry
-		 * @see IModuleScope#getModuleLineEntryProvider
-		 */
-		private ILineEntry getPreviousLineEntry(ILineEntry entry, boolean collapseInlineFunctions) {
-			return getModuleLineEntryProvider().getPreviousLineEntry(entry, collapseInlineFunctions);
-		}					
-
-		private void setSourceProperties(Map<String, Object> frameProperties,
-				ILineEntry entry) {
-			frameProperties.put(SOURCE_FILE, (sourceFile = entry.getFilePath().toOSString()));
-			frameProperties.put(LINE_NUMBER, (lineNumber = entry.getLineNumber()));
-		}
-
-		private String unmangle(String name) {
-			if (name == null)
-				return null;
-			
-			// unmangle the name
-			IUnmangler unmangler = null;
-			if (reader instanceof EDCSymbolReader) {
-				unmangler = ((EDCSymbolReader) reader).getUnmangler();
-			}
-			if (unmangler == null) {
-				unmangler = new UnmanglerEABI();
-			}
-			
-			if (!unmangler.isMangled(name))
-				return name;
-			
-			try {
-				return unmangler.unmangleWithoutArgs(name);
-			} catch (UnmanglingException e) {
-				return name;
-			}
-		}
-
-		private IAddress address(Object obj) {
-			if (obj instanceof Integer)
-				return new Addr64(obj.toString());
-			if (obj instanceof Long)
-				return new Addr64(obj.toString());
-			if (obj instanceof String) // the string should be hex string
-				return new Addr64((String) obj, 16);
-			return null;
-		}
-
-		private void setInstructionPtrAddress(IAddress ipAddrPtr) {
-			this.instructionPtrAddress = ipAddrPtr;
-			if (module != null)
-				this.instrPtrLinkAddr = module.toLinkAddress(instructionPtrAddress);
-		}
-
-		public IFunctionScope getFunctionScope() {
-			return functionScope;
-		}
-
-		public String getModuleName() {
-			return moduleName;
-		}
-
-		/**
-		 * Get source file name if any for the frame. 
-		 * @return valid file name or "" otherwise.
-		 */
-		public String getSourceFile() {
-			return sourceFile;
-		}
-
-		public String getFunctionName() {
-			return functionName;
-		}
-
-		public int getLineNumber() {
-			return lineNumber;
-		}
-
-		public IEDCExecutionDMC getExecutionDMC() {
-			return executionDMC;
-		}
-
-		public IAddress getBaseAddress() {
-			return baseAddress;
-		}
-
-		/**
-		 * @since 2.0
-		 */
-		public IAddress getInstructionPtrAddress() {
-			return instructionPtrAddress;
-		}
-
-		public int getLevel() {
-			return level;
-		}
-
-		/**
-		 * @since 2.0
-		 */
-		public EDCServicesTracker getEDCServicesTracker() {
-			return Stack.this.getEDCServicesTracker();
-		}
-
-		public int compareTo(StackFrameDMC f) {
-			if (level < f.level)
-				return -1;
-			if (level > f.level)
-				return +1;
-			return 0;
-		}
-
-		
-		@Override
-		public String toString() {
-			return "StackFrameDMC [baseAddress=" + baseAddress.toHexAddressString() + ", ipAddress="
-					+ instructionPtrAddress.toHexAddressString() + ", sourceFile=" + sourceFile
-					+ ", functionName=" + functionName + ", lineNumber="
-					+ lineNumber + "]";
-		}
-
-		@Override
-		public int hashCode() {
-			final int prime = 31;
-			int result = super.hashCode();
-			result = prime * result + getOuterType().hashCode();
-			result = prime * result
-					+ ((baseAddress == null) ? 0 : baseAddress.hashCode());
-			result = prime * result
-					+ ((executionDMC == null) ? 0 : executionDMC.hashCode());
-			result = prime * result + level;
-			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;
-
-			StackFrameDMC other = (StackFrameDMC) obj;
-			if (!getOuterType().equals(other.getOuterType()))
-				return false;
-
-			if (baseAddress == null) {
-				if (other.baseAddress != null)
-					return false;
-			} else if (!baseAddress.equals(other.baseAddress))
-				return false;
-
-			if (executionDMC == null) {
-				if (other.executionDMC != null)
-					return false;
-			} else if (!executionDMC.equals(other.executionDMC))
-				return false;
-
-			if (level != other.level)
-				return false;
-			return true;
-		}
-
-		/**
-		 * Finds a source file using the source lookup director.
-		 * 
-		 * @param sourceFile the raw source file location, usually from the symbol data
-		 * 
-		 * @return location of the source file
-		 */
-		private String findSourceFile(String sourceFile) {
-			String result = "";
-			CSourceLookup lookup = getService(CSourceLookup.class);
-			RunControl runControl = getService(RunControl.class);
-			CSourceLookupDirector[] directors = lookup.getSourceLookupDirectors(runControl.getRootDMC());
-
-			for (CSourceLookupDirector cSourceLookupDirector : directors) {
-				try {
-					Object[] elements = cSourceLookupDirector.findSourceElements(sourceFile);
-					if (elements != null && elements.length > 0)
-					{
-						Object element = elements[0];
-						if (element instanceof File) {
-							try {
-								result = (((File) element).getCanonicalPath());
-							} catch (IOException e) {
-								EDCDebugger.getMessageLogger().logError(null, e);
-							}
-						} else if (element instanceof IFile) {
-							result = (((IFile) element).getLocation().toOSString());
-						} else if (element instanceof IStorage) {
-							result = (((IStorage) element).getFullPath().toOSString());
-						} else if (element instanceof ITranslationUnit) {
-							result =(((ITranslationUnit) element).getLocation().toOSString());
-						}
-						break;
-					}			
-				} catch (CoreException e1) {
-					EDCDebugger.getMessageLogger().logError(sourceFile, e1);
-				}
-			}
-			return result;
-		}
-
-		/**
-		 * @since 2.0
-		 */
-		public Element takeSnapshot(IAlbum album, Document document, IProgressMonitor monitor) {
-			Element contextElement = document.createElement(STACK_FRAME);
-			contextElement.setAttribute(PROP_ID, this.getID());
-
-			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
-			contextElement.appendChild(propsElement);
-			// Locate the actual source file to be included in the album.
-			if (sourceFile.length() > 0) // No source file for this frame (just module/address)
-				album.addFile(new Path(findSourceFile(sourceFile)));
-			return contextElement;
-		}
-
-		@SuppressWarnings("unchecked")
-		public void loadSnapshot(Element element) {
-			// fix up registers to use integers again
-			Map<String, String> preservedRegisters = (Map<String, String>) properties.get(PRESERVED_REGISTERS);
-			if (preservedRegisters != null) {
-				Map<Integer, BigInteger> newPreservedRegisters = new HashMap<Integer, BigInteger>();
-				for (Map.Entry<String, String> entry : preservedRegisters.entrySet()) {
-					newPreservedRegisters.put(Integer.valueOf(entry.getKey().toString()), new BigInteger(entry.getValue().toString()));
-				}
-				properties.put(PRESERVED_REGISTERS, newPreservedRegisters);
-			}
-		}
-
-		public IVariableDMContext[] getLocals() {
-			return getLocals(/* boolean useCachedVariables => */ true);
-		}
-
-		private IVariableDMContext[] getLocals(boolean useCachedVariables) {
-			// may need to refresh the locals list because "Show All Variables"
-			// toggle has changed
-		    if (showAllVariablesEnabled == null) {
-				IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);
-		    	showAllVariablesEnabled = scope.getBoolean(IEDCSymbols.SHOW_ALL_VARIABLES_ENABLED, false);
-		    }
-
-			boolean enabled = showAllVariablesEnabled.booleanValue();
-			if (locals != null) {
-				IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);
-				enabled = scope.getBoolean(IEDCSymbols.SHOW_ALL_VARIABLES_ENABLED, showAllVariablesEnabled);
-			}
-
-			if (locals == null || !useCachedVariables || enabled != showAllVariablesEnabled) {
-				showAllVariablesEnabled = enabled;
-				locals = new ArrayList<VariableDMC>();
-				localsByName.clear();
-				thisPtrs.clear();
-				IEDCSymbols symbolsService = getService(IEDCSymbols.class);
-				IFunctionScope scope = symbolsService
-						.getFunctionAtAddress(executionDMC.getSymbolDMContext(), instructionPtrAddress);
-				if (scope != null) {
-					this.variableScope = scope;
-				}
-				
-				while (scope != null && instrPtrLinkAddr != null) {
-					Collection<IVariable> scopedVariables = scope.getScopedVariables(instrPtrLinkAddr);
-					for (IVariable variable : scopedVariables) {
-						VariableDMC var = new VariableDMC(Stack.this, this, variable);
-						String name = variable.getName();
-						// because of inlined functions, debugger information may indicate that
-						// more than one "this" pointer is live at one time
-						if (name != null && name.equals("this")) {
-							thisPtrs.put(variable.getScope().getName(), variable);
-						} else {
-							// now that we've screened out compiler generated "this" variables,
-							// get rid of other compiler generated variables
-							// TODO: Allow user to choose whether to show compiler generated variables
-							if (var.getVariable().isDeclared()) {
-								VariableDMC haveLocal = localsByName.get(name);
-								if (haveLocal != null) {
-									localsByName.remove(name);
-									locals.remove(haveLocal);
-								}
-								locals.add(var);
-								localsByName.put(name, var);
-							}
-						}
-					}
-
-					// if requesting to show all variables, add file-scope globals too
-					// (this isn't nearly sufficient since globals can show up
-					// in a header while all code is in the source file)
-					IScope parentScope = null;
-					if (showAllVariablesEnabled)
-						parentScope = scope.getParent();
-					while (parentScope != null) {
-						if (parentScope instanceof ICompileUnitScope) {
-							ICompileUnitScope cuScope = ((ICompileUnitScope) parentScope);
-
-							List<ICompileUnitScope> cuScopes = null;
-							if (this.debugInfoProvider != null) {
-								cuScopes = debugInfoProvider.getCompileUnitsForFile(cuScope.getFilePath());
-							} else {
-								cuScopes = new ArrayList<ICompileUnitScope>(1);
-								cuScopes.add(cuScope);
-							}
-
-							// add the globals of all compile unit scopes for the source file
-							String cuFile = ((ICompileUnitScope) parentScope).getFilePath().toOSString();
-							for (ICompileUnitScope nextCuScope : cuScopes) {
-								Collection<IVariable> globals = nextCuScope.getVariables();
-								if (globals != null) {
-									for (IVariable variable : globals) {
-										IPath varFile = variable.getDefiningFile();
-										if (varFile != null && !varFile.toOSString().equalsIgnoreCase(cuFile))
-											continue;
-
-										VariableDMC var = new VariableDMC(Stack.this, this, variable);
-										String name = var.getName();
-										VariableDMC haveLocal = localsByName.get(name);
-										if (haveLocal != null) {
-											localsByName.remove(name);
-											locals.remove(haveLocal);
-										}
-										locals.add(var);
-										localsByName.put(name, var);
-									}
-								}
-							}
-						}
-						parentScope = parentScope.getParent();
-					}
-					
-					if (!(scope.getParent() instanceof IFunctionScope))
-						break;
-					scope = (IFunctionScope) scope.getParent();
-				}
-			}
-			
-			// start with "this" pointers, if any
-			VariableDMC[] localsArray = new VariableDMC[(thisPtrs.isEmpty() ? 0 : 1) + locals.size()];
-			int i = 0;
-			if (!thisPtrs.isEmpty())
-				localsArray[i++] = new VariableDMC(Stack.this, this, getOuterThis());
-			// TODO For now, turn off ability to see multiple this pointers
-			// of the form "this$ScopeName"
-//			for (IVariable variable : thisPtrs.values()) {
-//				VariableDMC var = new VariableDMC(Stack.this, this, variable);
-//				var.setName("this$" + variable.getScope().getName());
-//				localsArray[i++] = var;
-//			}
-			for (VariableDMC var : locals)
-				localsArray[i++] = var;
-			return localsArray;
-		}
-		
-		/**
-		 * From a list of "this" pointers in scope, return the one from the outermost scope
-		 * @return this pointer from the outermost scope
-		 */
-		private IVariable getOuterThis() {
-			if (thisPtrs.isEmpty())
-				return null;
-			
-			if (thisPtrs.size() == 1)
-				return thisPtrs.values().iterator().next();
-
-			IVariable outer = null;
-			for (IVariable variable : thisPtrs.values()) {
-				if (outer == null)
-					outer = variable;
-				else {
-					IScope outerScope    = outer.getScope();
-					IScope variableScope = variable.getScope();
-					if (   variableScope.getLowAddress().compareTo(outerScope.getLowAddress()) < 0
-						|| variableScope.getHighAddress().compareTo(outerScope.getHighAddress()) > 0)
-						outer = variable;
-				}
-			}
-			return outer;
-		}
-
-
-		/**
-		 * Find a variable or enumerator by name
-		 * 
-		 * @param name required name of the variable or enumerator
-		 * @param qualifiedName optional fully qualified name of the variable or enumerator
-		 * @param localsOnly whether to restrict search to local variables and enumerators only
-		 * @return variable or enumerator, if found; otherwise, null
-		 * @since 2.0
-		 */
-		public IVariableEnumeratorContext findVariableOrEnumeratorByName(String name, String qualifiedName, boolean localsOnly) {
-			if (name == null)
-				return null;
-
-			if (locals == null)
-				getLocals();
-
-			// quickly check for a local variable or enumerator
-			IVariableEnumeratorContext variableOrEnumerator;
-			
-			if (qualifiedName != null) {
-				variableOrEnumerator = localsByName.get(qualifiedName);
-				if (variableOrEnumerator != null)
-					return variableOrEnumerator;
-			}
-
-			variableOrEnumerator = localsByName.get(name);
-			if (variableOrEnumerator != null)
-				return variableOrEnumerator;
-
-			if (enumerators == null)
-				getEnumerators();
-			
-			if (qualifiedName != null) {
-				variableOrEnumerator = enumeratorsByName.get(qualifiedName);
-				if (variableOrEnumerator != null)
-					return variableOrEnumerator;
-			}
-			
-			variableOrEnumerator = enumeratorsByName.get(name);
-			if (variableOrEnumerator != null)
-				return variableOrEnumerator;
-			
-			if (name.equals("this")) {
-				if (thisPtrs.isEmpty())
-					return null;
-				return new VariableDMC(Stack.this, this, getOuterThis());
-			}
-
-			// TODO For now, turn off ability to see multiple this pointers
-			// of the form "this$ScopeName"
-//			if (name.startsWith("this$")) {
-//				// return the one with the right scope
-//				if (thisPtrs.isEmpty())
-//					return null;
-//				IVariable variable = thisPtrs.get(name.substring("this$".length()));
-//				if (variable == null)
-//					return null;
-//				return new VariableDMC(Stack.this, this, variable);
-//			}
-
-			if (localsOnly || this.getVariableScope() == null)
-				return null;
-
-			// if there is no local variable or enumerator with this name, not very
-			// efficiently check enclosing scopes for a variable or enumerator
-			IScope variableScope = this.getVariableScope().getParent();
-
-			// to find file scope variables, we may need to check several compile units
-			// associated with one file
-			ArrayList<IScope> scopes = new ArrayList<IScope>();
-
-			while (variableOrEnumerator == null && variableScope != null) {
-				// At the module level, match against globals across the entire symbol
-				// file, even for big symbol files.
-				if (variableScope instanceof IModuleScope) {
-					Collection<IVariable> variables = ((IModuleScope)variableScope).getVariablesByName(qualifiedName != null ? qualifiedName : name, true);
-					if (variables != null && variables.size() > 0) {
-						// list may contain non-global variables, so return the first global
-						for (Object varObject : variables) {
-							if (varObject instanceof IVariable) {
-								IVariable variable = (IVariable)varObject;
-								if (variable.getScope() instanceof IModuleScope) {
-									variableOrEnumerator = new VariableDMC(Stack.this, this, variable);
-									break;
-								}
-							}
-						}
-					}
-					// module scope has no matching global variables
-					break;
-				}
-
-				scopes.clear();
-
-				if (variableScope instanceof ICompileUnitScope) {
-					// there may be several compile units for a file
-
-					// find the module scope parent of the compile unit
-					IScope parent = variableScope.getParent();
-					while (parent != null && !(parent instanceof IModuleScope))
-						parent = parent.getParent();
-
-					// find all compile units for the file
-					if (parent != null) {
-						IPath currentFile = ((ICompileUnitScope)variableScope).getFilePath();
-						if (currentFile != null)
-							for (ICompileUnitScope cu : ((IModuleScope)parent).getCompileUnitsForFile(currentFile))
-								scopes.add(cu);
-					}
-				}
-
-				if (scopes.isEmpty())
-					scopes.add(variableScope);
-
-				for (IScope scope : scopes) {
-					for (IVariable scopeVariable : scope.getVariables()) {
-						String scopeVariableName = scopeVariable.getName();
-						if (qualifiedName != null && scopeVariableName.equals(qualifiedName)) {
-							variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);
-							break;
-						}
-
-						if (scopeVariableName.equals(name)) {
-							variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);
-							break;
-						}
-					}
-
-					if (variableOrEnumerator == null && scope instanceof IFunctionScope) {
-						IFunctionScope functionScope = (IFunctionScope)scope;
-						for (IVariable scopeVariable : functionScope.getParameters()) {
-							String scopeVariableName = scopeVariable.getName();
-							if (qualifiedName != null && scopeVariableName.equals(qualifiedName)) {
-								variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);
-								break;
-							}
-
-							if (scopeVariableName.equals(name)) {
-								variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);
-								break;
-							}
-						}
-					}
-
-					if (variableOrEnumerator == null) {
-						for (IEnumerator scopeEnumerator : scope.getEnumerators()) {
-							String scopeEnumeratorName = scopeEnumerator.getName();
-							if (qualifiedName != null && scopeEnumeratorName.equals(qualifiedName)) {
-								variableOrEnumerator = new EnumeratorDMC(this, scopeEnumerator);
-								break;
-							}
-
-							if (scopeEnumeratorName.equals(name)) {
-								variableOrEnumerator = new EnumeratorDMC(this, scopeEnumerator);
-								break;
-							}
-						}
-					}
-				}
-
-				variableScope = variableScope.getParent();
-			}
-			
-			return variableOrEnumerator;
-		}
-		
-		public IScope getVariableScope() {
-			return variableScope;
-		}
-
-		public EnumeratorDMC[] getEnumerators() {
-			if (enumerators == null) {
-				enumerators = new ArrayList<EnumeratorDMC>();
-				if (getServicesTracker() != null) {
-					IEDCSymbols symbolsService = getService(Symbols.class);
-					if (executionDMC != null && symbolsService != null) {
-						IFunctionScope scope = symbolsService.getFunctionAtAddress(executionDMC.getSymbolDMContext(),
-								instructionPtrAddress);
-						while (scope != null) {
-							Collection<IEnumerator> localEnumerators = scope.getEnumerators();
-							for (IEnumerator enumerator : localEnumerators) {
-								EnumeratorDMC enumeratorDMC = new EnumeratorDMC(this, enumerator);
-								enumerators.add(enumeratorDMC);
-								enumeratorsByName.put(enumerator.getName(), enumeratorDMC);
-							}
-							if (!(scope.getParent() instanceof IFunctionScope))
-								break;
-							scope = (IFunctionScope) scope.getParent();
-						}
-					}
-				}
-			}
-			return enumerators.toArray(new EnumeratorDMC[enumerators.size()]);
-		}
-
-		public EnumeratorDMC findEnumeratorbyName(String name) {
-			if (enumerators == null)
-				getEnumerators();
-			return enumeratorsByName.get(name);
-		}
-		
-		/**
-		 * Get the view onto registers for this stack frame.  For the top stack frame, this
-		 * forwards to the {@link Registers} service.  Otherwise, this information
-		 * is synthesized from unwind information in the debug information.  
-		 * @return {@link IFrameRegisters}, never <code>null</code>
-		 */
-		@SuppressWarnings("unchecked")
-		public IFrameRegisters getFrameRegisters() {
-			if (frameRegisters == null) {
-				if (level == 0) {
-					// for top of stack, the registers service does the work
-					final Registers registers = getEDCServicesTracker().getService(Registers.class);
-					frameRegisters = new CurrentFrameRegisters(executionDMC, registers);
-				} else {
-					// see if symbolics can provide unwinding support
-					if (module != null) {
-						Symbols symbolsService = getService(Symbols.class);
-						IFrameRegisterProvider frameRegisterProvider = symbolsService.getFrameRegisterProvider(
-								executionDMC.getSymbolDMContext(), instructionPtrAddress);
-						if (frameRegisterProvider != null) {
-							try {
-								frameRegisters = frameRegisterProvider.getFrameRegisters(
-										getSession(), getEDCServicesTracker(), this);
-							} catch (CoreException e) {
-								// debug info failure; we should report this 
-								frameRegisters = new AlwaysFailingFrameRegisters(e);
-							}
-						}
-					}
-					
-					if (frameRegisters == null) {
-						// no information from symbolics; see if the stack unwinder found anything
-						final Map<Integer, BigInteger> preservedRegisters = (Map<Integer,BigInteger>) properties.get(
-								PRESERVED_REGISTERS);
-						if (preservedRegisters != null) {
-							frameRegisters = new PreservedFrameRegisters(dsfServicesTracker, StackFrameDMC.this, preservedRegisters);
-						}
-					}
-					
-					if (frameRegisters == null) {
-						frameRegisters = new AlwaysFailingFrameRegisters(
-								EDCDebugger.newCoreException("cannot read variables in this frame"));
-					}
-				}
-			}
-			return frameRegisters;
-		}
-
-		/**
-		 * Get the frame this one has called.
-		 * @return StackFrameDMC or <code>null</code> for top of stack
-		 */
-		public StackFrameDMC getCalledFrame() throws CoreException {
-			return calledFrame;
-		}
-
-		/**
-		 * Get a type engine (which holds cached information about types for use by expressions)
-		 * @return TypeEngine instance
-		 */
-		public TypeEngine getTypeEngine() {
-			return typeEngine;
-		}
-		
-		public IEDCModuleDMContext getModule() {
-			return module;
-		}
-
-		private Stack getOuterType() {
-			return Stack.this;
-		}
-		
-	}
-
-	public class VariableData implements IVariableDMData {
-
-		private final String name;
-
-		public VariableData(VariableDMC variableDMC) {
-			name = variableDMC.getName();
-		}
-
-		public String getName() {
-			return name;
-		}
-
-		/**
-		 * was initially implemented as "0".
-		 * currently returns null to guarantee anything calling this
-		 * knows it's getting a useless bit of data.
-		 * @see org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData#getValue()
-		 */
-		public String getValue() {
-			// TODO not implemented
-			return null;
-		}
-
-	}
-
-	public class VariableDMC extends DMContext implements IVariableDMContext, IVariableEnumeratorContext {
-
-		public static final String PROP_LOCATION = "Location";
-		private final IVariable variable;
-
-		public VariableDMC(IDsfService service, StackFrameDMC frame, IVariable variable) {
-			super(Stack.this, new IDMContext[] { frame }, variable.getName(), variable.getName());
-			this.variable = variable;
-		}
-
-		public IVariable getVariable() {
-			return variable;
-		}
-	}
-
-	public class EnumeratorDMC extends DMContext implements IEnumeratorDMContext, IVariableEnumeratorContext {
-
-		private final IEnumerator enumerator;
-
-		public EnumeratorDMC(StackFrameDMC frame, IEnumerator enumerator) {
-			super(Stack.this, new IDMContext[] { frame }, enumerator.getName(), enumerator.getName());
-			this.enumerator = enumerator;
-		}
-
-		public IEnumerator getEnumerator() {
-			return enumerator;
-		}
-	}
-
-	/**
-	 * @param classNames
-	 *            the type names the service will be registered under. See
-	 *            AbstractDsfService#register for details. We tack on base DSF's
-	 *            IStack and this class to the list if not provided.
-	 */
-	public Stack(DsfSession session, String[] classNames) {
-		super(session, 
-				massageClassNames(classNames, 
-						new String[] { IStack.class.getName(), Stack.class.getName() }));
-	}
-
-	/**
-	 * @since 2.0
-	 */
-	public static String createFrameID(IEDCExecutionDMC executionDMC, EdcStackFrame edcFrame) {
-		int level = (Integer) edcFrame.props.get(StackFrameDMC.LEVEL_INDEX);
-		String parentID = executionDMC.getID();
-		return parentID + ".frame[" + level + "]";
-	}
-
-	@Override
-	protected void doInitialize(RequestMonitor requestMonitor) {
-		super.doInitialize(requestMonitor);
-		getSession().addServiceEventListener(this, null);
-	}
-
-	public void getArguments(IFrameDMContext frameCtx, DataRequestMonitor<IVariableDMContext[]> rm) {
-		// never called by DSF. it expects arguments to be lumped in with
-		// locals.
-		rm.done();
-	}
-
-	public void getFrameData(IFrameDMContext frameDmc, DataRequestMonitor<IFrameDMData> rm) {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(frameDmc)); }
-		rm.setData(new StackFrameData((StackFrameDMC) frameDmc));
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }
-		rm.done();
-	}
-
-	public void getFrames(final IDMContext execContext, final DataRequestMonitor<IFrameDMContext[]> rm) {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(execContext)); }
-
-		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(execContext, ExecutionDMC.class);
-		if (execDmc != null)
-		{
-			if (!execDmc.isSuspended())
-			{
-				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$
-				rm.done();
-				return;
-			}
-			
-			asyncExec(new Runnable() {
-				public void run() {
-					try {
-						rm.setData(getFramesForDMC((ExecutionDMC) execContext, 0, ALL_FRAMES));
-						if (rm.getData().length == 0)
-							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execDmc, null)); //$NON-NLS-1$
-					} catch (CoreException e) {
-						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
-						EDCDebugger.getMessageLogger().log(s);
-						rm.setStatus(s);
-					}
-					if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }
-					rm.done();
-				}
-				
-			}, rm);
-
-		}
-		else {
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
-			rm.done();
-		}
-	}
-
-	public void getLocals(final IFrameDMContext frameCtx, final DataRequestMonitor<IVariableDMContext[]> rm) {
-		asyncExec(new Runnable() {
-			public void run() {
-				final StackFrameDMC frameContext = (StackFrameDMC) frameCtx;
-				IAddress contextIPAddress = frameContext.getInstructionPtrAddress();
-				boolean useVariableCache = false;
-				// the frame context passed in may be "stale".  it may prove equal to the current frame,
-				// but if the instruction ptr address is different, then the locals won't be collected properly
-				try {
-					IFrameDMContext[] iFrames = getFramesForDMC(frameContext.getExecutionDMC(), 0, ALL_FRAMES);
-					for (IFrameDMContext iFrameDMC : iFrames) {
-						if (frameCtx == iFrameDMC) {
-							useVariableCache = true;
-							break;
-						}
-						if (frameContext.equals(iFrameDMC)) {
-							StackFrameDMC frameDMC = (StackFrameDMC)iFrameDMC;
-							IAddress stackFrameIPAddr = frameDMC.getInstructionPtrAddress(); 
-							if (contextIPAddress.equals(stackFrameIPAddr)) {
-								useVariableCache = true;
-							} else {
-								frameContext.setInstructionPtrAddress(stackFrameIPAddr);
-							}
-							break;
-						}
-					}
-
-					rm.setData(frameContext.getLocals(useVariableCache));
-				} catch (CoreException e) {
-					EDCDebugger.getMessageLogger().log(e.getStatus());
-					rm.setStatus(e.getStatus());
-				}
-				rm.done();
-			}
-		}, rm);
-	}
-
-	public void getStackDepth(IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { dmc, maxDepth })); }
-		
-		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(dmc, ExecutionDMC.class);
-		if (execDmc != null)
-		{
-			if (!execDmc.isSuspended())
-			{
-				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$
-				rm.done();
-				return;
-			}
-
-			asyncExec(new Runnable() {
-				public void run() {
-					int startFrame = 0;
-					int endFrame = ALL_FRAMES;	
-					if (maxDepth > 0)
-						endFrame = maxDepth - 1;
-					try {
-						rm.setData(getFramesForDMC(execDmc, startFrame, endFrame).length);
-						if (rm.getData() == 0)
-							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execDmc, null)); //$NON-NLS-1$
-						if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, rm.getData()); }
-					} catch (CoreException e) {
-						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
-						EDCDebugger.getMessageLogger().log(s);
-						rm.setStatus(s);
-					}
-					rm.done();
-				}
-			}, rm);
-		}
-		else {
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
-			rm.done();
-		}
-	}
-
-	public void getTopFrame(final IDMContext execContext, final DataRequestMonitor<IFrameDMContext> rm) {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(execContext)); }
-
-		asyncExec(new Runnable() {
-			public void run() {
-				try {
-					IFrameDMContext[] frames = getFramesForDMC((ExecutionDMC) execContext, 0, 0);
-					if (frames.length == 0) {
-						rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE,
-								"No top stack frame available", null)); //$NON-NLS-1$
-						rm.done();
-						return;
-					}
-					rm.setData(frames[0]);
-				} catch (CoreException e) {
-					Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
-					EDCDebugger.getMessageLogger().log(s);
-					rm.setStatus(s);
-				}
-				if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }
-				rm.done();
-			}
-		}, rm);
-
-	}
-
-	public void getVariableData(IVariableDMContext variableDmc, DataRequestMonitor<IVariableDMData> rm) {
-		rm.setData(new VariableData((VariableDMC) variableDmc));
-		rm.done();
-	}
-
-	@SuppressWarnings("unchecked")
-	public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
-		if (dmc instanceof IFrameDMContext) {
-			getFrameData((IFrameDMContext) dmc, (DataRequestMonitor<IFrameDMData>) rm);
-		} else if (dmc instanceof IVariableDMContext) {
-			getVariableData((IVariableDMContext) dmc, (DataRequestMonitor<IVariableDMData>) rm);
-		} else
-			rm.done();
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.dsf.debug.service.IStack#getFrames(org.eclipse.cdt.dsf.datamodel.IDMContext, int, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
-	 */
-	public void getFrames(final IDMContext execContext, final int startIndex, final int endIndex, final DataRequestMonitor<IFrameDMContext[]> rm) {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { execContext, startIndex, endIndex })); }
-		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(execContext, ExecutionDMC.class);
-		if (execDmc != null)
-		{
-			if (!execDmc.isSuspended())
-			{
-				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$
-				rm.done();
-				return;
-			}
-
-			asyncExec(new Runnable() {
-				public void run() {
-					try {
-						rm.setData(getFramesForDMC((ExecutionDMC) execContext, startIndex, endIndex));
-						if (rm.getData().length == 0)
-							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execContext, null)); //$NON-NLS-1$
-					} catch (CoreException e) {
-						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);
-						EDCDebugger.getMessageLogger().log(s);
-						rm.setStatus(s);
-					}
-					if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(rm.getData())); }
-					rm.done();
-				}
-				
-			}, rm);
-
-		}
-		else {
-			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
-			rm.done();
-		}
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(rm.getData())); }
-	}
-
-	public IFrameDMContext[] getFramesForDMC(IEDCExecutionDMC context, int startIndex, int endIndex) throws CoreException {
-		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { context, startIndex, endIndex })); }
-
-		if (!context.isSuspended() || 
-			! RunControl.isNonContainer(context))	// no frames for container context. 
-		{
-			return new IFrameDMContext[0];
-		}
-
-		boolean needsUpdate = false;
-		synchronized (stackFrames) {
-			List<StackFrameDMC> frames = stackFrames.get(context.getID());
-			// Need to update the frames if there is no cached list for this
-			// context or if the cached list does not include all of the
-			// requested frames.
-			if (frames == null) {
-				// nothing in the cache so need to update
-				needsUpdate = true;
-			} else if (allFramesCached.containsKey(context.getID()) && allFramesCached.get(context.getID())) {
-				// all frames are cached
-				needsUpdate = false;
-			} else if (endIndex == ALL_FRAMES) {
-				// some but not all frames cached
-				needsUpdate = true;
-			} else {
-				// some but not all requested frames cached
-				needsUpdate = (frames.get(0).getLevel() > startIndex || 
-						frames.get(frames.size() - 1).getLevel() < endIndex);
-			}
-
-			if (needsUpdate)
-				updateFrames(context, startIndex, endIndex);
-
-			frames = stackFrames.get(context.getID());
-			// endIndex is inclusive and may be negative to fetch all frames
-			if (endIndex >= 0) {
-				if (startIndex < frames.size() && startIndex <= endIndex) {
-					frames = frames.subList(startIndex, Math.min(endIndex + 1, frames.size()));
-				} else {
-					frames = Collections.emptyList();
-				}
-			}
-			IFrameDMContext[] result = frames.toArray(new IFrameDMContext[frames.size()]);
-			if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(result)); }
-			return result;
-		}
-	}
-
-	private void updateFrames(IEDCExecutionDMC context, int startIndex, int endIndex) throws CoreException {
-		ArrayList<StackFrameDMC> frames = new ArrayList<StackFrameDMC>();
-		List<EdcStackFrame> edcFrames = computeStackFrames(context, startIndex, endIndex);
-		StackFrameDMC previous = null;
-		for (EdcStackFrame edcFrame : edcFrames) {
-			StackFrameDMC frame = new StackFrameDMC(context, edcFrame);
-			if (previous != null) {
-				frame.calledFrame = previous;
-				// note: don't store "callerFrame" since this is missing if only a partial stack was fetched
-			}
-			frames.add(frame);
-			previous = frame;
-		}
-		
-		stackFrames.put(context.getID(), frames);
-		
-		// all frames are cached if we request all frames, or if the returned number of frames was less than
-		// the requested max number of frames.  e.g. if we ask for 10 and they return 9, it's because there
-		// are only 9 frames.  so we have calculated all of them.
-		allFramesCached.put(context.getID(), startIndex == 0 && ((endIndex == ALL_FRAMES) || (frames.size() <= endIndex)));
-	}
-
-	/**
-	 * A stack frame described as one or more of the following properties, plus
-	 * any additional custom ones.
-	 * 
-	 * <ul>
-	 * <li>{@link StackFrameDMC#LEVEL_INDEX}
-	 * <li>{@link StackFrameDMC#ROOT_FRAME}
-	 * <li>{@link StackFrameDMC#BASE_ADDR}
-	 * <li>{@link StackFrameDMC#INSTRUCTION_PTR_ADDR}
-	 * <li>{@link StackFrameDMC#MODULE_NAME}
-	 * <li>{@link StackFrameDMC#SOURCE_FILE}
-	 * <li>{@link StackFrameDMC#FUNCTION_NAME}
-	 * <li>{@link StackFrameDMC#LINE_NUMBER}
-	 * <li>{@link StackFrameDMC#IN_PROLOGUE}
-	 * <li>{@link StackFrameDMC#PRESERVED_REGISTERS}
-	 * </ul>
-	 * 
-	 * @since 2.0
-	 */
-	public class EdcStackFrame {
-		public EdcStackFrame(Map<String, Object> props) { 
-			this.props = props; 
-		}
-		public Map<String, Object> props;
-	}
-	
-	protected abstract List<EdcStackFrame> computeStackFrames(IEDCExecutionDMC context, int startIndex, int endIndex) throws CoreException;
-
-	public void loadFramesForContext(IEDCExecutionDMC exeDmc, Element allFrames) throws Exception {
-		flushCache(null);
-		List<StackFrameDMC> frames = Collections.synchronizedList(new ArrayList<StackFrameDMC>());
-
-		NodeList frameElements = allFrames.getElementsByTagName(STACK_FRAME);
-
-		int numFrames = frameElements.getLength();
-		StackFrameDMC previousFrameDMC = null;
-		
-		for (int i = 0; i < numFrames; i++) {
-			Element groupElement = (Element) frameElements.item(i);
-			Element propElement = (Element) groupElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
-			HashMap<String, Object> properties = new HashMap<String, Object>();
-			SnapshotUtils.initializeFromXML(propElement, properties);
-
-			// ensure that stack level numbering is canonical: 
-			// we expect level==0 to be the top, but it used to be 1
-			properties.put(StackFrameDMC.LEVEL_INDEX, i);
-			
-			StackFrameDMC frameDMC = new StackFrameDMC(exeDmc, new EdcStackFrame(properties));
-			frameDMC.loadSnapshot(groupElement);
-			if (previousFrameDMC != null) {
-				frameDMC.calledFrame = previousFrameDMC;
-			}
-			frames.add(frameDMC);
-
-			previousFrameDMC = frameDMC;
-		}
-		stackFrames.put(exeDmc.getID(), frames);
-		allFramesCached.put(exeDmc.getID(), true);
-	}
-
-	public void flushCache(IDMContext context) {
-		if (isSnapshot())
-			return;
-		if (context != null && context instanceof IEDCDMContext) {
-			String contextID = ((IEDCDMContext) context).getID();
-			stackFrames.remove(contextID);
-			allFramesCached.remove(contextID);
-		} else {
-			stackFrames.clear();
-			allFramesCached.clear();
-		}
-	}
-
-	@DsfServiceEventHandler
-	public void eventDispatched(ISuspendedDMEvent e) {
-		flushCache(e.getDMContext());
-	}
-
-	@DsfServiceEventHandler
-	public void eventDispatched(IResumedDMEvent e) {
-		flushCache(e.getDMContext());
-	}
-
-}
+/*******************************************************************************

+// * 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.services;

+

+import java.io.File;

+import java.io.IOException;

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

+import java.util.List;

+import java.util.Map;

+

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

+import org.eclipse.cdt.core.model.ITranslationUnit;

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

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

+import org.eclipse.cdt.debug.edc.internal.launch.CSourceLookup;

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

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

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

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

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

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

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

+import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;

+import org.eclipse.cdt.debug.edc.internal.symbols.files.UnmanglerEABI;

+import org.eclipse.cdt.debug.edc.internal.symbols.files.UnmanglingException;

+import org.eclipse.cdt.debug.edc.snapshot.IAlbum;

+import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IStorage;

+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.preferences.IEclipsePreferences;

+import org.w3c.dom.Document;

+import org.w3c.dom.Element;

+import org.w3c.dom.NodeList;

+

+public abstract class Stack extends AbstractEDCService implements IStack, ICachingService {

+

+	public static final String STACK_FRAME = "stack_frame";

+	

+	public Boolean showAllVariablesEnabled = null;

+

+    /**

+	 * When retrieving locals, re-get only those frames that are already cached.

+	 */

+	private final static int REFRESH_CACHED_FRAMES = -2;

+

+	/**

+	 * this cache is maintained only for those occasions when getFramesForDMC()

+	 * is called from {@link #getLocals(IFrameDMContext, DataRequestMonitor)}

+	 * and no current cache is available, requiring a refresh.

+	 * <p>the cache value for an {@link IEDCExecutionDMC} is established at the

+	 * end of {@link #getFramesForDMC(IEDCExecutionDMC, int, int)} with the 

+	 * value {@link Math#min}(endIndex,frames.size()) .

+     */

+	private final Map<IEDCExecutionDMC, Integer> lastMaxFrameInContextCache

+	  = Collections.synchronizedMap(new HashMap<IEDCExecutionDMC, Integer>());

+

+	private final Map<String, List<StackFrameDMC>> stackFrames

+	  = Collections.synchronizedMap(new HashMap<String, List<StackFrameDMC>>());

+	private final Map<String, Boolean> allFramesCached

+	  = Collections.synchronizedMap(new HashMap<String, Boolean>());

+

+	

+	public static class StackFrameData implements IFrameDMData {

+

+		public final IAddress address;

+		public final int level;

+		public final String function;

+		public final String module;

+		private final String file;

+		private final int lineNumber;

+

+		StackFrameData(StackFrameDMC dmc) {

+			level = dmc.getLevel();

+			address = dmc.getInstructionPtrAddress();

+			module = dmc.getModuleName();

+			file = dmc.getSourceFile(); // "" instead of null if no file.

+			lineNumber = dmc.getLineNumber();

+			function = dmc.getFunctionName();

+		}

+

+		public IAddress getAddress() {

+			return address;

+		}

+

+		public String getFunction() {

+			return function;

+		}

+

+		public int getLevel() {

+			return level;

+		}

+

+		// DSF requires non-null return value.

+		public String getFile() {

+			return file;

+		}

+

+		public int getLine() {

+			return lineNumber;

+		}

+

+		public int getColumn() {

+			return 0;

+		}

+

+		public String getModule() {

+			return module;

+		}

+

+		private boolean equals(final IAddress right, final IAddress left) {

+			return right == left || right != null && right.equals(left);

+		}

+

+		private boolean equals(final String right, final String left) {

+			return right == left || right != null && right.equals(left);

+		}

+

+		@Override

+		public boolean equals(Object other) {

+			return

+				this == other

+				|| (other != null && other instanceof StackFrameData

+					&& equals(getAddress(), ((StackFrameData)other).getAddress())

+					&& equals(getFunction(), ((StackFrameData)other).getFunction())

+					&& getLevel() == ((StackFrameData)other).getLevel()

+					&& equals(getFile(), ((StackFrameData)other).getFile())

+					&& getLine() == ((StackFrameData)other).getLine()

+					&& getColumn() == ((StackFrameData)other).getColumn()

+					&& equals(getModule(), ((StackFrameData)other).getModule()));

+		}

+	}

+

+    /**

+     * Variable or enumerator context.  This interface provides a wrapper

+     * for treating variables and enumerators the same when needed.

+     **/

+    public interface IVariableEnumeratorContext {}

+

+    /**

+     * Enumerator context.

+     **/

+    public interface IEnumeratorDMContext {}

+

+    public static final class CurrentFrameRegisters implements IFrameRegisters {

+    	private final Registers registers;

+		private final IEDCExecutionDMC executionDMC;

+    	

+    	public CurrentFrameRegisters(IEDCExecutionDMC executionDMC, Registers registers) {

+    		this.executionDMC = executionDMC;

+			this.registers = registers;

+    	}

+    	

+    	public BigInteger getRegister(int regnum, int bytes) throws CoreException {

+    		String value = registers.getRegisterValue(executionDMC, regnum);

+    		if (value == null || value.equals(Registers.REGISTER_VALUE_ERROR))

+    			throw EDCDebugger.newCoreException("failed to read register");

+    		return new BigInteger(value, 16);

+    	}

+

+		public void writeRegister(int regnum, int bytes, BigInteger value) throws CoreException {

+			String id = registers.getRegisterNameFromCommonID(regnum);

+			if (id != null) {

+				// if value is negative, using value.toString(16) directly gives values such as '-af'

+				registers.writeRegister(executionDMC, id, Long.toHexString(value.longValue()));

+			} else

+				throw EDCDebugger.newCoreException(MessageFormat.format("could not find register number {0}", regnum));

+		}

+    }

+    

+    /**

+	 * Frame registers read from preserved registers on the stack frame.

+	 */

+	public static class PreservedFrameRegisters implements IFrameRegisters {

+		private final Map<Integer, BigInteger> preservedRegisters;

+		private final EDCServicesTracker dsfServicesTracker;

+		private final StackFrameDMC context;

+

+		/**

+		 * @param preservedRegisters map of register number to the address

+		 * where the register is saved

+		 * @since 2.0

+		 */

+		public PreservedFrameRegisters(EDCServicesTracker dsfServicesTracker,

+				StackFrameDMC context,

+				Map<Integer, BigInteger> preservedRegisters) {

+			this.dsfServicesTracker = dsfServicesTracker;

+			this.context = context;

+			this.preservedRegisters = preservedRegisters;

+		}

+

+		public BigInteger getRegister(int regnum, int bytes) throws CoreException {

+			BigInteger addrVal = preservedRegisters.get(regnum);

+			if (addrVal != null) {

+				MemoryVariableLocation location = new MemoryVariableLocation(

+						dsfServicesTracker, context, 

+						addrVal, true);

+				return location.readValue(bytes);

+			}

+			throw EDCDebugger.newCoreException("cannot read $R" + regnum + " from frame");

+		}

+

+		public void writeRegister(int regnum, int bytes, BigInteger value) throws CoreException {

+			BigInteger addrVal = preservedRegisters.get(regnum);

+			if (addrVal != null) {

+				MemoryVariableLocation location = new MemoryVariableLocation(

+						dsfServicesTracker, context, 

+						addrVal, true);

+				location.writeValue(bytes, value);

+			}

+		}

+	}

+

+	/**

+	 * Frame registers which always throws an exception.

+	 */

+	public static class AlwaysFailingFrameRegisters implements IFrameRegisters {

+		private final CoreException e;

+

+		public AlwaysFailingFrameRegisters(CoreException e) {

+			this.e = e;

+		}

+

+		public BigInteger getRegister(int regnum, int bytes) throws CoreException {

+			throw e;

+		}

+

+		public void writeRegister(int regnum, int bytes, BigInteger value)

+				throws CoreException {

+			throw e;

+		}

+	}

+

+	public class StackFrameDMC extends DMContext implements IFrameDMContext, Comparable<StackFrameDMC>,

+			ISnapshotContributor {

+

+		/** 

+		 * Stack frame level.  Zero is used for the first frame, where the PC is.

+		 */

+		public static final String LEVEL_INDEX = "Level";

+		/**

+		 * If set and True, tells that this frame is the topmost that we can fetch.

+		 */

+		public static final String ROOT_FRAME = "root_frame";

+		public static final String BASE_ADDR = "Base_address";

+		/**

+		 * @since 2.0 - previously "IP_ADDR"

+		 */

+		public static final String INSTRUCTION_PTR_ADDR = "Instruction_address";

+		public static final String MODULE_NAME = "module_name";

+		public static final String SOURCE_FILE = "source_file";

+		public static final String FUNCTION_NAME = "function_name";

+		public static final String LINE_NUMBER = "line_number";

+		/** 

+		 * For LEVEL_INDEX == 0, if set and True, this tells us that this frame

+		 * is not "authentic" yet, e.g., that the frame still represents the caller's

+		 * state.  This means we cannot trust the parameters and locals,

+		 * and must resolve variables from other frames differently.

+		 */

+		public static final String IN_PROLOGUE = "in_prologue"; // Boolean

+		/**

+		 * Provides a Map<Integer, BigInteger> instance which can yield addresses of

+		 * registers pushed into the stack frame if debug info does not provide it.

+		 */

+		public static final String PRESERVED_REGISTERS = "preserved_registers";

+		private static final String FRAME_PROPERTY_CACHE = "_frame_properties";

+		/**

+		 * @since 2.0 The id of the owning execution dmc

+		 */

+		public static final String EXECUTION_DMC_ID = "execution_dmc_id";

+

+		private final EDCServicesTracker dsfServicesTracker = Stack.this.getEDCServicesTracker();

+		private final IEDCExecutionDMC executionDMC;

+		private final int level;

+		private IAddress baseAddress;

+		private IAddress instructionPtrAddress;

+

+		private String moduleName = "";

+		private String sourceFile = "";

+		private String functionName = "";

+		private int lineNumber;

+		private IScope variableScope = null;

+		private List<VariableDMC> cachedLocals;

+		private List<EnumeratorDMC> cachedEnumerators;

+		private final Map<String, VariableDMC> localsByName

+		  = Collections.synchronizedMap(new HashMap<String, VariableDMC>());

+		private final Map<String, EnumeratorDMC> enumeratorsByName

+		  = Collections.synchronizedMap(new HashMap<String, EnumeratorDMC>());

+		private final Map<String, IVariable> thisPtrs

+		  = Collections.synchronizedMap(new LinkedHashMap<String, IVariable>());

+		private IFunctionScope functionScope;

+		private IFrameRegisters frameRegisters;

+		public StackFrameDMC calledFrame;

+		private TypeEngine typeEngine;

+		private IEDCModuleDMContext module;

+

+		// additional items may be null but are usually set early and used repeatedly

+		private IAddress instrPtrLinkAddr = null;

+		private IEDCSymbolReader reader = null;

+		private IModuleLineEntryProvider provider = null;

+		private IDebugInfoProvider debugInfoProvider = null;

+		private IPath symbolFile = null;

+

+		/**

+		 * @since 2.0

+		 */

+		@SuppressWarnings("unchecked")

+		public StackFrameDMC(final IEDCExecutionDMC executionDMC, EdcStackFrame edcFrame) {

+			super(Stack.this, new IDMContext[] { executionDMC }, createFrameID(executionDMC, edcFrame), edcFrame.props);

+			

+			Map<String, Object> frameProperties = edcFrame.props;

+			

+			this.executionDMC = executionDMC;

+			frameProperties.put(EXECUTION_DMC_ID, executionDMC.getID());

+

+			this.level = (Integer) frameProperties.get(LEVEL_INDEX);

+			this.moduleName = (String) frameProperties.get(MODULE_NAME);

+			this.baseAddress = address(frameProperties.get(BASE_ADDR));

+			this.instructionPtrAddress = address(frameProperties.get(INSTRUCTION_PTR_ADDR));

+

+			// compute the source location

+			IEDCSymbols symbolsService = getService(Symbols.class);

+			functionScope = symbolsService.getFunctionAtAddress(executionDMC.getSymbolDMContext(),

+																instructionPtrAddress);

+

+			boolean usingCachedProperties = false;

+			IEDCModules modules = dsfServicesTracker.getService(IEDCModules.class);

+			Map<IAddress, Map<String, Object>> cachedFrameProperties

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

+			if (modules != null) {

+				module = modules.getModuleByAddress(executionDMC.getSymbolDMContext(), instructionPtrAddress);

+				if (module != null) {

+					instrPtrLinkAddr = module.toLinkAddress(instructionPtrAddress);

+					reader = module.getSymbolReader();

+					if (reader != null) {

+						symbolFile = this.reader.getSymbolFile();

+						if (symbolFile != null) {

+							// Check the persistent cache

+							String cacheKey = reader.getSymbolFile().toOSString() + FRAME_PROPERTY_CACHE;

+							Map<IAddress, Map<String, Object>> cachedData

+							  = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class,

+									  											  reader.getModificationDate());

+							if (cachedData != null) {

+								cachedFrameProperties = cachedData;

+								Map<String, Object> cachedProperties

+								  = cachedFrameProperties.get(instrPtrLinkAddr);

+								if (cachedProperties != null) {

+									if (cachedProperties.containsKey(SOURCE_FILE))

+										frameProperties.put(SOURCE_FILE, cachedProperties.get(SOURCE_FILE));

+

+									boolean cachedPropertiesHasFunctionName = false;

+ 									if (cachedProperties.containsKey(FUNCTION_NAME)) {

+										Object fnObj = cachedProperties.get(FUNCTION_NAME);

+										if (fnObj != null 

+											&& fnObj instanceof String

+											&& ((String)fnObj).length() != 0) {

+											frameProperties.put(FUNCTION_NAME, fnObj);

+											cachedPropertiesHasFunctionName = true;

+									}	}

+

+									if (!cachedPropertiesHasFunctionName) {

+										setFunctionName(executionDMC, frameProperties, symbolsService);

+										cachedProperties.put(FUNCTION_NAME, functionName);

+									}

+

+									if (cachedProperties.containsKey(LINE_NUMBER))

+										frameProperties.put(LINE_NUMBER, cachedProperties.get(LINE_NUMBER));

+									usingCachedProperties = true;								

+			}	}	}	}	}	}	// null-checks on cachedProperties <= cachedData <= symbolFile

+

+			if (frameProperties.containsKey(SOURCE_FILE)) {

+				sourceFile   = (String) frameProperties.get(SOURCE_FILE);

+				functionName = (String) frameProperties.get(FUNCTION_NAME);

+				lineNumber   = (Integer) frameProperties.get(LINE_NUMBER);

+			} else if (frameProperties.containsKey(FUNCTION_NAME)) {

+				functionName = (String) frameProperties.get(FUNCTION_NAME);

+			} else if (!usingCachedProperties) {

+				ILineEntry line

+				  = symbolsService.getLineEntryForAddress(executionDMC.getSymbolDMContext(),

+														  instructionPtrAddress);

+				if (line != null)

+					setSourceProperties(frameProperties, line);

+			}

+			if (!usingCachedProperties || functionName == null || functionName.length() == 0)

+				setFunctionName(executionDMC, frameProperties, symbolsService);

+

+			properties.putAll(frameProperties);

+

+			if (symbolFile != null) {

+				String cacheKey = symbolFile.toOSString() + FRAME_PROPERTY_CACHE;

+				cachedFrameProperties.put(this.instrPtrLinkAddr, frameProperties);

+				EDCDebugger.getDefault().getCache().putCachedData(cacheKey,

+																  (Serializable)cachedFrameProperties,

+																  this.reader.getModificationDate());

+			}

+

+			if (reader instanceof EDCSymbolReader)

+				debugInfoProvider = ((EDCSymbolReader)reader).getDebugInfoProvider();

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

+		}

+

+		private void setFunctionName(final IEDCExecutionDMC executionDMC,

+				Map<String, Object> frameProperties, IEDCSymbols symbolsService) {

+			if (functionScope != null) {

+				// ignore inlined functions

+				IFunctionScope containerScope = functionScope;

+				while (containerScope.getParent() instanceof IFunctionScope) {

+					containerScope = (IFunctionScope) containerScope.getParent();

+				}

+				functionName = unmangle(containerScope.getName());

+				adjustFunctionSourceInfo(containerScope, frameProperties);

+			} else {

+				functionName

+				  = unmangle(symbolsService.getSymbolNameAtAddress(executionDMC.getSymbolDMContext(),

+						  										   instructionPtrAddress));

+			}

+

+			frameProperties.put(FUNCTION_NAME, functionName);

+		}

+

+		/**

+		 * Modify the name to refer to the inline function within the parent function.

+		 * <p>

+		 * However, ignore the inline function name if the pointer is on the first

+		 * line of the inline function and the "previous" line is

+		 * <br> (a) in the parent function; or

+		 * <br> (b) not in the original inline (meaning it was part of a prior inline); or 

+		 * <br> (c) is nested in another inline

+		 * @param container the ultimate function containing the inline(s)

+		 * @param frameProperties so source-file and line-number can also be adjusted

+		 */

+		private void adjustFunctionSourceInfo(IFunctionScope container,

+				Map<String, Object> frameProperties) {

+			if (functionScope.equals(container)) {

+				ILineEntry funcFirstEntry = this.getLineEntryInFunction(functionScope);

+				if (funcFirstEntry != null

+						&& !instrPtrLinkAddr.equals(funcFirstEntry.getLowAddress())) {

+					// this case covers the compiler having inline LNT entries

+					// whose bounds are outside the DWARF function scope boundaries

+					// for the inlines

+					setSourceProperties(frameProperties, funcFirstEntry);

+				}

+				return;		// i.e. never fall through to "inline" re-naming below

+			}

+

+			ILineEntry containerEntry = this.getLineEntryInFunction(container);

+			if (containerEntry != null && isInlineShouldBeHidden(containerEntry)) {

+				setSourceProperties(frameProperties, containerEntry);

+				return;

+			}

+

+			this.functionName

+			  = unmangle(functionScope.getName()) + " inlined in " + this.functionName;

+		}

+		

+		/**

+		 * Attempt to determine if the frame's instruction pointer is

+		 * <br>(a) at the first instruction of an inlined function; and

+		 * <br>(b) coincidentally at the first instruction of the line

+		 * entry corresponding to the line that caused the inline to

+		 * be generated.<p>

+		 * @param entry if null, will be calculated based on established

+		 * 			frame instruction pointer and function scope; can be passed

+		 * 			in if caller needs line entry for other usage

+		 * @return true if it can be determined that the instruction pointer is

+		 * 			the first instruction of an inline function and coincidentally the

+		 * 			first instruction of the line entry for which the inline was generated

+		 * @since 2.0

+		 */

+		public boolean isInlineShouldBeHidden(ILineEntry entry) {

+			if (functionScope == null

+					|| !(functionScope.getParent() instanceof IFunctionScope)

+					|| !instrPtrLinkAddr.equals(functionScope.getLowAddress()))

+				return false;

+

+			if (entry == null) {

+				entry = getLineEntryInFunction(functionScope);

+				if (entry == null)

+					return false;

+			}

+

+			if (instrPtrLinkAddr.equals(entry.getLowAddress())) {

+				ILineEntry prevEntry = getPreviousLineEntry(entry, true);

+				if (prevEntry != null) {

+					ILineEntry testEntry = getNextLineEntry(prevEntry, true);

+					if (entry.equals(testEntry)) {

+						return true;

+					}

+					return false;

+				}

+				return true;

+			}

+			return false;

+		}

+

+		/**

+		 * Private utility function to call the module's reader's provider's interfaces

+		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getLineEntryInFunction

+		 * @see IModuleScope#getModuleLineEntryProvider

+		 */

+		private ILineEntry getLineEntryInFunction(IFunctionScope func) {

+			return getModuleLineEntryProvider().getLineEntryInFunction(instrPtrLinkAddr, func);

+		}

+

+		/**

+		 * Private utility function to call the module's reader's provider's interfaces

+		 * @see IModuleScope#getModuleLineEntryProvider

+		 * @return {@link IModuleLineEntryProvider} never <code>null</code>

+		 */

+		private IModuleLineEntryProvider getModuleLineEntryProvider() {

+			if (provider == null && reader != null) {

+				IModuleScope moduleScope = reader.getModuleScope();

+				if (moduleScope != null)

+					provider = moduleScope.getModuleLineEntryProvider();			

+			}

+			return provider;

+		}

+

+		/**

+		 * Private utility function to call the module's reader's provider's interfaces

+		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getNextLineEntry

+		 * @see IModuleScope#getModuleLineEntryProvider

+		 */

+		private ILineEntry getNextLineEntry(ILineEntry entry, boolean collapseInlineFunctions) {

+			return getModuleLineEntryProvider().getNextLineEntry(entry, collapseInlineFunctions);

+		}					

+

+		/**

+		 * Private utility function to call the module's reader's provider's interfaces

+		 * @see org.eclipse.cdt.debug.edc.symbols.ILineEntryProvider#getPreviousLineEntry

+		 * @see IModuleScope#getModuleLineEntryProvider

+		 */

+		private ILineEntry getPreviousLineEntry(ILineEntry entry, boolean collapseInlineFunctions) {

+			return getModuleLineEntryProvider().getPreviousLineEntry(entry, collapseInlineFunctions);

+		}					

+

+		private void setSourceProperties(Map<String, Object> frameProperties,

+				ILineEntry entry) {

+			frameProperties.put(SOURCE_FILE, (sourceFile = entry.getFilePath().toOSString()));

+			frameProperties.put(LINE_NUMBER, (lineNumber = entry.getLineNumber()));

+		}

+

+		private String unmangle(String name) {

+			if (name == null)

+				return null;

+			

+			// unmangle the name

+			IUnmangler unmangler = null;

+			if (reader instanceof EDCSymbolReader) {

+				unmangler = ((EDCSymbolReader) reader).getUnmangler();

+			}

+			if (unmangler == null) {

+				unmangler = new UnmanglerEABI();

+			}

+			

+			if (!unmangler.isMangled(name))

+				return name;

+			

+			try {

+				return unmangler.unmangleWithoutArgs(name);

+			} catch (UnmanglingException e) {

+				return name;

+			}

+		}

+

+		private IAddress address(Object obj) {

+			if (obj instanceof Integer)

+				return new Addr64(obj.toString());

+			if (obj instanceof Long)

+				return new Addr64(obj.toString());

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

+				return new Addr64((String) obj, 16);

+			return null;

+		}

+

+		private void setInstructionPtrAddress(IAddress ipAddrPtr) {

+			this.instructionPtrAddress = ipAddrPtr;

+			if (module != null)

+				this.instrPtrLinkAddr = module.toLinkAddress(instructionPtrAddress);

+		}

+

+		public IFunctionScope getFunctionScope() {

+			return functionScope;

+		}

+

+		public String getModuleName() {

+			return moduleName;

+		}

+

+		/**

+		 * Get source file name if any for the frame. 

+		 * @return valid file name or "" otherwise.

+		 */

+		public String getSourceFile() {

+			return sourceFile;

+		}

+

+		public String getFunctionName() {

+			return functionName;

+		}

+

+		public int getLineNumber() {

+			return lineNumber;

+		}

+

+		public IEDCExecutionDMC getExecutionDMC() {

+			return executionDMC;

+		}

+

+		public IAddress getBaseAddress() {

+			return baseAddress;

+		}

+

+		/**

+		 * @since 2.0

+		 */

+		public IAddress getInstructionPtrAddress() {

+			return instructionPtrAddress;

+		}

+

+		public int getLevel() {

+			return level;

+		}

+

+		/**

+		 * @since 2.0

+		 */

+		public EDCServicesTracker getEDCServicesTracker() {

+			return Stack.this.getEDCServicesTracker();

+		}

+

+		public int compareTo(StackFrameDMC f) {

+			if (level < f.level)

+				return -1;

+			if (level > f.level)

+				return +1;

+			return 0;

+		}

+

+		

+		@Override

+		public String toString() {

+			return "StackFrameDMC [baseAddress=" + baseAddress.toHexAddressString() + ", ipAddress="

+					+ instructionPtrAddress.toHexAddressString() + ", sourceFile=" + sourceFile

+					+ ", functionName=" + functionName + ", lineNumber="

+					+ lineNumber + "]";

+		}

+

+		@Override

+		public int hashCode() {

+			final int prime = 31;

+			int result = super.hashCode();

+			result = prime * result + getOuterType().hashCode();

+			result = prime * result

+					+ ((baseAddress == null) ? 0 : baseAddress.hashCode());

+			result = prime * result

+					+ ((executionDMC == null) ? 0 : executionDMC.hashCode());

+			result = prime * result + level;

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

+

+			StackFrameDMC other = (StackFrameDMC) obj;

+			if (!getOuterType().equals(other.getOuterType()))

+				return false;

+

+			if (baseAddress == null) {

+				if (other.baseAddress != null)

+					return false;

+			} else if (!baseAddress.equals(other.baseAddress))

+				return false;

+

+			if (executionDMC == null) {

+				if (other.executionDMC != null)

+					return false;

+			} else if (!executionDMC.equals(other.executionDMC))

+				return false;

+

+			if (level != other.level)

+				return false;

+			return true;

+		}

+

+		/**

+		 * Finds a source file using the source lookup director.

+		 * 

+		 * @param sourceFile the raw source file location, usually from the symbol data

+		 * 

+		 * @return location of the source file

+		 */

+		private String findSourceFile(String sourceFile) {

+			String result = "";

+			CSourceLookup lookup = getService(CSourceLookup.class);

+			RunControl runControl = getService(RunControl.class);

+			CSourceLookupDirector[] directors = lookup.getSourceLookupDirectors(runControl.getRootDMC());

+

+			for (CSourceLookupDirector cSourceLookupDirector : directors) {

+				try {

+					Object[] elements = cSourceLookupDirector.findSourceElements(sourceFile);

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

+					{

+						Object element = elements[0];

+						if (element instanceof File) {

+							try {

+								result = (((File) element).getCanonicalPath());

+							} catch (IOException e) {

+								EDCDebugger.getMessageLogger().logError(null, e);

+							}

+						} else if (element instanceof IFile) {

+							result = (((IFile) element).getLocation().toOSString());

+						} else if (element instanceof IStorage) {

+							result = (((IStorage) element).getFullPath().toOSString());

+						} else if (element instanceof ITranslationUnit) {

+							result =(((ITranslationUnit) element).getLocation().toOSString());

+						}

+						break;

+					}			

+				} catch (CoreException e1) {

+					EDCDebugger.getMessageLogger().logError(sourceFile, e1);

+				}

+			}

+			return result;

+		}

+

+		/**

+		 * @since 2.0

+		 */

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

+			Element contextElement = document.createElement(STACK_FRAME);

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

+

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

+			contextElement.appendChild(propsElement);

+			// Locate the actual source file to be included in the album.

+			if (sourceFile.length() > 0) // No source file for this frame (just module/address)

+				album.addFile(new Path(findSourceFile(sourceFile)));

+			

+			IPath moduleFilePath = ((ModuleDMC)getModule()).getHostFilePath();

+			if (!moduleFilePath.isEmpty()) {

+				album.addFile(moduleFilePath);

+				IPath possibleSymFile = ExecutableSymbolicsReaderFactory.findSymbolicsFile(moduleFilePath);

+				if (possibleSymFile != null) {

+					album.addFile(possibleSymFile);

+				}

+			}

+

+			return contextElement;

+		}

+

+		@SuppressWarnings("unchecked")

+		public void loadSnapshot(Element element) {

+			// fix up registers to use integers again

+			Map<String, String> preservedRegisters = (Map<String, String>) properties.get(PRESERVED_REGISTERS);

+			if (preservedRegisters != null) {

+				Map<Integer, BigInteger> newPreservedRegisters = new HashMap<Integer, BigInteger>();

+				for (Map.Entry<String, String> entry : preservedRegisters.entrySet()) {

+					newPreservedRegisters.put(Integer.valueOf(entry.getKey().toString()), new BigInteger(entry.getValue().toString()));

+				}

+				properties.put(PRESERVED_REGISTERS, newPreservedRegisters);

+			}

+		}

+

+		public IVariableDMContext[] getLocals() {

+			return getLocals(/* boolean useCachedVariables => */ true);

+		}

+

+		synchronized private IVariableDMContext[] getLocals(boolean useCachedVariables) {

+			// may need to refresh the locals list because "Show All Variables"

+			// toggle has changed

+		    if (showAllVariablesEnabled == null) {

+				IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+		    	showAllVariablesEnabled = scope.getBoolean(IEDCSymbols.SHOW_ALL_VARIABLES_ENABLED, false);

+		    }

+

+			boolean enabled = showAllVariablesEnabled.booleanValue();

+			if (cachedLocals != null) {

+				IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID);

+				enabled = scope.getBoolean(IEDCSymbols.SHOW_ALL_VARIABLES_ENABLED, showAllVariablesEnabled);

+			}

+

+			if (cachedLocals == null || !useCachedVariables || enabled != showAllVariablesEnabled) {

+				showAllVariablesEnabled = enabled;

+				cachedLocals = new ArrayList<VariableDMC>();

+				localsByName.clear();

+				thisPtrs.clear();

+				IEDCSymbols symbolsService = getService(IEDCSymbols.class);

+				IFunctionScope scope = symbolsService

+						.getFunctionAtAddress(executionDMC.getSymbolDMContext(), instructionPtrAddress);

+				if (scope != null) {

+					this.variableScope = scope;

+				}

+				

+				while (scope != null && instrPtrLinkAddr != null) {

+					Collection<IVariable> scopedVariables = scope.getScopedVariables(instrPtrLinkAddr);

+					for (IVariable variable : scopedVariables) {

+						VariableDMC var = new VariableDMC(Stack.this, this, variable);

+						String name = variable.getName();

+						// because of inlined functions, debugger information may indicate that

+						// more than one "this" pointer is live at one time

+						if (name != null && name.equals("this")) {

+							thisPtrs.put(variable.getScope().getName(), variable);

+						} else {

+							// now that we've screened out compiler generated "this" variables,

+							// get rid of other compiler generated variables

+							// TODO: Allow user to choose whether to show compiler generated variables

+							if (var.getVariable().isDeclared()) {

+								VariableDMC haveLocal = localsByName.get(name);

+								if (haveLocal != null) {

+									localsByName.remove(name);

+									cachedLocals.remove(haveLocal);

+								}

+								cachedLocals.add(var);

+								localsByName.put(name, var);

+							}

+						}

+					}

+

+					// if requesting to show all variables, add file-scope globals too

+					// (this isn't nearly sufficient since globals can show up

+					// in a header while all code is in the source file)

+					IScope parentScope = null;

+					if (showAllVariablesEnabled)

+						parentScope = scope.getParent();

+					while (parentScope != null) {

+						if (parentScope instanceof ICompileUnitScope) {

+							ICompileUnitScope cuScope = ((ICompileUnitScope) parentScope);

+

+							List<ICompileUnitScope> cuScopes = null;

+							if (this.debugInfoProvider != null) {

+								cuScopes = debugInfoProvider.getCompileUnitsForFile(cuScope.getFilePath());

+							} else {

+								cuScopes = new ArrayList<ICompileUnitScope>(1);

+								cuScopes.add(cuScope);

+							}

+

+							// add the globals of all compile unit scopes for the source file

+							String cuFile = ((ICompileUnitScope) parentScope).getFilePath().toOSString();

+							for (ICompileUnitScope nextCuScope : cuScopes) {

+								Collection<IVariable> globals = nextCuScope.getVariables();

+								if (globals != null) {

+									for (IVariable variable : globals) {

+										IPath varFile = variable.getDefiningFile();

+										if (varFile != null && !varFile.toOSString().equalsIgnoreCase(cuFile))

+											continue;

+

+										VariableDMC var = new VariableDMC(Stack.this, this, variable);

+										String name = var.getName();

+										VariableDMC haveLocal = localsByName.get(name);

+										if (haveLocal != null) {

+											localsByName.remove(name);

+											cachedLocals.remove(haveLocal);

+										}

+										cachedLocals.add(var);

+										localsByName.put(name, var);

+									}

+								}

+							}

+						}

+						parentScope = parentScope.getParent();

+					}

+					

+					if (!(scope.getParent() instanceof IFunctionScope))

+						break;

+					scope = (IFunctionScope) scope.getParent();

+				}

+			}

+			

+			// start with "this" pointers, if any

+			VariableDMC[] localsArray = new VariableDMC[(thisPtrs.isEmpty() ? 0 : 1) + cachedLocals.size()];

+			int i = 0;

+			if (!thisPtrs.isEmpty())

+				localsArray[i++] = new VariableDMC(Stack.this, this, getOuterThis());

+			// TODO For now, turn off ability to see multiple this pointers

+			// of the form "this$ScopeName"

+//			for (IVariable variable : thisPtrs.values()) {

+//				VariableDMC var = new VariableDMC(Stack.this, this, variable);

+//				var.setName("this$" + variable.getScope().getName());

+//				localsArray[i++] = var;

+//			}

+			for (VariableDMC var : cachedLocals)

+				localsArray[i++] = var;

+			return localsArray;

+		}

+		

+		/**

+		 * From a list of "this" pointers in scope, return the one from the outermost scope

+		 * @return this pointer from the outermost scope

+		 */

+		private IVariable getOuterThis() {

+			if (thisPtrs.isEmpty())

+				return null;

+			

+			if (thisPtrs.size() == 1)

+				return thisPtrs.values().iterator().next();

+

+			IVariable outer = null;

+			for (IVariable variable : thisPtrs.values()) {

+				if (outer == null)

+					outer = variable;

+				else {

+					IScope outerScope    = outer.getScope();

+					IScope variableScope = variable.getScope();

+					if (   variableScope.getLowAddress().compareTo(outerScope.getLowAddress()) < 0

+						|| variableScope.getHighAddress().compareTo(outerScope.getHighAddress()) > 0)

+						outer = variable;

+				}

+			}

+			return outer;

+		}

+

+

+		/**

+		 * Find a variable or enumerator by name

+		 * 

+		 * @param name required name of the variable or enumerator

+		 * @param qualifiedName optional fully qualified name of the variable or enumerator

+		 * @param localsOnly whether to restrict search to local variables and enumerators only

+		 * @return variable or enumerator, if found; otherwise, null

+		 * @since 2.0

+		 */

+		synchronized public IVariableEnumeratorContext findVariableOrEnumeratorByName(String name, String qualifiedName, boolean localsOnly) {

+			if (name == null)

+				return null;

+

+			getLocals(); // This will ensure that localsByName is good

+

+			// quickly check for a local variable or enumerator

+			IVariableEnumeratorContext variableOrEnumerator;

+			

+			if (qualifiedName != null) {

+				variableOrEnumerator = localsByName.get(qualifiedName);

+				if (variableOrEnumerator != null)

+					return variableOrEnumerator;

+			}

+

+			variableOrEnumerator = localsByName.get(name);

+			if (variableOrEnumerator != null)

+				return variableOrEnumerator;

+

+			getEnumerators();

+			

+			if (qualifiedName != null) {

+				variableOrEnumerator = enumeratorsByName.get(qualifiedName);

+				if (variableOrEnumerator != null)

+					return variableOrEnumerator;

+			}

+			

+			variableOrEnumerator = enumeratorsByName.get(name);

+			if (variableOrEnumerator != null)

+				return variableOrEnumerator;

+			

+			if (name.equals("this")) {

+				if (thisPtrs.isEmpty())

+					return null;

+				return new VariableDMC(Stack.this, this, getOuterThis());

+			}

+

+			// TODO For now, turn off ability to see multiple this pointers

+			// of the form "this$ScopeName"

+//			if (name.startsWith("this$")) {

+//				// return the one with the right scope

+//				if (thisPtrs.isEmpty())

+//					return null;

+//				IVariable variable = thisPtrs.get(name.substring("this$".length()));

+//				if (variable == null)

+//					return null;

+//				return new VariableDMC(Stack.this, this, variable);

+//			}

+

+			if (localsOnly || this.getVariableScope() == null)

+				return null;

+

+			// if there is no local variable or enumerator with this name, not very

+			// efficiently check enclosing scopes for a variable or enumerator

+			IScope variableScope = this.getVariableScope().getParent();

+

+			// to find file scope variables, we may need to check several compile units

+			// associated with one file

+			ArrayList<IScope> scopes = new ArrayList<IScope>();

+

+			while (variableOrEnumerator == null && variableScope != null) {

+				// At the module level, match against globals across the entire symbol

+				// file, even for big symbol files.

+				if (variableScope instanceof IModuleScope) {

+					Collection<IVariable> variables = ((IModuleScope)variableScope).getVariablesByName(qualifiedName != null ? qualifiedName : name, true);

+					if (variables != null && variables.size() > 0) {

+						// list may contain non-global variables, so return the first global

+						for (Object varObject : variables) {

+							if (varObject instanceof IVariable) {

+								IVariable variable = (IVariable)varObject;

+								if (variable.getScope() instanceof IModuleScope) {

+									variableOrEnumerator = new VariableDMC(Stack.this, this, variable);

+									break;

+								}

+							}

+						}

+					}

+					// module scope has no matching global variables

+					break;

+				}

+

+				scopes.clear();

+

+				if (variableScope instanceof ICompileUnitScope) {

+					// there may be several compile units for a file

+

+					// find the module scope parent of the compile unit

+					IScope parent = variableScope.getParent();

+					while (parent != null && !(parent instanceof IModuleScope))

+						parent = parent.getParent();

+

+					// find all compile units for the file

+					if (parent != null) {

+						IPath currentFile = ((ICompileUnitScope)variableScope).getFilePath();

+						if (currentFile != null)

+							for (ICompileUnitScope cu : ((IModuleScope)parent).getCompileUnitsForFile(currentFile))

+								scopes.add(cu);

+					}

+				}

+

+				if (scopes.isEmpty())

+					scopes.add(variableScope);

+

+				for (IScope scope : scopes) {

+					for (IVariable scopeVariable : scope.getVariables()) {

+						String scopeVariableName = scopeVariable.getName();

+						if (qualifiedName != null && scopeVariableName.equals(qualifiedName)) {

+							variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);

+							break;

+						}

+

+						if (scopeVariableName.equals(name)) {

+							variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);

+							break;

+						}

+					}

+

+					if (variableOrEnumerator == null && scope instanceof IFunctionScope) {

+						IFunctionScope functionScope = (IFunctionScope)scope;

+						for (IVariable scopeVariable : functionScope.getParameters()) {

+							String scopeVariableName = scopeVariable.getName();

+							if (qualifiedName != null && scopeVariableName.equals(qualifiedName)) {

+								variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);

+								break;

+							}

+

+							if (scopeVariableName.equals(name)) {

+								variableOrEnumerator = new VariableDMC(Stack.this, this, scopeVariable);

+								break;

+							}

+						}

+					}

+

+					if (variableOrEnumerator == null) {

+						for (IEnumerator scopeEnumerator : scope.getEnumerators()) {

+							String scopeEnumeratorName = scopeEnumerator.getName();

+							if (qualifiedName != null && scopeEnumeratorName.equals(qualifiedName)) {

+								variableOrEnumerator = new EnumeratorDMC(this, scopeEnumerator);

+								break;

+							}

+

+							if (scopeEnumeratorName.equals(name)) {

+								variableOrEnumerator = new EnumeratorDMC(this, scopeEnumerator);

+								break;

+							}

+						}

+					}

+				}

+

+				variableScope = variableScope.getParent();

+			}

+			

+			return variableOrEnumerator;

+		}

+		

+		public IScope getVariableScope() {

+			return variableScope;

+		}

+

+		synchronized public EnumeratorDMC[] getEnumerators() {

+			if (cachedEnumerators == null) {

+				cachedEnumerators = new ArrayList<EnumeratorDMC>();

+				if (getServicesTracker() != null) {

+					IEDCSymbols symbolsService = getService(Symbols.class);

+					if (executionDMC != null && symbolsService != null) {

+						IFunctionScope scope = symbolsService.getFunctionAtAddress(executionDMC.getSymbolDMContext(),

+								instructionPtrAddress);

+						while (scope != null) {

+							Collection<IEnumerator> localEnumerators = scope.getEnumerators();

+							for (IEnumerator enumerator : localEnumerators) {

+								EnumeratorDMC enumeratorDMC = new EnumeratorDMC(this, enumerator);

+								cachedEnumerators.add(enumeratorDMC);

+								enumeratorsByName.put(enumerator.getName(), enumeratorDMC);

+							}

+							if (!(scope.getParent() instanceof IFunctionScope))

+								break;

+							scope = (IFunctionScope) scope.getParent();

+						}

+					}

+				}

+			}

+			return cachedEnumerators.toArray(new EnumeratorDMC[cachedEnumerators.size()]);

+		}

+

+		public EnumeratorDMC findEnumeratorbyName(String name) {

+			getEnumerators();

+			return enumeratorsByName.get(name);

+		}

+		

+		/**

+		 * Get the view onto registers for this stack frame.  For the top stack frame, this

+		 * forwards to the {@link Registers} service.  Otherwise, this information

+		 * is synthesized from unwind information in the debug information.  

+		 * @return {@link IFrameRegisters}, never <code>null</code>

+		 */

+		@SuppressWarnings("unchecked")

+		public IFrameRegisters getFrameRegisters() {

+			if (frameRegisters == null) {

+				if (level == 0) {

+					// for top of stack, the registers service does the work

+					final Registers registers = getEDCServicesTracker().getService(Registers.class);

+					frameRegisters = new CurrentFrameRegisters(executionDMC, registers);

+				} else {

+					// see if symbolics can provide unwinding support

+					if (module != null) {

+						Symbols symbolsService = getService(Symbols.class);

+						IFrameRegisterProvider frameRegisterProvider = symbolsService.getFrameRegisterProvider(

+								executionDMC.getSymbolDMContext(), instructionPtrAddress);

+						if (frameRegisterProvider != null) {

+							try {

+								frameRegisters = frameRegisterProvider.getFrameRegisters(

+										getSession(), getEDCServicesTracker(), this);

+							} catch (CoreException e) {

+								// debug info failure; we should report this 

+								frameRegisters = new AlwaysFailingFrameRegisters(e);

+							}

+						}

+					}

+					

+					if (frameRegisters == null) {

+						// no information from symbolics; see if the stack unwinder found anything

+						final Map<Integer, BigInteger> preservedRegisters = (Map<Integer,BigInteger>) properties.get(

+								PRESERVED_REGISTERS);

+						if (preservedRegisters != null) {

+							frameRegisters = new PreservedFrameRegisters(dsfServicesTracker, StackFrameDMC.this, preservedRegisters);

+						}

+					}

+					

+					if (frameRegisters == null) {

+						frameRegisters = new AlwaysFailingFrameRegisters(

+								EDCDebugger.newCoreException("cannot read variables in this frame"));

+					}

+				}

+			}

+			return frameRegisters;

+		}

+

+		/**

+		 * Get the frame this one has called.

+		 * @return StackFrameDMC or <code>null</code> for top of stack

+		 */

+		public StackFrameDMC getCalledFrame() throws CoreException {

+			return calledFrame;

+		}

+

+		/**

+		 * Get a type engine (which holds cached information about types for use by expressions)

+		 * @return TypeEngine instance

+		 */

+		public TypeEngine getTypeEngine() {

+			return typeEngine;

+		}

+		

+		public IEDCModuleDMContext getModule() {

+			return module;

+		}

+

+		private Stack getOuterType() {

+			return Stack.this;

+		}

+		

+	}

+

+	public class VariableData implements IVariableDMData {

+

+		private final String name;

+

+		public VariableData(VariableDMC variableDMC) {

+			name = variableDMC.getName();

+		}

+

+		public String getName() {

+			return name;

+		}

+

+		/**

+		 * was initially implemented as "0".

+		 * currently returns null to guarantee anything calling this

+		 * knows it's getting a useless bit of data.

+		 * @see org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData#getValue()

+		 */

+		public String getValue() {

+			// TODO not implemented

+			return null;

+		}

+

+	}

+

+	public class VariableDMC extends DMContext implements IVariableDMContext, IVariableEnumeratorContext {

+

+		public static final String PROP_LOCATION = "Location";

+		private IVariable variable;

+

+		public VariableDMC(IDsfService service, StackFrameDMC frame, IVariable variable) {

+			super(Stack.this, new IDMContext[] { frame }, variable.getName(), variable.getName());

+			this.variable = variable;

+		}

+

+		public IVariable getVariable() {

+			return variable;

+		}

+

+		/**

+		 * @since 3.0

+		 */

+		public void setVariable(IVariable variable) {

+			this.variable = variable;

+		}

+	}

+

+	public class EnumeratorDMC extends DMContext implements IEnumeratorDMContext, IVariableEnumeratorContext {

+

+		private final IEnumerator enumerator;

+

+		public EnumeratorDMC(StackFrameDMC frame, IEnumerator enumerator) {

+			super(Stack.this, new IDMContext[] { frame }, enumerator.getName(), enumerator.getName());

+			this.enumerator = enumerator;

+		}

+

+		public IEnumerator getEnumerator() {

+			return enumerator;

+		}

+	}

+

+	/**

+	 * @param classNames

+	 *            the type names the service will be registered under. See

+	 *            AbstractDsfService#register for details. We tack on base DSF's

+	 *            IStack and this class to the list if not provided.

+	 */

+	public Stack(DsfSession session, String[] classNames) {

+		super(session, 

+				massageClassNames(classNames, 

+						new String[] { IStack.class.getName(), Stack.class.getName() }));

+	}

+

+	/**

+	 * @since 2.0

+	 */

+	public static String createFrameID(IEDCExecutionDMC executionDMC, EdcStackFrame edcFrame) {

+		int level = (Integer) edcFrame.props.get(StackFrameDMC.LEVEL_INDEX);

+		String parentID = executionDMC.getID();

+		return parentID + ".frame[" + level + "]";

+	}

+

+	@Override

+	protected void doInitialize(RequestMonitor requestMonitor) {

+		super.doInitialize(requestMonitor);

+		getSession().addServiceEventListener(this, null);

+	}

+

+	public void getArguments(IFrameDMContext frameCtx, DataRequestMonitor<IVariableDMContext[]> rm) {

+		// never called by DSF. it expects arguments to be lumped in with

+		// locals.

+		rm.done();

+	}

+

+	public void getFrameData(IFrameDMContext frameDmc, DataRequestMonitor<IFrameDMData> rm) {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(frameDmc)); }

+		rm.setData(new StackFrameData((StackFrameDMC) frameDmc));

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }

+		rm.done();

+	}

+

+	public void getFrames(final IDMContext execContext, final DataRequestMonitor<IFrameDMContext[]> rm) {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(execContext)); }

+

+		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(execContext, ExecutionDMC.class);

+		if (execDmc != null)

+		{

+			if (!execDmc.isSuspended())

+			{

+				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$

+				rm.done();

+				return;

+			}

+			

+			asyncExec(new Runnable() {

+				public void run() {

+					try {

+						rm.setData(getFramesForDMC((ExecutionDMC) execContext, 0, ALL_FRAMES));

+						if (rm.getData().length == 0)

+							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execDmc, null)); //$NON-NLS-1$

+					} catch (CoreException e) {

+						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);

+						EDCDebugger.getMessageLogger().log(s);

+						rm.setStatus(s);

+					}

+					if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }

+					rm.done();

+				}

+				

+			}, rm);

+

+		}

+		else {

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$

+			rm.done();

+		}

+	}

+

+	public void getLocals(final IFrameDMContext frameCtx, final DataRequestMonitor<IVariableDMContext[]> rm) {

+		asyncExec(new Runnable() {

+			public void run() {

+				final StackFrameDMC frameContext = (StackFrameDMC) frameCtx;

+				IAddress contextIPAddress = frameContext.getInstructionPtrAddress();

+				boolean useVariableCache = false;

+				// the frame context passed in may be "stale".  it may prove equal to the current frame,

+				// but if the instruction ptr address is different, then the locals won't be collected properly

+				try {

+					IFrameDMContext[] iFrames

+					  = getFramesForDMC(frameContext.getExecutionDMC(), 0, REFRESH_CACHED_FRAMES);

+					for (IFrameDMContext iFrameDMC : iFrames) {

+						if (frameCtx == iFrameDMC) {

+							useVariableCache = true;

+							break;

+						}

+						if (frameContext.equals(iFrameDMC)) {

+							StackFrameDMC frameDMC = (StackFrameDMC)iFrameDMC;

+							IAddress stackFrameIPAddr = frameDMC.getInstructionPtrAddress(); 

+							if (contextIPAddress.equals(stackFrameIPAddr)) {

+								useVariableCache = true;

+							} else {

+								frameContext.setInstructionPtrAddress(stackFrameIPAddr);

+							}

+							break;

+						}

+					}

+

+					rm.setData(frameContext.getLocals(useVariableCache));

+				} catch (CoreException e) {

+					EDCDebugger.getMessageLogger().log(e.getStatus());

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

+				}

+				rm.done();

+			}

+		}, rm);

+	}

+

+	public void getStackDepth(IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { dmc, maxDepth })); }

+		

+		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(dmc, ExecutionDMC.class);

+		if (execDmc != null)

+		{

+			if (!execDmc.isSuspended())

+			{

+				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$

+				rm.done();

+				return;

+			}

+

+			asyncExec(new Runnable() {

+				public void run() {

+					int startFrame = 0;

+					int endFrame = ALL_FRAMES;	

+					if (maxDepth > 0)

+						endFrame = maxDepth - 1;

+					try {

+						rm.setData(getFramesForDMC(execDmc, startFrame, endFrame).length);

+						if (rm.getData() == 0)

+							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execDmc, null)); //$NON-NLS-1$

+						if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, rm.getData()); }

+					} catch (CoreException e) {

+						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);

+						EDCDebugger.getMessageLogger().log(s);

+						rm.setStatus(s);

+					}

+					rm.done();

+				}

+			}, rm);

+		}

+		else {

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$

+			rm.done();

+		}

+	}

+

+	public void getTopFrame(final IDMContext execContext, final DataRequestMonitor<IFrameDMContext> rm) {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(execContext)); }

+

+		asyncExec(new Runnable() {

+			public void run() {

+				try {

+					IFrameDMContext[] frames = getFramesForDMC((ExecutionDMC) execContext, 0, 0);

+					if (frames.length == 0) {

+						rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE,

+								"No top stack frame available", null)); //$NON-NLS-1$

+						rm.done();

+						return;

+					}

+					rm.setData(frames[0]);

+				} catch (CoreException e) {

+					Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);

+					EDCDebugger.getMessageLogger().log(s);

+					rm.setStatus(s);

+				}

+				if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArg(rm.getData())); }

+				rm.done();

+			}

+		}, rm);

+

+	}

+

+	public void getVariableData(IVariableDMContext variableDmc, DataRequestMonitor<IVariableDMData> rm) {

+		rm.setData(new VariableData((VariableDMC) variableDmc));

+		rm.done();

+	}

+

+	@SuppressWarnings("unchecked")

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

+		if (dmc instanceof IFrameDMContext) {

+			getFrameData((IFrameDMContext) dmc, (DataRequestMonitor<IFrameDMData>) rm);

+		} else if (dmc instanceof IVariableDMContext) {

+			getVariableData((IVariableDMContext) dmc, (DataRequestMonitor<IVariableDMData>) rm);

+		} else

+			rm.done();

+	}

+

+	/* (non-Javadoc)

+	 * @see org.eclipse.cdt.dsf.debug.service.IStack#getFrames(org.eclipse.cdt.dsf.datamodel.IDMContext, int, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)

+	 */

+	public void getFrames(final IDMContext execContext, final int startIndex, final int endIndex, final DataRequestMonitor<IFrameDMContext[]> rm) {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { execContext, startIndex, endIndex })); }

+		final ExecutionDMC execDmc = DMContexts.getAncestorOfType(execContext, ExecutionDMC.class);

+		if (execDmc != null)

+		{

+			if (!execDmc.isSuspended())

+			{

+				rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "Context is running: " + execDmc, null)); //$NON-NLS-1$

+				rm.done();

+				return;

+			}

+

+			asyncExec(new Runnable() {

+				public void run() {

+					try {

+						rm.setData(getFramesForDMC((ExecutionDMC) execContext, startIndex, endIndex));

+						if (rm.getData().length == 0)

+							rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_STATE, "No stack frame available for: " + execContext, null)); //$NON-NLS-1$

+					} catch (CoreException e) {

+						Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), null, e);

+						EDCDebugger.getMessageLogger().log(s);

+						rm.setStatus(s);

+					}

+					if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(rm.getData())); }

+					rm.done();

+				}

+				

+			}, rm);

+

+		}

+		else {

+			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$

+			rm.done();

+		}

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(rm.getData())); }

+	}

+

+	/**

+	 * This is loosely based on the concept provided by the pref acquired in

+	 * {@link org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode#getStackFrameLimit}

+	 * However, that code is not referred to by this method because the

+	 * plugin org.eclipse.cdt.debug.edc is designed not to depend upon

+	 * any UI code.  (and that's why you can't click through to the

+	 * javadoc for that link above.)

+	 * <p>

+	 * Fortunately, the value returned from that function is normally

+	 * eventually passed down to getFramesForDMC() early in the process

+	 * of performing stack-crawl.

+	 * <p>

+	 * This private function is designed to take advantage of that,

+	 * and it should to be called only when it is desired to

+	 * {@link #REFRESH_CACHED_FRAMES} when performing

+	 * {@link #getLocals(IFrameDMContext, DataRequestMonitor)}.

+	 *

+	 * @param context

+	 * @param endIndex to help ensure this is called only under proper circumstances

+	 * @return a limit based upon a value cached during previous stack crawl for this context

+	 */

+	private int getPreviousStackFrameLimit(IEDCExecutionDMC context, int endIndex) {

+		if (endIndex != REFRESH_CACHED_FRAMES)	// the guarantee

+			return endIndex;

+

+		Integer previousMax = lastMaxFrameInContextCache.get(context);

+

+		assert previousMax != null : "order of calls to getFramesForDMC should prevent this.";

+

+		if (previousMax != null)

+			return previousMax;

+

+		// as the assert above indicates, control shouldn't get this far.

+		// but provide a couple of fallbacks just in case.

+		

+		// first fallback: get any previousMax, since it will likely be something

+		// close to what the user set and/or last retrieved for a similar context.

+		if (!lastMaxFrameInContextCache.isEmpty())

+			return ((Integer[])lastMaxFrameInContextCache.values().toArray())[0];

+

+		// final fallback: something relatively sane to prevent the appearance of

+		// a hung Debug/Stack view that can occur when creating a stack-crawl for

+		// an execution context being accessed for the first time which happens

+		// to be in a state of relative runaway recursion on the target.

+		return 128;

+	}

+

+	public IFrameDMContext[] getFramesForDMC(IEDCExecutionDMC context,

+			int startIndex, int endIndex) throws CoreException {

+		if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArgs(new Object[] { context, startIndex, endIndex })); }

+

+		if (!context.isSuspended() || !RunControl.isNonContainer(context))

+			// no frames for container context.

+			return new IFrameDMContext[0];

+

+		boolean needsUpdate;

+		synchronized (stackFrames) {

+			List<StackFrameDMC> frames = stackFrames.get(context.getID());

+			// Need to update the frames if there is no cached list for this

+			// context or if the cached list does not include all of the

+			// requested frames.

+			if (frames == null) {

+				// nothing in the cache so need to update

+				needsUpdate = true;

+				endIndex = getPreviousStackFrameLimit(context, endIndex);

+			} else if (allFramesCached.containsKey(context.getID()) && allFramesCached.get(context.getID())) {

+				// all frames are cached

+				needsUpdate = false;

+			} else if (endIndex == ALL_FRAMES) {

+				// some but not all frames cached

+				needsUpdate = true;

+			} else if (endIndex == REFRESH_CACHED_FRAMES) {

+				// update only already cached frames for local variable retrieval

+				needsUpdate = true;

+				endIndex = frames.get(frames.size() - 1).getLevel();

+			} else {

+				// some but not all requested frames cached

+				needsUpdate = (frames.get(0).getLevel() > startIndex

+								|| frames.get(frames.size() - 1).getLevel() < endIndex);

+			}

+

+			if (needsUpdate)

+				updateFrames(context, startIndex, endIndex);

+

+			frames = stackFrames.get(context.getID());

+			// endIndex is inclusive and may be negative to fetch all frames

+			if (endIndex >= 0) {

+				int frameCount = frames.size();

+				if (startIndex < frameCount && startIndex <= endIndex)

+					frames = frames.subList(startIndex, Math.min(endIndex + 1, frameCount));

+				else

+					frames = Collections.emptyList();

+				if (needsUpdate && endIndex >= 0)

+					lastMaxFrameInContextCache.put(context, Math.min(endIndex + 1, frameCount));

+			}

+			IFrameDMContext[] result = frames.toArray(new IFrameDMContext[frames.size()]);

+			if (EDCTrace.STACK_TRACE_ON) { EDCTrace.getTrace().traceExit(null, EDCTrace.fixArgs(result)); }

+			return result;

+		}

+	}

+

+	private void updateFrames(IEDCExecutionDMC context, int startIndex, int endIndex) throws CoreException {

+		ArrayList<StackFrameDMC> frames = new ArrayList<StackFrameDMC>();

+		List<EdcStackFrame> edcFrames = computeStackFrames(context, startIndex, endIndex);

+		StackFrameDMC previous = null;

+		for (EdcStackFrame edcFrame : edcFrames) {

+			StackFrameDMC frame = new StackFrameDMC(context, edcFrame);

+			if (previous != null) {

+				frame.calledFrame = previous;

+				// note: don't store "callerFrame" since this is missing if only a partial stack was fetched

+			}

+			frames.add(frame);

+			previous = frame;

+		}

+		

+		stackFrames.put(context.getID(), frames);

+		

+		// all frames are cached if we request all frames, or if the returned number of frames was less than

+		// the requested max number of frames.  e.g. if we ask for 10 and they return 9, it's because there

+		// are only 9 frames.  so we have calculated all of them.

+		allFramesCached.put(context.getID(), startIndex == 0 && ((endIndex == ALL_FRAMES) || (frames.size() <= endIndex)));

+	}

+

+	/**

+	 * A stack frame described as one or more of the following properties, plus

+	 * any additional custom ones.

+	 * 

+	 * <ul>

+	 * <li>{@link StackFrameDMC#LEVEL_INDEX}

+	 * <li>{@link StackFrameDMC#ROOT_FRAME}

+	 * <li>{@link StackFrameDMC#BASE_ADDR}

+	 * <li>{@link StackFrameDMC#INSTRUCTION_PTR_ADDR}

+	 * <li>{@link StackFrameDMC#MODULE_NAME}

+	 * <li>{@link StackFrameDMC#SOURCE_FILE}

+	 * <li>{@link StackFrameDMC#FUNCTION_NAME}

+	 * <li>{@link StackFrameDMC#LINE_NUMBER}

+	 * <li>{@link StackFrameDMC#IN_PROLOGUE}

+	 * <li>{@link StackFrameDMC#PRESERVED_REGISTERS}

+	 * </ul>

+	 * 

+	 * @since 2.0

+	 */

+	public class EdcStackFrame {

+		public EdcStackFrame(Map<String, Object> props) { 

+			this.props = props; 

+		}

+		public Map<String, Object> props;

+	}

+	

+	protected abstract List<EdcStackFrame> computeStackFrames(IEDCExecutionDMC context, int startIndex, int endIndex) throws CoreException;

+

+	public void loadFramesForContext(IEDCExecutionDMC exeDmc, Element allFrames) throws Exception {

+		flushCache(null);

+		List<StackFrameDMC> frames = Collections.synchronizedList(new ArrayList<StackFrameDMC>());

+

+		NodeList frameElements = allFrames.getElementsByTagName(STACK_FRAME);

+

+		int numFrames = frameElements.getLength();

+		StackFrameDMC previousFrameDMC = null;

+		

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

+			Element groupElement = (Element) frameElements.item(i);

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

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

+			SnapshotUtils.initializeFromXML(propElement, properties);

+

+			// ensure that stack level numbering is canonical: 

+			// we expect level==0 to be the top, but it used to be 1

+			properties.put(StackFrameDMC.LEVEL_INDEX, i);

+			

+			StackFrameDMC frameDMC = new StackFrameDMC(exeDmc, new EdcStackFrame(properties));

+			frameDMC.loadSnapshot(groupElement);

+			if (previousFrameDMC != null) {

+				frameDMC.calledFrame = previousFrameDMC;

+			}

+			frames.add(frameDMC);

+

+			previousFrameDMC = frameDMC;

+		}

+		stackFrames.put(exeDmc.getID(), frames);

+		allFramesCached.put(exeDmc.getID(), true);

+	}

+

+	public void flushCache(IDMContext context) {

+		if (isSnapshot())

+			return;

+		if (context != null && context instanceof IEDCDMContext) {

+			String contextID = ((IEDCDMContext) context).getID();

+			stackFrames.remove(contextID);

+			allFramesCached.remove(contextID);

+		} else {

+			stackFrames.clear();

+			allFramesCached.clear();

+		}

+	}

+

+	@DsfServiceEventHandler

+	public void eventDispatched(ISuspendedDMEvent e) {

+		flushCache(e.getDMContext());

+	}

+

+	@DsfServiceEventHandler

+	public void eventDispatched(IResumedDMEvent e) {

+		flushCache(e.getDMContext());

+	}

+

+}

diff --git a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/symbols/IVariable.java b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/symbols/IVariable.java
index 0741195..9ac5413 100644
--- a/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/symbols/IVariable.java
+++ b/org.eclipse.cdt.debug.edc/src/org/eclipse/cdt/debug/edc/symbols/IVariable.java
@@ -1,83 +1,92 @@
-/*******************************************************************************
- * 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.symbols;
-
-import org.eclipse.cdt.debug.edc.internal.symbols.ILexicalBlockScope;
-import org.eclipse.core.runtime.IPath;
-
-/**
- * Interface representing a variable or parameter.
- */
-public interface IVariable {
-
-	/**
-	 * Get the name of the variable
-	 * 
-	 * @return the variable name
-	 */
-	String getName();
-
-	/**
-	 * Get the scope that the variable belongs to
-	 * 
-	 * @return the variable scope
-	 */
-	IScope getScope();
-
-	/**
-	 * Get the type of the variable
-	 * 
-	 * @return the variable type
-	 */
-	IType getType();
-
-	/**
-	 * Get the location provider for the variable
-	 * 
-	 * @return the location provider
-	 */
-	ILocationProvider getLocationProvider();
-
-	/**
-	 * A variable's lifetime may start somewhere inside its parent scope (without being
-	 * inside an {@link ILexicalBlockScope}).  This provides the offset from the
-	 * start address of the parent scope at which time the variable is considered
-	 * live.
-	 * <p>
-	 * This scope may be narrower than the scope implied by {@link ILocationProvider#isLocationKnown(org.eclipse.cdt.core.IAddress)}.
-	 * <p>
-	 * Note: a variable is always considered to be live until the end of the parent scope.
-	 * @return offset in bytes (0 means the lifetime is the same as the parent scope)
-	 */
-	long getStartScope();
-	
-	/**
-	 * Whether a variable was explicitly declared in the source, rather than generated
-	 * by a tool such as a compiler
-	 *  
-	 * @return whether the variable was explicitly declared 
-	 * @since 2.0
-	 */
-	boolean isDeclared();
-	
-	/**
-	 * Get the path of the file in which this variable is defined
-	 *  
-	 * @return file in which this variable is defined, or null if unknown
-	 * @since 2.0
-	 */
-	IPath getDefiningFile();
-
-	/**
-	 * 
-	 */
-	void dispose();
-}
+/*******************************************************************************

+ * 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.symbols;

+

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

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

+

+/**

+ * Interface representing a variable or parameter.

+ */

+public interface IVariable {

+

+	/**

+	 * Get the name of the variable

+	 * 

+	 * @return the variable name

+	 */

+	String getName();

+

+	/**

+	 * Get the scope that the variable belongs to

+	 * 

+	 * @return the variable scope

+	 */

+	IScope getScope();

+

+	/**

+	 * Get the type of the variable

+	 * 

+	 * @return the variable type

+	 */

+	IType getType();

+

+	/**

+	 * Get the location provider for the variable

+	 * 

+	 * @return the location provider

+	 */

+	ILocationProvider getLocationProvider();

+

+	/**

+	 * A variable's lifetime may start somewhere inside its parent scope (without being

+	 * inside an {@link ILexicalBlockScope}).  This provides the offset from the

+	 * start address of the parent scope at which time the variable is considered

+	 * live.

+	 * <p>

+	 * This scope may be narrower than the scope implied by {@link ILocationProvider#isLocationKnown(org.eclipse.cdt.core.IAddress)}.

+	 * <p>

+	 * Note: a variable is always considered to be live until the end of the parent scope.

+	 * @return offset in bytes (0 means the lifetime is the same as the parent scope)

+	 */

+	long getStartScope();

+	

+	/**

+	 * Whether a variable was explicitly declared in the source, rather than generated

+	 * by a tool such as a compiler

+	 *  

+	 * @return whether the variable was explicitly declared 

+	 * @since 2.0

+	 */

+	boolean isDeclared();

+	

+	/**

+	 * Get the path of the file in which this variable is defined

+	 *  

+	 * @return file in which this variable is defined, or null if unknown

+	 * @since 2.0

+	 */

+	IPath getDefiningFile();

+

+	/**

+	 * Copy the variable with a new (perhaps runtime dependent) type

+	 * 

+	 * @param newType variable type 

+	 * @return copy of this variable, but with the new type

+	 * @since 3.0

+	 */

+	IVariable copyWithNewType(IType newType);

+

+	/**

+	 * 

+	 */

+	void dispose();

+}