From 6c85c85a06dd20276ee65642c2d9c48dca0fd4e0 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Wed, 18 Sep 2013 09:09:16 -0400 Subject: [PATCH] Bug 323552: [registers] Register View content is not stack frame specific Change-Id: Ib7922f8487d10e3b9cb5b6dcb255590cc31d2a97 Signed-off-by: Alvaro Sanchez-Leon Reviewed-on: https://git.eclipse.org/r/16566 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../cdt/dsf/mi/service/MIRegisters.java | 192 ++++++++++++------ .../mi/service/command/CommandFactory.java | 17 ++ .../commands/MIDataListRegisterValues.java | 48 ++++- .../tests/dsf/gdb/tests/MIRegistersTest.java | 101 ++++++++- .../ui/viewmodel/register/RegisterVMNode.java | 4 + .../register/RegisterVMProvider.java | 24 ++- 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 cb2cbd4d9b3..817438db480 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 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(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 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(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 regDmcList = new ArrayList( 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 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 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(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(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 rm) { + + fRegisterNameCache.execute(fCommandFactory.createMIDataListRegisterNames(containerDmc), + new ImmediateDataRequestMonitor(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 10c1ff8b2fb..c58ef521201 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 createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) { return new MIDataListRegisterValues(ctx, fmt); } + @Deprecated public ICommand createMIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) { return new MIDataListRegisterValues(ctx, fmt, regnos); } + + /** + * @since 4.3 + */ + public ICommand createMIDataListRegisterValues(IFrameDMContext ctx, int fmt) { + return new MIDataListRegisterValues(ctx, fmt); + } + + /** + * @since 4.3 + */ + public ICommand createMIDataListRegisterValues(IFrameDMContext ctx, int fmt, int [] regnos) { + return new MIDataListRegisterValues(ctx, fmt, regnos); + } public ICommand 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 ead7f3f22a6..5599f6fc068 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 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 query = new Query() { @Override protected void execute(DataRequestMonitor 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 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 81dafb8f28d..1a4e393859c 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 8bb035c73c1..1835d0cda74 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; }