diff --git a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF index 3ab20a1b96b..05ae0f71e51 100644 --- a/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.core/META-INF/MANIFEST.MF @@ -15,6 +15,7 @@ Export-Package: org.eclipse.cdt.debug.core, org.eclipse.cdt.debug.core.disassembly, org.eclipse.cdt.debug.core.executables, org.eclipse.cdt.debug.core.model, + org.eclipse.cdt.debug.core.model.provisional;x-friends:="org.eclipse.cdt.dsf,org.eclipse.cdt.debug.ui.memory.memorybrowser,org.eclipse.cdt.dsf.gdb", org.eclipse.cdt.debug.core.sourcelookup, org.eclipse.cdt.debug.internal.core;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc,org.eclipse.cdt.dsf.gdb", diff --git a/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceEncoder.java b/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceEncoder.java new file mode 100644 index 00000000000..f11d3beb930 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceEncoder.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2010 Freescale Semiconductor, Inc. + * 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: + * Freescale Semiconductor, Inc. - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.cdi.model; + +import org.eclipse.cdt.debug.core.cdi.CDIException; + +/** + * Add-on interface for objects that implement ICDIMemorySpaceManagement. + * Provides the string encoding and decoding of a memory space qualified + * address. CDT provides a default encoding of [memory-space-id]:[expression]. + * If this is adequate, the CDI client need not implement this interface. This + * method is called when having to represent a memory-space qualified address as + * a single string. + * + * @since 7.0 + */ +public interface ICDIMemorySpaceEncoder extends ICDIObject { + /** + * Encode an expression + memory space ID to a string. + * + * @param expression + * the expression representing a location within a memory space. + * This can be a simple numeric expression like "0x10000" or + * something more complex "$EAX+(gCustomerCount*100)". + * @param memorySpaceID + * a string which represents the memory space + * @return the encoded string representation of the address; never null + */ + String encodeAddress(String expression, String memorySpaceID); + + /** + * The inverse of {@link #encodeAddress(String, String)}. + * + * @param str + * the encoded string + * @return the result of decoding the string into its components; never null + * @throws CDIException + * if string is not in the expected format + */ + DecodeResult decodeAddress(String str) throws CDIException; + + interface DecodeResult { + String getMemorySpaceId(); + String getExpression(); + } +} diff --git a/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceManagement.java b/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceManagement.java index a088800469f..64b4790e593 100644 --- a/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceManagement.java +++ b/debug/org.eclipse.cdt.debug.core/cdi/org/eclipse/cdt/debug/core/cdi/model/ICDIMemorySpaceManagement.java @@ -21,29 +21,38 @@ import org.eclipse.cdt.debug.core.cdi.CDIException; * as well if the target supports memory spaces. */ public interface ICDIMemorySpaceManagement extends ICDIObject { - /** - * Optionally provides the string encoding of a memory space qualified address. - * CDT provides a default encoding of :. - * If this is adequate, the client can return null from this function. + * Optionally provides the string encoding of a memory space qualified + * address. CDT provides a default encoding of + * :. If this is adequate, the client can + * return null from this function. * - * @param address - a numeric address - * @param memorySpaceID - a string which represents the memory space + * @param address + * a numeric address + * @param memorySpaceID + * a string which represents the memory space * @return the encoded string representation of the address or null + * @deprecated CDI clients should implement ICDIMemorySpaceEncoder */ String addressToString(BigInteger address, String memorySpaceID); /** * The inverse of addressToString. Optionally decodes a memoryspace/address - * string to its components. Client must provide decoding if it provides - * encoding in addressToString. Conversely, it should return null if + * string to its components. Client must provide decoding if it provides + * encoding in addressToString. Conversely, it should return null if * addressToString returns null. - * - * @param str - the encoded string (contains memory space + hex address value) - * @param memorySpaceID_out the memory space ID - * @return the BigInteger part of str; client should return null if the default decoding provided - * by CDT is sufficient (:) - * @throws CDIException if string is not in the expected format + * + * @param str + * the encoded string (contains memory space + hex address + * value) + * @param memorySpaceID_out + * the memory space ID + * @return the BigInteger part of str; client should return null if the + * default decoding provided by CDT is sufficient + * (:) + * @throws CDIException + * if string is not in the expected format + * @deprecated CDI clients should implement ICDIMemorySpaceEncoder */ BigInteger stringToAddress(String str, StringBuffer memorySpaceID_out) throws CDIException; diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemoryRenderingViewportProvider.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemoryRenderingViewportProvider.java new file mode 100644 index 00000000000..194d624e89b --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemoryRenderingViewportProvider.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010, Freescale Semiconductor 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: + * Freescale Semiconductor - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model.provisional; + +import java.math.BigInteger; + +/** + * An add-on interface for memory renderings to provide access to the first + * address being displayed. As the user scrolls the rendering, this value + * changes. + */ +public interface IMemoryRenderingViewportProvider { + + /** + * Return the first address being shown in the rendering. Subject to scrolling. + */ + BigInteger getViewportAddress(); +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlock.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlock.java new file mode 100644 index 00000000000..c6c2e313fd3 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlock.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2010, Texas Instruments, Freescale Semiconductor 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: + * Texas Instruments, Freescale Semiconductor - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model.provisional; + +import org.eclipse.debug.core.model.IMemoryBlockExtension; + +/** + * An extension of IMemoryBlockExtension that supports memory spaces. An + * instance of this is returned from IMemorySpaceAwareMemoryBlockRetrieval. The + * memory space interface is provisional, thus this class cannot yet be API. + * + * @author Alain Lee and John Cortell + */ +public interface IMemorySpaceAwareMemoryBlock extends IMemoryBlockExtension { + + /** + * Returns the memory space associated with this block + * + * @return a memory space ID, or null if the block was created without a + * memory space identifier. These IDs originate from the backend. See + * {@link IMemorySpaceAwareMemoryBlockRetrieval#getMemorySpaces(Object, IRequestListener)} + */ + public String getMemorySpaceID(); +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlockRetrieval.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlockRetrieval.java new file mode 100644 index 00000000000..812c77ee9e5 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/provisional/IMemorySpaceAwareMemoryBlockRetrieval.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2010, Texas Instruments, Freescale Semiconductor 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: + * Texas Instruments, Freescale Semiconductor - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model.provisional; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; + +/** + * An extension of the IMemoryBlockRetrievalExtension interface that supports + * memory spaces. The memory space interface is provisional, thus this class + * cannot yet be API. + * + * @author Alain Lee and John Cortell + */ +public interface IMemorySpaceAwareMemoryBlockRetrieval extends IMemoryBlockRetrievalExtension { + + /** + * Caller to {@link #getMemorySpaces()} provides one of these, as that + * method may need to consult the debugger backend, and thus needs to be + * asynchronous + */ + interface GetMemorySpacesRequest extends IRequest { + String[] getMemorySpaces(); + void setMemorySpaces(String[] memorySpaceIds); + } + + /** + * Provides the string encoding of a memory space qualified address. This + * method is called when having to represent a memory-space qualified + * address as a single string. + * + * @param expression + * the expression representing a location within a memory space. + * This can be a simple numeric expression like "0x10000" or + * something more complex "$EAX+(gCustomerCount*100)". + * @param memorySpaceID + * a string which represents the memory space + * @return the encoded string representation of the address, or null to + * indicate no custom encoding is required + */ + String encodeAddress(String expression, String memorySpaceID); + + /** + * The inverse of {@link #encodeAddress(String, String)}. + * + * @param str + * the encoded string + * @return the result of decoding the string into its components; never null + * @throws CoreException + * if decoding and string is not in the expected format + */ + DecodeResult decodeAddress(String str) throws CoreException; + + interface DecodeResult { + String getMemorySpaceId(); + String getExpression(); + } + + /** + * Provides the memory spaces available for the given debug context. + * + * @param context + * a debug context + * @param request + * the asynchronous data request object + * @return an array of memory space identifiers + */ + void getMemorySpaces(Object context, GetMemorySpacesRequest request); + + /** + * Retrieves and returns a memory block. + * + * @param expression + * expression to be evaluated to an address + * @param context + * a debug context + * @param memorySpaceID + * the memory space the block is being requested for, or null if + * n/a + * @return a memory block based on the given parameters + * @throws DebugException + * if unable to retrieve the specified memory + */ + public IMemorySpaceAwareMemoryBlock getMemoryBlock(String expression, Object context, String memorySpaceID) throws DebugException; + +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CMemoryBlockRetrievalExtension.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CMemoryBlockRetrievalExtension.java index 53e6f1ca2a5..11e6ce37787 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CMemoryBlockRetrievalExtension.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/CMemoryBlockRetrievalExtension.java @@ -11,7 +11,6 @@ package org.eclipse.cdt.debug.internal.core; import java.math.BigInteger; -import com.ibm.icu.text.MessageFormat; import java.util.ArrayList; import java.util.List; @@ -22,10 +21,13 @@ import org.eclipse.cdt.debug.core.CDebugCorePlugin; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.cdi.model.ICDIExpression; +import org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceEncoder; import org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.model.ICType; import org.eclipse.cdt.debug.core.model.ICValue; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlock; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval; import org.eclipse.cdt.debug.internal.core.model.CDebugTarget; import org.eclipse.cdt.debug.internal.core.model.CExpression; import org.eclipse.cdt.debug.internal.core.model.CMemoryBlockExtension; @@ -44,7 +46,6 @@ import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; -import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IValue; import org.w3c.dom.Document; @@ -52,10 +53,12 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import com.ibm.icu.text.MessageFormat; + /** * Implements the memory retrieval features based on the CDI model. */ -public class CMemoryBlockRetrievalExtension extends PlatformObject implements IMemoryBlockRetrievalExtension { +public class CMemoryBlockRetrievalExtension extends PlatformObject implements IMemorySpaceAwareMemoryBlockRetrieval { private static final String MEMORY_BLOCK_EXPRESSION_LIST = "memoryBlockExpressionList"; //$NON-NLS-1$ private static final String MEMORY_BLOCK_EXPRESSION_ITEM = "memoryBlockExpressionItem"; //$NON-NLS-1$ @@ -89,7 +92,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM } } - private void parseMementoExprItem(Element element, List expressions, List memorySpaceIDs) { + private void parseMementoExprItem(Element element, List expressions, List memorySpaceIDs) { NodeList list = element.getChildNodes(); int length = list.getLength(); String exp = null; @@ -115,8 +118,8 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM private void initializeFromMemento( String memento ) throws CoreException { Element root = DebugPlugin.parseDocument( memento ); if ( root.getNodeName().equalsIgnoreCase( MEMORY_BLOCK_EXPRESSION_LIST ) ) { - List expressions = new ArrayList(); - List memorySpaceIDs = new ArrayList(); + List expressions = new ArrayList(); + List memorySpaceIDs = new ArrayList(); NodeList list = root.getChildNodes(); int length = list.getLength(); for( int i = 0; i < length; ++i ) { @@ -128,8 +131,8 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM } } } - createMemoryBlocks( (String[])expressions.toArray( new String[expressions.size()]) , - (String[])memorySpaceIDs.toArray( new String[memorySpaceIDs.size()])); + createMemoryBlocks( expressions.toArray( new String[expressions.size()]) , + memorySpaceIDs.toArray( new String[memorySpaceIDs.size()])); return; } @@ -160,7 +163,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM } private void createMemoryBlocks( String[] expressions, String[] memorySpaceIDs ) { - ArrayList list = new ArrayList( expressions.length ); + List list = new ArrayList( expressions.length ); for ( int i = 0; i < expressions.length; ++i ) { try { IAddress address = getDebugTarget().getAddressFactory().createAddress( expressions[i] ); @@ -168,14 +171,14 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM if (memorySpaceIDs[i] == null) { list.add( new CMemoryBlockExtension( getDebugTarget(), address.toHexAddressString(), address.getValue() ) ); } else { - list.add( new CMemoryBlockExtension( getDebugTarget(), address.getValue(), memorySpaceIDs[i] ) ); + list.add( new CMemoryBlockExtension( getDebugTarget(), expressions[i], address.getValue(), memorySpaceIDs[i] ) ); } } } catch (NumberFormatException exc) { CDebugCorePlugin.log(exc); } } - DebugPlugin.getDefault().getMemoryBlockManager().addMemoryBlocks( (IMemoryBlock[])list.toArray( new IMemoryBlock[list.size()] ) ); + DebugPlugin.getDefault().getMemoryBlockManager().addMemoryBlocks( list.toArray( new IMemoryBlock[list.size()] ) ); } public String getMemento() throws CoreException { @@ -188,40 +191,15 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM Element exprItem = document.createElement( MEMORY_BLOCK_EXPRESSION_ITEM ); exprList.appendChild(exprItem); - BigInteger addrBigInt = null; String memorySpaceID = null; - if (hasMemorySpaces() && fDebugTarget != null) { - // Can't tell if block was created with a memory-space/address or with an expression. - // Assume the former and let an exception in the decoding tell us otherwise - ICDITarget cdiTarget = fDebugTarget.getCDITarget(); - try { - StringBuffer sbuf = new StringBuffer(); - addrBigInt = ((ICDIMemorySpaceManagement)cdiTarget).stringToAddress(memBlockExt.getExpression(), sbuf); - if (addrBigInt == null) { - // Client wants our default decoding; minimum is ":0x?" - addrBigInt = stringToAddress(memBlockExt.getExpression(), sbuf); - } - memorySpaceID = sbuf.toString(); - } - catch( CDIException e ) { // thrown by CDI client decoding method - } - catch (CoreException e) { // thrown by our decoding method - } + if (memBlockExt instanceof IMemorySpaceAwareMemoryBlock) { + memorySpaceID = ((IMemorySpaceAwareMemoryBlock)memBlockExt).getMemorySpaceID(); } - + BigInteger addrBigInt = memBlockExt.getBigBaseAddress(); + Element child = document.createElement( MEMORY_BLOCK_EXPRESSION ); - try { - if (addrBigInt != null && memorySpaceID != null) { - child.setAttribute( ATTR_MEMORY_BLOCK_EXPRESSION_TEXT, addrBigInt.toString() ); - } - else { - child.setAttribute( ATTR_MEMORY_BLOCK_EXPRESSION_TEXT, memBlockExt.getBigBaseAddress().toString() ); - } - exprItem.appendChild( child ); - } - catch( DebugException e ) { - CDebugCorePlugin.log( e.getStatus() ); - } + child.setAttribute( ATTR_MEMORY_BLOCK_EXPRESSION_TEXT, "0x" + addrBigInt.toString(16) ); //$NON-NLS-1$ + exprItem.appendChild( child ); if (memorySpaceID != null) { child = document.createElement( MEMORY_BLOCK_MEMSPACEID ); @@ -238,6 +216,13 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM * @see org.eclipse.debug.core.model.IMemoryBlockExtensionRetrieval#getExtendedMemoryBlock(java.lang.String, org.eclipse.debug.core.model.IDebugElement) */ public IMemoryBlockExtension getExtendedMemoryBlock( String expression, Object selected ) throws DebugException { + return getMemoryBlock(expression, selected, null); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.internal.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval#getExtendedMemoryBlock(java.lang.String, java.lang.Object, java.lang.String) + */ + public IMemorySpaceAwareMemoryBlock getMemoryBlock( String expression, Object selected, String memorySpaceID ) throws DebugException { String address = null; CExpression exp = null; String msg = null; @@ -252,7 +237,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM // See if the expression is a simple numeric value; if it is, we can avoid some costly // processing (calling the backend to resolve the expression) try { - return new CMemoryBlockExtension((CDebugTarget)target, expression, evaluateLiteralAddress(expression)); + return new CMemoryBlockExtension((CDebugTarget)target, expression, evaluateLiteralAddress(expression), memorySpaceID); } catch (NumberFormatException nfexc) {} // OK, expression is not a simple literal address; keep trucking and try to resolve as expression @@ -267,7 +252,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM if ( type != null ) { // get the address for the expression, allow all types String rawExpr = exp.getExpressionString(); - String voidExpr = "(void *)(" + rawExpr + ")"; + String voidExpr = "(void *)(" + rawExpr + ')'; //$NON-NLS-1$ String attempts[] = { rawExpr, voidExpr }; for (int i = 0; i < attempts.length; i++) { String expr = attempts[i]; @@ -275,7 +260,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM if (address != null) { try { BigInteger a = (address.startsWith("0x")) ? new BigInteger(address.substring(2), 16) : new BigInteger(address); //$NON-NLS-1$ - return new CMemoryBlockExtension((CDebugTarget) target, expression, a); + return new CMemoryBlockExtension((CDebugTarget) target, expression, a, memorySpaceID); } catch (NumberFormatException e) { // not pointer? lets cast it to void* if (i == 0) @@ -287,11 +272,11 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM } else { - msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.1" ), (Object[])new String[] { expression } ); //$NON-NLS-1$ + msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.1" ), new String[] { expression } ); //$NON-NLS-1$ } } else { - msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.2" ), (Object[])new String[] { expression } ); //$NON-NLS-1$ + msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.2" ), new String[] { expression } ); //$NON-NLS-1$ } } } @@ -300,7 +285,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM msg = e.getMessage(); } catch( NumberFormatException e ) { - msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.0" ), (Object[])new String[] { expression } ); //$NON-NLS-1$ + msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.0" ), new String[] { expression } ); //$NON-NLS-1$ } finally { if (exp != null) { @@ -327,38 +312,6 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM expression = "0x" + expression; //$NON-NLS-1$ return new CMemoryBlockExtension( getDebugTarget(), expression, address ); } - - /** - * Variant of getExtendedMemoryBlock that takes a memory space ID. Note that unlike that one, - * this method is not part of IMemoryBlockRetrievalExtension; it is not exercised by the - * platform. We invoke it internally in CDT from our hook into the platform's "add memory - * monitor" action. - * - * @param address - a numric address value, hex or decimal. An expression - * (even something simple like 10000 +1) is not allowed. - * @param memorySpaceID - identifies the memory space; cannot be null. - * @param selected - the object selected in the Debug view - * @return - * @throws DebugException - */ - public IMemoryBlockExtension getMemoryBlockWithMemorySpaceID( String address, String memorySpaceID, Object selected ) throws DebugException { - String msg = null; - try { - if (selected instanceof IDebugElement) { - IDebugElement debugElement = (IDebugElement)selected; - IDebugTarget target = debugElement.getDebugTarget(); - if ( target instanceof CDebugTarget ) { - if ( address != null ) { - return new CMemoryBlockExtension((CDebugTarget)target, evaluateLiteralAddress(address), memorySpaceID); - } - } - } - } - catch( NumberFormatException e ) { - msg = MessageFormat.format( InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.4" ), (Object[])new String[] { address } ); //$NON-NLS-1$ - } - throw new DebugException( new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), DebugException.REQUEST_FAILED, msg, null ) ); - } private CStackFrame getStackFrame( IDebugElement selected ) throws DebugException { if ( selected instanceof CStackFrame ) { @@ -411,11 +364,26 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM } /** - * Get the list of available memory spaces from the CDI backend - * - * @return an array of memory space identifiers + * @see org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval#getMemorySpaces(java.lang.Object, org.eclipse.cdt.debug.internal.core.model.provisional.IRequestListener) */ - public String [] getMemorySpaces() { + public void getMemorySpaces(final Object context, GetMemorySpacesRequest request) { + // We're not very asynchronous in CDI. DSF is another story. Also, note + // that we ignore the context. That's because we know that there's only + // one instance of this object per process object, and all elements of + // the project object (process, threads, frames) will have the same + // memory spaces + request.setMemorySpaces(getMemorySpaces()); + request.done(); + } + + /** + * This variant is called by code that is CDI-specific. This method and its + * uses predate the introduction of the DSF/CDI-agnostic + * IMemorySpaceAwareMemoryBlockRetrieval + * + * @return the memory spaces available in this debug session + */ + public String [] getMemorySpaces(){ if (fDebugTarget != null) { ICDITarget cdiTarget = fDebugTarget.getCDITarget(); if (cdiTarget instanceof ICDIMemorySpaceManagement) @@ -424,33 +392,79 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM return new String[0]; } - - /* - * static implementation of - * @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement#addressToString(java.math.BigInteger, java.lang.String) - * client may choose not to provide the encoding/decoding and instead use our built-in handling. - * + + /** + * The default encoding of an {expression, memory space ID} pair into a + * string. A CDI client can provide custom decoding by implementing + * ICDIMemorySpaceEncoder */ - public static String addressToString(BigInteger address, String memorySpaceID) { - return memorySpaceID + ":0x" + address.toString(16); //$NON-NLS-1$ + public static String encodeAddressDefault(String expression, String memorySpaceID) { + return memorySpaceID + ':' + expression; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.internal.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval#encodeAddress(java.math.BigInteger, java.lang.String) + */ + public String encodeAddress(final String expression, final String memorySpaceID) { + // See if the CDI client provides customized encoding/decoding + if (fDebugTarget != null) { + ICDITarget cdiTarget = fDebugTarget.getCDITarget(); + if (cdiTarget instanceof ICDIMemorySpaceEncoder) { + return ((ICDIMemorySpaceEncoder)cdiTarget).encodeAddress(expression, memorySpaceID); + } + } + + // Nope; use default encoding + return encodeAddressDefault(expression, memorySpaceID); } /* - * static implementation of - * @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement#stringToAddr(java.lang.String, java.math.BigInteger, java.lang.StringBuffer) - * client may choose not to provide the encoding/decoding and instead use our built-in handling. + * The default decoding of a string into an {expression, memory space ID} + * pair. A CDI client can provide custom decoding by implementing ICDIMemorySpaceEncoder */ - public static BigInteger stringToAddress(String str, StringBuffer memorySpaceID_out) throws CoreException { + public static DecodeResult decodeAddressDefault(String str) throws CoreException { int index = str.lastIndexOf(':'); - // minimum is ":0x?" - if (index == -1 || str.length() <= index + 3 || str.charAt(index+1) != '0' || str.charAt(index+2) != 'x') { + // minimum is ":" + if ((index == -1) || (index == str.length()-1)) { IStatus s = new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.5" ), null ); //$NON-NLS-1$ throw new CoreException( s ); } - memorySpaceID_out.setLength(0); - memorySpaceID_out.append(str.substring(0, index)); - return new BigInteger(str.substring(index+3), 16); + final String memorySpaceID = str.substring(0, index); + final String expression = str.substring(index+1); + + return new DecodeResult() { + public String getMemorySpaceId() { return memorySpaceID; } + public String getExpression() { return expression; } + }; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.internal.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval#decodeAddress(java.lang.String, java.lang.StringBuffer) + */ + public DecodeResult decodeAddress(final String str) throws CoreException { + + // See if the CDI client provides customized encoding/decoding + if (fDebugTarget != null) { + ICDITarget cdiTarget = fDebugTarget.getCDITarget(); + if (cdiTarget instanceof ICDIMemorySpaceEncoder) { + try { + final ICDIMemorySpaceEncoder.DecodeResult result = ((ICDIMemorySpaceEncoder)cdiTarget).decodeAddress(str); + return new DecodeResult() { + public String getMemorySpaceId() { return result.getMemorySpaceId(); } + public String getExpression() { return result.getExpression(); } + }; + } + catch (CDIException exc) { + IStatus s = new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.invalid_encoded_addresses" ), exc); //$NON-NLS-1$ + throw new CoreException(s); + + } + } + } + + // Nope; use default decoding + return decodeAddressDefault(str); } } diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/InternalDebugCoreMessages.properties b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/InternalDebugCoreMessages.properties index f4950f8872c..6197b55bac5 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/InternalDebugCoreMessages.properties +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/InternalDebugCoreMessages.properties @@ -14,6 +14,7 @@ CMemoryBlockRetrievalExtension.1=Invalid expression type: ''{0}'' CMemoryBlockRetrievalExtension.2=Invalid expression: ''{0}'' CMemoryBlockRetrievalExtension.3=Memory initialization: invalid memento. CMemoryBlockRetrievalExtension.4=Invalid address: ''{0}'' +CMemoryBlockRetrievalExtension.invalid_encoded_addresses=Format of encoded address is invalid. DebugConfiguration.0=This debugger no longer supports this operation CDebugAdapter.0=This debugger does not support debugging external files CDebugAdapter.1=Debugger Process diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CMemoryBlockExtension.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CMemoryBlockExtension.java index 22badab39ec..4e84bdd3f4f 100644 --- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CMemoryBlockExtension.java +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/model/CMemoryBlockExtension.java @@ -25,22 +25,23 @@ import org.eclipse.cdt.debug.core.cdi.event.ICDIRestartedEvent; import org.eclipse.cdt.debug.core.cdi.event.ICDIResumedEvent; import org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock; import org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlockManagement2; +import org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceEncoder; import org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement; import org.eclipse.cdt.debug.core.cdi.model.ICDIObject; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.model.IExecFileInfo; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlock; import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.IMemoryBlockRetrieval; import org.eclipse.debug.core.model.MemoryByte; /** * Represents a memory block in the CDI model. */ -public class CMemoryBlockExtension extends CDebugElement implements IMemoryBlockExtension, ICDIEventListener { +public class CMemoryBlockExtension extends CDebugElement implements IMemorySpaceAwareMemoryBlock, ICDIEventListener { /** * The address expression this memory block is based on. @@ -82,41 +83,63 @@ public class CMemoryBlockExtension extends CDebugElement implements IMemoryBlock /** - * Constructor for CMemoryBlockExtension. + * Constructor */ public CMemoryBlockExtension( CDebugTarget target, String expression, BigInteger baseAddress ) { - super( target ); - - fExpression = expression; - fBaseAddress = baseAddress; + this(target, expression, baseAddress, null); } /** - * Constructor for CMemoryBlockExtension. + * Constructor that takes a memory space identifier + */ + @SuppressWarnings("deprecation") + public CMemoryBlockExtension( CDebugTarget target, String expression, BigInteger baseAddress, String memorySpaceID ) { + super( target ); + + fBaseAddress = baseAddress; + fMemorySpaceID = memorySpaceID; + + if (memorySpaceID == null) { + fExpression = expression; + } + else { + assert memorySpaceID.length() > 0; + ICDITarget cdiTarget = target.getCDITarget(); + if (cdiTarget instanceof ICDIMemorySpaceEncoder) { + // new interface + fExpression = ((ICDIMemorySpaceEncoder)cdiTarget).encodeAddress(expression, memorySpaceID); + } + else if (cdiTarget instanceof ICDIMemorySpaceManagement) { + // old interface + fExpression = ((ICDIMemorySpaceManagement)target.getCDITarget()).addressToString(baseAddress, memorySpaceID); + } + + if (fExpression == null) { + // If the backend supports memory spaces, it should implement ICDIMemorySpaceManagement + // Even if it does, it may choose to use our built-in encoding/decoding + fExpression = CMemoryBlockRetrievalExtension.encodeAddressDefault(expression, memorySpaceID); + } + } + + } + + /** + * Constructor that takes the addressable size */ public CMemoryBlockExtension( CDebugTarget target, String expression, BigInteger baseAddress, int wordSize ) { + this( target, expression, baseAddress, wordSize, null ); + } + + /** + * Constructor that takes the addressable size and a memory space identifier + */ + public CMemoryBlockExtension( CDebugTarget target, String expression, BigInteger baseAddress, int wordSize, String memorySpaceID ) { super( target ); fExpression = expression; fBaseAddress = baseAddress; fWordSize= wordSize; fHaveWordSize= true; - } - - /** - * Constructor for CMemoryBlockExtension that supports memory spaces - * - */ - public CMemoryBlockExtension( CDebugTarget target, BigInteger baseAddress, String memorySpaceID ) { - super( target ); - fBaseAddress = baseAddress; - fMemorySpaceID = memorySpaceID; - if (target.getCDITarget() instanceof ICDIMemorySpaceManagement) - fExpression = ((ICDIMemorySpaceManagement)target.getCDITarget()).addressToString(baseAddress, memorySpaceID); - - if (fExpression == null) - // If the backend supports memory spaces, it should implement ICDIMemorySpaceManagement - // Even if it does, it may choose to use our built-in encoding/decoding - fExpression = CMemoryBlockRetrievalExtension.addressToString(baseAddress, memorySpaceID); + fMemorySpaceID = memorySpaceID; } /* (non-Javadoc) @@ -547,13 +570,7 @@ public class CMemoryBlockExtension extends CDebugElement implements IMemoryBlock /** - * Provides the memory space associated with this block if and only if the - * block was created with an address value + memory space qualifier. If the - * block was created from an expression, this method should return null-- - * even if the target CDI backend supports memory spaces. - * - * @return a memory space ID or null - * expression + * @see org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlock#getMemorySpaceID() */ public String getMemorySpaceID() { return fMemorySpaceID; diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml index 31c00afc9e8..6dccc237add 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.xml +++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml @@ -1388,24 +1388,11 @@ - - - - - - - - 1) - return fgAddMemoryBlocks; - } - } - - if (adapterType.equals(ILabelDecorator.class)) { - if (adaptableObject instanceof CMemoryBlockExtension) { - // If a memory space isn't involved, the standard label is fine - CMemoryBlockExtension memBlock = (CMemoryBlockExtension)adaptableObject; - if (memBlock.getMemorySpaceID() != null) - return new MemoryBlockLabelDecorator(memBlock); + if (adaptableObject instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + return fgAddMemoryBlocks; } } return null; } - /* - * (non-Javadoc) - * + /* (non-Javadoc) * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() */ + @SuppressWarnings("rawtypes") public Class[] getAdapterList() { - return new Class[] { IAddMemoryBlocksTarget.class, ILabelDecorator.class }; + return new Class[] { IAddMemoryBlocksTarget.class }; } } diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlockDialog.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlockDialog.java index 916c9788b6e..7a36f57463d 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlockDialog.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlockDialog.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 Freescale, Inc. + * Copyright (c) 2005, 2010 Freescale Semiconductor, Inc. * 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: - * Freescale, Inc. - initial API and implementation + * Freescale Semiconductor, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.views.memory; @@ -14,8 +14,6 @@ package org.eclipse.cdt.debug.internal.ui.views.memory; import java.util.ArrayList; import java.util.List; -import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension; -import org.eclipse.debug.core.model.IMemoryBlockRetrieval; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.swt.SWT; @@ -55,23 +53,33 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener, private Button fExpressionRadio; private String fAddress; private String fMemorySpace; - private boolean fEnteredExpression; // basically, which of the two radio buttons was selected when OK was hit - private CMemoryBlockRetrievalExtension fMemRetrieval; + private boolean fEnteredExpression; // basically, which of the two radio buttons was selected when OK was hit + + /** The memory spaces to expose. Given to use at instantiation time. */ + final private String[] fMemorySpaces; + + /** + * For improved usability, we persist the memory space selection from one + * invocation of the dialog to another, but we need not worry about + * persisting it from one instantiation of Eclipse to the next + */ + private static String fPreviousMemorySpaceSelection; private static List sAddressHistory = new ArrayList(); private static List sExpressionHistory = new ArrayList(); private static boolean sDefaultToExpression = true; - public AddMemoryBlockDialog(Shell parentShell, - IMemoryBlockRetrieval memRetrieval) { + public AddMemoryBlockDialog(Shell parentShell, String[] memorySpaces) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); + fMemorySpaces = memorySpaces; - if (memRetrieval instanceof CMemoryBlockRetrievalExtension) { - fMemRetrieval = (CMemoryBlockRetrievalExtension)memRetrieval; - } + // We shouldn't be using this custom dialog if there are none or only + // one memory spaces available. + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=309032#c50 + assert memorySpaces != null && memorySpaces.length >= 2; } /* (non-Javadoc) @@ -124,7 +132,27 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener, gridData = new GridData(); gridData.horizontalIndent = radioButtonWidth; fMemorySpaceInput.setLayoutData(gridData); - fMemorySpaceInput.addSelectionListener(this); + fMemorySpaceInput.addSelectionListener(this); + + fMemorySpaceInput.setItems(fMemorySpaces); + + // Try to persist the mem space selection from one invocation of the + // dialog to the next + String memSpaceSelection = null; + if (fPreviousMemorySpaceSelection != null) { + String[] items = fMemorySpaceInput.getItems(); + for (String item : items) { + if (item.equals(fPreviousMemorySpaceSelection)) { + memSpaceSelection = fPreviousMemorySpaceSelection; + } + } + } + if (memSpaceSelection != null) { + fMemorySpaceInput.setText(memSpaceSelection); + } + else { + fMemorySpaceInput.select(0); // the n/a entry + } fAddressInput = new Combo(parent, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); @@ -147,16 +175,6 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener, } }); - // Populate the memory space combobox with the available spaces - if (fMemRetrieval != null) { - String [] memorySpaces = fMemRetrieval.getMemorySpaces(); - for (int i = 0; i < memorySpaces.length; i++) - fMemorySpaceInput.add(memorySpaces[i]); - - if (memorySpaces.length > 0) - fMemorySpaceInput.select(0); - } - // add the history into the combo boxes String[] history = getHistory(sExpressionHistory); for (int i = 0; i < history.length; i++) @@ -201,7 +219,7 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener, fExpression = fExpressionInput.getText(); fAddress = fAddressInput.getText(); fMemorySpace = fMemorySpaceInput.getText(); - + // add to HISTORY list; add to the platform dialog's for the expression if (fExpression.length() > 0) addHistory(sExpressionHistory, fExpression); @@ -209,6 +227,8 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener, addHistory(sAddressHistory, fAddress); fEnteredExpression = fExpressionRadio.getSelection(); + + fPreviousMemorySpaceSelection = fMemorySpace; super.okPressed(); } diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlocks.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlocks.java index 56c2237b5a0..cb8c9e9a724 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlocks.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/AddMemoryBlocks.java @@ -1,12 +1,12 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 Freescale, Inc. + * Copyright (c) 2005, 2010 Freescale Semiconductor, Inc. * 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: - * Freescale, Inc. - initial API and implementation + * Freescale Semiconductor, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.views.memory; @@ -16,7 +16,9 @@ import java.util.List; import java.util.StringTokenizer; import org.eclipse.cdt.debug.core.model.ICVariable; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval; import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension; +import org.eclipse.cdt.debug.internal.core.CRequest; import org.eclipse.cdt.debug.internal.core.model.CRegister; import org.eclipse.cdt.debug.ui.CDebugUIPlugin; import org.eclipse.core.runtime.CoreException; @@ -31,17 +33,23 @@ import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.IMemoryBlockRetrieval; +import org.eclipse.debug.internal.ui.views.memory.AddMemoryBlockAction; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget; +import org.eclipse.debug.ui.contexts.IDebugContextService; import org.eclipse.debug.ui.memory.IMemoryRendering; import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; import org.eclipse.debug.ui.memory.IMemoryRenderingSite; import org.eclipse.debug.ui.memory.IMemoryRenderingType; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.progress.UIJob; @@ -60,33 +68,109 @@ import org.eclipse.ui.progress.UIJob; * */ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { + + /** Request object used to get the memory spaces */ + private static class GetMemorySpacesRequest extends CRequest implements IMemorySpaceAwareMemoryBlockRetrieval.GetMemorySpacesRequest { + String [] fMemorySpaces = new String[0]; + public String[] getMemorySpaces() { + return fMemorySpaces; + } + public void setMemorySpaces(String[] memorySpaceIds) { + fMemorySpaces = memorySpaceIds; + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget#addMemoryBlocks(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void addMemoryBlocks(final IWorkbenchPart part, final ISelection selection) throws CoreException { - public void addMemoryBlocks(IWorkbenchPart part, ISelection selection) throws CoreException { - - if (!(part instanceof IMemoryRenderingSite)) + if (!(part instanceof IMemoryRenderingSite)) { + assert false : "unexpected kind of view part"; //$NON-NLS-1$ return; + } + final IMemoryRenderingSite renderingSite = (IMemoryRenderingSite)part; - IAdaptable debugViewElement = DebugUITools.getDebugContext(); + final IAdaptable debugViewElement = DebugUITools.getDebugContext(); - CMemoryBlockRetrievalExtension cdtRetrieval = null; - - { - IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval)debugViewElement.getAdapter(IMemoryBlockRetrieval.class); - - if (retrieval == null && debugViewElement instanceof IDebugElement) - retrieval = ((IDebugElement)debugViewElement).getDebugTarget(); - - if (retrieval == null || !(retrieval instanceof CMemoryBlockRetrievalExtension)) - return; - - cdtRetrieval = (CMemoryBlockRetrievalExtension) retrieval; + IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval)debugViewElement.getAdapter(IMemoryBlockRetrieval.class); + if (retrieval == null && debugViewElement instanceof IDebugElement) { + // Added logic for CDI (which is based on the standard debug model) + retrieval = ((IDebugElement)debugViewElement).getDebugTarget(); } + // If the backend doesn't support memory spaces, use the standard + // (platform) dialog for adding a memory block + if (!(retrieval instanceof IMemorySpaceAwareMemoryBlockRetrieval)) { + invokePlatformAction(renderingSite); + return; + } + final IMemorySpaceAwareMemoryBlockRetrieval msRetrieval = (IMemorySpaceAwareMemoryBlockRetrieval)retrieval; + + // We still don't really know if this session actually involves any + // memory spaces. Finding out is not trivial since it requires an + // asynchronous call. + final Object context = getContextSelectionForPart(part); + Job job = new Job("update memory space choices") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + msRetrieval.getMemorySpaces(context, new GetMemorySpacesRequest(){ + public void done() { + runOnUIThread(new Runnable(){ + public void run() { + if (isSuccess()) { + String[] memorySpaces = getMemorySpaces(); + + // We shouldn't be using the custom dialog + // if there are none or only one memory + // spaces involved. + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=309032#c50 + if (memorySpaces.length >= 2) { + doAddMemoryBlocks(renderingSite, context, msRetrieval, memorySpaces); + return; + } + } + + // If we get here, then the custom dialog isn't + // necessary. Use the standard (platform) one + invokePlatformAction(renderingSite); + }}); + } + }); + return Status.OK_STATUS; + } + }; + job.setSystem(true); + job.schedule(); + } + + /** + * Invoke the platform's Add Memory Block action. + * + * @param site the rendering site + */ + void invokePlatformAction(IMemoryRenderingSite site) { + // We have to subclass to get access to the protected dispose method + class PlatformAction extends AddMemoryBlockAction { + PlatformAction(IMemoryRenderingSite site) { + super(site); + } + @Override + protected void dispose() { + super.dispose(); + } + }; + PlatformAction action = new PlatformAction(site); + action.run(); + action.dispose(); + } + + private void doAddMemoryBlocks(final IMemoryRenderingSite renderingSite, final Object context, final IMemorySpaceAwareMemoryBlockRetrieval retrieval, String[] memorySpaces) { Shell shell = CDebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(); // create dialog to ask for expression/address to block - AddMemoryBlockDialog dialog = new AddMemoryBlockDialog(shell, cdtRetrieval); + AddMemoryBlockDialog dialog = new AddMemoryBlockDialog(shell, memorySpaces); dialog.open(); int returnCode = dialog.getReturnCode(); if (returnCode == Window.CANCEL) @@ -112,20 +196,17 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { else params = new AddressAndSpaceHolder(addrsOrExprs, dialog.getMemorySpace()); - final IAdaptable debugViewElement_f = debugViewElement; - final CMemoryBlockRetrievalExtension retrieval_f = cdtRetrieval; final ParamHolder params_f = params; - final IMemoryRenderingSite memRendSite = (IMemoryRenderingSite) part; Job job = new Job("Add Memory Block") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { - addMemoryBlocks(debugViewElement_f, retrieval_f, params_f, - memRendSite); + addMemoryBlocks(context, retrieval, params_f, renderingSite); return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(); + } public boolean canAddMemoryBlocks(IWorkbenchPart part, ISelection selection) @@ -165,8 +246,8 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { public String[] expressions; } - private void addMemoryBlocks(IAdaptable debugViewElement, - CMemoryBlockRetrievalExtension memRetrieval, + private void addMemoryBlocks(Object context, + IMemorySpaceAwareMemoryBlockRetrieval memRetrieval, final ParamHolder params, IMemoryRenderingSite memRendSite) { final String[] addrsOrExprs = (params instanceof AddressAndSpaceHolder) ? ((AddressAndSpaceHolder) params).addresses @@ -181,13 +262,13 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { IMemoryBlockExtension memBlock; if (params instanceof AddressAndSpaceHolder) - memBlock = memRetrieval.getMemoryBlockWithMemorySpaceID( + memBlock = memRetrieval.getMemoryBlock( addrOrExpr, - ((AddressAndSpaceHolder) params).memorySpace, - debugViewElement); + context, + ((AddressAndSpaceHolder) params).memorySpace); else memBlock = memRetrieval.getExtendedMemoryBlock(addrOrExpr, - debugViewElement); + context); // add block to memory block manager if (memBlock != null) { @@ -295,7 +376,7 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { variables[i].getType().isReference() || variables[i] instanceof CRegister) expressions[i] = exp; else - expressions[i] = "&" + exp; + expressions[i] = "&" + exp; //$NON-NLS-1$ } ParamHolder params; @@ -345,5 +426,50 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget { uiJob.schedule(); } + private static Object getContextSelectionForPart(IWorkbenchPart part) { + IDebugContextService contextService = DebugUITools.getDebugContextManager().getContextService( + part.getSite().getWorkbenchWindow()); + + ISelection debugContext = contextService.getActiveContext(getPartId(part)); + if (debugContext == null) { + debugContext = contextService.getActiveContext(); + } + + if (debugContext instanceof IStructuredSelection) { + return ((IStructuredSelection) debugContext).getFirstElement(); + } + + return null; + } + + private static String getPartId(IWorkbenchPart part) { + if (part instanceof IViewPart) { + IViewSite site = (IViewSite) part.getSite(); + return site.getId() + (site.getSecondaryId() != null ? (":" + site.getSecondaryId()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + return part.getSite().getId(); + } + } + /** + * Execute runnable on UI thread if the current thread is not an UI thread. + * Otherwise execute it directly. + * + * @param runnable + * the runnable to execute + */ + private void runOnUIThread(final Runnable runnable) { + if (Display.getCurrent() != null) { + runnable.run(); + } + else { + UIJob job = new UIJob("Memory Browser UI Job"){ //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + runnable.run(); + return Status.OK_STATUS; + }}; + job.setSystem(true); + job.schedule(); + } + } } diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/MemoryBlockLabelDecorator.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/MemoryBlockLabelDecorator.java deleted file mode 100644 index c40ac4ad6c9..00000000000 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/MemoryBlockLabelDecorator.java +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005, 2006 Freescale, Inc. - * 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: - * Freescale, Inc. - initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.debug.internal.ui.views.memory; - -import org.eclipse.cdt.debug.internal.core.model.CMemoryBlockExtension; -import org.eclipse.jface.viewers.ILabelDecorator; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.swt.graphics.Image; - -/** - * Modifies the label shown in a rendering tab of the memory view. - * - *

