summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlvaro Sanchez-Leon2013-09-18 09:09:16 (EDT)
committer Marc Khouzam2013-09-27 10:07:02 (EDT)
commit6c85c85a06dd20276ee65642c2d9c48dca0fd4e0 (patch)
tree649984cb7835c2d5f01792d515f16ef66d808e63
parentc92d135f6df4fcc4fbaf2c519f9474cd3d6d8250 (diff)
downloadorg.eclipse.cdt-6c85c85a06dd20276ee65642c2d9c48dca0fd4e0.zip
org.eclipse.cdt-6c85c85a06dd20276ee65642c2d9c48dca0fd4e0.tar.gz
org.eclipse.cdt-6c85c85a06dd20276ee65642c2d9c48dca0fd4e0.tar.bz2
Bug 323552: [registers] Register View content is not stack framerefs/changes/66/16566/4
specific Change-Id: Ib7922f8487d10e3b9cb5b6dcb255590cc31d2a97 Signed-off-by: Alvaro Sanchez-Leon <alvsan09@gmail.com> Reviewed-on: https://git.eclipse.org/r/16566 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java192
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java17
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataListRegisterValues.java48
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java101
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java4
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java24
6 files changed, 303 insertions, 83 deletions
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 cb2cbd4..817438d 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
@@ -9,6 +9,7 @@
* Wind River Systems - initial API and implementation
* Ericsson - Modified for additional features in DSF Reference Implementation
* Roland Grunberg (RedHat) - Refresh all registers once one is changed (Bug 400840)
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@@ -17,6 +18,7 @@ import java.util.Hashtable;
import java.util.List;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
@@ -29,6 +31,8 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
@@ -97,6 +101,11 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
private int fRegNo;
private String fRegName;
+ /**
+ * An MIRegiserDMC created with no frame context will not be able to resolve the associated register value.
+ * However these instances are useful to provide the register name i.e. needed from the selection of a process,
+ * or a running thread where it is not possible to associate registers to frames and therefore values.
+ */
public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, int regNo, String regName) {
super(service.getSession().getId(),
new IDMContext[] { group });
@@ -104,9 +113,26 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
fRegName = regName;
}
+ @Deprecated
public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IMIExecutionDMContext execDmc, int regNo, String regName) {
super(service.getSession().getId(),
- new IDMContext[] { execDmc, group });
+ new IDMContext[] { execDmc, group });
+ fRegNo = regNo;
+ fRegName = regName;
+ }
+
+ /**
+ * This Register context is associated to two parent contexts. A stack frame context (IFrameDMContext), and a register group
+ * context (MIRegisterGroupDMC). When the scenario requires to build a register contexts from the selection of a thread, then the top
+ * frame shall be resolved and be provided in this constructor.
+ *
+ * The frame context is necessary to resolve the register's data e.g. value
+ *
+ * @since 4.3
+ */
+ public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IFrameDMContext frameDmc, int regNo, String regName) {
+ super(service.getSession().getId(),
+ new IDMContext[] { frameDmc, group });
fRegNo = regNo;
fRegName = regName;
}
@@ -265,17 +291,17 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
public void getRegisterData(IRegisterDMContext regDmc , final DataRequestMonitor<IRegisterDMData> rm) {
if (regDmc instanceof MIRegisterDMC) {
final MIRegisterDMC miRegDmc = (MIRegisterDMC)regDmc;
- IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class);
- // Create register DMC with name if execution DMC is not present.
- if(execDmc == null){
- rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, false));
+ final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regDmc, IFrameDMContext.class);
+ // Create register data with name only e.g. not editable.
+ if(frameDmc == null){
+ rm.setData(new RegisterData(null, miRegDmc.getName(), BLANK_STRING, false));
rm.done();
return;
}
int[] regnos = {miRegDmc.getRegNo()};
fRegisterValueCache.execute(
- fCommandFactory.createMIDataListRegisterValues(execDmc, MIFormat.HEXADECIMAL, regnos),
+ fCommandFactory.createMIDataListRegisterValues(frameDmc, MIFormat.HEXADECIMAL, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@@ -301,9 +327,9 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
if ( reg.getValue().contains("float")) { //$NON-NLS-1$
isFloat = true;
}
-
+
// Return the new register attributes.
- rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, isFloat));
+ rm.setData(new RegisterData(frameDmc, miRegDmc.getName(), BLANK_STRING, isFloat));
rm.done();
}
});
@@ -314,9 +340,9 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
private void getRegisterDataValue( final MIRegisterDMC regDmc, final String formatId, final DataRequestMonitor<FormattedValueDMData> rm) {
- IMIExecutionDMContext miExecDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class);
- if(miExecDmc == null){
- // Set value to blank if execution dmc is not present
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regDmc, IFrameDMContext.class);
+ if(frameDmc == null){
+ // Set value to blank if frame dmc is not present
rm.setData( new FormattedValueDMData( BLANK_STRING ) );
rm.done();
return;
@@ -333,7 +359,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
int[] regnos = {regDmc.getRegNo()};
fRegisterValueCache.execute(
- fCommandFactory.createMIDataListRegisterValues(miExecDmc, NumberFormat, regnos),
+ fCommandFactory.createMIDataListRegisterValues(frameDmc, NumberFormat, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@@ -362,12 +388,14 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
final private String fRegName;
final private String fRegDesc;
final private boolean fIsFloat;
+ final private IFrameDMContext fContext;
- public RegisterData(String regName, String regDesc, boolean isFloat ) {
+ public RegisterData(IFrameDMContext context, String regName, String regDesc, boolean isFloat ) {
fRegName = regName;
fRegDesc = regDesc;
fIsFloat = isFloat;
+ fContext = context;
}
@Override
@@ -375,7 +403,12 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
@Override
public boolean isReadOnce() { return false; }
@Override
- public boolean isWriteable() { return true; }
+ public boolean isWriteable() {
+ //The absence of the frame context is likely the result of a selection not specific to a stack frame
+ //e.g. the selection of a running thread, or the selection of a process.
+ //So, an instance with no stack frame is not writable
+ return (fContext != null);
+ }
@Override
public boolean isWriteOnce() { return false; }
@Override
@@ -397,13 +430,13 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
}
// Wraps a list of registers in DMContexts.
- private MIRegisterDMC[] makeRegisterDMCs(MIRegisterGroupDMC groupDmc, IMIExecutionDMContext execDmc, String[] regNames) {
+ private MIRegisterDMC[] makeRegisterDMCs(MIRegisterGroupDMC groupDmc, IFrameDMContext frameDmc, String[] regNames) {
List<MIRegisterDMC> regDmcList = new ArrayList<MIRegisters.MIRegisterDMC>( regNames.length );
int regNo = 0;
for (String regName : regNames) {
if(regName != null && regName.length() > 0) {
- if(execDmc != null)
- regDmcList.add(new MIRegisterDMC(this, groupDmc, execDmc, regNo, regName));
+ if(frameDmc != null)
+ regDmcList.add(new MIRegisterDMC(this, groupDmc, frameDmc, regNo, regName));
else
regDmcList.add(new MIRegisterDMC(this, groupDmc, regNo, regName));
}
@@ -494,57 +527,96 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
rm.done() ;
}
-
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisters(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
*/
@Override
- public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) {
- final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(dmc, MIRegisterGroupDMC.class);
- if ( groupDmc == null ) {
- rm.setStatus( new Status( IStatus.ERROR , GdbPlugin.PLUGIN_ID , INVALID_HANDLE , "RegisterGroup context not found", null ) ) ; //$NON-NLS-1$
- rm.done();
- return;
- }
+ public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) {
+ final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(dmc, MIRegisterGroupDMC.class);
+ if (groupDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "RegisterGroup context not found", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
- final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
- if ( containerDmc == null ) {
- rm.setStatus( new Status( IStatus.ERROR , GdbPlugin.PLUGIN_ID , INVALID_HANDLE , "Container context not found" , null ) ) ; //$NON-NLS-1$
- rm.done();
- return;
- }
+ final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
+ if (containerDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Container context not found", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
- // There is only one group and its number must be 0.
- if ( groupDmc.getGroupNo() == 0 ) {
- final IMIExecutionDMContext executionDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
- fRegisterNameCache.execute(
- fCommandFactory.createMIDataListRegisterNames(containerDmc),
- new DataRequestMonitor<MIDataListRegisterNamesInfo>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- // Retrieve the register names.
- String[] regNames = getData().getRegisterNames() ;
-
- // If the list is empty just return empty handed.
- if ( regNames.length == 0 ) {
- rm.done();
- return;
- }
- // Create DMContexts for each of the register names.
- if(executionDmc == null)
- rm.setData(makeRegisterDMCs(groupDmc, regNames));
- else
- rm.setData(makeRegisterDMCs(groupDmc, executionDmc, regNames));
- rm.done();
- }
- });
- } else {
- rm.setStatus(new Status(IStatus.ERROR , GdbPlugin.PLUGIN_ID , INTERNAL_ERROR , "Invalid group = " + groupDmc , null)); //$NON-NLS-1$
- rm.done();
- }
- }
+ // There is only one group and its number must be 0.
+ if (groupDmc.getGroupNo() == 0) {
+ final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(dmc, IFrameDMContext.class);
+ if (frameDmc == null) {
+ // The selection does not provide a specific frame, then resolve the top frame on the current thread
+ IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
+ if (execDmc != null) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService != null) {
+ stackService.getTopFrame(execDmc, new ImmediateDataRequestMonitor<IStack.IFrameDMContext>(rm) {
+ @Override
+ protected void handleSuccess() {
+ getRegisters(getData(), groupDmc, containerDmc, rm);
+ }
+
+ @Override
+ protected void handleFailure() {
+ //Unable to resolve top frame on current thread.
+ //The thread could e.g. be in running state,
+ //we return register instances with no associated execution context
+ //i.e. unable to resolve its associated value.
+ getRegisters(null, groupDmc, containerDmc, rm);
+ }
+ });
+
+ return;
+ }
+ }
+ }
+
+ getRegisters(frameDmc, groupDmc, containerDmc, rm);
+
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
+ "Invalid group = " + groupDmc, null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ private void getRegisters(final IFrameDMContext frameDmc, final MIRegisterGroupDMC groupDmc,
+ IContainerDMContext containerDmc, final DataRequestMonitor<IRegisterDMContext[]> rm) {
+
+ fRegisterNameCache.execute(fCommandFactory.createMIDataListRegisterNames(containerDmc),
+ new ImmediateDataRequestMonitor<MIDataListRegisterNamesInfo>(rm) {
+ @Override
+ protected void handleSuccess() {
+ // Retrieve the register names.
+ String[] regNames = getData().getRegisterNames();
+
+ // If the list is empty just return empty handed.
+ if (regNames.length == 0) {
+ rm.done();
+ return;
+ }
+
+ if (frameDmc == null)
+ // The selection does not provide a frame or thread context,
+ // This can happen e.g. if a container /process is selected
+ // Lets provide the list of register names applicable to the selected process
+ // i.e. instances with only name information which can not resolve a value
+ rm.setData(makeRegisterDMCs(groupDmc, regNames));
+ else
+ rm.setData(makeRegisterDMCs(groupDmc, frameDmc, regNames));
+ rm.done();
+ }
+ });
+ }
+
/*
* (non-Javadoc)
* @see org.eclipse.cdt.dsf.debug.service.IRegisters#getBitFields(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
index 10c1ff8..c58ef52 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
@@ -20,6 +20,7 @@
* Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536)
* Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314)
* John Dallaway - Support for -data-write-memory-bytes (Bug 387793)
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug (323552)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command;
@@ -429,13 +430,29 @@ public class CommandFactory {
return new MIDataListRegisterNames(ctx, regnos);
}
+ @Deprecated
public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
return new MIDataListRegisterValues(ctx, fmt);
}
+ @Deprecated
public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) {
return new MIDataListRegisterValues(ctx, fmt, regnos);
}
+
+ /**
+ * @since 4.3
+ */
+ public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IFrameDMContext ctx, int fmt) {
+ return new MIDataListRegisterValues(ctx, fmt);
+ }
+
+ /**
+ * @since 4.3
+ */
+ public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IFrameDMContext ctx, int fmt, int [] regnos) {
+ return new MIDataListRegisterValues(ctx, fmt, regnos);
+ }
public ICommand<MIDataReadMemoryInfo> createMIDataReadMemory(IDMContext ctx, long offset, String address,
int word_format, int word_size, int rows, int cols,
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataListRegisterValues.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataListRegisterValues.java
index ead7f3f..5599f6f 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataListRegisterValues.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataListRegisterValues.java
@@ -8,10 +8,13 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
* Wind River Systems - Modified for new DSF Reference Implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
@@ -35,12 +38,34 @@ public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValues
int[] regnums;
int fFmt;
- public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
+ /**
+ * @since 4.3
+ */
+ public MIDataListRegisterValues(IFrameDMContext ctx, int fmt) {
this(ctx, fmt, null);
}
+ /**
+ * @since 4.3
+ */
+ public MIDataListRegisterValues(IFrameDMContext ctx, int fmt, int [] regnos) {
+ super(ctx, "-data-list-register-values"); //$NON-NLS-1$
+ init(fmt, regnos);
+ }
+
+ @Deprecated
+ public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
+ this(ctx, fmt, null);
+ }
+
+ @Deprecated
public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) {
super(ctx, "-data-list-register-values"); //$NON-NLS-1$
+ init(fmt, regnos);
+ }
+
+
+ private void init(int fmt, int [] regnos) {
regnums = regnos;
String format = "x"; //$NON-NLS-1$
@@ -86,7 +111,16 @@ public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValues
/*
* Can coalesce only with other DsfMIDataListRegisterValues commands.
*/
- if (! (command instanceof MIDataListRegisterValues) ) return null;
+ if (! (command instanceof MIDataListRegisterValues) ) return null;
+
+ IDMContext context = getContext();
+
+ /*
+ * Make sure we are coalescing over the same context
+ */
+ if (!command.getContext().equals(context)) {
+ return null;
+ }
MIDataListRegisterValues cmd = (MIDataListRegisterValues) command;
@@ -145,6 +179,14 @@ public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValues
/*
* Now construct a new one. The format we will use is this command.
*/
- return( new MIDataListRegisterValues((IMIExecutionDMContext)getContext(), fFmt, finalregnums));
+ MIDataListRegisterValues dataValues;
+ if (context instanceof IFrameDMContext) {
+ dataValues = new MIDataListRegisterValues((IFrameDMContext)context, fFmt, finalregnums);
+ } else {
+ //Keeping for compatibility with potential users
+ dataValues = new MIDataListRegisterValues((IMIExecutionDMContext)context, fFmt, finalregnums);
+ }
+
+ return(dataValues);
}
}
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
index 5121a23..e3ef752 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIRegistersTest.java
@@ -7,15 +7,19 @@
*
* Contributors:
* Ericsson - initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
@@ -46,6 +50,7 @@ import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIRegisters.MIRegisterDMC;
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
@@ -279,7 +284,17 @@ public class MIRegistersTest extends BaseTestCase {
IFrameDMContext frameDmc = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
List<String> regNames = get_X86_REGS();
-
+
+ IRegisterDMData[] datas = getRegistersData(regDMCs);
+
+ for(IRegisterDMData data: datas){
+ String regName = data.getName();
+ Assert.assertFalse("GDB does not support register name: " + regName, !regNames.contains(regName));
+ }
+ }
+
+ private IRegisterDMData[] getRegistersData(final IRegisterDMContext[] regDMCs) throws InterruptedException, ExecutionException {
+
Query<IRegisterDMData[]> query = new Query<IRegisterDMData[]>() {
@Override
protected void execute(DataRequestMonitor<IRegisterDMData[]> rm) {
@@ -305,15 +320,10 @@ public class MIRegistersTest extends BaseTestCase {
fSession.getExecutor().execute(query);
- IRegisterDMData[] datas = query.get();
-
- for(IRegisterDMData data: datas){
- String regName = data.getName();
- Assert.assertFalse("GDB does not support register name: " + regName, !regNames.contains(regName));
- }
- }
-
- private String getModelDataForRegisterDataValue(IFrameDMContext frameDmc, String format, int regNo) throws Throwable {
+ return query.get();
+ }
+
+ private String getModelDataForRegisterDataValue(IFrameDMContext frameDmc, String format, int regNo) throws Throwable {
final AsyncCompletionWaitor wait = new AsyncCompletionWaitor();
final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
@@ -548,4 +558,75 @@ public class MIRegistersTest extends BaseTestCase {
assertTrue("Failed writing register. New value should have been " + regValue + "instead of " + val, regValue.equals(val));
}
+ /**
+ * This test validates retrieval of different values for the same register used on different frames
+ */
+ @Test
+ public void frameSpecificValues() throws Throwable {
+ // Step to a multi-level stack level to be able to test different stack frames
+ SyncUtil.runToLocation("PrintHello");
+ MIStoppedEvent stoppedEvent = SyncUtil.step(StepType.STEP_OVER);
+ int depth = SyncUtil.getStackDepth(stoppedEvent.getDMContext());
+
+ // validate expected stack depth
+ assertEquals(4, depth);
+
+ // Resolve the register name of the stack pointer
+ String sp_name = resolveStackPointerName();
+ assertNotNull(sp_name);
+
+ // Get the stack pointer value for frame0
+ IFrameDMContext frame0 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 0);
+ IRegisterDMContext[] registers_f0 = getRegisters(frame0);
+ MIRegisterDMC sp_reg_f0 = (MIRegisterDMC) findStackPointerRegister(sp_name, registers_f0);
+ assertNotNull(sp_reg_f0);
+ String sp_f0_str = getModelDataForRegisterDataValue(frame0, IFormattedValues.HEX_FORMAT, sp_reg_f0.getRegNo());
+
+ // Get the stack pointer value for frame1
+ IFrameDMContext frame1 = SyncUtil.getStackFrame(stoppedEvent.getDMContext(), 1);
+ IRegisterDMContext[] registers_f1 = getRegisters(frame1);
+ MIRegisterDMC sp_reg_f1 = (MIRegisterDMC) findStackPointerRegister(sp_name, registers_f1);
+ assertNotNull(sp_reg_f1);
+ String sp_f1_str = getModelDataForRegisterDataValue(frame1, IFormattedValues.HEX_FORMAT, sp_reg_f1.getRegNo());
+
+ //The stack pointer's are not expected to be the same among frames
+ assertNotEquals("Stack pointers shall be different among frames", sp_f0_str, sp_f1_str);
+ }
+
+ private IRegisterDMContext findStackPointerRegister(String sp_name, IRegisterDMContext[] registerDMCs) throws InterruptedException, ExecutionException {
+ IRegisterDMData[] registersData = getRegistersData(registerDMCs);
+ for (int i = 0; i < registersData.length; i++) {
+ IRegisterDMData registerData = registersData[i];
+
+ if (registerData.getName().equals(sp_name)) {
+ return registerDMCs[i];
+ }
+ }
+
+ return null;
+ }
+
+ private String resolveStackPointerName() throws Throwable {
+ List<String> regNames = get_X86_REGS();
+
+ // for 64 bits
+ String sp_name = "rsp";
+ if (regNames.contains(sp_name)) {
+ return sp_name;
+ }
+
+ // for 32 bits
+ sp_name = "esp";
+ if (regNames.contains(sp_name)) {
+ return sp_name;
+ }
+
+ // for 16 bits
+ sp_name = "sp";
+ if (regNames.contains(sp_name)) {
+ return sp_name;
+ }
+
+ return null;
+ }
}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java
index 81dafb8..1a4e393 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Wind River Systems - initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.register;
@@ -29,6 +30,7 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegistersChangedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
@@ -672,6 +674,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode
@Override
public int getDeltaFlags(Object e) {
if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IResumedDMEvent ||
e instanceof IMemoryChangedEvent ||
e instanceof IRegistersChangedDMEvent ||
(e instanceof PropertyChangeEvent &&
@@ -697,6 +700,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode
// The following events can affect any register's values,
// refresh the contents of the parent element (i.e. all the registers).
if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IResumedDMEvent ||
e instanceof IMemoryChangedEvent ||
e instanceof IRegistersChangedDMEvent ||
(e instanceof PropertyChangeEvent &&
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
index 8bb035c..1835d0c 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Wind River Systems - initial API and implementation
+ * Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug 323552)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.register;
@@ -19,6 +20,7 @@ import org.eclipse.cdt.dsf.debug.service.ICachingService;
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.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.ui.DsfDebugUITools;
import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
@@ -168,24 +170,26 @@ public class RegisterVMProvider extends AbstractDMVMProvider
*/
@Override
public void update(IViewerInputUpdate update) {
- /*
- * Use the execution context in the current selection as the input provider.
- * This insures that the REGISTER VIEW will not collapse and expand on stepping or on
- * re-selection in the DEBUG VIEW. Currently the register content is not stack frame
- * specific. If it were to become so then we would need to modify this policy.
- */
+ /*
+ * Using the frame context as first alternative to display register values per stack frame
+ * if not available e.g. user selected a thread, the execution context is used instead
+ */
Object element = update.getElement();
if (element instanceof IDMVMContext) {
IDMContext ctx = ((IDMVMContext) element).getDMContext();
-
- IExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class);
- if ( execDmc != null ) {
+
+ IDMContext selDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
+ if (selDmc == null) {
+ selDmc = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class);
+ }
+
+ if ( selDmc != null ) {
/*
* This tells the Flexible Hierarchy that element driving this view has not changed
* and there is no need to redraw the view. Since this is a somewhat fake VMContext
* we provide our Root Layout node as the representative VM node.
*/
- update.setInputElement(new ViewInputElement(RegisterVMProvider.this.getRootVMNode(), execDmc));
+ update.setInputElement(new ViewInputElement(RegisterVMProvider.this.getRootVMNode(), selDmc));
update.done();
return;
}