diff options
author | Alena Laskavaia | 2015-01-29 15:58:54 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2015-01-29 19:43:39 +0000 |
commit | 5df84dcfe0d5b55210ae490a0b2982f192e304d7 (patch) | |
tree | 0ce460f16475e195def3f6834fc26b5b52410952 /dsf-gdb | |
parent | 196d978624fcb25c379728d10ddfa50be16b6c5d (diff) | |
download | org.eclipse.cdt-5df84dcfe0d5b55210ae490a0b2982f192e304d7.tar.gz org.eclipse.cdt-5df84dcfe0d5b55210ae490a0b2982f192e304d7.tar.xz org.eclipse.cdt-5df84dcfe0d5b55210ae490a0b2982f192e304d7.zip |
MIStack correct code style
- removed trailing whitespace
- added/removed curly braces according to cdt style
- corrected indentation using tabs only policy
Change-Id: I605f68ed47753e0486aef42049f2e7392cadf9d0
Signed-off-by: Alena Laskavaia <elaskavaia.cdt@gmail.com>
Diffstat (limited to 'dsf-gdb')
-rw-r--r-- | dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java | 1777 |
1 files changed, 892 insertions, 885 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java index 3a4e1ab1ae2..f0a3f076193 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java @@ -4,11 +4,11 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Wind River Systems - initial API and implementation - * Ericsson - Modified for handling of multiple execution contexts - * Marc Khouzam (Ericsson) - Show return value of the method when doing a step-return (Bug 341731) + * Ericsson - Modified for handling of multiple execution contexts + * Marc Khouzam (Ericsson) - Show return value of the method when doing a step-return (Bug 341731) *******************************************************************************/ package org.eclipse.cdt.dsf.mi.service; @@ -64,108 +64,112 @@ import org.eclipse.core.runtime.Status; import org.osgi.framework.BundleContext; public class MIStack extends AbstractDsfService - implements IStack, ICachingService +implements IStack, ICachingService { - protected static class MIFrameDMC extends AbstractDMContext - implements IFrameDMContext - { - private final int fLevel; - public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) { - super(sessionId, new IDMContext[] { execDmc }); - fLevel = level; - } - - @Override - public int getLevel() { return fLevel; } - - @Override - public boolean equals(Object other) { - return super.baseEquals(other) && ((MIFrameDMC)other).fLevel == fLevel; - } - - @Override - public int hashCode() { - return super.baseHashCode() ^ fLevel; - } - - @Override - public String toString() { - return baseToString() + ".frame[" + fLevel + "]"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - protected static class MIVariableDMC extends AbstractDMContext - implements IVariableDMContext - { - public enum Type { ARGUMENT, LOCAL, /** @since 4.4 */RETURN_VALUES } - final private Type fType; - final private int fIndex; - - public MIVariableDMC(MIStack service, IFrameDMContext frame, Type type, int index) { - super(service, new IDMContext[] { frame }); - fIndex = index; - fType = type; - } - - public int getIndex() { return fIndex; } - public Type getType() { return fType; } - - @Override - public boolean equals(Object other) { - return super.baseEquals(other) && - ((MIVariableDMC)other).fType == fType && - ((MIVariableDMC)other).fIndex == fIndex; - } - - @Override - public int hashCode() { - int typeFactor = 0; - if (fType == Type.LOCAL) typeFactor = 2; - else if (fType == Type.ARGUMENT) typeFactor = 3; - else if (fType == Type.RETURN_VALUES) typeFactor = 4; - return super.baseHashCode() ^ typeFactor ^ fIndex; - } - - @Override - public String toString() { - return baseToString() + ".variable(" + fType + ")[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - } - - /** - * Class to track stack depth requests for our internal cache - */ - private class StackDepthInfo { - // The maximum depth we requested - public int maxDepthRequested; - // The actual depth we received - public int returnedDepth; - - StackDepthInfo(int requested, int returned) { - maxDepthRequested = requested; - returnedDepth = returned; - } - } - - /** - * A HashMap for our StackDepth cache, that can clear based on a context. - */ - @SuppressWarnings("serial") - private class StackDepthHashMap<V,T> extends HashMap<V,T> { - public void clear(IDMContext context) { - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); - if (execDmc != null) { - remove(execDmc.getThreadId()); - } else { - clear(); - }; - } - } - - /** - * Same as with frame objects, this is a base class for the IVariableDMData object that uses an MIArg object to - * provide the data. Sub-classes must supply the MIArg object. - */ + protected static class MIFrameDMC extends AbstractDMContext + implements IFrameDMContext + { + private final int fLevel; + public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) { + super(sessionId, new IDMContext[] { execDmc }); + fLevel = level; + } + + @Override + public int getLevel() { return fLevel; } + + @Override + public boolean equals(Object other) { + return super.baseEquals(other) && ((MIFrameDMC)other).fLevel == fLevel; + } + + @Override + public int hashCode() { + return super.baseHashCode() ^ fLevel; + } + + @Override + public String toString() { + return baseToString() + ".frame[" + fLevel + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + protected static class MIVariableDMC extends AbstractDMContext + implements IVariableDMContext + { + public enum Type { ARGUMENT, LOCAL, /** @since 4.4 */RETURN_VALUES } + final private Type fType; + final private int fIndex; + + public MIVariableDMC(MIStack service, IFrameDMContext frame, Type type, int index) { + super(service, new IDMContext[] { frame }); + fIndex = index; + fType = type; + } + + public int getIndex() { return fIndex; } + public Type getType() { return fType; } + + @Override + public boolean equals(Object other) { + return super.baseEquals(other) && + ((MIVariableDMC)other).fType == fType && + ((MIVariableDMC)other).fIndex == fIndex; + } + + @Override + public int hashCode() { + int typeFactor = 0; + if (fType == Type.LOCAL) { + typeFactor = 2; + } else if (fType == Type.ARGUMENT) { + typeFactor = 3; + } else if (fType == Type.RETURN_VALUES) { + typeFactor = 4; + } + return super.baseHashCode() ^ typeFactor ^ fIndex; + } + + @Override + public String toString() { + return baseToString() + ".variable(" + fType + ")[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + + /** + * Class to track stack depth requests for our internal cache + */ + private class StackDepthInfo { + // The maximum depth we requested + public int maxDepthRequested; + // The actual depth we received + public int returnedDepth; + + StackDepthInfo(int requested, int returned) { + maxDepthRequested = requested; + returnedDepth = returned; + } + } + + /** + * A HashMap for our StackDepth cache, that can clear based on a context. + */ + @SuppressWarnings("serial") + private class StackDepthHashMap<V,T> extends HashMap<V,T> { + public void clear(IDMContext context) { + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + if (execDmc != null) { + remove(execDmc.getThreadId()); + } else { + clear(); + }; + } + } + + /** + * Same as with frame objects, this is a base class for the IVariableDMData object that uses an MIArg object to + * provide the data. Sub-classes must supply the MIArg object. + */ private class VariableData implements IVariableDMData { private MIArg fMIArg; @@ -174,17 +178,17 @@ public class MIStack extends AbstractDsfService } @Override - public String getName() { - return fMIArg.getName(); + public String getName() { + return fMIArg.getName(); } - + @Override - public String getValue() { - return fMIArg.getValue(); + public String getValue() { + return fMIArg.getValue(); } - + @Override - public String toString() { + public String toString() { return fMIArg.toString(); } } @@ -192,7 +196,7 @@ public class MIStack extends AbstractDsfService private CommandCache fMICommandCache; private CommandFactory fCommandFactory; - // Two commands such as + // Two commands such as // -stack-info-depth 11 // -stack-info-depth 2 // would both be sent to GDB because the command cache sees them as different. @@ -200,48 +204,47 @@ public class MIStack extends AbstractDsfService // we can potentially re-use the answer. private StackDepthHashMap<Integer, StackDepthInfo> fStackDepthCache = new StackDepthHashMap<Integer, StackDepthInfo>(); - private MIStoppedEvent fCachedStoppedEvent; - private IRunControl fRunControl; + private MIStoppedEvent fCachedStoppedEvent; + private IRunControl fRunControl; - /** + /** * Indicates that we are currently visualizing trace data. * In this case, some errors should not be reported. */ private boolean fTraceVisualization; /** - * A Map of a return value for each thread. + * A Map of a return value for each thread. * A return value is stored when the user performs a step-return, * and it cleared as soon as that thread executes again. */ private Map<IMIExecutionDMContext, VariableData> fThreadToReturnVariable = new HashMap<IMIExecutionDMContext, VariableData>(); - public MIStack(DsfSession session) + public MIStack(DsfSession session) { super(session); } - @Override - protected BundleContext getBundleContext() - { - return GdbPlugin.getBundleContext(); - } - - @Override - public void initialize(final RequestMonitor rm) { - super.initialize( - new ImmediateRequestMonitor(rm) { - @Override - protected void handleSuccess() { - doInitialize(rm); - } - }); - } - - private void doInitialize(RequestMonitor rm) { - ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class); + @Override + protected BundleContext getBundleContext() { + return GdbPlugin.getBundleContext(); + } + + @Override + public void initialize(final RequestMonitor rm) { + super.initialize( + new ImmediateRequestMonitor(rm) { + @Override + protected void handleSuccess() { + doInitialize(rm); + } + }); + } + + private void doInitialize(RequestMonitor rm) { + ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class); BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2); - + // This cache stores the result of a command when received; also, this cache // is manipulated when receiving events. Currently, events are received after // three scheduling of the executor, while command results after only one. This @@ -250,248 +253,246 @@ public class MIStack extends AbstractDsfService // To solve this, we use a bufferedCommandControl that will delay the command // result by two scheduling of the executor. // See bug 280461 - fMICommandCache = new CommandCache(getSession(), bufferedCommandControl); - fMICommandCache.setContextAvailable(commandControl.getContext(), true); - fRunControl = getServicesTracker().getService(IRunControl.class); - - fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); - - getSession().addServiceEventListener(this, null); - register(new String[]{IStack.class.getName(), MIStack.class.getName()}, new Hashtable<String,String>()); - rm.done(); - } - - @Override - public void shutdown(RequestMonitor rm) - { - unregister(); - getSession().removeServiceEventListener(this); - fMICommandCache.reset(); - super.shutdown(rm); - } - - /** - * Creates a frame context. This method is intended to be used by other MI - * services and sub-classes which need to create a frame context directly. - * <p> - * Sub-classes can override this method to provide custom stack frame - * context implementation. - * </p> - * @param execDmc Execution context that this frame is to be a child of. - * @param level Level of the new context. - * @return A new frame context. - */ - public IFrameDMContext createFrameDMContext(IExecutionDMContext execDmc, int level) { - return new MIFrameDMC(getSession().getId(), execDmc, level); - } - + fMICommandCache = new CommandCache(getSession(), bufferedCommandControl); + fMICommandCache.setContextAvailable(commandControl.getContext(), true); + fRunControl = getServicesTracker().getService(IRunControl.class); + + fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + + getSession().addServiceEventListener(this, null); + register(new String[]{IStack.class.getName(), MIStack.class.getName()}, new Hashtable<String,String>()); + rm.done(); + } + @Override - public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) { - getFrames(ctx, 0, ALL_FRAMES, rm); - } + public void shutdown(RequestMonitor rm) + { + unregister(); + getSession().removeServiceEventListener(this); + fMICommandCache.reset(); + super.shutdown(rm); + } + + /** + * Creates a frame context. This method is intended to be used by other MI + * services and sub-classes which need to create a frame context directly. + * <p> + * Sub-classes can override this method to provide custom stack frame + * context implementation. + * </p> + * @param execDmc Execution context that this frame is to be a child of. + * @param level Level of the new context. + * @return A new frame context. + */ + public IFrameDMContext createFrameDMContext(IExecutionDMContext execDmc, int level) { + return new MIFrameDMC(getSession().getId(), execDmc, level); + } + + @Override + public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) { + getFrames(ctx, 0, ALL_FRAMES, rm); + } @Override public void getFrames(final IDMContext ctx, final int startIndex, final int endIndex, final DataRequestMonitor<IFrameDMContext[]> rm) { - if (startIndex < 0 || endIndex > 0 && endIndex < startIndex) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid stack frame range [" + startIndex + ',' + endIndex + ']', null)); //$NON-NLS-1$ - rm.done(); - return; - } + if (startIndex < 0 || endIndex > 0 && endIndex < startIndex) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid stack frame range [" + startIndex + ',' + endIndex + ']', null)); //$NON-NLS-1$ + rm.done(); + return; + } final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class); - - if (execDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Make sure the thread is stopped but only if we are not visualizing trace data - if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context is running: " + ctx, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - if (startIndex == 0 && endIndex == 0) { - // Try to retrieve the top stack frame from the cached stopped event. - if (fCachedStoppedEvent != null && - fCachedStoppedEvent.getFrame() != null && - execDmc.equals(fCachedStoppedEvent.getDMContext())) - { - rm.setData(new IFrameDMContext[] { createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()) }); - rm.done(); - return; - } - } - - final ICommand<MIStackListFramesInfo> miStackListCmd; - // firstIndex is the first index retrieved - final int firstIndex; - if (endIndex >= 0) { - miStackListCmd = fCommandFactory.createMIStackListFrames(execDmc, startIndex, endIndex); - firstIndex = startIndex; - } else { - miStackListCmd = fCommandFactory.createMIStackListFrames(execDmc); - firstIndex = 0; - } + + if (execDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Make sure the thread is stopped but only if we are not visualizing trace data + if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context is running: " + ctx, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + if (startIndex == 0 && endIndex == 0) { + // Try to retrieve the top stack frame from the cached stopped event. + if (fCachedStoppedEvent != null && + fCachedStoppedEvent.getFrame() != null && + execDmc.equals(fCachedStoppedEvent.getDMContext())) + { + rm.setData(new IFrameDMContext[] { createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()) }); + rm.done(); + return; + } + } + + final ICommand<MIStackListFramesInfo> miStackListCmd; + // firstIndex is the first index retrieved + final int firstIndex; + if (endIndex >= 0) { + miStackListCmd = fCommandFactory.createMIStackListFrames(execDmc, startIndex, endIndex); + firstIndex = startIndex; + } else { + miStackListCmd = fCommandFactory.createMIStackListFrames(execDmc); + firstIndex = 0; + } fMICommandCache.execute( - miStackListCmd, - new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - rm.setData(getFrames(execDmc, getData(), firstIndex, endIndex, startIndex)); - rm.done(); - } - }); + miStackListCmd, + new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + rm.setData(getFrames(execDmc, getData(), firstIndex, endIndex, startIndex)); + rm.done(); + } + }); } - + @Override - public void getTopFrame(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext> rm) { - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class); - if (execDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Try to retrieve the top stack frame from the cached stopped event. - if (fCachedStoppedEvent != null && - fCachedStoppedEvent.getFrame() != null && - execDmc.equals(fCachedStoppedEvent.getDMContext())) - { - rm.setData(createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel())); - rm.done(); - return; - } - - // If stopped event is not available or doesn't contain frame info, - // query top stack frame - getFrames( - ctx, - 0, - 0, - new DataRequestMonitor<IFrameDMContext[]>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - rm.setData(getData()[0]); - rm.done(); - } - }); - } - - private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) { - int length = info.getMIFrames().length; - if (lastIndex > 0) { - int limit= lastIndex - startIndex + 1; - if (limit < length) { - length = limit; - } - } + public void getTopFrame(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext> rm) { + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class); + if (execDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Try to retrieve the top stack frame from the cached stopped event. + if (fCachedStoppedEvent != null && + fCachedStoppedEvent.getFrame() != null && + execDmc.equals(fCachedStoppedEvent.getDMContext())) + { + rm.setData(createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel())); + rm.done(); + return; + } + + // If stopped event is not available or doesn't contain frame info, + // query top stack frame + getFrames( + ctx, + 0, + 0, + new DataRequestMonitor<IFrameDMContext[]>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + rm.setData(getData()[0]); + rm.done(); + } + }); + } + + private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) { + int length = info.getMIFrames().length; + if (lastIndex > 0) { + int limit= lastIndex - startIndex + 1; + if (limit < length) { + length = limit; + } + } IFrameDMContext[] frameDMCs = new MIFrameDMC[length]; - for (int i = 0; i < length; i++) { - //frameDMCs[i] = new MIFrameDMC(this, info.getMIFrames()[i].getLevel()); - final MIFrame frame= info.getMIFrames()[i + startIndex - firstIndex]; + for (int i = 0; i < length; i++) { + //frameDMCs[i] = new MIFrameDMC(this, info.getMIFrames()[i].getLevel()); + final MIFrame frame= info.getMIFrames()[i + startIndex - firstIndex]; assert startIndex + i == frame.getLevel(); - frameDMCs[i] = createFrameDMContext(execDmc, frame.getLevel()); - } - return frameDMCs; - } - + frameDMCs[i] = createFrameDMContext(execDmc, frame.getLevel()); + } + return frameDMCs; + } + + - @Override - public void getFrameData(final IFrameDMContext frameDmc, final DataRequestMonitor<IFrameDMData> rm) { - if (!(frameDmc instanceof MIFrameDMC)) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - final MIFrameDMC miFrameDmc = (MIFrameDMC)frameDmc; - - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); - if (execDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - /** - * Base class for the IFrameDMData object that uses an MIFrame object to - * provide the data. Sub-classes must provide the MIFrame object - */ - abstract class FrameData implements IFrameDMData - { - abstract protected MIFrame getMIFrame(); - - @Override - public IAddress getAddress() { - String addr = getMIFrame().getAddress(); - if (addr == null || addr.length() == 0) { - return new Addr32(0); - } - if (addr.startsWith("0x")) { //$NON-NLS-1$ - addr = addr.substring(2); - } - if (addr.length() <= 8) { - return new Addr32(getMIFrame().getAddress()); - } else { - return new Addr64(getMIFrame().getAddress()); - } - } - - @Override - public int getColumn() { return 0; } - - @Override - public String getFile() { return getMIFrame().getFile(); } - @Override - public int getLine() { return getMIFrame().getLine(); } - @Override - public String getFunction() { return getMIFrame().getFunction(); } - @Override - public String getModule() { return ""; }//$NON-NLS-1$ - - @Override - public String toString() { return getMIFrame().toString(); } - } - - // If requested frame is the top stack frame, try to retrieve it from - // the stopped event data. - class FrameDataFromStoppedEvent extends FrameData { - private final MIStoppedEvent fEvent; - FrameDataFromStoppedEvent(MIStoppedEvent event) { fEvent = event; } - @Override - protected MIFrame getMIFrame() { return fEvent.getFrame(); } - } - - // Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event - // is raised - if (miFrameDmc.fLevel == 0) { - if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null && - (execDmc.equals(fCachedStoppedEvent.getDMContext()) || fTraceVisualization)) - { - rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent)); - rm.done(); - return; - } - } - - // If not, retrieve the full list of frame data. - class FrameDataFromMIStackFrameListInfo extends FrameData { - private MIStackListFramesInfo fFrameDataCacheInfo; - private int fFrameIndex; - - FrameDataFromMIStackFrameListInfo(MIStackListFramesInfo info, int index) { - fFrameDataCacheInfo = info; - fFrameIndex = index; - } - - @Override - protected MIFrame getMIFrame() { return fFrameDataCacheInfo.getMIFrames()[fFrameIndex]; } - } + public void getFrameData(final IFrameDMContext frameDmc, final DataRequestMonitor<IFrameDMData> rm) { + if (!(frameDmc instanceof MIFrameDMC)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + final MIFrameDMC miFrameDmc = (MIFrameDMC)frameDmc; + + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); + if (execDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + /** + * Base class for the IFrameDMData object that uses an MIFrame object to + * provide the data. Sub-classes must provide the MIFrame object + */ + abstract class FrameData implements IFrameDMData + { + abstract protected MIFrame getMIFrame(); + + @Override + public IAddress getAddress() { + String addr = getMIFrame().getAddress(); + if (addr == null || addr.length() == 0) + return new Addr32(0); + if (addr.startsWith("0x")) { //$NON-NLS-1$ + addr = addr.substring(2); + } + if (addr.length() <= 8) + return new Addr32(getMIFrame().getAddress()); + else + return new Addr64(getMIFrame().getAddress()); + } + + @Override + public int getColumn() { return 0; } + + @Override + public String getFile() { return getMIFrame().getFile(); } + @Override + public int getLine() { return getMIFrame().getLine(); } + @Override + public String getFunction() { return getMIFrame().getFunction(); } + @Override + public String getModule() { return ""; }//$NON-NLS-1$ + + @Override + public String toString() { return getMIFrame().toString(); } + } + + // If requested frame is the top stack frame, try to retrieve it from + // the stopped event data. + class FrameDataFromStoppedEvent extends FrameData { + private final MIStoppedEvent fEvent; + FrameDataFromStoppedEvent(MIStoppedEvent event) { fEvent = event; } + @Override + protected MIFrame getMIFrame() { return fEvent.getFrame(); } + } + + // Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event + // is raised + if (miFrameDmc.fLevel == 0) { + if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null && + (execDmc.equals(fCachedStoppedEvent.getDMContext()) || fTraceVisualization)) + { + rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent)); + rm.done(); + return; + } + } + + // If not, retrieve the full list of frame data. + class FrameDataFromMIStackFrameListInfo extends FrameData { + private MIStackListFramesInfo fFrameDataCacheInfo; + private int fFrameIndex; + + FrameDataFromMIStackFrameListInfo(MIStackListFramesInfo info, int index) { + fFrameDataCacheInfo = info; + fFrameIndex = index; + } + + @Override + protected MIFrame getMIFrame() { return fFrameDataCacheInfo.getMIFrames()[fFrameIndex]; } + } fMICommandCache.execute( fCommandFactory.createMIStackListFrames(execDmc), @@ -540,414 +541,419 @@ public class MIStack extends AbstractDsfService }); } }); - } + } @Override public void getArguments(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) { - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); - if (execDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - - // If requested frame is the top stack frame, try to retrieve it from - // the stopped event data. - if (frameDmc.getLevel() == 0 && - fCachedStoppedEvent != null && - fCachedStoppedEvent.getFrame() != null && - execDmc.equals(fCachedStoppedEvent.getDMContext()) && - fCachedStoppedEvent.getFrame().getArgs() != null) - { - rm.setData(makeVariableDMCs( - frameDmc, MIVariableDMC.Type.ARGUMENT, fCachedStoppedEvent.getFrame().getArgs())); - rm.done(); - return; - } - - // If not, retrieve the full list of frame data. Although we only need one frame - // for this call, it will be stored the cache and made available for other calls. - fMICommandCache.execute( - // We don't actually need to ask for the values in this case, but since - // we will ask for them right after, it is more efficient to ask for them now - // so as to cache the result. If the command fails, then we will ask for - // the result without the values - // Don't ask for value when we are visualizing trace data, since some - // data will not be there, and the command will fail - fCommandFactory.createMIStackListArguments(execDmc, true), - new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - // Find the index to the correct MI frame object. - // Note: this is a short-cut, but it won't work once we implement retrieving - // partial lists of stack frames. - int idx = frameDmc.getLevel(); - if (idx == -1 || idx >= getData().getMIFrames().length) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Create the variable array out of MIArg array. - MIArg[] args = getData().getMIFrames()[idx].getArgs(); - if (args == null) args = new MIArg[0]; - rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args)); - rm.done(); - } - @Override - protected void handleError() { - // If the command fails it can be because we asked for values. - // This can happen with uninitialized values and pretty printers (bug 307614). - // Since asking for values was simply an optimization - // to store the command in the cache, let's retry the command without asking for values. - fMICommandCache.execute( - fCommandFactory.createMIStackListArguments(execDmc, false), - new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - // Find the index to the correct MI frame object. - // Note: this is a short-cut, but it won't work once we implement retrieving - // partial lists of stack frames. - int idx = frameDmc.getLevel(); - if (idx == -1 || idx >= getData().getMIFrames().length) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Create the variable array out of MIArg array. - MIArg[] args = getData().getMIFrames()[idx].getArgs(); - if (args == null) args = new MIArg[0]; - rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args)); - rm.done(); - } - }); - } - }); - } - + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); + if (execDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + + // If requested frame is the top stack frame, try to retrieve it from + // the stopped event data. + if (frameDmc.getLevel() == 0 && + fCachedStoppedEvent != null && + fCachedStoppedEvent.getFrame() != null && + execDmc.equals(fCachedStoppedEvent.getDMContext()) && + fCachedStoppedEvent.getFrame().getArgs() != null) + { + rm.setData(makeVariableDMCs( + frameDmc, MIVariableDMC.Type.ARGUMENT, fCachedStoppedEvent.getFrame().getArgs())); + rm.done(); + return; + } + + // If not, retrieve the full list of frame data. Although we only need one frame + // for this call, it will be stored the cache and made available for other calls. + fMICommandCache.execute( + // We don't actually need to ask for the values in this case, but since + // we will ask for them right after, it is more efficient to ask for them now + // so as to cache the result. If the command fails, then we will ask for + // the result without the values + // Don't ask for value when we are visualizing trace data, since some + // data will not be there, and the command will fail + fCommandFactory.createMIStackListArguments(execDmc, true), + new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Find the index to the correct MI frame object. + // Note: this is a short-cut, but it won't work once we implement retrieving + // partial lists of stack frames. + int idx = frameDmc.getLevel(); + if (idx == -1 || idx >= getData().getMIFrames().length) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Create the variable array out of MIArg array. + MIArg[] args = getData().getMIFrames()[idx].getArgs(); + if (args == null) { + args = new MIArg[0]; + } + rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args)); + rm.done(); + } + @Override + protected void handleError() { + // If the command fails it can be because we asked for values. + // This can happen with uninitialized values and pretty printers (bug 307614). + // Since asking for values was simply an optimization + // to store the command in the cache, let's retry the command without asking for values. + fMICommandCache.execute( + fCommandFactory.createMIStackListArguments(execDmc, false), + new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Find the index to the correct MI frame object. + // Note: this is a short-cut, but it won't work once we implement retrieving + // partial lists of stack frames. + int idx = frameDmc.getLevel(); + if (idx == -1 || idx >= getData().getMIFrames().length) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Create the variable array out of MIArg array. + MIArg[] args = getData().getMIFrames()[idx].getArgs(); + if (args == null) { + args = new MIArg[0]; + } + rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args)); + rm.done(); + } + }); + } + }); + } + @Override - public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) { - if (!(variableDmc instanceof MIVariableDMC)) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - final MIVariableDMC miVariableDmc = (MIVariableDMC)variableDmc; - - // Extract the frame DMC from the variable DMC. - final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(variableDmc, MIFrameDMC.class); - if (frameDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No frame context found in " + variableDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); - if (execDmc == null) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Check if the stopped event can be used to extract the variable value. - if (execDmc != null && miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT && - frameDmc.fLevel == 0 && fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null && - execDmc.equals(fCachedStoppedEvent.getDMContext()) && - fCachedStoppedEvent.getFrame().getArgs() != null) - { - if (miVariableDmc.fIndex >= fCachedStoppedEvent.getFrame().getArgs().length) { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - rm.setData(new VariableData(fCachedStoppedEvent.getFrame().getArgs()[miVariableDmc.fIndex])); - rm.done(); - return; - } - - if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){ - fMICommandCache.execute( - // Don't ask for value when we are visualizing trace data, since some - // data will not be there, and the command will fail - fCommandFactory.createMIStackListArguments(execDmc, true), - new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - // Find the correct frame and argument - if ( frameDmc.fLevel >= getData().getMIFrames().length || - miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length ) - { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Create the data object. - rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex])); - rm.done(); - } - @Override - protected void handleError() { - // Unable to get the values. This can happen with uninitialized values and pretty printers (bug 307614) - // Let's try to ask for the arguments without their values, which is better than nothing - fMICommandCache.execute( - fCommandFactory.createMIStackListArguments(execDmc, false), - new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - // Find the correct frame and argument - if ( frameDmc.fLevel >= getData().getMIFrames().length || - miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length ) - { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Create the data object. - rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex])); - rm.done(); - } - }); - } - }); - } else if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){ - fMICommandCache.execute( - // Don't ask for value when we are visualizing trace data, since some - // data will not be there, and the command will fail - fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), - new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - - // Create the data object. - MIArg[] locals = getData().getLocals(); - if (locals.length > miVariableDmc.fIndex) { - rm.setData(new VariableData(locals[miVariableDmc.fIndex])); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ - } - rm.done(); - } - @Override - protected void handleError() { - // Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614). - // Let's try to ask for the variables without their values, which is better than nothing - fMICommandCache.execute( - fCommandFactory.createMIStackListLocals(frameDmc, false), - new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - - // Create the data object. - MIArg[] locals = getData().getLocals(); - if (locals.length > miVariableDmc.fIndex) { - rm.setData(new VariableData(locals[miVariableDmc.fIndex])); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ - } - rm.done(); - } - }); - } - }); - } else if (miVariableDmc.fType == MIVariableDMC.Type.RETURN_VALUES) { - VariableData var = fThreadToReturnVariable.get(execDmc); - if (var != null) { - rm.setData(var); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Return value not found", null)); //$NON-NLS-1$ - } - rm.done(); - } else { - rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable type " + miVariableDmc.fType, null)); //$NON-NLS-1$ - } - - } - - private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, MIArg[] miArgs) { - // Use LinkedHashMap in order to keep the original ordering. - // We don't currently support variables with the same name in the same frame, - // so we only keep the first one. - // Bug 327621 and 328573 - Map<String, MIVariableDMC> variableNames = new LinkedHashMap<String, MIVariableDMC>(); - - for (int i = 0; i < miArgs.length; i++) { - String name = miArgs[i].getName(); - MIVariableDMC var = variableNames.get(name); - - if (var == null) { - variableNames.put(name, new MIVariableDMC(this, frame, type, i)); - } - } - - return variableNames.values().toArray(new MIVariableDMC[0]); - } - - private int findFrameIndex(MIFrame[] frames, int level) { - for (int idx = 0; idx < frames.length; idx++) { - if (frames[idx].getLevel() == level) { - return idx; - } - } - return -1; - } - - /** - * Retrieves variables which are used to store the return values of functions. - */ - private void getReturnValues(IFrameDMContext frameDmc, DataRequestMonitor<IVariableDMContext[]> rm) { + public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) { + if (!(variableDmc instanceof MIVariableDMC)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + final MIVariableDMC miVariableDmc = (MIVariableDMC)variableDmc; + + // Extract the frame DMC from the variable DMC. + final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(variableDmc, MIFrameDMC.class); + if (frameDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No frame context found in " + variableDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); + if (execDmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Check if the stopped event can be used to extract the variable value. + if (execDmc != null && miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT && + frameDmc.fLevel == 0 && fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null && + execDmc.equals(fCachedStoppedEvent.getDMContext()) && + fCachedStoppedEvent.getFrame().getArgs() != null) + { + if (miVariableDmc.fIndex >= fCachedStoppedEvent.getFrame().getArgs().length) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + rm.setData(new VariableData(fCachedStoppedEvent.getFrame().getArgs()[miVariableDmc.fIndex])); + rm.done(); + return; + } + + if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){ + fMICommandCache.execute( + // Don't ask for value when we are visualizing trace data, since some + // data will not be there, and the command will fail + fCommandFactory.createMIStackListArguments(execDmc, true), + new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Find the correct frame and argument + if ( frameDmc.fLevel >= getData().getMIFrames().length || + miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length ) + { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Create the data object. + rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex])); + rm.done(); + } + @Override + protected void handleError() { + // Unable to get the values. This can happen with uninitialized values and pretty printers (bug 307614) + // Let's try to ask for the arguments without their values, which is better than nothing + fMICommandCache.execute( + fCommandFactory.createMIStackListArguments(execDmc, false), + new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Find the correct frame and argument + if ( frameDmc.fLevel >= getData().getMIFrames().length || + miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length ) + { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Create the data object. + rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex])); + rm.done(); + } + }); + } + }); + } else if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){ + fMICommandCache.execute( + // Don't ask for value when we are visualizing trace data, since some + // data will not be there, and the command will fail + fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), + new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Create the data object. + MIArg[] locals = getData().getLocals(); + if (locals.length > miVariableDmc.fIndex) { + rm.setData(new VariableData(locals[miVariableDmc.fIndex])); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ + } + rm.done(); + } + @Override + protected void handleError() { + // Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614). + // Let's try to ask for the variables without their values, which is better than nothing + fMICommandCache.execute( + fCommandFactory.createMIStackListLocals(frameDmc, false), + new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Create the data object. + MIArg[] locals = getData().getLocals(); + if (locals.length > miVariableDmc.fIndex) { + rm.setData(new VariableData(locals[miVariableDmc.fIndex])); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$ + } + rm.done(); + } + }); + } + }); + } else if (miVariableDmc.fType == MIVariableDMC.Type.RETURN_VALUES) { + VariableData var = fThreadToReturnVariable.get(execDmc); + if (var != null) { + rm.setData(var); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Return value not found", null)); //$NON-NLS-1$ + } + rm.done(); + } else { + rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable type " + miVariableDmc.fType, null)); //$NON-NLS-1$ + } + + } + + private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, MIArg[] miArgs) { + // Use LinkedHashMap in order to keep the original ordering. + // We don't currently support variables with the same name in the same frame, + // so we only keep the first one. + // Bug 327621 and 328573 + Map<String, MIVariableDMC> variableNames = new LinkedHashMap<String, MIVariableDMC>(); + + for (int i = 0; i < miArgs.length; i++) { + String name = miArgs[i].getName(); + MIVariableDMC var = variableNames.get(name); + + if (var == null) { + variableNames.put(name, new MIVariableDMC(this, frame, type, i)); + } + } + + return variableNames.values().toArray(new MIVariableDMC[0]); + } + + private int findFrameIndex(MIFrame[] frames, int level) { + for (int idx = 0; idx < frames.length; idx++) { + if (frames[idx].getLevel() == level) + return idx; + } + return -1; + } + + /** + * Retrieves variables which are used to store the return values of functions. + */ + private void getReturnValues(IFrameDMContext frameDmc, DataRequestMonitor<IVariableDMContext[]> rm) { IVariableDMContext[] values = new IVariableDMContext[0]; // Return values are only relevant for the top stack-frame if (!fTraceVisualization && frameDmc.getLevel() == 0) { - IMIExecutionDMContext threadDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); - VariableData var = fThreadToReturnVariable.get(threadDmc); - if (var != null) { - values = new IVariableDMContext[1]; - values[0] = new MIVariableDMC(this, frameDmc, MIVariableDMC.Type.RETURN_VALUES, 0); - } - } + IMIExecutionDMContext threadDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class); + VariableData var = fThreadToReturnVariable.get(threadDmc); + if (var != null) { + values = new IVariableDMContext[1]; + values[0] = new MIVariableDMC(this, frameDmc, MIVariableDMC.Type.RETURN_VALUES, 0); + } + } rm.done(values); } - + @Override - public void getLocals(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) { - - final List<IVariableDMContext> localsList = new ArrayList<IVariableDMContext>(); - - final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) { - @Override - protected void handleSuccess() { - rm.setData( localsList.toArray(new IVariableDMContext[localsList.size()]) ); - rm.done(); - } - }; - countingRm.setDoneCount(3); - - // First show any return values of methods - getReturnValues( - frameDmc, - new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) { - @Override - protected void handleSuccess() { - localsList.addAll( Arrays.asList(getData()) ); - countingRm.done(); - } - }); - - // Then show arguments - getArguments( - frameDmc, - new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) { - @Override - protected void handleSuccess() { - localsList.addAll( Arrays.asList(getData()) ); - countingRm.done(); - } - }); - - // Finally get the local variables - fMICommandCache.execute( - // We don't actually need to ask for the values in this case, but since - // we will ask for them right after, it is more efficient to ask for them now - // so as to cache the result. If the command fails, then we will ask for - // the result without the values - // Don't ask for value when we are visualizing trace data, since some - // data will not be there, and the command will fail - fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), - new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { - @Override - protected void handleSuccess() { - localsList.addAll( Arrays.asList( - makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals())) ); - countingRm.done(); - } - @Override - protected void handleError() { - // If the command fails it can be because we asked for values. - // This can happen with uninitialized values and pretty printers (bug 307614). - // Since asking for values was simply an optimization - // to store the command in the cache, let's retry the command without asking for values. - fMICommandCache.execute( - fCommandFactory.createMIStackListLocals(frameDmc, false), - new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { - @Override - protected void handleSuccess() { - localsList.addAll( Arrays.asList( - makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals())) ); - countingRm.done(); - } - }); - } - }); - } + public void getLocals(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) { + + final List<IVariableDMContext> localsList = new ArrayList<IVariableDMContext>(); + + final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + rm.setData( localsList.toArray(new IVariableDMContext[localsList.size()]) ); + rm.done(); + } + }; + countingRm.setDoneCount(3); + + // First show any return values of methods + getReturnValues( + frameDmc, + new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList(getData()) ); + countingRm.done(); + } + }); + + // Then show arguments + getArguments( + frameDmc, + new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList(getData()) ); + countingRm.done(); + } + }); + + // Finally get the local variables + fMICommandCache.execute( + // We don't actually need to ask for the values in this case, but since + // we will ask for them right after, it is more efficient to ask for them now + // so as to cache the result. If the command fails, then we will ask for + // the result without the values + // Don't ask for value when we are visualizing trace data, since some + // data will not be there, and the command will fail + fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), + new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList( + makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals())) ); + countingRm.done(); + } + @Override + protected void handleError() { + // If the command fails it can be because we asked for values. + // This can happen with uninitialized values and pretty printers (bug 307614). + // Since asking for values was simply an optimization + // to store the command in the cache, let's retry the command without asking for values. + fMICommandCache.execute( + fCommandFactory.createMIStackListLocals(frameDmc, false), + new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList( + makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals())) ); + countingRm.done(); + } + }); + } + }); + } @Override - public void getStackDepth(final IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) { - final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class); - if (execDmc != null) { - // Make sure the thread is stopped - if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) { - rm.setData(0); - rm.done(); - return; - } - - // Check our internal cache first because different commands can - // still be re-used. - StackDepthInfo cachedDepth = fStackDepthCache.get(execDmc.getThreadId()); - if (cachedDepth != null) { - if (cachedDepth.maxDepthRequested == 0 || - (maxDepth != 0 && cachedDepth.maxDepthRequested >= maxDepth)) - { - rm.setData(cachedDepth.returnedDepth); - rm.done(); - return; - } - } - - ICommand<MIStackInfoDepthInfo> depthCommand = null; - if (maxDepth > 0) depthCommand = fCommandFactory.createMIStackInfoDepth(execDmc, maxDepth); - else depthCommand = fCommandFactory.createMIStackInfoDepth(execDmc); - - fMICommandCache.execute( - depthCommand, - new DataRequestMonitor<MIStackInfoDepthInfo>(getExecutor(), rm) { - @Override - protected void handleSuccess() { - // Store result in our internal cache - fStackDepthCache.put(execDmc.getThreadId(), new StackDepthInfo(maxDepth, getData().getDepth())); - - rm.setData(getData().getDepth()); - rm.done(); - } - @Override - protected void handleError() { - if (fTraceVisualization) { - // when visualizing trace data with GDB 7.2, the command - // -stack-info-depth will return an error if we ask for any level - // that GDB does not know about. We would have to iteratively - // try different depths until we found the deepest that succeeds. - // That is too much of a hack, especially since GDB 7.3 answers correctly. - // For 7.2, we can safely say we have one stack - // frame, which is going to be the case for 95% of the cases. - // To have more stack frames, the user would have to have collected - // the registers and enough stack memory for GDB to build another frame. - rm.setData(1); - rm.done(); - } else { + public void getStackDepth(final IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) { + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class); + if (execDmc != null) { + // Make sure the thread is stopped + if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) { + rm.setData(0); + rm.done(); + return; + } + + // Check our internal cache first because different commands can + // still be re-used. + StackDepthInfo cachedDepth = fStackDepthCache.get(execDmc.getThreadId()); + if (cachedDepth != null) { + if (cachedDepth.maxDepthRequested == 0 || + (maxDepth != 0 && cachedDepth.maxDepthRequested >= maxDepth)) + { + rm.setData(cachedDepth.returnedDepth); + rm.done(); + return; + } + } + + ICommand<MIStackInfoDepthInfo> depthCommand = null; + if (maxDepth > 0) { + depthCommand = fCommandFactory.createMIStackInfoDepth(execDmc, maxDepth); + } else { + depthCommand = fCommandFactory.createMIStackInfoDepth(execDmc); + } + + fMICommandCache.execute( + depthCommand, + new DataRequestMonitor<MIStackInfoDepthInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Store result in our internal cache + fStackDepthCache.put(execDmc.getThreadId(), new StackDepthInfo(maxDepth, getData().getDepth())); + + rm.setData(getData().getDepth()); + rm.done(); + } + @Override + protected void handleError() { + if (fTraceVisualization) { + // when visualizing trace data with GDB 7.2, the command + // -stack-info-depth will return an error if we ask for any level + // that GDB does not know about. We would have to iteratively + // try different depths until we found the deepest that succeeds. + // That is too much of a hack, especially since GDB 7.3 answers correctly. + // For 7.2, we can safely say we have one stack + // frame, which is going to be the case for 95% of the cases. + // To have more stack frames, the user would have to have collected + // the registers and enough stack memory for GDB to build another frame. + rm.setData(1); + rm.done(); + } else { // We're seeing gdb in some cases fail when it's // being asked for the stack depth but stack frames command succeeds // it seems like an overkill but it will cached and ui later will ask for it anyway ICommand<MIStackListFramesInfo> listFramesCommand; - if (maxDepth <= 0) + if (maxDepth <= 0) { listFramesCommand = fCommandFactory.createMIStackListFrames(execDmc); - else + } else { listFramesCommand = fCommandFactory.createMIStackListFrames(execDmc, 0, maxDepth - 1); + } fMICommandCache.execute( listFramesCommand, new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) { @@ -958,8 +964,9 @@ public class MIStack extends AbstractDsfService MIFrame[] miFrames = getData().getMIFrames(); int level = 0; for (MIFrame miFrame : miFrames) { - if (miFrame.getLevel() > level) + if (miFrame.getLevel() > level) { level = miFrame.getLevel(); + } } // Create the data object. Depth is +1 of maximum frame level int depth = level + 1; @@ -979,138 +986,138 @@ public class MIStack extends AbstractDsfService }; } ); - } - } - }); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ - rm.done(); - } - } - - /** - * @nooverride This method is not intended to be re-implemented or extended by clients. - * @noreference This method is not intended to be referenced by clients. - */ - @DsfServiceEventHandler - public void eventDispatched(IResumedDMEvent e) { - fMICommandCache.setContextAvailable(e.getDMContext(), false); - if (e.getReason() != StateChangeReason.STEP) { - fCachedStoppedEvent = null; - fMICommandCache.reset(); - fStackDepthCache.clear(); - } - - handleReturnValues(e); - } - - private void handleReturnValues(IResumedDMEvent e) { - // Whenever the execution resumes, we can clear any - // return values of previous methods for the resuming - // thread context. For all-stop mode, we get a container event here, - // and we can clear the entire list, which should contain at most one - // value for all-stop. - if (e instanceof IContainerResumedDMEvent) { - // All-stop mode - assert fThreadToReturnVariable.size() <= 1; - fThreadToReturnVariable.clear(); - } else { - // Non-stop mode - IDMContext ctx = e.getDMContext(); - if (ctx instanceof IMIExecutionDMContext) { - fThreadToReturnVariable.remove(ctx); - } else if (ctx instanceof IContainerDMContext) { - fThreadToReturnVariable.clear(); - } - } - } - - /** - * @nooverride This method is not intended to be re-implemented or extended by clients. - * @noreference This method is not intended to be referenced by clients. - * @since 1.1 - */ - @DsfServiceEventHandler - public void eventDispatched(ISuspendedDMEvent e) { - fMICommandCache.setContextAvailable(e.getDMContext(), true); - fMICommandCache.reset(); - fStackDepthCache.clear(); - - handleReturnValues(e); - } - - private void handleReturnValues(ISuspendedDMEvent e) { - // Process MIFunctionFinishedEvent from within the ISuspendedDMEvent - // instead of MIStoppedEvent. - // This avoids a race conditions where the actual MIFunctionFinishedEvent - // can arrive here, faster that a preceding IResumedDMEvent - if (e instanceof IMIDMEvent) { - Object miEvent = ((IMIDMEvent)e).getMIEvent(); - if (miEvent instanceof MIFunctionFinishedEvent) { - // When returning out of a function, we want to show the return value - // for the thread that finished the call. To do that, we store - // the variable in which GDB stores that return value, and we do - // that for the proper thread. - - IMIExecutionDMContext finishedEventThread = null; - if (e instanceof IContainerSuspendedDMEvent) { - // All-stop mode - IExecutionDMContext[] triggerContexts = ((IContainerSuspendedDMEvent)e).getTriggeringContexts(); - if (triggerContexts.length != 0 && triggerContexts[0] instanceof IMIExecutionDMContext) { - finishedEventThread = (IMIExecutionDMContext)triggerContexts[0]; - } - } else { - // Non-stop mode - IDMContext ctx = e.getDMContext(); - if (ctx instanceof IMIExecutionDMContext) { - finishedEventThread = (IMIExecutionDMContext)ctx; - } - } - - if (finishedEventThread != null) { - String name = ((MIFunctionFinishedEvent)miEvent).getGDBResultVar(); - String value = ((MIFunctionFinishedEvent)miEvent).getReturnValue(); - - if (name != null && !name.isEmpty() && value != null && !value.isEmpty()) { - fThreadToReturnVariable.put(finishedEventThread, new VariableData(new MIArg(name, value))); - } - } - } - } - } - - /** - * @nooverride This method is not intended to be re-implemented or extended by clients. - * @noreference This method is not intended to be referenced by clients. - * @since 1.1 - */ - @DsfServiceEventHandler - public void eventDispatched(IMIDMEvent e) { - if (e.getMIEvent() instanceof MIStoppedEvent) { - fCachedStoppedEvent = (MIStoppedEvent)e.getMIEvent(); - } - } - - /** @since 3.0 */ - @DsfServiceEventHandler - public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) { - if (e.isVisualizationModeEnabled()) { - fTraceVisualization = true; - } else { - fTraceVisualization = false; - fCachedStoppedEvent = null; - } - } - - /** - * {@inheritDoc} - * @since 1.1 - */ + } + } + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + } + } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + */ + @DsfServiceEventHandler + public void eventDispatched(IResumedDMEvent e) { + fMICommandCache.setContextAvailable(e.getDMContext(), false); + if (e.getReason() != StateChangeReason.STEP) { + fCachedStoppedEvent = null; + fMICommandCache.reset(); + fStackDepthCache.clear(); + } + + handleReturnValues(e); + } + + private void handleReturnValues(IResumedDMEvent e) { + // Whenever the execution resumes, we can clear any + // return values of previous methods for the resuming + // thread context. For all-stop mode, we get a container event here, + // and we can clear the entire list, which should contain at most one + // value for all-stop. + if (e instanceof IContainerResumedDMEvent) { + // All-stop mode + assert fThreadToReturnVariable.size() <= 1; + fThreadToReturnVariable.clear(); + } else { + // Non-stop mode + IDMContext ctx = e.getDMContext(); + if (ctx instanceof IMIExecutionDMContext) { + fThreadToReturnVariable.remove(ctx); + } else if (ctx instanceof IContainerDMContext) { + fThreadToReturnVariable.clear(); + } + } + } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * @since 1.1 + */ + @DsfServiceEventHandler + public void eventDispatched(ISuspendedDMEvent e) { + fMICommandCache.setContextAvailable(e.getDMContext(), true); + fMICommandCache.reset(); + fStackDepthCache.clear(); + + handleReturnValues(e); + } + + private void handleReturnValues(ISuspendedDMEvent e) { + // Process MIFunctionFinishedEvent from within the ISuspendedDMEvent + // instead of MIStoppedEvent. + // This avoids a race conditions where the actual MIFunctionFinishedEvent + // can arrive here, faster that a preceding IResumedDMEvent + if (e instanceof IMIDMEvent) { + Object miEvent = ((IMIDMEvent)e).getMIEvent(); + if (miEvent instanceof MIFunctionFinishedEvent) { + // When returning out of a function, we want to show the return value + // for the thread that finished the call. To do that, we store + // the variable in which GDB stores that return value, and we do + // that for the proper thread. + + IMIExecutionDMContext finishedEventThread = null; + if (e instanceof IContainerSuspendedDMEvent) { + // All-stop mode + IExecutionDMContext[] triggerContexts = ((IContainerSuspendedDMEvent)e).getTriggeringContexts(); + if (triggerContexts.length != 0 && triggerContexts[0] instanceof IMIExecutionDMContext) { + finishedEventThread = (IMIExecutionDMContext)triggerContexts[0]; + } + } else { + // Non-stop mode + IDMContext ctx = e.getDMContext(); + if (ctx instanceof IMIExecutionDMContext) { + finishedEventThread = (IMIExecutionDMContext)ctx; + } + } + + if (finishedEventThread != null) { + String name = ((MIFunctionFinishedEvent)miEvent).getGDBResultVar(); + String value = ((MIFunctionFinishedEvent)miEvent).getReturnValue(); + + if (name != null && !name.isEmpty() && value != null && !value.isEmpty()) { + fThreadToReturnVariable.put(finishedEventThread, new VariableData(new MIArg(name, value))); + } + } + } + } + } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * @since 1.1 + */ + @DsfServiceEventHandler + public void eventDispatched(IMIDMEvent e) { + if (e.getMIEvent() instanceof MIStoppedEvent) { + fCachedStoppedEvent = (MIStoppedEvent)e.getMIEvent(); + } + } + + /** @since 3.0 */ + @DsfServiceEventHandler + public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) { + if (e.isVisualizationModeEnabled()) { + fTraceVisualization = true; + } else { + fTraceVisualization = false; + fCachedStoppedEvent = null; + } + } + + /** + * {@inheritDoc} + * @since 1.1 + */ @Override public void flushCache(IDMContext context) { - fMICommandCache.reset(context); - fStackDepthCache.clear(context); - fCachedStoppedEvent = null; + fMICommandCache.reset(context); + fStackDepthCache.clear(context); + fCachedStoppedEvent = null; } } |