/******************************************************************************* * Copyright (c) 2000, 2010 QNX Software 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: * QNX Software Systems - Initial API and implementation * ARM Limited - https://bugs.eclipse.org/bugs/show_bug.cgi?id=186981 *******************************************************************************/ package org.eclipse.cdt.debug.internal.core.model; import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.ICDebugConstants; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.cdi.event.ICDIEvent; import org.eclipse.cdt.debug.core.cdi.event.ICDIMemoryChangedEvent; import org.eclipse.cdt.debug.core.cdi.event.ICDIResumedEvent; import org.eclipse.cdt.debug.core.cdi.model.ICDIArgumentDescriptor; import org.eclipse.cdt.debug.core.cdi.model.ICDIObject; import org.eclipse.cdt.debug.core.cdi.model.ICDIRegister; import org.eclipse.cdt.debug.core.cdi.model.ICDIRegisterDescriptor; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration3; import org.eclipse.cdt.debug.core.cdi.model.ICDIValue; import org.eclipse.cdt.debug.core.cdi.model.ICDIVariable; import org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor; import org.eclipse.cdt.debug.core.cdi.model.type.ICDIArrayValue; import org.eclipse.cdt.debug.core.cdi.model.type.ICDIType; import org.eclipse.cdt.debug.core.model.CVariableFormat; import org.eclipse.cdt.debug.core.model.ICRegister; import org.eclipse.cdt.debug.core.model.ICStackFrame; import org.eclipse.cdt.debug.core.model.ICType; import org.eclipse.cdt.debug.core.model.ICValue; import org.eclipse.cdt.debug.core.model.IRegisterDescriptor; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IRegisterGroup; /** * Represents a register in the CDI model. */ public class CRegister extends CVariable implements ICRegister { private class InternalVariable implements IInternalVariable { /** * The enclosing <code>CVariable</code> instance. */ private CVariable fVariable; /** * The CDI variable object this variable is based on. */ private ICDIVariableDescriptor fCDIVariableObject; /** * The underlying CDI register. */ private ICDIRegister fCDIRegister; /** * The type of this variable. */ private CType fType; /** * The expression used to eveluate the value of this variable. */ private String fQualifiedName; /** * The cache of the current value. */ private ICValue fValue = CValueFactory.NULL_VALUE; /** * The change flag. */ private boolean fChanged = false; /** * Constructor for InternalVariable. */ InternalVariable( CVariable var, ICDIVariableDescriptor varObject ) { setVariable( var ); setCDIVariableObject( varObject ); setCDIRegister( (varObject instanceof ICDIRegister) ? (ICDIRegister)varObject : null ); } public IInternalVariable createShadow( int start, int length ) throws DebugException { IInternalVariable iv = null; try { iv = new InternalVariable( getVariable(), getCDIVariableObject().getVariableDescriptorAsArray( start, length ) ); } catch( CDIException e ) { requestFailed( e.getMessage(), null ); } return iv; } public IInternalVariable createShadow( String type ) throws DebugException { IInternalVariable iv = null; try { iv = new InternalVariable( getVariable(), getCDIVariableObject().getVariableDescriptorAsType( type ) ); } catch( CDIException e ) { requestFailed( e.getMessage(), null ); } return iv; } private synchronized ICDIRegister getCDIRegister() throws DebugException { if ( fCDIRegister == null ) { try { fCDIRegister = getCDITarget().createRegister( (ICDIRegisterDescriptor)getCDIVariableObject() ); } catch( CDIException e ) { requestFailed( e.getMessage(), null ); } } return fCDIRegister; } private void setCDIRegister( ICDIRegister register ) { fCDIRegister = register; } private ICDIVariableDescriptor getCDIVariableObject() { if ( fCDIRegister != null ) { return fCDIRegister; } return fCDIVariableObject; } private void setCDIVariableObject( ICDIVariableDescriptor variableObject ) { fCDIVariableObject = variableObject; } public String getQualifiedName() throws DebugException { if ( fQualifiedName == null ) { try { fQualifiedName = (fCDIVariableObject != null) ? fCDIVariableObject.getQualifiedName() : null; } catch( CDIException e ) { requestFailed( e.getMessage(), null ); } } return fQualifiedName; } public CType getType() throws DebugException { if ( fType == null ) { ICDIVariableDescriptor varObject = getCDIVariableObject(); if ( varObject != null ) { synchronized( this ) { if ( fType == null ) { try { fType = new CType( varObject.getType() ); } catch( CDIException e ) { requestFailed( e.getMessage(), null ); } } } } } return fType; } private synchronized void invalidate( boolean destroy ) { try { if ( destroy && fCDIRegister != null ) fCDIRegister.dispose(); } catch( CDIException e ) { logError( e.getMessage() ); } invalidateValue(); setCDIRegister( null ); if ( fType != null ) fType.dispose(); fType = null; } public void dispose( boolean destroy ) { invalidate( destroy ); } public boolean isSameVariable( ICDIVariable cdiVar ) { return ( fCDIRegister != null ) ? fCDIRegister.equals( cdiVar ) : false; } public int sizeof() { if ( getCDIVariableObject() != null ) { try { return getCDIVariableObject().sizeof(); } catch( CDIException e ) { } } return 0; } public boolean isArgument() { return ( getCDIVariableObject() instanceof ICDIArgumentDescriptor ); } public void setValue( String expression ) throws DebugException { ICDIRegister cdiRegister = null; try { cdiRegister = getCDIRegister(); if ( cdiRegister != null ) cdiRegister.setValue( expression ); else requestFailed( CoreModelMessages.getString( "CModificationVariable.0" ), null ); //$NON-NLS-1$ } catch( CDIException e ) { targetRequestFailed( e.getMessage(), null ); } } public synchronized ICValue getValue() throws DebugException { CStackFrame frame = getCurrentStackFrame(); if ( frame == null || frame.isDisposed() ) fValue = CValueFactory.NULL_VALUE; else if ( fValue.equals( CValueFactory.NULL_VALUE ) ) { ICDIRegister reg = getCDIRegister(); if ( reg != null ) { try { ICDIValue cdiValue = reg.getValue( getCurrentStackFrame().getCDIStackFrame() ); if ( cdiValue != null ) { ICDIType cdiType = cdiValue.getType(); if ( cdiValue instanceof ICDIArrayValue && cdiType != null ) { ICType type = new CType( cdiType ); if ( type.isArray() ) { int[] dims = type.getArrayDimensions(); if ( dims.length > 0 && dims[0] > 0 ) fValue = CValueFactory.createIndexedValue( getVariable(), (ICDIArrayValue)cdiValue, 0, dims[0] ); } } else { fValue = CValueFactory.createValue( getVariable(), cdiValue ); } } } catch( CDIException e ) { requestFailed( e.getMessage(), e ); } } } return fValue; } public void invalidateValue() { if ( fValue instanceof AbstractCValue ) { ((AbstractCValue)fValue).dispose(); fValue = CValueFactory.NULL_VALUE; } } public boolean isChanged() { return fChanged; } public synchronized void setChanged( boolean changed ) { if ( changed ) { invalidateValue(); } if ( fValue instanceof AbstractCValue ) { ((AbstractCValue)fValue).setChanged( changed ); } fChanged = changed; } public synchronized void preserve() { setChanged( false ); if ( fValue instanceof AbstractCValue ) { ((AbstractCValue)fValue).preserve(); } } CVariable getVariable() { return fVariable; } private void setVariable( CVariable variable ) { fVariable = variable; } public void resetValue() { if ( fValue instanceof AbstractCValue ) { ((AbstractCValue)fValue).reset(); } } public boolean isEditable() throws DebugException { ICDIRegister reg = getCDIRegister(); if ( reg != null && reg.getTarget().getConfiguration().supportsRegisterModification() ) { try { return reg.isEditable(); } catch( CDIException e ) { } } return false; } /** * Compares the underlying variable objects. * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals( Object obj ) { if ( obj instanceof InternalVariable ) { return getCDIVariableObject().equals( ((InternalVariable)obj).getCDIVariableObject() ); } return false; } public boolean isSameDescriptor( ICDIVariableDescriptor desc ) { return getCDIVariableObject().equals( desc ); } public ICDIObject getCdiObject() { return fCDIRegister; } } /** * Constructor for CRegister. */ protected CRegister( CRegisterGroup parent, IRegisterDescriptor descriptor ) { super( parent, ((CRegisterDescriptor)descriptor).getCDIDescriptor() ); setFormat( CVariableFormat.getFormat( CDebugCorePlugin.getDefault().getPluginPreferences().getInt( ICDebugConstants.PREF_DEFAULT_REGISTER_FORMAT ) ) ); setInitialFormat(); } /** * Constructor for CRegister. */ protected CRegister( CRegisterGroup parent, IRegisterDescriptor descriptor, String message ) { super( parent, ((CRegisterDescriptor)descriptor).getCDIDescriptor(), message ); setFormat( CVariableFormat.getFormat( CDebugCorePlugin.getDefault().getPluginPreferences().getInt( ICDebugConstants.PREF_DEFAULT_REGISTER_FORMAT ) ) ); setInitialFormat(); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IRegister#getRegisterGroup() */ public IRegisterGroup getRegisterGroup() throws DebugException { return (IRegisterGroup)getParent(); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.internal.core.model.CVariable#isBookkeepingEnabled() */ protected boolean isBookkeepingEnabled() { boolean result = false; try { result = getLaunch().getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_REGISTER_BOOKKEEPING, false ); } catch( CoreException e ) { } return result; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.model.ICVariable#canEnableDisable() */ public boolean canEnableDisable() { return true; } /* (non-Javadoc) * @see org.eclipse.cdt.debug.core.cdi.event.ICDIEventListener#handleDebugEvents(org.eclipse.cdt.debug.core.cdi.event.ICDIEvent[]) */ public void handleDebugEvents( ICDIEvent[] events ) { for( int i = 0; i < events.length; i++ ) { ICDIEvent event = events[i]; ICDIObject source = event.getSource(); if (source != null) { ICDITarget cdiTarget = source.getTarget(); if ( event instanceof ICDIResumedEvent ) { if ( getCDITarget().equals( cdiTarget ) ) { setChanged( false ); } } else if ( event instanceof ICDIMemoryChangedEvent && cdiTarget.getConfiguration() instanceof ICDITargetConfiguration3 && ((ICDITargetConfiguration3)cdiTarget.getConfiguration()).needsRegistersUpdated(event)) { resetValue(); return; // avoid similar but logic inappropriate for us in CVariable } } } super.handleDebugEvents( events ); } /* (non-Javadoc) * @see org.eclipse.cdt.debug.internal.core.model.AbstractCVariable#dispose() */ public void dispose() { internalDispose( true ); setDisposed( true ); } protected ICStackFrame getStackFrame() { ICStackFrame frame = super.getStackFrame(); if (frame == null) frame = getCurrentStackFrame(); return frame; } protected CStackFrame getCurrentStackFrame() { return ((CDebugTarget)getDebugTarget()).getRegisterManager().getCurrentFrame(); } protected void createOriginal( ICDIVariableDescriptor vo ) { if ( vo != null ) { setName( vo.getName() ); setOriginal( new InternalVariable( this, vo ) ); } } }