From b44541d2d13c417f197e711e9655bdcd2b3a628b Mon Sep 17 00:00:00 2001 From: Mikhail Khodjaiants Date: Sat, 16 Nov 2002 00:48:31 +0000 Subject: [PATCH] If the backtrace is very deep the debugger is unable to parse MI output. The limited number of stack frames will be displayed. --- debug/org.eclipse.cdt.debug.core/ChangeLog | 8 + .../cdt/debug/core/IDummyStackFrame.java | 15 ++ .../internal/core/model/CDummyStackFrame.java | 244 ++++++++++++++++++ .../internal/core/model/CStackFrame.java | 4 + .../debug/internal/core/model/CThread.java | 195 ++++++++++---- 5 files changed, 410 insertions(+), 56 deletions(-) create mode 100644 debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/IDummyStackFrame.java create mode 100644 debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDummyStackFrame.java diff --git a/debug/org.eclipse.cdt.debug.core/ChangeLog b/debug/org.eclipse.cdt.debug.core/ChangeLog index 53c2c50154d..6bd01851916 100644 --- a/debug/org.eclipse.cdt.debug.core/ChangeLog +++ b/debug/org.eclipse.cdt.debug.core/ChangeLog @@ -1,3 +1,11 @@ +2002-11-15 Mikhail Khodjaiants + If the backtrace is very deep the debugger is unable to parse MI output. + The limited number of stack frames will be displayed. + * IDummyStackFrame.java + * CDummyStackFrame.java + * CStackFrame.java + * CThread.java + 2002-11-14 Alain Magloire This is needed in post-mortem, application doing a diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/IDummyStackFrame.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/IDummyStackFrame.java new file mode 100644 index 00000000000..822d0d91d8c --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/IDummyStackFrame.java @@ -0,0 +1,15 @@ +/* + *(c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + * + */ +package org.eclipse.cdt.debug.core; + +/** + * Enter type comment. + * + * @since: Nov 13, 2002 + */ +public interface IDummyStackFrame +{ +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDummyStackFrame.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDummyStackFrame.java new file mode 100644 index 00000000000..0d4a4fa570e --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CDummyStackFrame.java @@ -0,0 +1,244 @@ +/* + *(c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + * + */ +package org.eclipse.cdt.debug.internal.core.model; + +import org.eclipse.cdt.debug.core.IDummyStackFrame; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IRegisterGroup; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IVariable; + +/** + * Enter type comment. + * + * @since: Nov 13, 2002 + */ +public class CDummyStackFrame extends CDebugElement implements IStackFrame, IDummyStackFrame +{ + /** + * Containing thread. + */ + private CThread fThread; + + /** + * Constructor for CDummyStackFrame. + * @param target + */ + public CDummyStackFrame( CThread thread ) + { + super( (CDebugTarget)thread.getDebugTarget() ); + setThread( thread ); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getThread() + */ + public IThread getThread() + { + return fThread; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getVariables() + */ + public IVariable[] getVariables() throws DebugException + { + return new IVariable[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#hasVariables() + */ + public boolean hasVariables() throws DebugException + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getLineNumber() + */ + public int getLineNumber() throws DebugException + { + return 0; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getCharStart() + */ + public int getCharStart() throws DebugException + { + return 0; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getCharEnd() + */ + public int getCharEnd() throws DebugException + { + return 0; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getName() + */ + public String getName() throws DebugException + { + return "..."; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups() + */ + public IRegisterGroup[] getRegisterGroups() throws DebugException + { + return ((CDebugTarget)getDebugTarget()).getRegisterGroups(); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups() + */ + public boolean hasRegisterGroups() throws DebugException + { + return ((CDebugTarget)getDebugTarget()).getRegisterGroups().length > 0; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#canStepInto() + */ + public boolean canStepInto() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#canStepOver() + */ + public boolean canStepOver() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#canStepReturn() + */ + public boolean canStepReturn() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#isStepping() + */ + public boolean isStepping() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#stepInto() + */ + public void stepInto() throws DebugException + { + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#stepOver() + */ + public void stepOver() throws DebugException + { + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IStep#stepReturn() + */ + public void stepReturn() throws DebugException + { + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ISuspendResume#canResume() + */ + public boolean canResume() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend() + */ + public boolean canSuspend() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended() + */ + public boolean isSuspended() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ISuspendResume#resume() + */ + public void resume() throws DebugException + { + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ISuspendResume#suspend() + */ + public void suspend() throws DebugException + { + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ITerminate#canTerminate() + */ + public boolean canTerminate() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ITerminate#isTerminated() + */ + public boolean isTerminated() + { + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.ITerminate#terminate() + */ + public void terminate() throws DebugException + { + } + + /** + * Sets the containing thread. + * + * @param thread the containing thread + */ + protected void setThread( CThread thread ) + { + fThread = thread; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class) + */ + public Object getAdapter( Class adapter ) + { + if ( adapter.equals( IDummyStackFrame.class ) ) + return this; + if ( adapter.equals( IStackFrame.class ) ) + return this; + return super.getAdapter(adapter); + } +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CStackFrame.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CStackFrame.java index 7371a940b6f..287f3ae06c2 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CStackFrame.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CStackFrame.java @@ -538,6 +538,10 @@ public class CStackFrame extends CDebugElement */ public Object getAdapter( Class adapter ) { + if ( adapter == CStackFrame.class ) + { + return this; + } if ( adapter == IStackFrame.class ) { return this; diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CThread.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CThread.java index aaaeaacaf20..69df692a089 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CThread.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CThread.java @@ -7,10 +7,10 @@ package org.eclipse.cdt.debug.internal.core.model; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.eclipse.cdt.debug.core.IDummyStackFrame; import org.eclipse.cdt.debug.core.IInstructionStep; import org.eclipse.cdt.debug.core.IRestart; import org.eclipse.cdt.debug.core.IState; @@ -33,6 +33,7 @@ import org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.cdi.model.ICDIThread; import org.eclipse.cdt.debug.core.sourcelookup.ISourceMode; +import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IBreakpoint; @@ -53,6 +54,8 @@ public class CThread extends CDebugElement ISwitchToFrame, ICDIEventListener { + private final static int MAX_STACK_DEPTH = 100; + /** * Underlying CDI thread. */ @@ -61,7 +64,7 @@ public class CThread extends CDebugElement /** * Collection of stack frames */ - private List fStackFrames; + private ArrayList fStackFrames; /** * Whether running. @@ -96,6 +99,8 @@ public class CThread extends CDebugElement private boolean fIsCurrent = false; private CStackFrame fLastStackFrame = null; + + private int fLastStackDepth = 0; /** * Constructor for CThread. @@ -119,7 +124,7 @@ public class CThread extends CDebugElement */ protected void initialize() { - fStackFrames = Collections.EMPTY_LIST; + fStackFrames = new ArrayList(); setRunning( false ); // setRunning( !getCDIThread().isSuspended() ); } @@ -162,70 +167,67 @@ public class CThread extends CDebugElement { if ( isTerminated() ) { - fStackFrames = Collections.EMPTY_LIST; + fStackFrames = new ArrayList(); } else if ( refreshChildren ) { + if ( fStackFrames.size() > 0 ) + { + Object frame = fStackFrames.get( fStackFrames.size() - 1 ); + if ( frame instanceof IDummyStackFrame ) + { + fStackFrames.remove( frame ); + } + } + int depth = getStackDepth(); + ICDIStackFrame[] frames = ( depth != 0 ) ? + getCDIStackFrames( 0, ( depth > getMaxStackDepth() ) ? getMaxStackDepth() - 1 : depth - 1 ) : + new ICDIStackFrame[0]; if ( fStackFrames.isEmpty() ) { - fStackFrames = createAllStackFrames(); - setRefreshChildren( false ); - return fStackFrames; + addStackFrames( frames, 0, frames.length ); } - ICDIStackFrame[] frames = getCDIStackFrames(); - // compute new or removed stack frames - int offset = 0, length = frames.length; - if ( length > fStackFrames.size() ) + else if ( depth < getLastStackDepth() ) { - // compute new frames - offset = length - fStackFrames.size(); - for ( int i = offset - 1; i >= 0; i-- ) + disposeStackFrames( 0, getLastStackDepth() - depth ); + updateStackFrames( frames, 0, fStackFrames, fStackFrames.size() ); + if ( fStackFrames.size() < frames.length ) { - fStackFrames.add( 0, new CStackFrame( this, frames[i] ) ); - } - length = fStackFrames.size() - offset; - } - else if ( length < fStackFrames.size() ) - { - // compute removed children - int removed = fStackFrames.size() - length; - for ( int i = 0; i < removed; i++ ) - { - ((CStackFrame)fStackFrames.get( 0 )).dispose(); - fStackFrames.remove( 0 ); + addStackFrames( frames, fStackFrames.size(), frames.length - fStackFrames.size() ); } } - else + else if ( depth > getLastStackDepth() ) { - if ( frames.length == 0 ) - { - fStackFrames = Collections.EMPTY_LIST; - } - else + disposeStackFrames( frames.length - depth + getLastStackDepth(), depth - getLastStackDepth() ); + addStackFrames( frames, 0, depth - getLastStackDepth() ); + updateStackFrames( frames, depth - getLastStackDepth(), fStackFrames, frames.length - depth + getLastStackDepth() ); + } + else // depth == getLastStackDepth() + { + if ( depth != 0 ) { // same number of frames - if top frames are in different // method, replace all frames - ICDIStackFrame newTop = frames[0]; - ICDIStackFrame oldTop = ((CStackFrame)fStackFrames.get( 0 ) ).getLastCDIStackFrame(); - if ( !CStackFrame.equalFrame( newTop, oldTop ) ) + ICDIStackFrame newTopFrame = frames[0]; + ICDIStackFrame oldTopFrame = ((CStackFrame)fStackFrames.get( 0 ) ).getLastCDIStackFrame(); + if ( !CStackFrame.equalFrame( newTopFrame, oldTopFrame ) ) { - disposeStackFrames(); - fStackFrames = new ArrayList( frames.length ); - for ( int i = 0; i < frames.length; ++i ) - { - fStackFrames.add( new CStackFrame( this, frames[i] ) ); - } - offset = fStackFrames.size(); + disposeStackFrames( 0, fStackFrames.size() ); + addStackFrames( frames, 0, frames.length ); + } + else // we are in the same frame + { + updateStackFrames( frames, 0, fStackFrames, frames.length ); } } } - // update preserved frames - if ( offset < fStackFrames.size() ) + if ( depth > getMaxStackDepth() ) { - updateStackFrames( frames, offset, fStackFrames, length ); + fStackFrames.add( new CDummyStackFrame( this ) ); } + setLastStackDepth( depth ); + setRefreshChildren( false ); } - setRefreshChildren( false ); } return fStackFrames; } @@ -239,10 +241,24 @@ public class CThread extends CDebugElement * */ protected ICDIStackFrame[] getCDIStackFrames() throws DebugException + { + return new ICDIStackFrame[0]; + } + + /** + * Retrieves and returns underlying stack frames between lowFrame + * and highFrame. + * + * @return list of StackFrame + * @exception DebugException if this method fails. Reasons include: + *
    + *
+ */ + protected ICDIStackFrame[] getCDIStackFrames( int lowFrame, int highFrame ) throws DebugException { try { - return getCDIThread().getStackFrames(); + return getCDIThread().getStackFrames( lowFrame, highFrame ); } catch( CDIException e ) { @@ -277,6 +293,19 @@ public class CThread extends CDebugElement } } + protected void addStackFrames( ICDIStackFrame[] newFrames, + int startIndex, + int length ) + { + if ( newFrames.length >= startIndex + length ) + { + for ( int i = 0; i < length; ++i ) + { + fStackFrames.add( i, new CStackFrame( this, newFrames[startIndex + i] ) ); + } + } + } + /** * Returns this thread's current stack frames as a list, computing * them if required. Returns an empty collection if this thread is @@ -326,20 +355,18 @@ public class CThread extends CDebugElement * underlying stack frames. * * @exception DebugException if this method fails. Reasons include: - *
    - *
  • Failure communicating with the VM. The DebugException's - * status code contains the underlying exception responsible for - * the failure.
  • - *
*/ - protected List createAllStackFrames() throws DebugException + protected List createAllStackFrames( int depth, ICDIStackFrame[] frames ) throws DebugException { - ICDIStackFrame[] frames = getCDIStackFrames(); List list= new ArrayList( frames.length ); for ( int i = 0; i < frames.length; ++i ) { list.add( new CStackFrame( this, frames[i] ) ); } + if ( depth > frames.length ) + { + list.add( new CDummyStackFrame( this ) ); + } return list; } @@ -672,7 +699,11 @@ public class CThread extends CDebugElement Iterator it = fStackFrames.iterator(); while( it.hasNext() ) { - ((CStackFrame)it.next()).preserve(); + CStackFrame frame = (CStackFrame)(((IAdaptable)it.next()).getAdapter( CStackFrame.class )); + if ( frame != null ) + { + frame.preserve(); + } } setRefreshChildren( true ); } @@ -689,12 +720,35 @@ public class CThread extends CDebugElement Iterator it = fStackFrames.iterator(); while( it.hasNext() ) { - ((CStackFrame)it.next()).dispose(); + CStackFrame frame = (CStackFrame)(((IAdaptable)it.next()).getAdapter( CStackFrame.class )); + if ( frame != null ) + { + ((CStackFrame)frame).dispose(); + } } fStackFrames.clear(); + setLastStackDepth( 0 ); setRefreshChildren( true ); } + protected void disposeStackFrames( int index, int length ) + { + List removeList = new ArrayList( length ); + Iterator it = fStackFrames.iterator(); + int counter = 0; + while( it.hasNext() ) + { + CStackFrame frame = (CStackFrame)(((IAdaptable)it.next()).getAdapter( CStackFrame.class )); + if ( frame != null && counter >= index && counter < index + length ) + { + frame.dispose(); + removeList.add( frame ); + } + ++counter; + } + fStackFrames.removeAll( removeList ); + } + /** * Notification this thread has terminated - update state * and fire a terminate event. @@ -1004,4 +1058,33 @@ public class CThread extends CDebugElement { return fLastStackFrame; } + + protected int getStackDepth() throws DebugException + { + int depth = 0; + try + { + depth = getCDIThread().getStackFrameCount(); + } + catch( CDIException e ) + { +// targetRequestFailed( e.getMessage(), null ); + } + return depth; + } + + protected int getMaxStackDepth() + { + return MAX_STACK_DEPTH; + } + + private void setLastStackDepth( int depth ) + { + fLastStackDepth = depth; + } + + private int getLastStackDepth() + { + return fLastStackDepth; + } }