Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Medeiros2017-01-19 17:14:24 +0000
committerAlvaro Sanchez-Leon2017-02-28 20:41:10 +0000
commit5a71bf21d82d2563b0d37d73a99977d5617c2788 (patch)
tree4b2c65d3e204a04a42cf5b97827e84d709f8832b
parent064ce187b6de00e343b26a614a98846ef46213d7 (diff)
downloadorg.eclipse.cdt-5a71bf21d82d2563b0d37d73a99977d5617c2788.tar.gz
org.eclipse.cdt-5a71bf21d82d2563b0d37d73a99977d5617c2788.tar.xz
org.eclipse.cdt-5a71bf21d82d2563b0d37d73a99977d5617c2788.zip
Bug 449104: Enhance Register Grouping for multi processes
This patch adds support to GDBRegisters for persisting the register group configuration on a per-process/per-core basis. The default behavior of GDBRegisters is not modified. Instead, subclasses must override getPersistenceIdForRegisterGroupContainer(IContainerDMContext) to enable the new behavior, and provide a persistence id that is stable across launches. Update: fixed bug in RegisterGroupDescriptor.getContainerId() Change-Id: I284df3ee215d9a4a9f72f3dca9aba5c16ca4b850 Signed-off-by: Bruno Medeiros <bruno.do.medeiros@gmail.com>
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java41
-rw-r--r--debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java9
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/.settings/org.eclipse.jdt.core.prefs2
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/CommonDsfTest.java109
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisterTest.java199
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/tests/AutomatedIntegrationSuite.java8
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java91
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java12
8 files changed, 435 insertions, 36 deletions
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java
index ac3b737b0a8..55afb154c97 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/RegisterGroupsPersistance.java
@@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - Initial API and implementation in CRegisterManager.java and CRegisterGroup.java
* Alvaro Sanchez-Leon (Ericsson) - Integrated from files above for Bug 235747
+ * Bruno Medeiros (Renesas) - Persistence of register groups per process (449104)
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core;
@@ -39,6 +40,7 @@ public class RegisterGroupsPersistance {
private static final String ELEMENT_GROUP = "group"; //$NON-NLS-1$
private static final String ELEMENT_REGISTER_GROUP = "registerGroup"; //$NON-NLS-1$
private static final String ATTR_REGISTER_GROUP_NAME = "name"; //$NON-NLS-1$
+ private static final String ATTR_REGISTER_CONTAINER_ID = "parent_id"; //$NON-NLS-1$
private static final String ATTR_REGISTER_GROUP_ENABLED = "enabled"; //$NON-NLS-1$
private static final String ELEMENT_REGISTER = "register"; //$NON-NLS-1$
@@ -60,12 +62,17 @@ public class RegisterGroupsPersistance {
private final String fMemento;
private final String fName;
private final boolean fEnabled;
+ private final String fContainerId;
IRegisterDescriptor[] fRegisterDescriptors = null;
- public RegisterGroupDescriptor(String memento, String groupName, boolean enabled) {
+ public RegisterGroupDescriptor(String memento, String groupName, boolean enabled, String containerId) {
fMemento = memento;
fName = groupName;
fEnabled = enabled;
+ if (containerId != null && containerId.length() == 0) {
+ containerId = null;
+ }
+ fContainerId = containerId;
}
@Override
@@ -77,6 +84,11 @@ public class RegisterGroupsPersistance {
public boolean isEnabled() {
return fEnabled;
}
+
+ @Override
+ public String getContainerId() {
+ return fContainerId;
+ }
@Override
public IRegisterDescriptor[] getChildren() throws CoreException {
@@ -144,11 +156,16 @@ public class RegisterGroupsPersistance {
return fLaunchConfigTargetAttribute;
}
-
- public IRegisterGroupDescriptor[] parseGroups() {
+
+ /**
+ * Parse register groups.
+ * If given containerId is not null, the only returned register groups are the one
+ * whose container id matches given containerId
+ */
+ public IRegisterGroupDescriptor[] parseGroups(String containerId) throws CoreException {
List<IRegisterGroupDescriptor> groups = new ArrayList<IRegisterGroupDescriptor>();
String memento;
- try {
+
memento = fLaunchConfig.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_REGISTER_GROUPS, BLANK_STRING);
if (memento != null && memento.length() > 0) {
@@ -168,10 +185,12 @@ public class RegisterGroupsPersistance {
Element child = (Element) childNode;
if (ELEMENT_GROUP.equals(child.getNodeName())) {
String groupMemento = child.getAttribute(ATTR_REGISTER_GROUP_MEMENTO);
- //
+
IRegisterGroupDescriptor groupdesc = createGroupFromMemento(groupMemento);
if (groupdesc != null) {
- groups.add(groupdesc);
+ if(containerId == null || containerId.equals(groupdesc.getContainerId())) {
+ groups.add(groupdesc);
+ }
}
}
}
@@ -179,10 +198,6 @@ public class RegisterGroupsPersistance {
}
}
- } catch (CoreException e) {
-
- e.printStackTrace();
- }
return groups.toArray(new IRegisterGroupDescriptor[groups.size()]);
@@ -217,12 +232,11 @@ public class RegisterGroupsPersistance {
if (groupName == null || groupName.length() == 0) {
abort(CoreModelMessages.getString("CRegisterGroup.2"), null); //$NON-NLS-1$
}
+ String containerId = element.getAttribute(ATTR_REGISTER_CONTAINER_ID);
String e = element.getAttribute(ATTR_REGISTER_GROUP_ENABLED);
boolean enabled = Boolean.parseBoolean(e);
- IRegisterGroupDescriptor group = new RegisterGroupDescriptor(memento, groupName, enabled);
-
- return group;
+ return new RegisterGroupDescriptor(memento, groupName, enabled, containerId);
}
private String getMemento(IRegisterGroupDescriptor[] groups) throws CoreException {
@@ -243,6 +257,7 @@ public class RegisterGroupsPersistance {
Element element = document.createElement(ELEMENT_REGISTER_GROUP);
element.setAttribute(ATTR_REGISTER_GROUP_NAME, group.getName());
element.setAttribute(ATTR_REGISTER_GROUP_ENABLED, String.valueOf(group.isEnabled()));
+ element.setAttribute(ATTR_REGISTER_CONTAINER_ID, group.getContainerId());
IRegisterDescriptor[] registerDescriptors = group.getChildren();
for (int i = 0; i < registerDescriptors.length; ++i) {
Element child = document.createElement(ELEMENT_REGISTER);
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java
index ff72c97a26b..83a80a6b794 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/IRegisterGroupDescriptor.java
@@ -32,4 +32,13 @@ public interface IRegisterGroupDescriptor {
* @throws CoreException
*/
public IRegisterDescriptor[] getChildren() throws CoreException;
+
+ /**
+ * The id of the container this register group belongs to.
+ * If null, the register group applies to the entire launch,
+ * otherwise it applies only to a given core, or process, within the launch.
+ */
+ default String getContainerId() {
+ return null;
+ };
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/.settings/org.eclipse.jdt.core.prefs b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/.settings/org.eclipse.jdt.core.prefs
index ce1f6109477..87965802f37 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/.settings/org.eclipse.jdt.core.prefs
@@ -60,7 +60,7 @@ org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverridin
org.eclipse.jdt.core.compiler.problem.unusedImport=error
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/CommonDsfTest.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/CommonDsfTest.java
new file mode 100644
index 00000000000..094bcb18f75
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/CommonDsfTest.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Renesas Electronics 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:
+ * Bruno Medeiros (Renesas) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import static org.junit.Assert.fail;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.debug.model.DsfLaunch;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+/**
+ * Helper base class for running DSF related tests
+ */
+public class CommonDsfTest extends CommonTest {
+
+ protected static DsfSession fSession = null;
+
+ /**
+ * Setup the test.
+ * The session is typically configured once per class load, but we allow subclasses to override this,
+ * and sometimes re-setup during a test (or interactive debugging).
+ * Therefore {@link Before} is used, not {@link BeforeClass}.
+ */
+ @Before
+ public void setup() {
+ if(fSession != null) {
+ return; // Already set-up
+ }
+
+ doSetupSession();
+ }
+
+ protected void doSetupSession() {
+ fSession = DsfSession.startSession(new DefaultDsfExecutor(GdbPlugin.PLUGIN_ID), GdbPlugin.PLUGIN_ID);
+
+ registerLaunch();
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ if(fSession != null) {
+ DsfSession.endSession(fSession);
+ fSession = null;
+ }
+ }
+
+ protected ILaunchConfigurationType getCLaunchConfigType() {
+ return getLaunchManager().getLaunchConfigurationType(ICDTLaunchConfigurationConstants.ID_LAUNCH_C_APP);
+ }
+
+ protected ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+
+ protected void registerLaunch() {
+ ILaunchConfigurationWorkingCopy lc;
+ try {
+ lc = getCLaunchConfigType().newInstance(null, "TestLaunch");
+ } catch(CoreException e) {
+ fail(e.getMessage());
+ return;
+ }
+ ISourceLocator sourceLocator = null;
+ DsfLaunch dsfLaunch = new DsfLaunch(lc, ILaunchManager.DEBUG_MODE, sourceLocator);
+ fSession.registerModelAdapter(ILaunch.class, dsfLaunch);
+ }
+
+ protected RequestMonitor newRequestMonitor() {
+ return new RequestMonitor(fSession.getExecutor(), null);
+ }
+
+ protected <T> DataRequestMonitor<T> newDataRequestMonitor() {
+ return new DataRequestMonitor<>(fSession.getExecutor(), null);
+ }
+}
+
+/**
+ * Misc test utilities.
+ */
+class CommonTest {
+ /* ----------------- ----------------- */
+
+ @SafeVarargs
+ public static <T> T[] array(T... elems) {
+ return elems;
+ }
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisterTest.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisterTest.java
new file mode 100644
index 00000000000..eb22e775d3d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisterTest.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Renesas Electronics 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:
+ * Bruno Medeiros (Renesas) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.eclipse.cdt.debug.internal.core.model.IRegisterGroupDescriptor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterDMC;
+import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterGroupDMC;
+import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
+import org.eclipse.core.runtime.Assert;
+import org.junit.Test;
+
+
+public class GDBRegisterTest extends CommonDsfTest {
+
+ public static final String PROCESS_A = "processA";
+ public static final String PROCESS_B = "processB";
+
+ protected MIProcesses miProcesses;
+ protected GDBRegisters gdbRegisters;
+
+ @Override
+ protected void doSetupSession() {
+ super.doSetupSession();
+
+ miProcesses = new MIProcesses(fSession);
+ gdbRegisters = createGdbRegisters();
+ }
+
+ protected GDBRegisters createGdbRegisters() {
+ return new GDBRegisters(fSession) {
+ @Override
+ protected boolean useProcessIdAsRegisterGroupPersistanceId() {
+ return true;
+ }
+ };
+ }
+
+ @Test
+ public void testRegisterPersistence() throws Exception { testRegisterPersistence$(); }
+ public void testRegisterPersistence$() throws Exception {
+
+ MIControlDMContext controlDmc = new MIControlDMContext(fSession.getId(), "TestControl");
+
+ IProcessDMContext processDmcA = miProcesses.createProcessContext(controlDmc, PROCESS_A);
+ IProcessDMContext processDmcB = miProcesses.createProcessContext(controlDmc, PROCESS_B);
+ IMIContainerDMContext containerA = miProcesses.createContainerContext(processDmcA, "containerA");
+ IMIContainerDMContext containerB = miProcesses.createContainerContext(processDmcB, "containerB");
+
+
+ MIRegisterGroupDMC[] initialRegisterGroups = gdbRegisters.readGroupsFromMemento(containerA);
+ Assert.isTrue(initialRegisterGroups.length == 0);
+
+ MIRegisterGroupDMC registerGroupA = addRegisterGroup(containerA, "RegGroupA", "register_foo");
+ // check build descriptors
+ IRegisterGroupDescriptor[] buildDescriptors = gdbRegisters.buildDescriptors();
+ org.junit.Assert.assertEquals(buildDescriptors[0].getContainerId(), gdbRegisters.getPersistenceIdForRegisterGroupContainer(containerA));
+
+ // Save then check persistence
+ gdbRegisters.save();
+ checkAfterAdding_GroupA(containerA, containerB, registerGroupA);
+
+ // Now add a second register group to a different process context
+ MIRegisterGroupDMC registerGroupB = addRegisterGroup(containerB, "RegGroupB", "register_bar");
+ gdbRegisters.save();
+ checkAfterAdding_GroupB(containerA, containerB, registerGroupA, registerGroupB);
+ }
+
+ protected void checkAfterAdding_GroupA(
+ IMIContainerDMContext containerA, IMIContainerDMContext containerB, MIRegisterGroupDMC registerGroupA
+ ) {
+ checkRegisterGroupMemento(containerA, registerGroupA);
+ checkRegisterGroupsMemento(containerB, array());
+ }
+
+ protected void checkAfterAdding_GroupB(
+ IMIContainerDMContext containerA, IMIContainerDMContext containerB,
+ MIRegisterGroupDMC registerGroupA, MIRegisterGroupDMC registerGroupB
+ ) {
+ checkRegisterGroupMemento(containerA, registerGroupA);
+ checkRegisterGroupMemento(containerB, registerGroupB);
+ }
+
+ protected MIRegisterGroupDMC addRegisterGroup(IMIContainerDMContext container, String groupName, String registerName) {
+ MIRegisterGroupDMC registerGroup = new MIRegisterGroupDMC(gdbRegisters, container, 1, groupName);
+ MIRegisterDMC rgFoo = new MIRegisterDMC(gdbRegisters, registerGroup, 1, registerName);
+
+ gdbRegisters.addRegisterGroup(container, registerGroup.getName(), array(rgFoo), newRequestMonitor());
+ return registerGroup;
+ }
+
+ protected void checkRegisterGroupMemento(IMIContainerDMContext container, MIRegisterGroupDMC registerGroup) {
+ checkRegisterGroupsMemento(container, array(registerGroup));
+ }
+
+ protected void checkRegisterGroupsMemento(IMIContainerDMContext container, MIRegisterGroupDMC[] expectedRegisterGroups) {
+ MIRegisterGroupDMC[] savedRegisterGroups = gdbRegisters.readGroupsFromMemento(container);
+ if(expectedRegisterGroups == null) {
+ assertTrue(savedRegisterGroups == null);
+ return;
+ }
+
+ assertTrue(expectedRegisterGroups.length == savedRegisterGroups.length);
+
+ for (int ix = 0; ix < expectedRegisterGroups.length; ix++) {
+ MIRegisterGroupDMC expectedRG = expectedRegisterGroups[ix];
+ int groupNo = savedRegisterGroups[ix].getGroupNo(); // Don't check group number, so set expected to obtained value
+ expectedRegisterGroups[ix] = new MIRegisterGroupDMC(gdbRegisters, container, groupNo, expectedRG.getName());
+ }
+
+ assertTrue(Arrays.equals(expectedRegisterGroups, savedRegisterGroups));
+ }
+
+ /* ----------------- ----------------- */
+
+ /**
+ * Variant of {@link GDBRegisterTest} where register groups are saved without a container id.
+ * This is the default behavior for register group persistence.
+ */
+ public static class GDBRegisterTest_NoContainerTest extends GDBRegisterTest {
+
+ @Override
+ protected GDBRegisters createGdbRegisters() {
+ return new GDBRegisters(fSession) {
+ @Override
+ protected boolean useProcessIdAsRegisterGroupPersistanceId() {
+ return false;
+ }
+ };
+ }
+
+ @Override
+ protected void checkAfterAdding_GroupA(
+ IMIContainerDMContext containerA, IMIContainerDMContext containerB, MIRegisterGroupDMC registerGroupA
+ ) {
+ checkRegisterGroupMemento(containerA, registerGroupA);
+ checkRegisterGroupMemento(containerB, registerGroupA);
+ }
+
+ @Override
+ protected void checkAfterAdding_GroupB(
+ IMIContainerDMContext containerA, IMIContainerDMContext containerB,
+ MIRegisterGroupDMC registerGroupA, MIRegisterGroupDMC registerGroupB
+ ) {
+ checkRegisterGroupsMemento(containerA, array(registerGroupA, registerGroupB));
+ checkRegisterGroupsMemento(containerB, array(registerGroupA, registerGroupB));
+ }
+ }
+
+ public static class GDBRegisterTest_WithAlternativeProcessIdTest extends GDBRegisterTest {
+
+ @Override
+ protected GDBRegisters createGdbRegisters() {
+ return new GDBRegisters(fSession) {
+ @Override
+ protected boolean useProcessIdAsRegisterGroupPersistanceId() {
+ return true;
+ }
+ @Override
+ protected String getPersistenceIdForRegisterGroupContainer(IContainerDMContext contDmc) {
+ return super.getPersistenceIdForRegisterGroupContainer(contDmc) + "XXX";
+ }
+ };
+ }
+
+ }
+
+
+ public static class GDBRegisterTest_WithContainerDMContextTest extends GDBRegisterTest {
+
+ @Override
+ protected GDBRegisters createGdbRegisters() {
+ return new GDBRegisters(fSession) {
+ @Override
+ protected String getPersistenceIdForRegisterGroupContainer(IContainerDMContext contDmc) {
+ IMIContainerDMContext contextDmc = DMContexts.getAncestorOfType(contDmc, IMIContainerDMContext.class);
+ return contextDmc.getGroupId();
+ }
+ };
+ }
+
+ }
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/tests/AutomatedIntegrationSuite.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/tests/AutomatedIntegrationSuite.java
index 37eb0477a83..2ab2a2e0c41 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/tests/AutomatedIntegrationSuite.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.tests/src/org/eclipse/cdt/dsf/gdb/tests/AutomatedIntegrationSuite.java
@@ -10,6 +10,10 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.tests;
+import org.eclipse.cdt.dsf.gdb.service.GDBRegisterTest;
+import org.eclipse.cdt.dsf.gdb.service.GDBRegisterTest.GDBRegisterTest_NoContainerTest;
+import org.eclipse.cdt.dsf.gdb.service.GDBRegisterTest.GDBRegisterTest_WithAlternativeProcessIdTest;
+import org.eclipse.cdt.dsf.gdb.service.GDBRegisterTest.GDBRegisterTest_WithContainerDMContextTest;
import org.eclipse.cdt.dsf.mi.service.command.commands.TestMIBreakInsertCommand;
import org.eclipse.cdt.dsf.mi.service.command.commands.TestMICommandConstructCommand;
import org.eclipse.cdt.dsf.mi.service.command.commands.TestMIGDBSetSysroot;
@@ -30,6 +34,10 @@ import org.junit.runners.Suite.SuiteClasses;
MIStringHandlerTests.class,
ProcStatParserTest.class,
FilePartsTest.class,
+ GDBRegisterTest.class,
+ GDBRegisterTest_NoContainerTest.class,
+ GDBRegisterTest_WithAlternativeProcessIdTest.class,
+ GDBRegisterTest_WithContainerDMContextTest.class,
})
public class AutomatedIntegrationSuite {
// Often overriding BeforeClass method here
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java
index d9bda88cb36..537fdbb23d3 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRegisters.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Alvaro Sanchez-Leon (Ericsson) - First Implementation and API (Bug 235747)
+ * Bruno Medeiros (Renesas) - Persistence of register groups per process (449104)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@@ -15,7 +16,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -40,6 +40,7 @@ import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
import org.eclipse.cdt.dsf.mi.service.MIRegisters;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
@@ -52,7 +53,9 @@ import org.eclipse.osgi.util.NLS;
/**
* <p>An extension of MIRegisters to support management of Register Groups as per the IRegisters2 interface.</p>
* <p>The managed registered groups are user-defined subsets of the complete list of Registers reported by GDB for a specific Target</p>
- * <p>This class also triggers the read/write (persistence) of the user-defined Register Groups during the start/shutdown process of a session respectively</p>
+ * <p>This class also triggers the read/write (persistence) of the user-defined Register Groups during the start/shutdown process of a session respectively.
+ * It optionally supports persistence of user-defined Register Groups per container/process,
+ * see {@link #getPersistenceIdForRegisterGroupContainer(IContainerDMContext)}.</p>
* @since 4.6
*/
public class GDBRegisters extends MIRegisters implements IRegisters2 {
@@ -239,6 +242,12 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
public boolean isEnabled() {
return fEnabled;
}
+
+ @Override
+ public String getContainerId() {
+ IContainerDMContext parent = fgroup.getContainerParent();
+ return getPersistenceIdForRegisterGroupContainer(parent);
+ }
@Override
public IRegisterDescriptor[] getChildren() throws CoreException {
@@ -520,9 +529,6 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
}
}
- // must be a child of an existing container, at least the root group must be present
- assert (fContextToGroupsMap.containsKey(contDmc));
-
// Make sure the name is not currently in use
if (fContextToGroupsMap.getGroupNameMap(contDmc).get(groupName) != null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, NLS.bind(
@@ -727,17 +733,21 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
super.shutdown(rm);
}
+ /**
+ * Save the register group settings into the underlying launch configuration.
+ */
public void save() {
- IRegisterGroupDescriptor[] groups = buildDescriptors();
- ILaunchConfiguration launchConfig = getLaunchConfig();
- if (launchConfig != null) {
- RegisterGroupsPersistance serializer = new RegisterGroupsPersistance(launchConfig);
- try {
- serializer.saveGroups(groups);
- } catch (CoreException e1) {
- e1.printStackTrace();
- }
- }
+ IRegisterGroupDescriptor[] groups = buildDescriptors();
+ ILaunchConfiguration launchConfig = getLaunchConfig();
+ if (launchConfig != null) {
+ RegisterGroupsPersistance serializer = new RegisterGroupsPersistance(launchConfig);
+ try {
+ serializer.saveGroups(groups);
+ } catch (CoreException e) {
+ GdbPlugin.log(e);
+ }
+ }
+
}
/**
@@ -855,7 +865,7 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
return config;
}
- private IRegisterGroupDescriptor[] buildDescriptors() {
+ IRegisterGroupDescriptor[] buildDescriptors() {
// use a tree map to sort the entries by group number
TreeMap<Integer, MIRegisterGroupDMC> sortedGroups = new TreeMap<Integer, MIRegisterGroupDMC>();
@@ -872,9 +882,8 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
// load group descriptors sorted in ascending order to their group
// number into the result array
int i = 0;
- for (Iterator<Entry<Integer, MIRegisterGroupDMC>> iterator = groupSet.iterator(); iterator.hasNext();) {
- Entry<Integer, MIRegisterGroupDMC> entry = iterator.next();
- descriptors[i] = new RegisterGroupDescriptor(entry.getValue(), true);
+ for (Entry<Integer, MIRegisterGroupDMC> groupEntry : groupSet) {
+ descriptors[i] = new RegisterGroupDescriptor(groupEntry.getValue(), true);
i++;
}
@@ -895,9 +904,16 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
return newArr;
}
- private MIRegisterGroupDMC[] readGroupsFromMemento(final IContainerDMContext contDmc) {
+ MIRegisterGroupDMC[] readGroupsFromMemento(final IContainerDMContext contDmc) {
+ String containerId = getPersistenceIdForRegisterGroupContainer(contDmc);
+
RegisterGroupsPersistance deserializer = new RegisterGroupsPersistance(getLaunchConfig());
- IRegisterGroupDescriptor[] groupDescriptions = deserializer.parseGroups();
+ IRegisterGroupDescriptor[] groupDescriptions;
+ try {
+ groupDescriptions = deserializer.parseGroups(containerId);
+ } catch(CoreException e) {
+ return new MIRegisterGroupDMC[0];
+ }
List<MIRegisterGroupDMC> groups = new ArrayList<MIRegisterGroupDMC>();
for (IRegisterGroupDescriptor group : groupDescriptions) {
@@ -908,6 +924,39 @@ public class GDBRegisters extends MIRegisters implements IRegisters2 {
return groups.toArray(new MIRegisterGroupDMC[groups.size()]);
}
+
+ /**
+ * @return the persistence id for the register group in the given contDmc container context,
+ * or null to associate the Register Groups in the given container to the launch itself (this is the default behavior).
+ *
+ * Subclasses may override. Alternatively simply use override {@link #useProcessIdAsRegisterGroupPersistanceId()} to return true to have
+ * the process id be used as the persistence id.
+ *
+ * Note that for this to work correctly the id returned for a given container must be same across launch sessions,
+ * otherwise persistence info will be lost. (Hence why null is the default behavior)
+ *
+ * @since 5.3
+ */
+ protected String getPersistenceIdForRegisterGroupContainer(final IContainerDMContext contDmc) {
+ if(useProcessIdAsRegisterGroupPersistanceId()) {
+ IMIProcessDMContext processDmc = DMContexts.getAncestorOfType(contDmc, IMIProcessDMContext.class);
+ return processDmc == null ? null : processDmc.getProcId();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @return whether the process id should be used as a container id for the persistence
+ * of the register groups. Subclasses may override.
+ *
+ * @see #getPersistenceIdForRegisterGroupContainer(IContainerDMContext)
+ *
+ * @since 5.3
+ */
+ protected boolean useProcessIdAsRegisterGroupPersistanceId() {
+ return false;
+ }
private void getUserGroupRegisters(IDMContext ctx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
index 94b9b865bf3..27154be2e66 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java
@@ -85,17 +85,27 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
*/
public static class MIRegisterGroupDMC extends AbstractDMContext implements IRegisterGroupDMContext {
- private int fGroupNo;
+ private final int fGroupNo;
+ private final IContainerDMContext parent;
private String fGroupName;
public MIRegisterGroupDMC(MIRegisters service, IContainerDMContext contDmc, int groupNo, String groupName) {
super(service.getSession().getId(), new IDMContext[] { contDmc });
+ this.parent = contDmc;
fGroupNo = groupNo;
fGroupName = groupName;
}
public int getGroupNo() { return fGroupNo; }
public String getName() { return fGroupName; }
+
+ /**
+ * @since 5.3
+ */
+ public IContainerDMContext getContainerParent() {
+ return parent;
+ }
+
/**
* @since 4.6
*/

Back to the top