1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-28 19:35:36 +02:00

Bug 323552: [registers] Register View content is not stack frame

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>
This commit is contained in:
Alvaro Sanchez-Leon 2013-09-18 09:09:16 -04:00 committed by Marc Khouzam
parent c92d135f6d
commit 6c85c85a06
6 changed files with 303 additions and 83 deletions

View file

@ -9,6 +9,7 @@
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Ericsson - Modified for additional features in DSF Reference Implementation * Ericsson - Modified for additional features in DSF Reference Implementation
* Roland Grunberg (RedHat) - Refresh all registers once one is changed (Bug 400840) * 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; package org.eclipse.cdt.dsf.mi.service;
@ -17,6 +18,7 @@ import java.util.Hashtable;
import java.util.List; import java.util.List;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; 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.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; 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;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; 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.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.BufferedCommandControl;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache; import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; 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 int fRegNo;
private String fRegName; 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) { public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, int regNo, String regName) {
super(service.getSession().getId(), super(service.getSession().getId(),
new IDMContext[] { group }); new IDMContext[] { group });
@ -104,6 +113,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
fRegName = regName; fRegName = regName;
} }
@Deprecated
public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IMIExecutionDMContext execDmc, int regNo, String regName) { public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IMIExecutionDMContext execDmc, int regNo, String regName) {
super(service.getSession().getId(), super(service.getSession().getId(),
new IDMContext[] { execDmc, group }); new IDMContext[] { execDmc, group });
@ -111,6 +121,22 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
fRegName = regName; 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;
}
public int getRegNo() { return fRegNo; } public int getRegNo() { return fRegNo; }
public String getName() { return fRegName; } public String getName() { return fRegName; }
@ -265,17 +291,17 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
public void getRegisterData(IRegisterDMContext regDmc , final DataRequestMonitor<IRegisterDMData> rm) { public void getRegisterData(IRegisterDMContext regDmc , final DataRequestMonitor<IRegisterDMData> rm) {
if (regDmc instanceof MIRegisterDMC) { if (regDmc instanceof MIRegisterDMC) {
final MIRegisterDMC miRegDmc = (MIRegisterDMC)regDmc; final MIRegisterDMC miRegDmc = (MIRegisterDMC)regDmc;
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class); final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regDmc, IFrameDMContext.class);
// Create register DMC with name if execution DMC is not present. // Create register data with name only e.g. not editable.
if(execDmc == null){ if(frameDmc == null){
rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, false)); rm.setData(new RegisterData(null, miRegDmc.getName(), BLANK_STRING, false));
rm.done(); rm.done();
return; return;
} }
int[] regnos = {miRegDmc.getRegNo()}; int[] regnos = {miRegDmc.getRegNo()};
fRegisterValueCache.execute( fRegisterValueCache.execute(
fCommandFactory.createMIDataListRegisterValues(execDmc, MIFormat.HEXADECIMAL, regnos), fCommandFactory.createMIDataListRegisterValues(frameDmc, MIFormat.HEXADECIMAL, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) { new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -303,7 +329,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
} }
// Return the new register attributes. // 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(); 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) { private void getRegisterDataValue( final MIRegisterDMC regDmc, final String formatId, final DataRequestMonitor<FormattedValueDMData> rm) {
IMIExecutionDMContext miExecDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class); IFrameDMContext frameDmc = DMContexts.getAncestorOfType(regDmc, IFrameDMContext.class);
if(miExecDmc == null){ if(frameDmc == null){
// Set value to blank if execution dmc is not present // Set value to blank if frame dmc is not present
rm.setData( new FormattedValueDMData( BLANK_STRING ) ); rm.setData( new FormattedValueDMData( BLANK_STRING ) );
rm.done(); rm.done();
return; return;
@ -333,7 +359,7 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
int[] regnos = {regDmc.getRegNo()}; int[] regnos = {regDmc.getRegNo()};
fRegisterValueCache.execute( fRegisterValueCache.execute(
fCommandFactory.createMIDataListRegisterValues(miExecDmc, NumberFormat, regnos), fCommandFactory.createMIDataListRegisterValues(frameDmc, NumberFormat, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) { new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -362,12 +388,14 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
final private String fRegName; final private String fRegName;
final private String fRegDesc; final private String fRegDesc;
final private boolean fIsFloat; 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; fRegName = regName;
fRegDesc = regDesc; fRegDesc = regDesc;
fIsFloat = isFloat; fIsFloat = isFloat;
fContext = context;
} }
@Override @Override
@ -375,7 +403,12 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
@Override @Override
public boolean isReadOnce() { return false; } public boolean isReadOnce() { return false; }
@Override @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 @Override
public boolean isWriteOnce() { return false; } public boolean isWriteOnce() { return false; }
@Override @Override
@ -397,13 +430,13 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
} }
// Wraps a list of registers in DMContexts. // 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 ); List<MIRegisterDMC> regDmcList = new ArrayList<MIRegisters.MIRegisterDMC>( regNames.length );
int regNo = 0; int regNo = 0;
for (String regName : regNames) { for (String regName : regNames) {
if(regName != null && regName.length() > 0) { if(regName != null && regName.length() > 0) {
if(execDmc != null) if(frameDmc != null)
regDmcList.add(new MIRegisterDMC(this, groupDmc, execDmc, regNo, regName)); regDmcList.add(new MIRegisterDMC(this, groupDmc, frameDmc, regNo, regName));
else else
regDmcList.add(new MIRegisterDMC(this, groupDmc, regNo, regName)); regDmcList.add(new MIRegisterDMC(this, groupDmc, regNo, regName));
} }
@ -494,7 +527,6 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
rm.done() ; rm.done() ;
} }
/* /*
* (non-Javadoc) * (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) * @see org.eclipse.cdt.dsf.debug.service.IRegisters#getRegisters(org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
@ -502,47 +534,87 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
@Override @Override
public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) { public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) {
final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(dmc, MIRegisterGroupDMC.class); final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(dmc, MIRegisterGroupDMC.class);
if ( groupDmc == null ) { if (groupDmc == null) {
rm.setStatus( new Status( IStatus.ERROR , GdbPlugin.PLUGIN_ID , INVALID_HANDLE , "RegisterGroup context not found", null ) ) ; //$NON-NLS-1$ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
"RegisterGroup context not found", null)); //$NON-NLS-1$
rm.done(); rm.done();
return; return;
} }
final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class); final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
if ( containerDmc == null ) { if (containerDmc == null) {
rm.setStatus( new Status( IStatus.ERROR , GdbPlugin.PLUGIN_ID , INVALID_HANDLE , "Container context not found" , null ) ) ; //$NON-NLS-1$ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
"Container context not found", null)); //$NON-NLS-1$
rm.done(); rm.done();
return; return;
} }
// There is only one group and its number must be 0. // There is only one group and its number must be 0.
if ( groupDmc.getGroupNo() == 0 ) { if (groupDmc.getGroupNo() == 0) {
final IMIExecutionDMContext executionDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class); final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(dmc, IFrameDMContext.class);
fRegisterNameCache.execute( if (frameDmc == null) {
fCommandFactory.createMIDataListRegisterNames(containerDmc), // The selection does not provide a specific frame, then resolve the top frame on the current thread
new DataRequestMonitor<MIDataListRegisterNamesInfo>(getExecutor(), rm) { 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 @Override
protected void handleSuccess() { protected void handleSuccess() {
// Retrieve the register names. // Retrieve the register names.
String[] regNames = getData().getRegisterNames() ; String[] regNames = getData().getRegisterNames();
// If the list is empty just return empty handed. // If the list is empty just return empty handed.
if ( regNames.length == 0 ) { if (regNames.length == 0) {
rm.done(); rm.done();
return; return;
} }
// Create DMContexts for each of the register names.
if(executionDmc == null) 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)); rm.setData(makeRegisterDMCs(groupDmc, regNames));
else else
rm.setData(makeRegisterDMCs(groupDmc, executionDmc, regNames)); rm.setData(makeRegisterDMCs(groupDmc, frameDmc, regNames));
rm.done(); rm.done();
} }
}); });
} else {
rm.setStatus(new Status(IStatus.ERROR , GdbPlugin.PLUGIN_ID , INTERNAL_ERROR , "Invalid group = " + groupDmc , null)); //$NON-NLS-1$
rm.done();
}
} }
/* /*

View file

@ -20,6 +20,7 @@
* Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536) * Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536)
* Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314) * Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314)
* John Dallaway - Support for -data-write-memory-bytes (Bug 387793) * 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; package org.eclipse.cdt.dsf.mi.service.command;
@ -429,14 +430,30 @@ public class CommandFactory {
return new MIDataListRegisterNames(ctx, regnos); return new MIDataListRegisterNames(ctx, regnos);
} }
@Deprecated
public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) { public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
return new MIDataListRegisterValues(ctx, fmt); return new MIDataListRegisterValues(ctx, fmt);
} }
@Deprecated
public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) { public ICommand<MIDataListRegisterValuesInfo> createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) {
return new MIDataListRegisterValues(ctx, fmt, 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, public ICommand<MIDataReadMemoryInfo> createMIDataReadMemory(IDMContext ctx, long offset, String address,
int word_format, int word_size, int rows, int cols, int word_format, int word_size, int rows, int cols,
Character asChar) { Character asChar) {

View file

@ -8,10 +8,13 @@
* Contributors: * Contributors:
* QNX Software Systems - Initial API and implementation * QNX Software Systems - Initial API and implementation
* Wind River Systems - Modified for new DSF Reference 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; 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.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult; import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
@ -35,12 +38,34 @@ public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValues
int[] regnums; int[] regnums;
int fFmt; int fFmt;
/**
* @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) { public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
this(ctx, fmt, null); this(ctx, fmt, null);
} }
@Deprecated
public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) { public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) {
super(ctx, "-data-list-register-values"); //$NON-NLS-1$ super(ctx, "-data-list-register-values"); //$NON-NLS-1$
init(fmt, regnos);
}
private void init(int fmt, int [] regnos) {
regnums = regnos; regnums = regnos;
String format = "x"; //$NON-NLS-1$ String format = "x"; //$NON-NLS-1$
@ -88,6 +113,15 @@ public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValues
*/ */
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; 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. * 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);
} }
} }

