diff options
Diffstat (limited to 'dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java')
-rw-r--r-- | dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java | 698 |
1 files changed, 698 insertions, 0 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 new file mode 100644 index 00000000000..755fdebaa8d --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java @@ -0,0 +1,698 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + * Ericsson - Modified for handling of multiple execution contexts + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IStack; +import org.eclipse.cdt.dsf.debug.service.IStack2; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.cdt.dsf.debug.service.command.CommandCache; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIStackInfoDepth; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIStackListArguments; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIStackListFrames; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIStackListLocals; +import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; +import org.eclipse.cdt.dsf.mi.service.command.output.MIArg; +import org.eclipse.cdt.dsf.mi.service.command.output.MIFrame; +import org.eclipse.cdt.dsf.mi.service.command.output.MIStackInfoDepthInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListArgumentsInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListFramesInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListLocalsInfo; +import org.eclipse.cdt.dsf.service.AbstractDsfService; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.utils.Addr32; +import org.eclipse.cdt.utils.Addr64; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.osgi.framework.BundleContext; + +public class MIStack extends AbstractDsfService + implements IStack2, ICachingService +{ + protected static class MIFrameDMC extends AbstractDMContext + implements IFrameDMContext + { + private final int fLevel; + // public MIFrameDMC(MIStack service, int level) { + public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) { + super(sessionId, new IDMContext[] { execDmc }); + fLevel = level; + } + + 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 } + 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; + return super.baseHashCode() ^ typeFactor ^ fIndex; + } + + @Override + public String toString() { + return baseToString() + ".variable(" + fType + ")[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + + private CommandCache fMICommandCache; + private MIStoppedEvent fCachedStoppedEvent; + private IRunControl fRunControl; + + public MIStack(DsfSession session) + { + super(session); + } + + @Override + protected BundleContext getBundleContext() + { + return GdbPlugin.getBundleContext(); + } + + @Override + public void initialize(final RequestMonitor rm) { + super.initialize( + new RequestMonitor(getExecutor(), rm) { + @Override + protected void handleSuccess() { + doInitialize(rm); + } + }); + } + + private void doInitialize(RequestMonitor rm) { + ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class); + fMICommandCache = new CommandCache(getSession(), commandControl); + fMICommandCache.setContextAvailable(commandControl.getContext(), true); + fRunControl = getServicesTracker().getService(IRunControl.class); + + 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); + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) { + if (dmc instanceof MIFrameDMC) { + getFrameData((MIFrameDMC)dmc, (DataRequestMonitor<IFrameDMData>)rm); + // getFrameData invokes rm + } else if (dmc instanceof MIVariableDMC) { + getVariableData((MIVariableDMC)dmc, (DataRequestMonitor<IVariableDMData>)rm); + // getVariablesData invokes rm + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + /** + * 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); + } + + public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) { + getFrames(ctx, 0, ALL_FRAMES, rm); + } + + 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; + } + + final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class); + + if (execDmc == null) { + //rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "No frame context found in " + ctx, null)); //$NON-NLS-1$ + 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 + if (!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 MIStackListFrames miStackListCmd; + // firstIndex is the first index retrieved + final int firstIndex; + if (endIndex >= 0) { + miStackListCmd = new MIStackListFrames(execDmc, startIndex, endIndex); + firstIndex = startIndex; + } else { + miStackListCmd = new MIStackListFrames(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(); + } + }); + } + + 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 MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) { + 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]; + assert startIndex + i == frame.getLevel(); + frameDMCs[i] = createFrameDMContext(execDmc, frame.getLevel()); + } + return frameDMCs; + } + + + + 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; + + 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(); + + public IAddress getAddress() { + String addr = getMIFrame().getAddress(); + 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()); + } + } + + public int getColumn() { return 0; } + + public String getFile() { return getMIFrame().getFile(); } + public int getLine() { return getMIFrame().getLine(); } + public String getFunction() { return getMIFrame().getFunction(); } + + @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 (fCachedStoppedEvent != null && + execDmc.equals(fCachedStoppedEvent.getDMContext()) && + miFrameDmc.fLevel == 0 && + fCachedStoppedEvent.getFrame() != null) + { + 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( + new MIStackListFrames(execDmc), + new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Find the index to the correct MI frame object. + int idx = findFrameIndex(getData().getMIFrames(), miFrameDmc.fLevel); + if (idx == -1) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Create the data object. + rm.setData(new FrameDataFromMIStackFrameListInfo(getData(), idx)); + rm.done(); + } + }); + } + + 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().length)); + rm.done(); + return; + } + + // If not, retrieve the full list of frame data. + fMICommandCache.execute( + new MIStackListArguments(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.length)); + rm.done(); + } + }); + } + + 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; + } + + /** + * 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. + */ + class VariableData implements IVariableDMData { + private MIArg dsfMIArg; + VariableData(MIArg arg){ + dsfMIArg = arg; + } + public String getName() { return dsfMIArg.getName(); } + public String getValue() { return dsfMIArg.getValue(); } + @Override + public String toString() { return dsfMIArg.toString(); } + } + + // 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( + new MIStackListArguments(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(); + }}); + }//if + if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){ + fMICommandCache.execute( + new MIStackListLocals(frameDmc, true), + 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(); + } + }); + + }//if + + } + + private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) { + MIVariableDMC[] variables = new MIVariableDMC[count]; + for (int i = 0; i < count; i++) { + variables[i]= new MIVariableDMC(this, frame, type, i); + } + return variables; + } + + private int findFrameIndex(MIFrame[] frames, int level) { + for (int idx = 0; idx < frames.length; idx++) { + if (frames[idx].getLevel() == level) { + return idx; + } + } + return -1; + } + + + 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(2); + + getArguments( + frameDmc, + new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList(getData()) ); + countingRm.done(); + } + }); + + fMICommandCache.execute( + new MIStackListLocals(frameDmc, true), + new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + localsList.addAll( Arrays.asList( + makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals().length)) ); + countingRm.done(); + } + }); + } + + public void getStackDepth(IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) { + IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class); + if (execDmc != null) { + // Make sure the thread is stopped + if (!fRunControl.isSuspended(execDmc)) { + rm.setData(0); + rm.done(); + return; + } + + MIStackInfoDepth depthCommand = null; + if (maxDepth > 0) depthCommand = new MIStackInfoDepth(execDmc, maxDepth); + else depthCommand = new MIStackInfoDepth(execDmc); + + fMICommandCache.execute( + depthCommand, + new DataRequestMonitor<MIStackInfoDepthInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + rm.setData(getData().getDepth()); + rm.done(); + } + }); + } 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(); + } + } + + /** + * @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(); + } + + + /** + * @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(); + } + } + + /** + * This method is left for API compatibility only. + * @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(MIRunControl.ContainerSuspendedEvent e) { + } + + /** + * {@inheritDoc} + * @since 1.1 + */ + public void flushCache(IDMContext context) { + fMICommandCache.reset(context); + } + +} |