CDT adapter logic will link us to a CMemoryBlockExtension if and - * only if that block was created by specifying a memory space. In that - * case, a literal address and memory space identifier are the basis for - * the memory monitor, and the default label provided by the platform: - *

   expression : address <rendering-name> 
- * isn't well suited. Our job is to reduce this to - *
   expression <rendering-name> 
- * The expression ends up being the back-end provided string encoding of - * a memory space + address pair. - *

- * @since 3.2 - */ -public class MemoryBlockLabelDecorator implements ILabelDecorator { - - /** - * The memory block we decorate the label for - */ - private CMemoryBlockExtension fMemoryBlock; - - /** - * Constructor - * @param memoryBlock the memory block we decorate the label for - */ - public MemoryBlockLabelDecorator(CMemoryBlockExtension memoryBlock) { - super(); - fMemoryBlock = memoryBlock; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object) - */ - public Image decorateImage(Image image, Object element) { - // we only decorate the text - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object) - */ - public String decorateText(String text, Object element) { - // The rendering name is enclosed in <>. We replace everything before - // that with the memory block's expression. - int i = text.indexOf('<'); - if (i >= 0) - return fMemoryBlock.getExpression() + " " + text.substring(i); - - return text; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) - */ - public void addListener(ILabelProviderListener listener) { - // how we decorate labels is not affected by any state - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() - */ - public void dispose() { - // nothing to clean up - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String) - */ - public boolean isLabelProperty(Object element, String property) { - // how we decorate a label is not affected by any properties - return false; - } - - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener) - */ - public void removeListener(ILabelProviderListener listener) { - // how we decorate labels is not affected by any state - } - -} diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/Messages.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/Messages.java index 48cb4b9693b..258793cf9ed 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/Messages.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 Freescale, Inc. + * Copyright (c) 2005, 2010 Freescale, Inc. * 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 diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/messages.properties b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/messages.properties index e8ba9005cd3..face5431f25 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/messages.properties +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/memory/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2005, 2007 Freescale, Inc. +# Copyright (c) 2005, 2010 Freescale, Inc. # 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 diff --git a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF index 4a4f0adff6a..e2a08fc607d 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF @@ -9,7 +9,9 @@ Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.debug.core;bundle-version="3.5.0", - org.eclipse.debug.ui;bundle-version="3.5.0" + org.eclipse.debug.ui;bundle-version="3.5.0", + org.eclipse.cdt.debug.core;bundle-version="7.0.0", + org.eclipse.cdt.debug.ui;bundle-version="7.0.0" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.debug.ui.memory.memorybrowser diff --git a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java index a1c6a996c3f..e106f7b64de 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java @@ -15,9 +15,14 @@ package org.eclipse.cdt.debug.ui.memory.memorybrowser; import java.lang.reflect.Type; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval; +import org.eclipse.cdt.debug.internal.core.CRequest; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; @@ -62,6 +67,7 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; @@ -81,6 +87,7 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; @@ -110,40 +117,77 @@ import org.eclipse.ui.progress.WorkbenchJob; @SuppressWarnings("restriction") public class MemoryBrowser extends ViewPart implements IDebugContextListener, IMemoryRenderingSite, IDebugEventSetListener { - public static final String ID = "org.eclipse.cdt.debug.ui.memory.memorybrowser.MemoryBrowser"; //$NON-NLS-1$ - protected StackLayout fStackLayout; private Composite fRenderingsComposite; - private HashMap fContextFolders = new HashMap (); private GoToAddressBarWidget fGotoAddressBar; private Control fGotoAddressBarControl; - - // revisit; see bug 307023 - // private Combo fGotoAddressSpaceControl; - + private Combo fGotoMemorySpaceControl; private Label fUnsupportedLabel; private Composite fMainComposite; private String defaultRenderingTypeId = null; + + /** + * Every memory retrieval object is given its own tab folder. Typically all + * elements of a "process" (process, threads, frames) have the same + * retrieval object. + */ + private Map fContextFolders = new HashMap (); - private ArrayList fCurrentContainers = new ArrayList(); + private List fCurrentContainers = new ArrayList(); - private final static String KEY_RENDERING = "RENDERING"; //$NON-NLS-1$ private final static String KEY_CONTEXT = "CONTEXT"; //$NON-NLS-1$ - private final static String KEY_MEMORY_BLOCK = "MEMORY"; //$NON-NLS-1$ - private final static String KEY_RETRIEVAL = "RETRIEVAL"; //$NON-NLS-1$ private final static String KEY_CONTAINER = "CONTAINER"; //$NON-NLS-1$ + private final static String KEY_RENDERING_TYPE = "RENDERING_TYPE"; //$NON-NLS-1$ - // revisit; see bug 307023 - // private final static String KEY_ADDRESS_SPACE_PREFIXES = "ADDRESSSPACEPREFIXES"; //$NON-NLS-1$ + /** + * Property we attach to a CTabItem to track the retrieval object we use to + * create memory blocks on the tab's behalf. Value is an + * {@link IMemoryBlockRetrieval} + */ + private final static String KEY_RETRIEVAL = "RETRIEVAL"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track the memory space it's + * associated with. Value is a memory space ID (String), or null if n/a + */ + private final static String KEY_MEMORY_SPACE = "MEMORY_SPACE"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track what renderings have been + * created on its behalf. There will be more than one rendering if the + * backend supports memory spaces, there is more than one such space, and + * the user has viewed memory in multiple memory spaces within that tab. + * The value is a map of memory-space-ID==>IMemoryRendering. + */ + private final static String KEY_RENDERINGS = "RENDERINGS"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track the active rendering in the + * tab. The value is an IMemoryRendering. + */ + private final static String KEY_RENDERING = "RENDERING"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track what memory blocks have been + * created on its behalf. There can be multiple when dealing with memory + * spaces, for the same reasons there can be multiple renderings. There is a + * 1:1:1 association between rendering, block and memory space. The value is + * a list of IMemoryBlockExtension + */ + private final static String KEY_MEMORY_BLOCKS = "MEMORY_BLOCKS"; //$NON-NLS-1$ - public static final String PREF_DEFAULT_RENDERING = "org.eclipse.cdt.debug.ui.memory.memorybrowser.defaultRendering"; //$NON-NLS-1$ + public static final String PREF_DEFAULT_RENDERING = "org.eclipse.cdt.debug.ui.memory.memorybrowser.defaultRendering"; //$NON-NLS-1$ + + /** + * The text we use in the combobox to represent no memory space specification + */ + private static final String NA_MEMORY_SPACE_ID = " -----"; public MemoryBrowser() { } - public Control getControl() - { + public Control getControl() { return fMainComposite; } @@ -180,9 +224,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM layout.spacing = 0; fMainComposite.setLayout(layout); - // revisit; see bug 307023 - //fGotoAddressSpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY); - + fGotoMemorySpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY); fGotoAddressBar = new GoToAddressBarWidget(); fGotoAddressBarControl = fGotoAddressBar.createControl(fMainComposite); @@ -210,9 +252,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM FormData data = new FormData(); data.top = new FormAttachment(0); - // revisit; see bug 307023 - //data.left = new FormAttachment(fGotoAddressSpaceControl); - data.left = new FormAttachment(0); + data.left = new FormAttachment(fGotoMemorySpaceControl); data.right = new FormAttachment(100); fGotoAddressBarControl.setLayoutData(data); @@ -300,7 +340,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM for (DebugEvent event: events) { Object source = event.getSource(); if (event.getKind() == DebugEvent.TERMINATE && source instanceof IMemoryBlockRetrieval) { - releaseTabFolder(source); + releaseTabFolder((IMemoryBlockRetrieval)source); } } } @@ -321,55 +361,67 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM return null; } - private void handleUnsupportedSelection() - { + private void handleUnsupportedSelection() { fStackLayout.topControl = fUnsupportedLabel; fGotoAddressBarControl.setVisible(false); + fGotoMemorySpaceControl.setVisible(false); + } + + private void performGo(boolean inNewTab) { + // Index zero is the 'auto' (n/a) memory space entry + String memorySpace = null; + if (fGotoMemorySpaceControl.isVisible() && (fGotoMemorySpaceControl.getSelectionIndex() != 0)) { + memorySpace = fGotoMemorySpaceControl.getText(); + assert (memorySpace != null) && (memorySpace.length() > 0); + } - // revisit; see bug 307023 - //fGotoAddressSpaceControl.setVisible(false); + String expression = fGotoAddressBar.getExpressionText(); + if (expression.length() > 0) { + performGo(inNewTab, fGotoAddressBar.getExpressionText(), memorySpace); + } } - private void performGo(boolean inNewTab) - { - performGo(inNewTab, fGotoAddressBar.getExpressionText(), (short)0); - } - - public void performGo(boolean inNewTab, final String expression, short memoryPage) - { + public void performGo(boolean inNewTab, final String expression, final String memorySpaceId) { final CTabFolder activeFolder = (CTabFolder) fStackLayout.topControl; - if(activeFolder != null) - { + if (activeFolder != null) { final IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) activeFolder.getData(KEY_RETRIEVAL); final Object context = activeFolder.getData(KEY_CONTEXT); - if(inNewTab || activeFolder.getSelection() == null) - { - CTabItem item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1); - populateTabWithRendering(item, retrieval, context); - setTabFolder(retrieval, activeFolder); + CTabItem item = activeFolder.getSelection(); + if (inNewTab || item == null) { + item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1); + populateTabWithRendering(item, retrieval, context, memorySpaceId); + + fContextFolders.put(retrieval, activeFolder); activeFolder.setSelection(item); getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING))); } - final IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); - final String gotoExpression = getAddressSpacePrefix() + expression; - - if(retrieval instanceof IMemoryBlockRetrievalExtension) - { - new Thread() - { - public void run() - { + IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); + IMemoryRenderingContainer container = (IMemoryRenderingContainer)item.getData(KEY_CONTAINER); + String oldMemorySpaceId = (String)activeFolder.getSelection().getData(KEY_MEMORY_SPACE); + assert oldMemorySpaceId == null || !oldMemorySpaceId.equals(NA_MEMORY_SPACE_ID) : "should be null reference, not 'auto'"; + if ((oldMemorySpaceId != null && !oldMemorySpaceId.equals(memorySpaceId)) + || (oldMemorySpaceId == null && memorySpaceId != null)) { + updateTabWithRendering(item, retrieval, container, context, memorySpaceId); + activeFolder.setSelection(item); + getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING))); + rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); + } + final IRepositionableMemoryRendering renderingFinal = rendering; + if (retrieval instanceof IMemoryBlockRetrievalExtension) { + new Thread() { + public void run() { try { - BigInteger newBase = getExpressionAddress(retrieval, gotoExpression, context); - if(((IMemoryBlockExtension) rendering.getMemoryBlock()).supportBaseAddressModification()) - ((IMemoryBlockExtension) rendering.getMemoryBlock()).setBaseAddress(newBase); - rendering.goToAddress(newBase); + BigInteger newBase = getExpressionAddress(retrieval, expression, context, memorySpaceId); + IMemoryBlockExtension block = (IMemoryBlockExtension) renderingFinal.getMemoryBlock(); + if (block.supportBaseAddressModification()) { + block.setBaseAddress(newBase); + } + renderingFinal.goToAddress(newBase); runOnUIThread(new Runnable(){ - public void run() - { - updateLabel(activeFolder.getSelection(), rendering); + public void run() { + updateLabel(activeFolder.getSelection(), renderingFinal); } }); } catch (DebugException e1) { @@ -380,68 +432,59 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } } } - - private String getAddressSpacePrefix() - { - // revisit; see bug 307023 -// if(fGotoAddressSpaceControl.isVisible()) -// { -// String prefixes[] = (String[]) fGotoAddressSpaceControl.getData(KEY_ADDRESS_SPACE_PREFIXES); -// if(prefixes != null && prefixes.length > 0) -// { -// return prefixes[fGotoAddressSpaceControl.getSelectionIndex()]; -// } -// } - return ""; - } -// MemoryBrowser.FailedToGoToAddressTitle=Unable to Go To specified address -// MemoryBrowser.UnableToEvaluateAddress - - private void updateLabel(CTabItem tab, IMemoryRendering rendering) - { - String label = null; - - // This is a hack and needs to be revisited. -// -// // would like to avoid using reflection -// try { -// Method m = rendering.getControl().getClass().getMethod("getViewportStartAddress", new Class[0]); //$NON-NLS-1$ -// if(m != null) -// label = "0x" + ((BigInteger) m.invoke(rendering.getControl(), new Object[0])).toString(16).toUpperCase(); //$NON-NLS-1$ -// } -// catch (Exception e) -// { -// } + private void updateLabel(CTabItem tab, IMemoryRendering rendering) { + // The default is to use the label provided by the base rendering + // interface. + String label = rendering.getLabel(); - if(label == null) - label = rendering.getLabel(); + // We create all memory blocks using address 0 regardless of where the + // user wants to see memory. We then go-to the requested location. So, + // if we rely on the default rendering label, all tabs will show + // address zero, which will be confusing. To avoid this, the rendering + // object should implement this interface that allows us to get to the + // first address being shown. We'll use that for the label + if (rendering instanceof IMemoryRenderingViewportProvider) { + BigInteger viewportAddress = ((IMemoryRenderingViewportProvider)rendering).getViewportAddress(); + + // The base label generation puts the rendering type name in "<>" and + // appends it to the label. Fish that out + String renderingType = null; + int i = label.indexOf('<'); + if (i >= 0) { + renderingType = label.substring(i); + } + + label = null; + + // If a memory space is involved, we want to include its ID in the label + String memorySpaceID = (String)tab.getData(KEY_MEMORY_SPACE); + if (memorySpaceID != null) { + IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) tab.getParent().getData(KEY_RETRIEVAL); + if (retrieval instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + label = ((IMemorySpaceAwareMemoryBlockRetrieval)retrieval).encodeAddress("0x" + viewportAddress.toString(16), memorySpaceID); + } + } + if (label == null) { + label = "0x" + viewportAddress.toString(16) + ' ' + renderingType; + } + + // Allow the memory block to customize the label. The platform's + // Memory view support this (it was done in the call to + // rendering.getLabel() above) + IMemoryBlock block = rendering.getMemoryBlock(); + ILabelDecorator labelDec = (ILabelDecorator)block.getAdapter(ILabelDecorator.class); + if (labelDec != null) { + String newLabel = labelDec.decorateText(label, rendering); + if (newLabel != null) { + label = newLabel; + } + } + } tab.setText(label); } - /** - * fetch memory spaces for a given IMemoryBlockRetrieval - * @param retrieval memory block retrieval. - * @return two arrays, the first containing memory space mnemonics, the second containing associated expression prefixes - */ - // revisit; see bug 307023 -// private String[][] getAddressSpaces(IMemoryBlockRetrieval retrieval) -// { -// // would like to avoid using reflection, but necessary interface additions should live in platform to avoid introducing dependencies. -// -// String[][] addressSpaceTitles = new String[0][0]; -// try { -// Method m = retrieval.getClass().getMethod("getAddressSpaces", new Class[0]); //$NON-NLS-1$ -// if(m != null) -// addressSpaceTitles = (String[][]) m.invoke(retrieval, new Object[0]); -// } -// catch (Exception e) -// { -// } -// return addressSpaceTitles; -// } - private CTabFolder createTabFolder(Composite parent) { final CTabFolder folder = new CTabFolder(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.FLAT); @@ -475,6 +518,19 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM return folder; } + // these utility methods allow us restrict the scope of the unavoidable @SuppressWarnings + + @SuppressWarnings("unchecked") + private static Map getRenderings(CTabItem tabItem) { + return (Map)tabItem.getData(KEY_RENDERINGS); + } + + @SuppressWarnings("unchecked") + private static List getMemoryBlocks(CTabItem tabItem) { + return (List)tabItem.getData(KEY_MEMORY_BLOCKS); + } + + /** * dispose rendering resources associated with the tab item * @param item @@ -485,24 +541,31 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM IMemoryRenderingContainer container = (IMemoryRenderingContainer) item.getData(KEY_CONTAINER); fCurrentContainers.remove( container ); - IMemoryRendering rendering = (IMemoryRendering) item.getData(KEY_RENDERING); - // always deactivate rendering before disposing it. - if ( rendering != null ) { + Map map = getRenderings(item); + Collection renderings = map.values(); + for (IMemoryRendering rendering : renderings) { + // always deactivate rendering before disposing it. rendering.deactivated(); rendering.dispose(); } - IMemoryBlockExtension block = (IMemoryBlockExtension) item.getData(KEY_MEMORY_BLOCK); - try { - if (block != null) + map.clear(); + + List blocks = getMemoryBlocks(item); + for (IMemoryBlockExtension block : blocks) { + try { block.dispose(); - } catch (DebugException e) { - MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Could not dispose memory block", e)); //$NON-NLS-1$ - } + } catch (DebugException e) { + MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Could not dispose memory block", e)); //$NON-NLS-1$ + } + } + blocks.clear(); } private CTabItem createTab(CTabFolder tabFolder, int index) { int swtStyle = SWT.CLOSE; CTabItem tab = new CTabItem(tabFolder, swtStyle, index); + tab.setData(KEY_RENDERINGS, new HashMap()); + tab.setData(KEY_MEMORY_BLOCKS, new ArrayList()); return tab; } @@ -544,7 +607,6 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } manager.add(sub); - manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } @@ -601,44 +663,83 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM public void debugContextChanged(DebugContextEvent event) { handleDebugContextChanged(((StructuredSelection) event.getContext()).getFirstElement()); } + + private class GetMemorySpacesRequest extends CRequest implements IMemorySpaceAwareMemoryBlockRetrieval.GetMemorySpacesRequest { + String [] fMemorySpaces; + public String[] getMemorySpaces() { + return fMemorySpaces; + } + public void setMemorySpaces(String[] memorySpaceIds) { + fMemorySpaces = memorySpaceIds; + } + } - public void handleDebugContextChanged(Object context) { + public void handleDebugContextChanged(final Object context) { if(defaultRenderingTypeId == null) return; if(context instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) context; - IMemoryBlockRetrieval retrieval = ((IMemoryBlockRetrieval) adaptable.getAdapter(IMemoryBlockRetrieval.class)); + final IMemoryBlockRetrieval retrieval = ((IMemoryBlockRetrieval) adaptable.getAdapter(IMemoryBlockRetrieval.class)); ILaunch launch = ((ILaunch) adaptable.getAdapter(ILaunch.class)); - if(retrieval != null && launch != null && !launch.isTerminated()) - { + if(retrieval != null && launch != null && !launch.isTerminated()) { + if (retrieval instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + ((IMemorySpaceAwareMemoryBlockRetrieval)retrieval).getMemorySpaces(context, new GetMemorySpacesRequest(){ + public void done() { + updateTab(retrieval, context, isSuccess() ? getMemorySpaces() : new String[0]); + } + }); + } + else { + updateTab(retrieval, context, new String[0]); + } + } + else { + handleUnsupportedSelection(); + } + + fGotoMemorySpaceControl.pack(true); + fStackLayout.topControl.getParent().layout(true); + } + } + + /** + * Called to update the tab once the asynchronous query for memory spaces + * has returned a result. + * + * @param retrieval + * the retrieval object associated with the newly active debug + * context + * @param context + * the newly active context + * @param memorySpaces + * the memory spaces, if applicable. Otherwise an empty array. + */ + private void updateTab(final IMemoryBlockRetrieval retrieval, final Object context, final String[] memorySpaces) { + // GUI activity must be on the main thread + runOnUIThread(new Runnable(){ + public void run() { + if (fGotoAddressBarControl.isDisposed()) { + return; + } + fGotoAddressBarControl.setVisible(true); - - // revisit; see bug 307023 -// String addressSpaces[][] = getAddressSpaces(retrieval); -// if(addressSpaces.length > 0) -// { -// fGotoAddressSpaceControl.setVisible(true); -// fGotoAddressSpaceControl.setItems(addressSpaces[0]); -// fGotoAddressSpaceControl.setData(KEY_ADDRESS_SPACE_PREFIXES, addressSpaces[1]); -// } -// else -// fGotoAddressSpaceControl.setVisible(false); - - CTabFolder tabFolder = getTabFolder(retrieval); - if(tabFolder != null) - { + + // If we've already created a tab folder for this retrieval + // object, bring it to the forefront. Otherwise create the + // folder. + CTabFolder tabFolder = fContextFolders.get(retrieval); + if(tabFolder != null) { fStackLayout.topControl = tabFolder; } - else - { - tabFolder = this.createTabFolder(fRenderingsComposite); - tabFolder.addSelectionListener(new SelectionListener() - { + else { + tabFolder = createTabFolder(fRenderingsComposite); + tabFolder.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) {} public void widgetSelected(SelectionEvent e) { + updateMemorySpaceControlSelection((CTabItem)e.item); getSite().getSelectionProvider().setSelection(new StructuredSelection(((CTabItem) e.item).getData(KEY_RENDERING))); } }); @@ -646,24 +747,76 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM tabFolder.setData(KEY_RETRIEVAL, retrieval); CTabItem item = createTab(tabFolder, 0); - populateTabWithRendering(item, retrieval, context); - setTabFolder(retrieval, tabFolder); - - fStackLayout.topControl = getTabFolder(retrieval); + populateTabWithRendering(item, retrieval, context, null); + fContextFolders.put(retrieval, tabFolder); + fStackLayout.topControl = tabFolder; } // update debug context to the new selection tabFolder.setData(KEY_CONTEXT, context); + + + final CTabFolder activeFolder = tabFolder; + if (!activeFolder.equals(tabFolder)) { + return; + } + + CTabItem tabItem = activeFolder.getSelection(); + if (tabItem != null) { + if(memorySpaces.length > 0) { + fGotoMemorySpaceControl.setVisible(true); + fGotoMemorySpaceControl.setItems(memorySpaces); + + // the n/a entry; don't think this needs to be translated + fGotoMemorySpaceControl.add(NA_MEMORY_SPACE_ID, 0); //$NON-NLS-1$ + } + else { + fGotoMemorySpaceControl.setVisible(false); + fGotoMemorySpaceControl.setItems(new String[0]); + } + + updateMemorySpaceControlSelection(tabItem); + } + fStackLayout.topControl.getParent().layout(true); } - else - { - handleUnsupportedSelection(); - } + }); + } - // revisit; see bug 307023 - //fGotoAddressSpaceControl.pack(true); - - fStackLayout.topControl.getParent().layout(true); + /** + * Update the selection in the memory space combobox to reflect the memory + * space being shown in the given tab + * + * @param item + * the active tab + */ + private void updateMemorySpaceControlSelection(CTabItem item) { + String[] memorySpaces = fGotoMemorySpaceControl.getItems(); + if (memorySpaces.length > 0 ) { + // Don't assume that the memory space previously set in the tab + // is one of the ones now available. If it isn't, then select + // the first available one and update the tab data + boolean foundIt = false; + String currentMemorySpace = (String) item.getData(KEY_MEMORY_SPACE); + if (currentMemorySpace != null) { + assert currentMemorySpace.length() > 0; + for (String memorySpace : memorySpaces) { + if (memorySpace.equals(currentMemorySpace)) { + foundIt = true; + fGotoMemorySpaceControl.setText(currentMemorySpace); + break; + } + } + } + if (!foundIt) { + fGotoMemorySpaceControl.select(0); + item.setData(KEY_MEMORY_SPACE, null); + } + fGotoMemorySpaceControl.setVisible(true); } + else { + fGotoMemorySpaceControl.setVisible(false); + } + fGotoMemorySpaceControl.getParent().layout(true); + } private String getDefaultRenderingTypeId() @@ -678,14 +831,12 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM store.setValue(PREF_DEFAULT_RENDERING, defaultRenderingTypeId); } - private void populateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, Object context) - { + private void populateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, Object context, String memorySpaceId) { IMemoryRenderingType type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId()); try { final IMemoryRendering rendering = type.createRendering(); - IMemoryRenderingContainer container = new IMemoryRenderingContainer() - { + IMemoryRenderingContainer container = new IMemoryRenderingContainer() { public void addMemoryRendering(IMemoryRendering rendering) {} public IMemoryRendering getActiveRendering() { @@ -712,16 +863,19 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM }; - IMemoryBlock block = createMemoryBlock(retrieval, "0", context); //$NON-NLS-1$ + IMemoryBlockExtension block = createMemoryBlock(retrieval, "0", context, memorySpaceId); //$NON-NLS-1$ fCurrentContainers.add(container); rendering.init(container, block); rendering.createControl(tab.getParent()); tab.setControl(rendering.getControl()); tab.getParent().setSelection(0); + getRenderings(tab).put(memorySpaceId, rendering); tab.setData(KEY_RENDERING, rendering); + tab.setData(KEY_MEMORY_SPACE, memorySpaceId); tab.setData(KEY_CONTAINER, container); - tab.setData(KEY_MEMORY_BLOCK, block); + getMemoryBlocks(tab).add(block); + tab.setData(KEY_RENDERING_TYPE, type); getSite().getSelectionProvider().setSelection(new StructuredSelection(tab.getData(KEY_RENDERING))); updateLabel(tab, rendering); @@ -748,19 +902,60 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } } - private CTabFolder getTabFolder(Object context) - { - return fContextFolders.get(context); + private void updateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, IMemoryRenderingContainer container, Object context, String memorySpaceId) { + IMemoryRenderingType type = (IMemoryRenderingType)tab.getData(KEY_RENDERING_TYPE); + if (type == null) { + type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId()); + } + try { + Map renderings = getRenderings(tab); + + // Note: memorySpaceId can be null. In that case, there will just be + // one rendering in the tab + IMemoryRendering rendering = renderings.get(memorySpaceId); + if (rendering == null) { + // No rendering yet. Create one. + final IMemoryRendering newRendering = type.createRendering(); + IMemoryBlockExtension block = createMemoryBlock(retrieval, "0", context, memorySpaceId); //$NON-NLS-1$ + newRendering.init(container, block); + getMemoryBlocks(tab).add(block); + renderings.put(memorySpaceId, newRendering); + newRendering.createControl(tab.getParent()); + newRendering.addPropertyChangeListener(new IPropertyChangeListener() { + public void propertyChange(final PropertyChangeEvent event) { + WorkbenchJob job = new WorkbenchJob("MemoryBrowser PropertyChanged") { //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + if(tab.isDisposed()) + return Status.OK_STATUS; + + if (event.getProperty().equals(IBasicPropertyConstants.P_TEXT)) + updateLabel(tab, newRendering); + return Status.OK_STATUS; + } + }; + job.setSystem(true); + job.schedule(); + } + }); + rendering = newRendering; + } + tab.setControl(rendering.getControl()); + tab.getParent().setSelection(0); + tab.setData(KEY_RENDERING, rendering); + tab.setData(KEY_MEMORY_SPACE, memorySpaceId); + tab.setData(KEY_CONTAINER, container); + tab.setData(KEY_RENDERING_TYPE, type); + getSite().getSelectionProvider().setSelection(new StructuredSelection(tab.getData(KEY_RENDERING))); + updateLabel(tab, rendering); + fStackLayout.topControl.getParent().layout(true); + } catch (CoreException e) { + MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "", e)); //$NON-NLS-1$ + } } - - private CTabFolder setTabFolder(Object context, CTabFolder folder) + + private void releaseTabFolder(final IMemoryBlockRetrieval retrieval) { - return fContextFolders.put(context, folder); - } - - private void releaseTabFolder(final Object context) - { - final CTabFolder folder = getTabFolder(context); + final CTabFolder folder = fContextFolders.get(retrieval); if(folder != null) { Runnable run = new Runnable() { @@ -768,7 +963,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM for(CTabItem tab : folder.getItems()) { disposeTab(tab); } - fContextFolders.remove(context); + fContextFolders.remove(retrieval); folder.dispose(); if (fStackLayout.topControl.equals(folder)) { @@ -821,17 +1016,22 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @param expression expression to be evaluated to an addressL * @param context context for evaluating the expression. This is typically * a debug element. + * @param memorySpaceID a memory space identifier, or null if n/a * @return a memory block based on the given expression and context * @throws DebugException if unable to retrieve the specified memory */ - private IMemoryBlockExtension createMemoryBlock(IMemoryBlockRetrieval retrieval, String expression, Object context) throws DebugException { + private IMemoryBlockExtension createMemoryBlock(IMemoryBlockRetrieval retrieval, String expression, Object context, String memorySpaceID) throws DebugException { IMemoryBlockExtension block = null; - if(retrieval instanceof IAdaptable) - { - IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension) - ((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class); - if(retrievalExtension != null) - block = retrievalExtension.getExtendedMemoryBlock(expression, context); //$NON-NLS-1$ + if(retrieval instanceof IAdaptable) { + IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension)((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class); + if (retrievalExtension != null) { + if (retrievalExtension instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + block = ((IMemorySpaceAwareMemoryBlockRetrieval)retrievalExtension).getMemoryBlock(expression, context, memorySpaceID); + } + else { + block = retrievalExtension.getExtendedMemoryBlock(expression, context); + } + } } if ( block == null ) { throw new DebugException(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Extended Memory Block could not be obtained")); //$NON-NLS-1$ @@ -847,9 +1047,9 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @return BigInteger address of the expression * @throws DebugException */ - private BigInteger getExpressionAddress(IMemoryBlockRetrieval retrieval, String expression, Object context) throws DebugException { + private BigInteger getExpressionAddress(IMemoryBlockRetrieval retrieval, String expression, Object context, String memorySpaceId) throws DebugException { // Until 257842 issue is solved this is done via IMemoryBlockRetrievalExtension API. - IMemoryBlockExtension newBlock = createMemoryBlock(retrieval, expression, context); + IMemoryBlockExtension newBlock = createMemoryBlock(retrieval, expression, context, memorySpaceId); BigInteger address = newBlock.getBigBaseAddress(); newBlock.dispose(); return address; @@ -862,9 +1062,8 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @param runnable * the runnable to execute */ - private void runOnUIThread(final Runnable runnable) - { - if (Display.getCurrent() != null) { + private void runOnUIThread(final Runnable runnable) { + if (Display.getCurrent() != null) { runnable.run(); } else { diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF index afe55dce916..9de58377e45 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF @@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.debug.core, org.eclipse.swt, org.eclipse.jface, org.eclipse.ui, - org.eclipse.search;bundle-version="3.4.0" + org.eclipse.search;bundle-version="3.4.0", + org.eclipse.cdt.debug.core;bundle-version="7.0.0" Bundle-ActivationPolicy: lazy Bundle-Activator: org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPlugin Bundle-Vendor: %providerName diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java index 8b78eca15af..1fa1a2e1eab 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.debug.ui.memory.traditional; import java.lang.reflect.Method; import java.math.BigInteger; +import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; @@ -83,7 +84,7 @@ import org.eclipse.ui.progress.UIJob; */ @SuppressWarnings("restriction") -public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering +public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering, IMemoryRenderingViewportProvider { protected Rendering fRendering; protected Action displayEndianBigAction; @@ -1264,6 +1265,13 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe public void resetRendering() throws DebugException { fRendering.gotoAddress(fRendering.fBaseAddress); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.internal.core.model.provisional.IMemoryRenderingViewportProvider#getViewportAddress() + */ + public BigInteger getViewportAddress() { + return fRendering.getViewportStartAddress(); + } } class CopyAction extends Action