View file

@ -7,15 +7,19 @@
* *
* Contributors: * Contributors:
* Ericsson - initial API and implementation * 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; package org.eclipse.cdt.tests.dsf.gdb.tests;
import static org.junit.Assert.assertEquals; 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 static org.junit.Assert.assertTrue;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; 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.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIProcesses; import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
import org.eclipse.cdt.dsf.mi.service.MIProcesses; 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.events.MIStoppedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIDataListRegisterNamesInfo;
import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfServicesTracker;
@ -280,6 +285,16 @@ public class MIRegistersTest extends BaseTestCase {
final IRegisterDMContext[] regDMCs = getRegisters(frameDmc); final IRegisterDMContext[] regDMCs = getRegisters(frameDmc);
List<String> regNames = get_X86_REGS(); 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[]>() { Query<IRegisterDMData[]> query = new Query<IRegisterDMData[]>() {
@Override @Override
protected void execute(DataRequestMonitor<IRegisterDMData[]> rm) { protected void execute(DataRequestMonitor<IRegisterDMData[]> rm) {
@ -305,12 +320,7 @@ public class MIRegistersTest extends BaseTestCase {
fSession.getExecutor().execute(query); fSession.getExecutor().execute(query);
IRegisterDMData[] datas = query.get(); return 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 { private String getModelDataForRegisterDataValue(IFrameDMContext frameDmc, String format, int regNo) throws Throwable {
@ -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)); 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;
}
} }

View file

@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * 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; 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.IRegisterDMData;
import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData; 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.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.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground; import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelForeground;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
@ -672,6 +674,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode
@Override @Override
public int getDeltaFlags(Object e) { public int getDeltaFlags(Object e) {
if ( e instanceof ISuspendedDMEvent || if ( e instanceof ISuspendedDMEvent ||
e instanceof IResumedDMEvent ||
e instanceof IMemoryChangedEvent || e instanceof IMemoryChangedEvent ||
e instanceof IRegistersChangedDMEvent || e instanceof IRegistersChangedDMEvent ||
(e instanceof PropertyChangeEvent && (e instanceof PropertyChangeEvent &&
@ -697,6 +700,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode
// The following events can affect any register's values, // The following events can affect any register's values,
// refresh the contents of the parent element (i.e. all the registers). // refresh the contents of the parent element (i.e. all the registers).
if ( e instanceof ISuspendedDMEvent || if ( e instanceof ISuspendedDMEvent ||
e instanceof IResumedDMEvent ||
e instanceof IMemoryChangedEvent || e instanceof IMemoryChangedEvent ||
e instanceof IRegistersChangedDMEvent || e instanceof IRegistersChangedDMEvent ||
(e instanceof PropertyChangeEvent && (e instanceof PropertyChangeEvent &&

View file

@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * 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; 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.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; 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.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.DsfDebugUITools;
import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy; import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
@ -169,23 +171,25 @@ public class RegisterVMProvider extends AbstractDMVMProvider
@Override @Override
public void update(IViewerInputUpdate update) { public void update(IViewerInputUpdate update) {
/* /*
* Use the execution context in the current selection as the input provider. * Using the frame context as first alternative to display register values per stack frame
* This insures that the REGISTER VIEW will not collapse and expand on stepping or on * if not available e.g. user selected a thread, the execution context is used instead
* 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.
*/ */
Object element = update.getElement(); Object element = update.getElement();
if (element instanceof IDMVMContext) { if (element instanceof IDMVMContext) {
IDMContext ctx = ((IDMVMContext) element).getDMContext(); IDMContext ctx = ((IDMVMContext) element).getDMContext();
IExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class); IDMContext selDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
if ( execDmc != null ) { 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 * 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 * 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. * 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(); update.done();
return; return;
} }