1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

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>
This commit is contained in:
Bruno Medeiros 2017-01-19 17:14:24 +00:00 committed by Alvaro Sanchez-Leon
parent 064ce187b6
commit 5a71bf21d8
8 changed files with 435 additions and 36 deletions

View file

@ -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);

View file

@ -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;
};
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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();
}
};
}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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
*/