mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-06 17:26:01 +02:00
More implementation.
This commit is contained in:
parent
619ee91fb2
commit
0fecb04151
6 changed files with 1480 additions and 60 deletions
|
@ -6,6 +6,8 @@
|
|||
|
||||
package org.eclipse.cdt.debug.core;
|
||||
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents the current state of debug element.
|
||||
|
@ -27,5 +29,17 @@ public interface IState
|
|||
public static final int TERMINATED = 10;
|
||||
public static final int CORE_DUMP_FILE = 11;
|
||||
|
||||
int getCurrentState();
|
||||
/**
|
||||
* Returns the identifier of the current state.
|
||||
*
|
||||
* @return the identifier of the current state
|
||||
*/
|
||||
int getCurrentStateId();
|
||||
|
||||
/**
|
||||
* Returns the info object associated with the current state.
|
||||
*
|
||||
* @return the info object associated with the current state
|
||||
*/
|
||||
Object getCurrentStateInfo();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
*(c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.debug.internal.core;
|
||||
|
||||
import org.eclipse.cdt.debug.core.cdi.ICSession;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides the convenience access methods to the configuration
|
||||
* parameters of the debug session.
|
||||
*
|
||||
* @since Aug 6, 2002
|
||||
*/
|
||||
public class CDebugConfiguration
|
||||
{
|
||||
private ICSession fSession;
|
||||
|
||||
/**
|
||||
* Constructor for CDebugConfiguration.
|
||||
*/
|
||||
public CDebugConfiguration( ICSession session )
|
||||
{
|
||||
fSession = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports termination.
|
||||
*
|
||||
* @return whether this session supports termination
|
||||
*/
|
||||
public boolean supportsTerminate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports disconnecting.
|
||||
*
|
||||
* @return whether this session supports disconnecting
|
||||
*/
|
||||
public boolean supportsDisconnect()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports suspend/resume.
|
||||
*
|
||||
* @return whether this session supports suspend/resume
|
||||
*/
|
||||
public boolean supportsSuspendResume()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports restarting.
|
||||
*
|
||||
* @return whether this session supports restarting
|
||||
*/
|
||||
public boolean supportsRestart()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports stepping.
|
||||
*
|
||||
* @return whether this session supports stepping
|
||||
*/
|
||||
public boolean supportsStepping()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports instruction stepping.
|
||||
*
|
||||
* @return whether this session supports instruction stepping
|
||||
*/
|
||||
public boolean supportsInstructionStepping()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports breakpoints.
|
||||
*
|
||||
* @return whether this session supports breakpoints
|
||||
*/
|
||||
public boolean supportsBreakpoints()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports registers.
|
||||
*
|
||||
* @return whether this session supports registers
|
||||
*/
|
||||
public boolean supportsRegisters()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports register modification.
|
||||
*
|
||||
* @return whether this session supports registers modification
|
||||
*/
|
||||
public boolean supportsRegisterModification()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports memory retrieval.
|
||||
*
|
||||
* @return whether this session supports memory retrieval
|
||||
*/
|
||||
public boolean supportsMemoryRetrieval()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports memory modification.
|
||||
*
|
||||
* @return whether this session supports memory modification
|
||||
*/
|
||||
public boolean supportsMemoryModification()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this session supports expression evaluation.
|
||||
*
|
||||
* @return whether this session supports expression evaluation
|
||||
*/
|
||||
public boolean supportsExpressionEvaluation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ package org.eclipse.cdt.debug.internal.core;
|
|||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugModel;
|
||||
|
@ -46,6 +47,7 @@ import org.eclipse.debug.core.model.IBreakpoint;
|
|||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
import org.eclipse.debug.core.model.IMemoryBlock;
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.debug.core.model.IStep;
|
||||
import org.eclipse.debug.core.model.IThread;
|
||||
|
||||
/**
|
||||
|
@ -58,7 +60,6 @@ public class CDebugTarget extends CDebugElement
|
|||
implements IDebugTarget,
|
||||
ICEventListener,
|
||||
IRestart,
|
||||
IInstructionStep,
|
||||
IFormattedMemoryRetrieval,
|
||||
IState,
|
||||
ILaunchListener
|
||||
|
@ -76,7 +77,7 @@ public class CDebugTarget extends CDebugElement
|
|||
private IProcess fProcess;
|
||||
|
||||
/**
|
||||
* Underlying CDI target.
|
||||
* The underlying CDI target.
|
||||
*/
|
||||
private ICTarget fCDITarget;
|
||||
|
||||
|
@ -115,6 +116,11 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
private ILaunch fLaunch;
|
||||
|
||||
/**
|
||||
* The debug configuration of this session
|
||||
*/
|
||||
private CDebugConfiguration fConfig;
|
||||
|
||||
/**
|
||||
* Whether terminate is supported.
|
||||
*/
|
||||
|
@ -125,6 +131,16 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
private boolean fSupportsDisconnect;
|
||||
|
||||
/**
|
||||
* The current state identifier.
|
||||
*/
|
||||
private int fCurrentStateId = IState.UNKNOWN;
|
||||
|
||||
/**
|
||||
* The current state info.
|
||||
*/
|
||||
private Object fCurrentStateInfo = null;
|
||||
|
||||
/**
|
||||
* Constructor for CDebugTarget.
|
||||
* @param target
|
||||
|
@ -143,6 +159,9 @@ public class CDebugTarget extends CDebugElement
|
|||
setName( name );
|
||||
setProcess( process );
|
||||
setCDITarget( cdiTarget );
|
||||
fConfig = new CDebugConfiguration( cdiTarget.getSession() );
|
||||
fSupportsTerminate = allowsTerminate & fConfig.supportsTerminate();
|
||||
fSupportsDisconnect = allowsDisconnect & fConfig.supportsDisconnect();
|
||||
setThreadList( new ArrayList( 5 ) );
|
||||
initialize();
|
||||
DebugPlugin.getDefault().getLaunchManager().addLaunchListener( this );
|
||||
|
@ -299,7 +318,7 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public boolean canTerminate()
|
||||
{
|
||||
return false;
|
||||
return supportsTerminate() && isAvailable();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -370,6 +389,23 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public void resume() throws DebugException
|
||||
{
|
||||
if ( !isSuspended() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setSuspended( false );
|
||||
getCDITarget().resume();
|
||||
resumeThreads();
|
||||
fireResumeEvent( DebugEvent.CLIENT_REQUEST );
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setSuspended( true );
|
||||
fireSuspendEvent( DebugEvent.CLIENT_REQUEST );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred resuming target.", new String[] { e.toString() } ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -404,6 +440,13 @@ public class CDebugTarget extends CDebugElement
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies threads that they have been resumed
|
||||
*/
|
||||
protected void resumeThreads()
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(IBreakpoint)
|
||||
*/
|
||||
|
@ -425,12 +468,32 @@ public class CDebugTarget extends CDebugElement
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this debug target supports disconnecting.
|
||||
*
|
||||
* @return whether this debug target supports disconnecting
|
||||
*/
|
||||
protected boolean supportsDisconnect()
|
||||
{
|
||||
return fConfig.supportsDisconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this debug target supports termination.
|
||||
*
|
||||
* @return whether this debug target supports termination
|
||||
*/
|
||||
protected boolean supportsTerminate()
|
||||
{
|
||||
return fConfig.supportsTerminate();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
|
||||
*/
|
||||
public boolean canDisconnect()
|
||||
{
|
||||
return false;
|
||||
return supportsDisconnect() && !isDisconnected();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -438,6 +501,26 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public void disconnect() throws DebugException
|
||||
{
|
||||
if ( isDisconnected() )
|
||||
{
|
||||
// already done
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !canDisconnect() )
|
||||
{
|
||||
notSupported( "Session does not support \'disconnect\'" );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
getCDITarget().disconnect();
|
||||
disconnected();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
targetRequestFailed( MessageFormat.format( "{0} ocurred disconnecting from target.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -530,6 +613,8 @@ public class CDebugTarget extends CDebugElement
|
|||
return this;
|
||||
if ( adapter.equals( ICTarget.class ) )
|
||||
return fCDITarget;
|
||||
if ( adapter.equals( IState.class ) )
|
||||
return this;
|
||||
return super.getAdapter( adapter );
|
||||
}
|
||||
|
||||
|
@ -623,7 +708,7 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public boolean canRestart()
|
||||
{
|
||||
return false;
|
||||
return fConfig.supportsRestart() && isSuspended() && isAvailable();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -631,35 +716,27 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public void restart() throws DebugException
|
||||
{
|
||||
if ( !canRestart() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
getCDITarget().restart();
|
||||
restarted();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
targetRequestFailed( MessageFormat.format( "{0} ocurred restarting the target.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#canStepIntoInstruction()
|
||||
/**
|
||||
* Updates the state of this target for restarting.
|
||||
*
|
||||
*/
|
||||
public boolean canStepIntoInstruction()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#canStepOverInstruction()
|
||||
*/
|
||||
public boolean canStepOverInstruction()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#stepIntoInstruction()
|
||||
*/
|
||||
public void stepIntoInstruction() throws DebugException
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#stepOverInstruction()
|
||||
*/
|
||||
public void stepOverInstruction() throws DebugException
|
||||
protected void restarted()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -704,7 +781,7 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
public boolean isAvailable()
|
||||
{
|
||||
return false;
|
||||
return !( isTerminated() || isTerminating() || isDisconnected() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -754,8 +831,8 @@ public class CDebugTarget extends CDebugElement
|
|||
}
|
||||
|
||||
/**
|
||||
* Updates the state of this target for disconnection
|
||||
* from the VM.
|
||||
* Updates the state of this target for disconnection.
|
||||
*
|
||||
*/
|
||||
protected void disconnected()
|
||||
{
|
||||
|
@ -788,6 +865,13 @@ public class CDebugTarget extends CDebugElement
|
|||
*/
|
||||
protected void removeAllThreads()
|
||||
{
|
||||
Iterator itr = getThreadList().iterator();
|
||||
setThreadList( new ArrayList( 0 ) );
|
||||
while( itr.hasNext() )
|
||||
{
|
||||
CThread thread = (CThread)itr.next();
|
||||
thread.terminated();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -863,7 +947,9 @@ public class CDebugTarget extends CDebugElement
|
|||
private void handleSuspendedEvent( ICSuspendedEvent event )
|
||||
{
|
||||
setSuspended( true );
|
||||
setCurrentStateId( IState.SUSPENDED );
|
||||
ICSessionObject reason = event.getReason();
|
||||
setCurrentStateInfo( reason );
|
||||
if ( reason instanceof ICEndSteppingRange )
|
||||
{
|
||||
handleEndSteppingRange( (ICEndSteppingRange)reason );
|
||||
|
@ -881,6 +967,8 @@ public class CDebugTarget extends CDebugElement
|
|||
private void handleResumedEvent( ICResumedEvent event )
|
||||
{
|
||||
setSuspended( false );
|
||||
setCurrentStateId( IState.RUNNING );
|
||||
setCurrentStateInfo( null );
|
||||
fireResumeEvent( DebugEvent.UNSPECIFIED );
|
||||
}
|
||||
|
||||
|
@ -901,16 +989,22 @@ public class CDebugTarget extends CDebugElement
|
|||
|
||||
private void handleExitedEvent( ICExitedEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.EXITED );
|
||||
setCurrentStateInfo( event.getExitInfo() );
|
||||
fireChangeEvent( DebugEvent.STATE );
|
||||
}
|
||||
|
||||
private void handleTerminatedEvent( ICTerminatedEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.TERMINATED );
|
||||
setCurrentStateInfo( null );
|
||||
terminated();
|
||||
}
|
||||
|
||||
private void handleDisconnectedEvent( ICDisconnectedEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.DISCONNECTED );
|
||||
setCurrentStateInfo( null );
|
||||
disconnected();
|
||||
}
|
||||
|
||||
|
@ -928,6 +1022,8 @@ public class CDebugTarget extends CDebugElement
|
|||
|
||||
private void handleSteppingEvent( ICSteppingEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.STEPPING );
|
||||
setCurrentStateInfo( null );
|
||||
}
|
||||
|
||||
private void handleThreadCreatedEvent( ICCreatedEvent event )
|
||||
|
@ -976,10 +1072,38 @@ public class CDebugTarget extends CDebugElement
|
|||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentState()
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentStateId()
|
||||
*/
|
||||
public int getCurrentState()
|
||||
public int getCurrentStateId()
|
||||
{
|
||||
return IState.UNKNOWN;
|
||||
return fCurrentStateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current state identifier.
|
||||
*
|
||||
* @param id the identifier
|
||||
*/
|
||||
private void setCurrentStateId( int id )
|
||||
{
|
||||
fCurrentStateId = id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentStateInfo()
|
||||
*/
|
||||
public Object getCurrentStateInfo()
|
||||
{
|
||||
return fCurrentStateInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the info object of the current state.
|
||||
*
|
||||
* @param id the info object
|
||||
*/
|
||||
private void setCurrentStateInfo( Object info )
|
||||
{
|
||||
fCurrentStateInfo = info;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
*(c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.debug.internal.core;
|
||||
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEventListener;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICVariable;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IValue;
|
||||
import org.eclipse.debug.core.model.IVariable;
|
||||
|
||||
/**
|
||||
*
|
||||
* Proxy to a local variaable on the target.
|
||||
*
|
||||
* @since Aug 7, 2002
|
||||
*/
|
||||
public class CLocalVariable extends CDebugElement
|
||||
implements IVariable,
|
||||
ICEventListener
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor for CLocalVariable.
|
||||
* @param target
|
||||
*/
|
||||
public CLocalVariable( CStackFrame stackFrame, ICVariable cdiVariable )
|
||||
{
|
||||
super( (CDebugTarget)stackFrame.getDebugTarget() );
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IVariable#getValue()
|
||||
*/
|
||||
public IValue getValue() throws DebugException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IVariable#getName()
|
||||
*/
|
||||
public String getName() throws DebugException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IVariable#getReferenceTypeName()
|
||||
*/
|
||||
public String getReferenceTypeName() throws DebugException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IVariable#hasValueChanged()
|
||||
*/
|
||||
public boolean hasValueChanged() throws DebugException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.cdi.event.ICEventListener#handleDebugEvent(ICEvent)
|
||||
*/
|
||||
public void handleDebugEvent( ICEvent event )
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IValueModification#setValue(String)
|
||||
*/
|
||||
public void setValue( String expression ) throws DebugException
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IValueModification#setValue(IValue)
|
||||
*/
|
||||
public void setValue( IValue value ) throws DebugException
|
||||
{
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
|
||||
*/
|
||||
public boolean supportsValueModification()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IValueModification#verifyValue(String)
|
||||
*/
|
||||
public boolean verifyValue( String expression ) throws DebugException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IValueModification#verifyValue(IValue)
|
||||
*/
|
||||
public boolean verifyValue( IValue value ) throws DebugException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
*(c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
package org.eclipse.cdt.debug.internal.core;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.debug.core.cdi.CDIException;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEventListener;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICArgument;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICStackFrame;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICVariable;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* Proxy to a stack frame on the target.
|
||||
*
|
||||
* @since Aug 7, 2002
|
||||
*/
|
||||
public class CStackFrame extends CDebugElement
|
||||
implements IStackFrame,
|
||||
ICEventListener
|
||||
{
|
||||
/**
|
||||
* Underlying CDI stack frame.
|
||||
*/
|
||||
private ICStackFrame fCDIStackFrame;
|
||||
|
||||
/**
|
||||
* Containing thread.
|
||||
*/
|
||||
private CThread fThread;
|
||||
|
||||
/**
|
||||
* Visible variables.
|
||||
*/
|
||||
private List fVariables;
|
||||
|
||||
/**
|
||||
* Whether the variables need refreshing
|
||||
*/
|
||||
private boolean fRefreshVariables = true;
|
||||
|
||||
/**
|
||||
* Constructor for CStackFrame.
|
||||
* @param target
|
||||
*/
|
||||
public CStackFrame( CThread thread, ICStackFrame cdiFrame )
|
||||
{
|
||||
super( (CDebugTarget)thread.getDebugTarget() );
|
||||
fCDIStackFrame = cdiFrame;
|
||||
setThread( thread );
|
||||
getCDISession().getEventManager().addEventListener( this );
|
||||
}
|
||||
|
||||
/* (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
|
||||
{
|
||||
List list = getVariables0();
|
||||
return (IVariable[])list.toArray( new IVariable[list.size()] );
|
||||
}
|
||||
|
||||
protected synchronized List getVariables0() throws DebugException
|
||||
{
|
||||
if ( fVariables == null )
|
||||
{
|
||||
fVariables = new ArrayList();
|
||||
fVariables.addAll( getCDIArguments() );
|
||||
fVariables.addAll( getCDILocalVariables() );
|
||||
}
|
||||
else if ( fRefreshVariables )
|
||||
{
|
||||
updateVariables();
|
||||
}
|
||||
fRefreshVariables = false;
|
||||
return fVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrementally updates this stack frames variables.
|
||||
*
|
||||
*/
|
||||
protected void updateVariables() throws DebugException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the containing thread.
|
||||
*
|
||||
* @param thread the containing thread
|
||||
*/
|
||||
protected void setThread( CThread thread )
|
||||
{
|
||||
fThread = thread;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IStackFrame#hasVariables()
|
||||
*/
|
||||
public boolean hasVariables() throws DebugException
|
||||
{
|
||||
return getVariables0().size() > 0;
|
||||
}
|
||||
|
||||
/* (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 null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups()
|
||||
*/
|
||||
public IRegisterGroup[] getRegisterGroups() throws DebugException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups()
|
||||
*/
|
||||
public boolean hasRegisterGroups() throws DebugException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.cdi.event.ICEventListener#handleDebugEvent(ICEvent)
|
||||
*/
|
||||
public void handleDebugEvent(ICEvent event)
|
||||
{
|
||||
}
|
||||
|
||||
/* (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
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying CDI stack frame that this model object is
|
||||
* a proxy to.
|
||||
*
|
||||
* @return the underlying CDI stack frame
|
||||
*/
|
||||
protected ICStackFrame getCDIStackFrame()
|
||||
{
|
||||
return fCDIStackFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the underlying CDI stack frame. Called by a thread
|
||||
* when incrementally updating after a step has completed.
|
||||
*
|
||||
* @param frame the underlying stack frame
|
||||
*/
|
||||
protected void setCDIStackFrame( ICStackFrame frame )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The underlying stack frame that existed before the current underlying
|
||||
* stack frame. Used only so that equality can be checked on stack frame
|
||||
* after the new one has been set.
|
||||
*/
|
||||
protected ICStackFrame getLastCDIStackFrame()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for computeStackFrames(). For the purposes of detecting if
|
||||
* an underlying stack frame needs to be disposed, stack frames are equal if
|
||||
* the frames are equal and the locations are equal.
|
||||
*/
|
||||
protected static boolean equalFrame( ICStackFrame frameOne, ICStackFrame frameTwo )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean exists() throws DebugException
|
||||
{
|
||||
return ((CThread)getThread()).computeStackFrames().indexOf( this ) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IAdaptable#getAdapter(Class)
|
||||
*/
|
||||
public Object getAdapter( Class adapter )
|
||||
{
|
||||
if ( adapter == IStackFrame.class )
|
||||
{
|
||||
return this;
|
||||
}
|
||||
if ( adapter == ICStackFrame.class )
|
||||
{
|
||||
return getCDIStackFrame();
|
||||
}
|
||||
return super.getAdapter( adapter );
|
||||
}
|
||||
|
||||
protected void dispose()
|
||||
{
|
||||
getCDISession().getEventManager().removeEventListener( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves local variables in this stack frame. Returns an empty
|
||||
* list if there are no local variables.
|
||||
*
|
||||
*/
|
||||
protected List getCDILocalVariables() throws DebugException
|
||||
{
|
||||
List list = Collections.EMPTY_LIST;
|
||||
try
|
||||
{
|
||||
ICVariable[] vars = getCDIStackFrame().getLocalVariables();
|
||||
list = new ArrayList( vars.length );
|
||||
for ( int i = 0; i < vars.length; ++i )
|
||||
list.add( new CLocalVariable( this, vars[i] ) );
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred retrieving local variables", new String[] { e.toString() } ), e );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves arguments in this stack frame. Returns an empty list
|
||||
* if there are no arguments.
|
||||
*
|
||||
*/
|
||||
protected List getCDIArguments() throws DebugException
|
||||
{
|
||||
List list = Collections.EMPTY_LIST;
|
||||
try
|
||||
{
|
||||
ICArgument[] args = getCDIStackFrame().getArguments();
|
||||
list = new ArrayList( args.length );
|
||||
for ( int i = 0; i < args.length; ++i )
|
||||
list.add( new CLocalVariable( this, args[i] ) );
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred retrieving arguments", new String[] { e.toString() } ), e );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -6,10 +6,31 @@
|
|||
|
||||
package org.eclipse.cdt.debug.internal.core;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.debug.core.IInstructionStep;
|
||||
import org.eclipse.cdt.debug.core.IState;
|
||||
import org.eclipse.cdt.debug.core.cdi.CDIException;
|
||||
import org.eclipse.cdt.debug.core.cdi.ICBreakpoint;
|
||||
import org.eclipse.cdt.debug.core.cdi.ICEndSteppingRange;
|
||||
import org.eclipse.cdt.debug.core.cdi.ICSessionObject;
|
||||
import org.eclipse.cdt.debug.core.cdi.ICSignal;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICChangedEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICDisconnectedEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICEventListener;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICResumedEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICSteppingEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICSuspendedEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.event.ICTerminatedEvent;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICObject;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICStackFrame;
|
||||
import org.eclipse.cdt.debug.core.cdi.model.ICThread;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IBreakpoint;
|
||||
import org.eclipse.debug.core.model.IStackFrame;
|
||||
|
@ -23,14 +44,47 @@ import org.eclipse.debug.core.model.IThread;
|
|||
*/
|
||||
public class CThread extends CDebugElement
|
||||
implements IThread,
|
||||
IState,
|
||||
IState,
|
||||
IInstructionStep,
|
||||
ICEventListener
|
||||
{
|
||||
/**
|
||||
* Underlying CDI target.
|
||||
* Underlying CDI thread.
|
||||
*/
|
||||
private ICThread fCDIThread;
|
||||
|
||||
/**
|
||||
* Collection of stack frames
|
||||
*/
|
||||
private List fStackFrames;
|
||||
|
||||
/**
|
||||
* Whether running.
|
||||
*/
|
||||
private boolean fRunning;
|
||||
|
||||
/**
|
||||
* Whether children need to be refreshed. Set to
|
||||
* <code>true</code> when stack frames are re-used
|
||||
* on the next suspend.
|
||||
*/
|
||||
private boolean fRefreshChildren = true;
|
||||
|
||||
/**
|
||||
* The current state identifier.
|
||||
*/
|
||||
private int fCurrentStateId = IState.UNKNOWN;
|
||||
|
||||
/**
|
||||
* The current state info.
|
||||
*/
|
||||
private Object fCurrentStateInfo = null;
|
||||
|
||||
/**
|
||||
* The debug configuration of this session.
|
||||
*/
|
||||
private CDebugConfiguration fConfig;
|
||||
|
||||
/**
|
||||
* Constructor for CThread.
|
||||
* @param target
|
||||
|
@ -39,6 +93,22 @@ public class CThread extends CDebugElement
|
|||
{
|
||||
super( target );
|
||||
setCDIThread( cdiThread );
|
||||
fConfig = new CDebugConfiguration( getCDISession() );
|
||||
initialize();
|
||||
getCDISession().getEventManager().addEventListener( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread initialization:<ul>
|
||||
* <li>Sets terminated state to <code>false</code></li>
|
||||
* <li>Determines suspended state from underlying thread</li>
|
||||
* <li>Sets this threads stack frames to an empty collection</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected void initialize()
|
||||
{
|
||||
fStackFrames = Collections.EMPTY_LIST;
|
||||
setRunning( !getCDIThread().isSuspended() );
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -46,7 +116,8 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public IStackFrame[] getStackFrames() throws DebugException
|
||||
{
|
||||
return null;
|
||||
List list = computeStackFrames();
|
||||
return (IStackFrame[])list.toArray( new IStackFrame[list.size()] );
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -54,9 +125,217 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean hasStackFrames() throws DebugException
|
||||
{
|
||||
try
|
||||
{
|
||||
return computeStackFrames().size() > 0;
|
||||
}
|
||||
catch( DebugException e )
|
||||
{
|
||||
// do not throw an exception if the thread resumed while determining
|
||||
// whether stack frames are present
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see computeStackFrames()
|
||||
*
|
||||
* @param refreshChildren whether or not this method should request new stack
|
||||
* frames from the target
|
||||
*/
|
||||
protected synchronized List computeStackFrames( boolean refreshChildren ) throws DebugException
|
||||
{
|
||||
if ( isSuspended() )
|
||||
{
|
||||
if ( isTerminated() )
|
||||
{
|
||||
fStackFrames = Collections.EMPTY_LIST;
|
||||
}
|
||||
else if ( refreshChildren )
|
||||
{
|
||||
if ( fStackFrames.isEmpty() )
|
||||
{
|
||||
fStackFrames = createAllStackFrames();
|
||||
if ( fStackFrames.isEmpty() )
|
||||
{
|
||||
//leave fRefreshChildren == true
|
||||
//bug 6393
|
||||
// ?????
|
||||
return fStackFrames;
|
||||
}
|
||||
}
|
||||
ICStackFrame[] frames = getCDIStackFrames();
|
||||
// compute new or removed stack frames
|
||||
int offset = 0, length = frames.length;
|
||||
if ( length > fStackFrames.size() )
|
||||
{
|
||||
// compute new frames
|
||||
offset = length - fStackFrames.size();
|
||||
for ( int i = offset - 1; i >= 0; i-- )
|
||||
{
|
||||
CStackFrame newStackFrame = new CStackFrame( this, frames[i] );
|
||||
fStackFrames.add( 0, newStackFrame );
|
||||
}
|
||||
length = fStackFrames.size() - offset;
|
||||
}
|
||||
else if ( length < fStackFrames.size() )
|
||||
{
|
||||
// compute removed children
|
||||
int removed = fStackFrames.size() - length;
|
||||
for ( int i = 0; i < removed; i++ )
|
||||
{
|
||||
fStackFrames.remove( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( frames.length == 0 )
|
||||
{
|
||||
fStackFrames = Collections.EMPTY_LIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
// same number of frames - if top frames are in different
|
||||
// method, replace all frames
|
||||
ICStackFrame newTop = frames[0];
|
||||
ICStackFrame oldTop = ((CStackFrame)fStackFrames.get( 0 ) ).getLastCDIStackFrame();
|
||||
if (!CStackFrame.equalFrame( newTop, oldTop ) )
|
||||
{
|
||||
fStackFrames = createAllStackFrames();
|
||||
offset = fStackFrames.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
// update preserved frames
|
||||
if ( offset < fStackFrames.size() )
|
||||
{
|
||||
updateStackFrames( frames, offset, fStackFrames, length );
|
||||
}
|
||||
}
|
||||
fRefreshChildren = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
return fStackFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and returns all underlying stack frames
|
||||
*
|
||||
* @return list of <code>StackFrame</code>
|
||||
* @exception DebugException if this method fails. Reasons include:
|
||||
* <ul>
|
||||
* </ul>
|
||||
*/
|
||||
protected ICStackFrame[] getCDIStackFrames() throws DebugException
|
||||
{
|
||||
try
|
||||
{
|
||||
return getCDIThread().getStackFrames();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
requestFailed( MessageFormat.format( "{0} occurred retrieving stack frames.", new String[] { e.toString() } ), e );
|
||||
// execution will not reach this line, as
|
||||
// #targetRequestFailed will thrown an exception
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the underlying stack frame objects in the preserved frames
|
||||
* list with the current underlying stack frames.
|
||||
*
|
||||
* @param newFrames list of current underlying <code>ICStackFrame</code>s.
|
||||
* Frames from this list are assigned to the underlying frames in
|
||||
* the <code>oldFrames</code> list.
|
||||
* @param offset the offset in the lists at which to start replacing
|
||||
* the old underlying frames
|
||||
* @param oldFrames list of preserved frames, of type <code>CStackFrame</code>
|
||||
* @param length the number of frames to replace
|
||||
*/
|
||||
protected void updateStackFrames( ICStackFrame[] newFrames,
|
||||
int offset,
|
||||
List oldFrames,
|
||||
int length ) throws DebugException
|
||||
{
|
||||
for ( int i = 0; i < length; i++ )
|
||||
{
|
||||
CStackFrame frame = (CStackFrame)oldFrames.get( offset );
|
||||
frame.setCDIStackFrame( newFrames[offset] );
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this thread's current stack frames as a list, computing
|
||||
* them if required. Returns an empty collection if this thread is
|
||||
* not currently suspended, or this thread is terminated. This
|
||||
* method should be used internally to get the current stack frames,
|
||||
* instead of calling <code>#getStackFrames()</code>, which makes a
|
||||
* copy of the current list.
|
||||
* <p>
|
||||
* Before a thread is resumed a call must be made to one of:<ul>
|
||||
* <li><code>preserveStackFrames()</code></li>
|
||||
* <li><code>disposeStackFrames()</code></li>
|
||||
* </ul>
|
||||
* If stack frames are disposed before a thread is resumed, stack frames
|
||||
* are completely re-computed on the next call to this method. If stack
|
||||
* frames are to be preserved, this method will attempt to re-use any stack
|
||||
* frame objects which represent the same stack frame as on the previous
|
||||
* suspend. Stack frames are cached until a subsequent call to preserve
|
||||
* or dispose stack frames.
|
||||
* </p>
|
||||
*
|
||||
* @return list of <code>IStackFrame</code>
|
||||
* @exception DebugException if this method fails. Reasons include:
|
||||
* <ul>
|
||||
* </ul>
|
||||
*/
|
||||
public List computeStackFrames() throws DebugException
|
||||
{
|
||||
return computeStackFrames( fRefreshChildren );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CThread#computeStackFrames()
|
||||
*
|
||||
* This method differs from computeStackFrames() in that it
|
||||
* always requests new stack frames from the target. As this is
|
||||
* an expensive operation, this method should only be used
|
||||
* by clients who know for certain that the stack frames
|
||||
* on the target have changed.
|
||||
*/
|
||||
public List computeNewStackFrames() throws DebugException
|
||||
{
|
||||
return computeStackFrames( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for <code>#computeStackFrames()</code> to create all
|
||||
* underlying stack frames.
|
||||
*
|
||||
* @exception DebugException if this method fails. Reasons include:
|
||||
* <ul>
|
||||
* <li>Failure communicating with the VM. The DebugException's
|
||||
* status code contains the underlying exception responsible for
|
||||
* the failure.</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected List createAllStackFrames() throws DebugException
|
||||
{
|
||||
ICStackFrame[] frames = getCDIStackFrames();
|
||||
List list= new ArrayList( frames.length );
|
||||
for ( int i = 0; i < frames.length; ++i )
|
||||
{
|
||||
CStackFrame newStackFrame = new CStackFrame( this, frames[i] );
|
||||
list.add( newStackFrame );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.debug.core.model.IThread#getPriority()
|
||||
*/
|
||||
|
@ -70,7 +349,8 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public IStackFrame getTopStackFrame() throws DebugException
|
||||
{
|
||||
return null;
|
||||
List c = computeStackFrames();
|
||||
return ( c.isEmpty() ) ? null : (IStackFrame)c.get( 0 );
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -78,7 +358,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public String getName() throws DebugException
|
||||
{
|
||||
return null;
|
||||
return "Thread " + getCDIThread().getId();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -94,6 +374,52 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void handleDebugEvent( ICEvent event )
|
||||
{
|
||||
ICObject source = event.getSource();
|
||||
if ( source.getCDITarget().equals( getCDITarget() ) )
|
||||
{
|
||||
if ( event instanceof ICSuspendedEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleSuspendedEvent( (ICSuspendedEvent)event );
|
||||
}
|
||||
}
|
||||
else if ( event instanceof ICResumedEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleResumedEvent( (ICResumedEvent)event );
|
||||
}
|
||||
}
|
||||
else if ( event instanceof ICTerminatedEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleTerminatedEvent( (ICTerminatedEvent)event );
|
||||
}
|
||||
}
|
||||
else if ( event instanceof ICDisconnectedEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleDisconnectedEvent( (ICDisconnectedEvent)event );
|
||||
}
|
||||
}
|
||||
else if ( event instanceof ICChangedEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleChangedEvent( (ICChangedEvent)event );
|
||||
}
|
||||
}
|
||||
else if ( event instanceof ICSteppingEvent )
|
||||
{
|
||||
if ( source instanceof ICThread )
|
||||
{
|
||||
handleSteppingEvent( (ICSteppingEvent)event );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -101,7 +427,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canResume()
|
||||
{
|
||||
return false;
|
||||
return isSuspended() && !getDebugTarget().isSuspended();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -109,7 +435,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canSuspend()
|
||||
{
|
||||
return false;
|
||||
return !isSuspended();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -117,7 +443,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean isSuspended()
|
||||
{
|
||||
return false;
|
||||
return !fRunning && !isTerminated();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -125,6 +451,23 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void resume() throws DebugException
|
||||
{
|
||||
if ( !isSuspended() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
disposeStackFrames();
|
||||
fireResumeEvent( DebugEvent.CLIENT_REQUEST );
|
||||
getCDIThread().resume();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.CLIENT_REQUEST );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred resuming thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -132,6 +475,22 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void suspend() throws DebugException
|
||||
{
|
||||
if ( isSuspended() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( false );
|
||||
getCDIThread().suspend();
|
||||
fireSuspendEvent( DebugEvent.CLIENT_REQUEST );
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( true );
|
||||
fireResumeEvent( DebugEvent.CLIENT_REQUEST );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred suspending thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -139,7 +498,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canStepInto()
|
||||
{
|
||||
return false;
|
||||
return canStep();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -147,7 +506,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canStepOver()
|
||||
{
|
||||
return false;
|
||||
return canStep();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -155,7 +514,26 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canStepReturn()
|
||||
{
|
||||
return false;
|
||||
return canStep();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this thread is in a valid state to
|
||||
* step.
|
||||
*
|
||||
* @return whether this thread is in a valid state to
|
||||
* step
|
||||
*/
|
||||
protected boolean canStep()
|
||||
{
|
||||
try
|
||||
{
|
||||
return fConfig.supportsStepping() && isSuspended() && getTopStackFrame() != null;
|
||||
}
|
||||
catch( DebugException e )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -163,7 +541,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean isStepping()
|
||||
{
|
||||
return false;
|
||||
return getCurrentStateId() == IState.STEPPING; // ????
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -171,6 +549,23 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void stepInto() throws DebugException
|
||||
{
|
||||
if ( !canStepInto() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
preserveStackFrames();
|
||||
fireResumeEvent( DebugEvent.STEP_INTO );
|
||||
getCDIThread().stepInto();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.STEP_INTO );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred stepping in thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -178,6 +573,23 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void stepOver() throws DebugException
|
||||
{
|
||||
if ( !canStepOver() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
preserveStackFrames();
|
||||
fireResumeEvent( DebugEvent.STEP_OVER );
|
||||
getCDIThread().stepInto();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.STEP_OVER );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred stepping in thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -185,6 +597,23 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void stepReturn() throws DebugException
|
||||
{
|
||||
if ( !canStepReturn() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
preserveStackFrames();
|
||||
fireResumeEvent( DebugEvent.STEP_RETURN );
|
||||
getCDIThread().stepInto();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.STEP_RETURN );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred stepping in thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -192,7 +621,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean canTerminate()
|
||||
{
|
||||
return false;
|
||||
return !isTerminated();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -200,7 +629,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public boolean isTerminated()
|
||||
{
|
||||
return false;
|
||||
return getDebugTarget().isTerminated();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -208,6 +637,7 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
public void terminate() throws DebugException
|
||||
{
|
||||
getDebugTarget().terminate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,15 +669,26 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
protected void setRunning( boolean running )
|
||||
{
|
||||
fRunning = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this thread is terminated
|
||||
* Preserves stack frames to be used on the next suspend event.
|
||||
* Iterates through all current stack frames, setting their
|
||||
* state as invalid. This method should be called before this thread
|
||||
* is resumed, when stack frames are to be re-used when it later
|
||||
* suspends.
|
||||
*
|
||||
* @param terminated whether this thread is terminated
|
||||
* @see computeStackFrames()
|
||||
*/
|
||||
protected void setTerminated( boolean terminated )
|
||||
protected void preserveStackFrames()
|
||||
{
|
||||
fRefreshChildren = true;
|
||||
Iterator frames = fStackFrames.iterator();
|
||||
while( frames.hasNext() )
|
||||
{
|
||||
((CStackFrame)frames.next()).setCDIStackFrame( null );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,6 +700,13 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
protected synchronized void disposeStackFrames()
|
||||
{
|
||||
Iterator it = fStackFrames.iterator();
|
||||
while( it.hasNext() )
|
||||
{
|
||||
((CStackFrame)it.next()).dispose();
|
||||
}
|
||||
fStackFrames = Collections.EMPTY_LIST;
|
||||
fRefreshChildren = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,17 +715,185 @@ public class CThread extends CDebugElement
|
|||
*/
|
||||
protected void terminated()
|
||||
{
|
||||
setTerminated( true );
|
||||
setRunning( false );
|
||||
setRunning( false );
|
||||
cleanup();
|
||||
fireTerminateEvent();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentState()
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentStateId()
|
||||
*/
|
||||
public int getCurrentState()
|
||||
public int getCurrentStateId()
|
||||
{
|
||||
return IState.UNKNOWN;
|
||||
return fCurrentStateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current state identifier.
|
||||
*
|
||||
* @param id the identifier
|
||||
*/
|
||||
private void setCurrentStateId( int id )
|
||||
{
|
||||
fCurrentStateId = id;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IState#getCurrentStateInfo()
|
||||
*/
|
||||
public Object getCurrentStateInfo()
|
||||
{
|
||||
return fCurrentStateInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the info object of the current state.
|
||||
*
|
||||
* @param id the info object
|
||||
*/
|
||||
private void setCurrentStateInfo( Object info )
|
||||
{
|
||||
fCurrentStateInfo = info;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#canStepIntoInstruction()
|
||||
*/
|
||||
public boolean canStepIntoInstruction()
|
||||
{
|
||||
return canStepInto();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#canStepOverInstruction()
|
||||
*/
|
||||
public boolean canStepOverInstruction()
|
||||
{
|
||||
return canStepOver();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#stepIntoInstruction()
|
||||
*/
|
||||
public void stepIntoInstruction() throws DebugException
|
||||
{
|
||||
if ( !canStepIntoInstruction() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
preserveStackFrames();
|
||||
fireResumeEvent( DebugEvent.STEP_INTO );
|
||||
getCDIThread().stepIntoInstruction();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.STEP_INTO );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred stepping in thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.IInstructionStep#stepOverInstruction()
|
||||
*/
|
||||
public void stepOverInstruction() throws DebugException
|
||||
{
|
||||
if ( !canStepOverInstruction() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
setRunning( true );
|
||||
preserveStackFrames();
|
||||
fireResumeEvent( DebugEvent.STEP_OVER );
|
||||
getCDIThread().stepOverInstruction();
|
||||
}
|
||||
catch( CDIException e )
|
||||
{
|
||||
setRunning( false );
|
||||
fireSuspendEvent( DebugEvent.STEP_OVER );
|
||||
targetRequestFailed( MessageFormat.format( "{0} occurred stepping in thread.", new String[] { e.toString()} ), e );
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSuspendedEvent( ICSuspendedEvent event )
|
||||
{
|
||||
setRunning( false );
|
||||
setCurrentStateId( IState.SUSPENDED );
|
||||
ICSessionObject reason = event.getReason();
|
||||
setCurrentStateInfo( reason );
|
||||
if ( reason instanceof ICEndSteppingRange )
|
||||
{
|
||||
handleEndSteppingRange( (ICEndSteppingRange)reason );
|
||||
}
|
||||
else if ( reason instanceof ICBreakpoint )
|
||||
{
|
||||
handleBreakpointHit( (ICBreakpoint)reason );
|
||||
}
|
||||
else if ( reason instanceof ICSignal )
|
||||
{
|
||||
handleSuspendedBySignal( (ICSignal)reason );
|
||||
}
|
||||
}
|
||||
|
||||
private void handleResumedEvent( ICResumedEvent event )
|
||||
{
|
||||
setRunning( true );
|
||||
setCurrentStateId( IState.RUNNING );
|
||||
setCurrentStateInfo( null );
|
||||
fireResumeEvent( DebugEvent.UNSPECIFIED );
|
||||
}
|
||||
|
||||
private void handleEndSteppingRange( ICEndSteppingRange endSteppingRange )
|
||||
{
|
||||
fireSuspendEvent( DebugEvent.UNSPECIFIED );
|
||||
}
|
||||
|
||||
private void handleBreakpointHit( ICBreakpoint breakpoint )
|
||||
{
|
||||
fireSuspendEvent( DebugEvent.BREAKPOINT );
|
||||
}
|
||||
|
||||
private void handleSuspendedBySignal( ICSignal signal )
|
||||
{
|
||||
fireSuspendEvent( DebugEvent.UNSPECIFIED );
|
||||
}
|
||||
|
||||
private void handleTerminatedEvent( ICTerminatedEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.TERMINATED );
|
||||
setCurrentStateInfo( null );
|
||||
terminated();
|
||||
}
|
||||
|
||||
private void handleDisconnectedEvent( ICDisconnectedEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.TERMINATED );
|
||||
setCurrentStateInfo( null );
|
||||
terminated();
|
||||
}
|
||||
|
||||
private void handleChangedEvent( ICChangedEvent event )
|
||||
{
|
||||
}
|
||||
|
||||
private void handleSteppingEvent( ICSteppingEvent event )
|
||||
{
|
||||
setCurrentStateId( IState.STEPPING );
|
||||
setCurrentStateInfo( null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the internal state of this thread.
|
||||
*
|
||||
*/
|
||||
protected void cleanup()
|
||||
{
|
||||
getCDISession().getEventManager().removeEventListener( this );
|
||||
disposeStackFrames();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue