1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

Bug 309032: Need APIs to support memory pages (or memory spaces)

This commit is contained in:
John Cortell 2010-05-13 19:43:47 +00:00
parent 6a61597cf9
commit 5a1558ddd2
20 changed files with 1018 additions and 538 deletions

View file

@ -15,6 +15,7 @@ Export-Package: org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.core.disassembly, org.eclipse.cdt.debug.core.disassembly,
org.eclipse.cdt.debug.core.executables, org.eclipse.cdt.debug.core.executables,
org.eclipse.cdt.debug.core.model, 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.core.sourcelookup,
org.eclipse.cdt.debug.internal.core;x-friends:="org.eclipse.cdt.dsf.gdb.ui", 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", org.eclipse.cdt.debug.internal.core.breakpoints;x-friends:="org.eclipse.cdt.debug.edc,org.eclipse.cdt.dsf.gdb",

View file

@ -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();
}
}

View file

@ -21,15 +21,18 @@ import org.eclipse.cdt.debug.core.cdi.CDIException;
* as well if the target supports memory spaces. * as well if the target supports memory spaces.
*/ */
public interface ICDIMemorySpaceManagement extends ICDIObject { public interface ICDIMemorySpaceManagement extends ICDIObject {
/** /**
* Optionally provides the string encoding of a memory space qualified address. * Optionally provides the string encoding of a memory space qualified
* CDT provides a default encoding of <memory-space-id>:<address(hex)>. * address. CDT provides a default encoding of
* If this is adequate, the client can return null from this function. * <memory-space-id>:<address(hex)>. If this is adequate, the client can
* return null from this function.
* *
* @param address - a numeric address * @param address
* @param memorySpaceID - a string which represents the memory space * a numeric address
* @param memorySpaceID
* a string which represents the memory space
* @return the encoded string representation of the address or null * @return the encoded string representation of the address or null
* @deprecated CDI clients should implement ICDIMemorySpaceEncoder
*/ */
String addressToString(BigInteger address, String memorySpaceID); String addressToString(BigInteger address, String memorySpaceID);
@ -39,11 +42,17 @@ public interface ICDIMemorySpaceManagement extends ICDIObject {
* encoding in addressToString. Conversely, it should return null if * encoding in addressToString. Conversely, it should return null if
* addressToString returns null. * addressToString returns null.
* *
* @param str - the encoded string (contains memory space + hex address value) * @param str
* @param memorySpaceID_out the memory space ID * the encoded string (contains memory space + hex address
* @return the BigInteger part of str; client should return null if the default decoding provided * value)
* by CDT is sufficient (<memory-space-id>:<address(hex)>) * @param memorySpaceID_out
* @throws CDIException if string is not in the expected format * the memory space ID
* @return the BigInteger part of str; client should return null if the
* default decoding provided by CDT is sufficient
* (<memory-space-id>:<address(hex)>)
* @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; BigInteger stringToAddress(String str, StringBuffer memorySpaceID_out) throws CDIException;

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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;
}

View file

@ -11,7 +11,6 @@
package org.eclipse.cdt.debug.internal.core; package org.eclipse.cdt.debug.internal.core;
import java.math.BigInteger; import java.math.BigInteger;
import com.ibm.icu.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.cdi.CDIException; 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.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.ICDIMemorySpaceManagement;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.debug.core.model.ICType; import org.eclipse.cdt.debug.core.model.ICType;
import org.eclipse.cdt.debug.core.model.ICValue; 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.CDebugTarget;
import org.eclipse.cdt.debug.internal.core.model.CExpression; import org.eclipse.cdt.debug.internal.core.model.CExpression;
import org.eclipse.cdt.debug.internal.core.model.CMemoryBlockExtension; 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.IDebugTarget;
import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension; 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.IStackFrame;
import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IValue;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -52,10 +53,12 @@ import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import com.ibm.icu.text.MessageFormat;
/** /**
* Implements the memory retrieval features based on the CDI model. * 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_LIST = "memoryBlockExpressionList"; //$NON-NLS-1$
private static final String MEMORY_BLOCK_EXPRESSION_ITEM = "memoryBlockExpressionItem"; //$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<String> expressions, List<String> memorySpaceIDs) {
NodeList list = element.getChildNodes(); NodeList list = element.getChildNodes();
int length = list.getLength(); int length = list.getLength();
String exp = null; String exp = null;
@ -115,8 +118,8 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
private void initializeFromMemento( String memento ) throws CoreException { private void initializeFromMemento( String memento ) throws CoreException {
Element root = DebugPlugin.parseDocument( memento ); Element root = DebugPlugin.parseDocument( memento );
if ( root.getNodeName().equalsIgnoreCase( MEMORY_BLOCK_EXPRESSION_LIST ) ) { if ( root.getNodeName().equalsIgnoreCase( MEMORY_BLOCK_EXPRESSION_LIST ) ) {
List expressions = new ArrayList(); List<String> expressions = new ArrayList<String>();
List memorySpaceIDs = new ArrayList(); List<String> memorySpaceIDs = new ArrayList<String>();
NodeList list = root.getChildNodes(); NodeList list = root.getChildNodes();
int length = list.getLength(); int length = list.getLength();
for( int i = 0; i < length; ++i ) { 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()]) , createMemoryBlocks( expressions.toArray( new String[expressions.size()]) ,
(String[])memorySpaceIDs.toArray( new String[memorySpaceIDs.size()])); memorySpaceIDs.toArray( new String[memorySpaceIDs.size()]));
return; return;
} }
@ -160,7 +163,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
} }
private void createMemoryBlocks( String[] expressions, String[] memorySpaceIDs ) { private void createMemoryBlocks( String[] expressions, String[] memorySpaceIDs ) {
ArrayList list = new ArrayList( expressions.length ); List<CMemoryBlockExtension> list = new ArrayList<CMemoryBlockExtension>( expressions.length );
for ( int i = 0; i < expressions.length; ++i ) { for ( int i = 0; i < expressions.length; ++i ) {
try { try {
IAddress address = getDebugTarget().getAddressFactory().createAddress( expressions[i] ); IAddress address = getDebugTarget().getAddressFactory().createAddress( expressions[i] );
@ -168,14 +171,14 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
if (memorySpaceIDs[i] == null) { if (memorySpaceIDs[i] == null) {
list.add( new CMemoryBlockExtension( getDebugTarget(), address.toHexAddressString(), address.getValue() ) ); list.add( new CMemoryBlockExtension( getDebugTarget(), address.toHexAddressString(), address.getValue() ) );
} else { } else {
list.add( new CMemoryBlockExtension( getDebugTarget(), address.getValue(), memorySpaceIDs[i] ) ); list.add( new CMemoryBlockExtension( getDebugTarget(), expressions[i], address.getValue(), memorySpaceIDs[i] ) );
} }
} }
} catch (NumberFormatException exc) { } catch (NumberFormatException exc) {
CDebugCorePlugin.log(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 { public String getMemento() throws CoreException {
@ -188,40 +191,15 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
Element exprItem = document.createElement( MEMORY_BLOCK_EXPRESSION_ITEM ); Element exprItem = document.createElement( MEMORY_BLOCK_EXPRESSION_ITEM );
exprList.appendChild(exprItem); exprList.appendChild(exprItem);
BigInteger addrBigInt = null;
String memorySpaceID = null; String memorySpaceID = null;
if (hasMemorySpaces() && fDebugTarget != null) { if (memBlockExt instanceof IMemorySpaceAwareMemoryBlock) {
// Can't tell if block was created with a memory-space/address or with an expression. memorySpaceID = ((IMemorySpaceAwareMemoryBlock)memBlockExt).getMemorySpaceID();
// 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 "<space>: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
}
} }
BigInteger addrBigInt = memBlockExt.getBigBaseAddress();
Element child = document.createElement( MEMORY_BLOCK_EXPRESSION ); Element child = document.createElement( MEMORY_BLOCK_EXPRESSION );
try { child.setAttribute( ATTR_MEMORY_BLOCK_EXPRESSION_TEXT, "0x" + addrBigInt.toString(16) ); //$NON-NLS-1$
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 ); exprItem.appendChild( child );
}
catch( DebugException e ) {
CDebugCorePlugin.log( e.getStatus() );
}
if (memorySpaceID != null) { if (memorySpaceID != null) {
child = document.createElement( MEMORY_BLOCK_MEMSPACEID ); 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) * @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 { 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; String address = null;
CExpression exp = null; CExpression exp = null;
String msg = 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 // 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) // processing (calling the backend to resolve the expression)
try { try {
return new CMemoryBlockExtension((CDebugTarget)target, expression, evaluateLiteralAddress(expression)); return new CMemoryBlockExtension((CDebugTarget)target, expression, evaluateLiteralAddress(expression), memorySpaceID);
} catch (NumberFormatException nfexc) {} } catch (NumberFormatException nfexc) {}
// OK, expression is not a simple literal address; keep trucking and try to resolve as expression // 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 ) { if ( type != null ) {
// get the address for the expression, allow all types // get the address for the expression, allow all types
String rawExpr = exp.getExpressionString(); String rawExpr = exp.getExpressionString();
String voidExpr = "(void *)(" + rawExpr + ")"; String voidExpr = "(void *)(" + rawExpr + ')'; //$NON-NLS-1$
String attempts[] = { rawExpr, voidExpr }; String attempts[] = { rawExpr, voidExpr };
for (int i = 0; i < attempts.length; i++) { for (int i = 0; i < attempts.length; i++) {
String expr = attempts[i]; String expr = attempts[i];
@ -275,7 +260,7 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
if (address != null) { if (address != null) {
try { try {
BigInteger a = (address.startsWith("0x")) ? new BigInteger(address.substring(2), 16) : new BigInteger(address); //$NON-NLS-1$ 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) { } catch (NumberFormatException e) {
// not pointer? lets cast it to void* // not pointer? lets cast it to void*
if (i == 0) if (i == 0)
@ -287,11 +272,11 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
} }
else { 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 { 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(); msg = e.getMessage();
} }
catch( NumberFormatException e ) { 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 { finally {
if (exp != null) { if (exp != null) {
@ -328,38 +313,6 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
return new CMemoryBlockExtension( getDebugTarget(), expression, address ); 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 { private CStackFrame getStackFrame( IDebugElement selected ) throws DebugException {
if ( selected instanceof CStackFrame ) { if ( selected instanceof CStackFrame ) {
return (CStackFrame)selected; return (CStackFrame)selected;
@ -411,9 +364,24 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
} }
/** /**
* Get the list of available memory spaces from the CDI backend * @see org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval#getMemorySpaces(java.lang.Object, org.eclipse.cdt.debug.internal.core.model.provisional.IRequestListener)
*/
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 an array of memory space identifiers * @return the memory spaces available in this debug session
*/ */
public String [] getMemorySpaces(){ public String [] getMemorySpaces(){
if (fDebugTarget != null) { if (fDebugTarget != null) {
@ -425,32 +393,78 @@ public class CMemoryBlockRetrievalExtension extends PlatformObject implements IM
return new String[0]; return new String[0];
} }
/* /**
* static implementation of * The default encoding of an {expression, memory space ID} pair into a
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement#addressToString(java.math.BigInteger, java.lang.String) * string. A CDI client can provide custom decoding by implementing
* client may choose not to provide the encoding/decoding and instead use our built-in handling. * ICDIMemorySpaceEncoder
*
*/ */
public static String addressToString(BigInteger address, String memorySpaceID) { public static String encodeAddressDefault(String expression, String memorySpaceID) {
return memorySpaceID + ":0x" + address.toString(16); //$NON-NLS-1$ 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 * The default decoding of a string into an {expression, memory space ID}
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemorySpaceManagement#stringToAddr(java.lang.String, java.math.BigInteger, java.lang.StringBuffer) * pair. A CDI client can provide custom decoding by implementing ICDIMemorySpaceEncoder
* client may choose not to provide the encoding/decoding and instead use our built-in handling.
*/ */
public static BigInteger stringToAddress(String str, StringBuffer memorySpaceID_out) throws CoreException { public static DecodeResult decodeAddressDefault(String str) throws CoreException {
int index = str.lastIndexOf(':'); int index = str.lastIndexOf(':');
// minimum is "<space>:0x?" // minimum is "<space>:<expression>"
if (index == -1 || str.length() <= index + 3 || str.charAt(index+1) != '0' || str.charAt(index+2) != 'x') { 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$ IStatus s = new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, InternalDebugCoreMessages.getString( "CMemoryBlockRetrievalExtension.5" ), null ); //$NON-NLS-1$
throw new CoreException( s ); throw new CoreException( s );
} }
memorySpaceID_out.setLength(0); final String memorySpaceID = str.substring(0, index);
memorySpaceID_out.append(str.substring(0, index)); final String expression = str.substring(index+1);
return new BigInteger(str.substring(index+3), 16);
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);
} }
} }

View file

@ -14,6 +14,7 @@ CMemoryBlockRetrievalExtension.1=Invalid expression type: ''{0}''
CMemoryBlockRetrievalExtension.2=Invalid expression: ''{0}'' CMemoryBlockRetrievalExtension.2=Invalid expression: ''{0}''
CMemoryBlockRetrievalExtension.3=Memory initialization: invalid memento. CMemoryBlockRetrievalExtension.3=Memory initialization: invalid memento.
CMemoryBlockRetrievalExtension.4=Invalid address: ''{0}'' CMemoryBlockRetrievalExtension.4=Invalid address: ''{0}''
CMemoryBlockRetrievalExtension.invalid_encoded_addresses=Format of encoded address is invalid.
DebugConfiguration.0=This debugger no longer supports this operation DebugConfiguration.0=This debugger no longer supports this operation
CDebugAdapter.0=This debugger does not support debugging external files CDebugAdapter.0=This debugger does not support debugging external files
CDebugAdapter.1=Debugger Process CDebugAdapter.1=Debugger Process

View file

@ -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.event.ICDIResumedEvent;
import org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock; 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.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.ICDIMemorySpaceManagement;
import org.eclipse.cdt.debug.core.cdi.model.ICDIObject; import org.eclipse.cdt.debug.core.cdi.model.ICDIObject;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.debug.core.model.IExecFileInfo; 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.cdt.debug.internal.core.CMemoryBlockRetrievalExtension;
import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin; 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.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.MemoryByte; import org.eclipse.debug.core.model.MemoryByte;
/** /**
* Represents a memory block in the CDI model. * 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. * 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 ) { public CMemoryBlockExtension( CDebugTarget target, String expression, BigInteger baseAddress ) {
super( target ); this(target, expression, baseAddress, null);
fExpression = expression;
fBaseAddress = baseAddress;
} }
/** /**
* 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 ) { 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 ); super( target );
fExpression = expression; fExpression = expression;
fBaseAddress = baseAddress; fBaseAddress = baseAddress;
fWordSize= wordSize; fWordSize= wordSize;
fHaveWordSize= true; fHaveWordSize= true;
}
/**
* Constructor for CMemoryBlockExtension that supports memory spaces
*
*/
public CMemoryBlockExtension( CDebugTarget target, BigInteger baseAddress, String memorySpaceID ) {
super( target );
fBaseAddress = baseAddress;
fMemorySpaceID = memorySpaceID; 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);
} }
/* (non-Javadoc) /* (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 * @see org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlock#getMemorySpaceID()
* 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
*/ */
public String getMemorySpaceID() { public String getMemorySpaceID() {
return fMemorySpaceID; return fMemorySpaceID;

View file

@ -1388,24 +1388,11 @@
</adapter> </adapter>
</factory> </factory>
<factory <factory
adaptableType="org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension" adaptableType="org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval"
class="org.eclipse.cdt.debug.internal.ui.elements.adapters.CMemoryAdapterFactory"> class="org.eclipse.cdt.debug.internal.ui.elements.adapters.CMemoryAdapterFactory">
<adapter <adapter
type="org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget"> type="org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget">
</adapter> </adapter>
<adapter
type="org.eclipse.jface.viewers.ILabelDecorator">
</adapter>
</factory>
<factory
adaptableType="org.eclipse.debug.core.model.IMemoryBlockExtension"
class="org.eclipse.cdt.debug.internal.ui.elements.adapters.CMemoryAdapterFactory">
<adapter
type="org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget">
</adapter>
<adapter
type="org.eclipse.jface.viewers.ILabelDecorator">
</adapter>
</factory> </factory>
<factory <factory
adaptableType="org.eclipse.cdt.debug.core.model.IDisassemblyLine" adaptableType="org.eclipse.cdt.debug.core.model.IDisassemblyLine"

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,60 +11,46 @@
package org.eclipse.cdt.debug.internal.ui.elements.adapters; package org.eclipse.cdt.debug.internal.ui.elements.adapters;
import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension; import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval;
import org.eclipse.cdt.debug.internal.core.model.CMemoryBlockExtension;
import org.eclipse.cdt.debug.internal.ui.views.memory.AddMemoryBlocks; import org.eclipse.cdt.debug.internal.ui.views.memory.AddMemoryBlocks;
import org.eclipse.cdt.debug.internal.ui.views.memory.MemoryBlockLabelDecorator;
import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget; import org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget;
import org.eclipse.jface.viewers.ILabelDecorator;
/** /**
* Provides the IAdaptable mapping for things related to the memory-space * Provides the IAdaptable mapping for things related to the memory-space
* extension of the platform's Memory view * support in the Memory and Memory Browser views.
*/ */
public class CMemoryAdapterFactory implements IAdapterFactory { public class CMemoryAdapterFactory implements IAdapterFactory {
private static IAddMemoryBlocksTarget fgAddMemoryBlocks = new AddMemoryBlocks(); private static IAddMemoryBlocksTarget fgAddMemoryBlocks = new AddMemoryBlocks();
/* /* (non-Javadoc)
* (non-Javadoc) * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
*
* @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object,
* java.lang.Class)
*/ */
@SuppressWarnings("rawtypes")
public Object getAdapter(Object adaptableObject, Class adapterType) { public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType.isInstance(adaptableObject)) { if (adapterType.isInstance(adaptableObject)) {
return adaptableObject; return adaptableObject;
} }
// If the target supports memory spaces and there's more than one // If the backend supports memory spaces we use a custom Add Monitor
// available, we use a custom Add Monitor dialog // dialog, though our IAddMemoryBlocksTarget may decide to invoke the
// standard, platform dialog if the customization isn't actually
// necessary.
if (adapterType.equals(IAddMemoryBlocksTarget.class)) { if (adapterType.equals(IAddMemoryBlocksTarget.class)) {
if (adaptableObject instanceof CMemoryBlockRetrievalExtension) { if (adaptableObject instanceof IMemorySpaceAwareMemoryBlockRetrieval) {
if (((CMemoryBlockRetrievalExtension)adaptableObject).getMemorySpaces().length > 1)
return fgAddMemoryBlocks; 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);
}
}
return null; return null;
} }
/* /* (non-Javadoc)
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
*/ */
@SuppressWarnings("rawtypes")
public Class[] getAdapterList() { public Class[] getAdapterList() {
return new Class[] { IAddMemoryBlocksTarget.class, ILabelDecorator.class }; return new Class[] { IAddMemoryBlocksTarget.class };
} }
} }

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Freescale, Inc. - initial API and implementation * Freescale Semiconductor, Inc. - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.debug.internal.ui.views.memory; 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.ArrayList;
import java.util.List; 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.debug.ui.IDebugUIConstants;
import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
@ -56,22 +54,32 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener,
private String fAddress; private String fAddress;
private String fMemorySpace; private String fMemorySpace;
private boolean fEnteredExpression; // basically, which of the two radio buttons was selected when OK was hit private boolean fEnteredExpression; // basically, which of the two radio buttons was selected when OK was hit
private CMemoryBlockRetrievalExtension fMemRetrieval;
/** 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<String> sAddressHistory = new ArrayList<String>(); private static List<String> sAddressHistory = new ArrayList<String>();
private static List<String> sExpressionHistory = new ArrayList<String>(); private static List<String> sExpressionHistory = new ArrayList<String>();
private static boolean sDefaultToExpression = true; private static boolean sDefaultToExpression = true;
public AddMemoryBlockDialog(Shell parentShell, public AddMemoryBlockDialog(Shell parentShell, String[] memorySpaces) {
IMemoryBlockRetrieval memRetrieval) {
super(parentShell); super(parentShell);
setShellStyle(getShellStyle() | SWT.RESIZE); setShellStyle(getShellStyle() | SWT.RESIZE);
fMemorySpaces = memorySpaces;
if (memRetrieval instanceof CMemoryBlockRetrievalExtension) { // We shouldn't be using this custom dialog if there are none or only
fMemRetrieval = (CMemoryBlockRetrievalExtension)memRetrieval; // one memory spaces available.
} // https://bugs.eclipse.org/bugs/show_bug.cgi?id=309032#c50
assert memorySpaces != null && memorySpaces.length >= 2;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -126,6 +134,26 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener,
fMemorySpaceInput.setLayoutData(gridData); 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); fAddressInput = new Combo(parent, SWT.BORDER);
gridData = new GridData(GridData.FILL_HORIZONTAL); gridData = new GridData(GridData.FILL_HORIZONTAL);
GC gc = new GC(fAddressInput); GC gc = new GC(fAddressInput);
@ -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 // add the history into the combo boxes
String[] history = getHistory(sExpressionHistory); String[] history = getHistory(sExpressionHistory);
for (int i = 0; i < history.length; i++) for (int i = 0; i < history.length; i++)
@ -209,6 +227,8 @@ public class AddMemoryBlockDialog extends TrayDialog implements ModifyListener,
addHistory(sAddressHistory, fAddress); addHistory(sAddressHistory, fAddress);
fEnteredExpression = fExpressionRadio.getSelection(); fEnteredExpression = fExpressionRadio.getSelection();
fPreviousMemorySpaceSelection = fMemorySpace;
super.okPressed(); super.okPressed();
} }

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Freescale, Inc. - initial API and implementation * Freescale Semiconductor, Inc. - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.debug.internal.ui.views.memory; package org.eclipse.cdt.debug.internal.ui.views.memory;
@ -16,7 +16,9 @@ import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.eclipse.cdt.debug.core.model.ICVariable; 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.CMemoryBlockRetrievalExtension;
import org.eclipse.cdt.debug.internal.core.CRequest;
import org.eclipse.cdt.debug.internal.core.model.CRegister; import org.eclipse.cdt.debug.internal.core.model.CRegister;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin; import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.CoreException; 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.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval; 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.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.actions.IAddMemoryBlocksTarget; 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.IMemoryRendering;
import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; import org.eclipse.debug.ui.memory.IMemoryRenderingContainer;
import org.eclipse.debug.ui.memory.IMemoryRenderingSite; import org.eclipse.debug.ui.memory.IMemoryRenderingSite;
import org.eclipse.debug.ui.memory.IMemoryRenderingType; import org.eclipse.debug.ui.memory.IMemoryRenderingType;
import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window; import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; 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.IWorkbenchPart;
import org.eclipse.ui.progress.UIJob; import org.eclipse.ui.progress.UIJob;
@ -61,32 +69,108 @@ import org.eclipse.ui.progress.UIJob;
*/ */
public class AddMemoryBlocks implements IAddMemoryBlocksTarget { public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
public void addMemoryBlocks(IWorkbenchPart part, ISelection selection) throws CoreException { /** Request object used to get the memory spaces */
private static class GetMemorySpacesRequest extends CRequest implements IMemorySpaceAwareMemoryBlockRetrieval.GetMemorySpacesRequest {
if (!(part instanceof IMemoryRenderingSite)) String [] fMemorySpaces = new String[0];
return; public String[] getMemorySpaces() {
return fMemorySpaces;
IAdaptable debugViewElement = DebugUITools.getDebugContext(); }
public void setMemorySpaces(String[] memorySpaceIds) {
fMemorySpaces = memorySpaceIds;
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;
} }
/* (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 {
if (!(part instanceof IMemoryRenderingSite)) {
assert false : "unexpected kind of view part"; //$NON-NLS-1$
return;
}
final IMemoryRenderingSite renderingSite = (IMemoryRenderingSite)part;
final IAdaptable debugViewElement = DebugUITools.getDebugContext();
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(); Shell shell = CDebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
// create dialog to ask for expression/address to block // create dialog to ask for expression/address to block
AddMemoryBlockDialog dialog = new AddMemoryBlockDialog(shell, cdtRetrieval); AddMemoryBlockDialog dialog = new AddMemoryBlockDialog(shell, memorySpaces);
dialog.open(); dialog.open();
int returnCode = dialog.getReturnCode(); int returnCode = dialog.getReturnCode();
if (returnCode == Window.CANCEL) if (returnCode == Window.CANCEL)
@ -112,20 +196,17 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
else else
params = new AddressAndSpaceHolder(addrsOrExprs, dialog.getMemorySpace()); params = new AddressAndSpaceHolder(addrsOrExprs, dialog.getMemorySpace());
final IAdaptable debugViewElement_f = debugViewElement;
final CMemoryBlockRetrievalExtension retrieval_f = cdtRetrieval;
final ParamHolder params_f = params; final ParamHolder params_f = params;
final IMemoryRenderingSite memRendSite = (IMemoryRenderingSite) part;
Job job = new Job("Add Memory Block") { //$NON-NLS-1$ Job job = new Job("Add Memory Block") { //$NON-NLS-1$
@Override @Override
protected IStatus run(IProgressMonitor monitor) { protected IStatus run(IProgressMonitor monitor) {
addMemoryBlocks(debugViewElement_f, retrieval_f, params_f, addMemoryBlocks(context, retrieval, params_f, renderingSite);
memRendSite);
return Status.OK_STATUS; return Status.OK_STATUS;
} }
}; };
job.setSystem(true); job.setSystem(true);
job.schedule(); job.schedule();
} }
public boolean canAddMemoryBlocks(IWorkbenchPart part, ISelection selection) public boolean canAddMemoryBlocks(IWorkbenchPart part, ISelection selection)
@ -165,8 +246,8 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
public String[] expressions; public String[] expressions;
} }
private void addMemoryBlocks(IAdaptable debugViewElement, private void addMemoryBlocks(Object context,
CMemoryBlockRetrievalExtension memRetrieval, IMemorySpaceAwareMemoryBlockRetrieval memRetrieval,
final ParamHolder params, IMemoryRenderingSite memRendSite) { final ParamHolder params, IMemoryRenderingSite memRendSite) {
final String[] addrsOrExprs = (params instanceof AddressAndSpaceHolder) ? ((AddressAndSpaceHolder) params).addresses final String[] addrsOrExprs = (params instanceof AddressAndSpaceHolder) ? ((AddressAndSpaceHolder) params).addresses
@ -181,13 +262,13 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
IMemoryBlockExtension memBlock; IMemoryBlockExtension memBlock;
if (params instanceof AddressAndSpaceHolder) if (params instanceof AddressAndSpaceHolder)
memBlock = memRetrieval.getMemoryBlockWithMemorySpaceID( memBlock = memRetrieval.getMemoryBlock(
addrOrExpr, addrOrExpr,
((AddressAndSpaceHolder) params).memorySpace, context,
debugViewElement); ((AddressAndSpaceHolder) params).memorySpace);
else else
memBlock = memRetrieval.getExtendedMemoryBlock(addrOrExpr, memBlock = memRetrieval.getExtendedMemoryBlock(addrOrExpr,
debugViewElement); context);
// add block to memory block manager // add block to memory block manager
if (memBlock != null) { if (memBlock != null) {
@ -295,7 +376,7 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
variables[i].getType().isReference() || variables[i] instanceof CRegister) variables[i].getType().isReference() || variables[i] instanceof CRegister)
expressions[i] = exp; expressions[i] = exp;
else else
expressions[i] = "&" + exp; expressions[i] = "&" + exp; //$NON-NLS-1$
} }
ParamHolder params; ParamHolder params;
@ -345,5 +426,50 @@ public class AddMemoryBlocks implements IAddMemoryBlocksTarget {
uiJob.schedule(); 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();
}
}
} }

View file

@ -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.
*
* <p> 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:
* <PRE> expression : address &lt;rendering-name&gt; </PRE>
* isn't well suited. Our job is to reduce this to
* <pre> expression &lt;rendering-name&gt; </PRE>
* The expression ends up being the back-end provided string encoding of
* a memory space + address pair.
* <p>
* @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
}
}

View file

@ -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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at

View file

@ -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 # All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0 # are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at # which accompanies this distribution, and is available at

View file

@ -9,7 +9,9 @@ Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui, Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime, org.eclipse.core.runtime,
org.eclipse.debug.core;bundle-version="3.5.0", 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-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.debug.ui.memory.memorybrowser Export-Package: org.eclipse.cdt.debug.ui.memory.memorybrowser

View file

@ -15,9 +15,14 @@ package org.eclipse.cdt.debug.ui.memory.memorybrowser;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; 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.CoreException;
import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor; 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.PropertyChangeEvent;
import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IBasicPropertyConstants; import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider; 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.FormAttachment;
import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
@ -110,40 +117,77 @@ import org.eclipse.ui.progress.WorkbenchJob;
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
public class MemoryBrowser extends ViewPart implements IDebugContextListener, IMemoryRenderingSite, IDebugEventSetListener 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; protected StackLayout fStackLayout;
private Composite fRenderingsComposite; private Composite fRenderingsComposite;
private HashMap<Object,CTabFolder> fContextFolders = new HashMap<Object,CTabFolder> ();
private GoToAddressBarWidget fGotoAddressBar; private GoToAddressBarWidget fGotoAddressBar;
private Control fGotoAddressBarControl; private Control fGotoAddressBarControl;
private Combo fGotoMemorySpaceControl;
// revisit; see bug 307023
// private Combo fGotoAddressSpaceControl;
private Label fUnsupportedLabel; private Label fUnsupportedLabel;
private Composite fMainComposite; private Composite fMainComposite;
private String defaultRenderingTypeId = null; private String defaultRenderingTypeId = null;
private ArrayList<IMemoryRenderingContainer> fCurrentContainers = new ArrayList<IMemoryRenderingContainer>(); /**
* 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<IMemoryBlockRetrieval,CTabFolder> fContextFolders = new HashMap<IMemoryBlockRetrieval,CTabFolder> ();
private List<IMemoryRenderingContainer> fCurrentContainers = new ArrayList<IMemoryRenderingContainer>();
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_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_CONTAINER = "CONTAINER"; //$NON-NLS-1$
private final static String KEY_RENDERING_TYPE = "RENDERING_TYPE"; //$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$
// revisit; see bug 307023
// private final static String KEY_ADDRESS_SPACE_PREFIXES = "ADDRESSSPACEPREFIXES"; //$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 MemoryBrowser() {
} }
public Control getControl() public Control getControl() {
{
return fMainComposite; return fMainComposite;
} }
@ -180,9 +224,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
layout.spacing = 0; layout.spacing = 0;
fMainComposite.setLayout(layout); fMainComposite.setLayout(layout);
// revisit; see bug 307023 fGotoMemorySpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
//fGotoAddressSpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
fGotoAddressBar = new GoToAddressBarWidget(); fGotoAddressBar = new GoToAddressBarWidget();
fGotoAddressBarControl = fGotoAddressBar.createControl(fMainComposite); fGotoAddressBarControl = fGotoAddressBar.createControl(fMainComposite);
@ -210,9 +252,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
FormData data = new FormData(); FormData data = new FormData();
data.top = new FormAttachment(0); data.top = new FormAttachment(0);
// revisit; see bug 307023 data.left = new FormAttachment(fGotoMemorySpaceControl);
//data.left = new FormAttachment(fGotoAddressSpaceControl);
data.left = new FormAttachment(0);
data.right = new FormAttachment(100); data.right = new FormAttachment(100);
fGotoAddressBarControl.setLayoutData(data); fGotoAddressBarControl.setLayoutData(data);
@ -300,7 +340,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
for (DebugEvent event: events) { for (DebugEvent event: events) {
Object source = event.getSource(); Object source = event.getSource();
if (event.getKind() == DebugEvent.TERMINATE && source instanceof IMemoryBlockRetrieval) { 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; return null;
} }
private void handleUnsupportedSelection() private void handleUnsupportedSelection() {
{
fStackLayout.topControl = fUnsupportedLabel; fStackLayout.topControl = fUnsupportedLabel;
fGotoAddressBarControl.setVisible(false); fGotoAddressBarControl.setVisible(false);
fGotoMemorySpaceControl.setVisible(false);
// revisit; see bug 307023
//fGotoAddressSpaceControl.setVisible(false);
} }
private void performGo(boolean inNewTab) private void performGo(boolean inNewTab) {
{ // Index zero is the 'auto' (n/a) memory space entry
performGo(inNewTab, fGotoAddressBar.getExpressionText(), (short)0); String memorySpace = null;
if (fGotoMemorySpaceControl.isVisible() && (fGotoMemorySpaceControl.getSelectionIndex() != 0)) {
memorySpace = fGotoMemorySpaceControl.getText();
assert (memorySpace != null) && (memorySpace.length() > 0);
} }
public void performGo(boolean inNewTab, final String expression, short memoryPage) String expression = fGotoAddressBar.getExpressionText();
{ if (expression.length() > 0) {
performGo(inNewTab, fGotoAddressBar.getExpressionText(), memorySpace);
}
}
public void performGo(boolean inNewTab, final String expression, final String memorySpaceId) {
final CTabFolder activeFolder = (CTabFolder) fStackLayout.topControl; final CTabFolder activeFolder = (CTabFolder) fStackLayout.topControl;
if(activeFolder != null) if (activeFolder != null) {
{
final IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) activeFolder.getData(KEY_RETRIEVAL); final IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) activeFolder.getData(KEY_RETRIEVAL);
final Object context = activeFolder.getData(KEY_CONTEXT); final Object context = activeFolder.getData(KEY_CONTEXT);
if(inNewTab || activeFolder.getSelection() == null) CTabItem item = activeFolder.getSelection();
{ if (inNewTab || item == null) {
CTabItem item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1); item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1);
populateTabWithRendering(item, retrieval, context); populateTabWithRendering(item, retrieval, context, memorySpaceId);
setTabFolder(retrieval, activeFolder);
fContextFolders.put(retrieval, activeFolder);
activeFolder.setSelection(item); activeFolder.setSelection(item);
getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING))); getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING)));
} }
final IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING);
final String gotoExpression = getAddressSpacePrefix() + expression; IMemoryRenderingContainer container = (IMemoryRenderingContainer)item.getData(KEY_CONTAINER);
String oldMemorySpaceId = (String)activeFolder.getSelection().getData(KEY_MEMORY_SPACE);
if(retrieval instanceof IMemoryBlockRetrievalExtension) assert oldMemorySpaceId == null || !oldMemorySpaceId.equals(NA_MEMORY_SPACE_ID) : "should be null reference, not 'auto'";
{ if ((oldMemorySpaceId != null && !oldMemorySpaceId.equals(memorySpaceId))
new Thread() || (oldMemorySpaceId == null && memorySpaceId != null)) {
{ updateTabWithRendering(item, retrieval, container, context, memorySpaceId);
public void run() 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 { try {
BigInteger newBase = getExpressionAddress(retrieval, gotoExpression, context); BigInteger newBase = getExpressionAddress(retrieval, expression, context, memorySpaceId);
if(((IMemoryBlockExtension) rendering.getMemoryBlock()).supportBaseAddressModification()) IMemoryBlockExtension block = (IMemoryBlockExtension) renderingFinal.getMemoryBlock();
((IMemoryBlockExtension) rendering.getMemoryBlock()).setBaseAddress(newBase); if (block.supportBaseAddressModification()) {
rendering.goToAddress(newBase); block.setBaseAddress(newBase);
}
renderingFinal.goToAddress(newBase);
runOnUIThread(new Runnable(){ runOnUIThread(new Runnable(){
public void run() public void run() {
{ updateLabel(activeFolder.getSelection(), renderingFinal);
updateLabel(activeFolder.getSelection(), rendering);
} }
}); });
} catch (DebugException e1) { } catch (DebugException e1) {
@ -381,67 +433,58 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
} }
} }
private String getAddressSpacePrefix() private void updateLabel(CTabItem tab, IMemoryRendering rendering) {
{ // The default is to use the label provided by the base rendering
// revisit; see bug 307023 // interface.
// if(fGotoAddressSpaceControl.isVisible()) String label = rendering.getLabel();
// {
// String prefixes[] = (String[]) fGotoAddressSpaceControl.getData(KEY_ADDRESS_SPACE_PREFIXES); // We create all memory blocks using address 0 regardless of where the
// if(prefixes != null && prefixes.length > 0) // 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
// return prefixes[fGotoAddressSpaceControl.getSelectionIndex()]; // 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
return ""; 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);
} }
// MemoryBrowser.FailedToGoToAddressTitle=Unable to Go To specified address label = null;
// MemoryBrowser.UnableToEvaluateAddress
private void updateLabel(CTabItem tab, IMemoryRendering rendering) // If a memory space is involved, we want to include its ID in the label
{ String memorySpaceID = (String)tab.getData(KEY_MEMORY_SPACE);
String label = null; 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;
}
// This is a hack and needs to be revisited. // Allow the memory block to customize the label. The platform's
// // Memory view support this (it was done in the call to
// // would like to avoid using reflection // rendering.getLabel() above)
// try { IMemoryBlock block = rendering.getMemoryBlock();
// Method m = rendering.getControl().getClass().getMethod("getViewportStartAddress", new Class[0]); //$NON-NLS-1$ ILabelDecorator labelDec = (ILabelDecorator)block.getAdapter(ILabelDecorator.class);
// if(m != null) if (labelDec != null) {
// label = "0x" + ((BigInteger) m.invoke(rendering.getControl(), new Object[0])).toString(16).toUpperCase(); //$NON-NLS-1$ String newLabel = labelDec.decorateText(label, rendering);
// } if (newLabel != null) {
// catch (Exception e) label = newLabel;
// { }
// } }
}
if(label == null)
label = rendering.getLabel();
tab.setText(label); 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) private CTabFolder createTabFolder(Composite parent)
{ {
final CTabFolder folder = new CTabFolder(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.FLAT); 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; return folder;
} }
// these utility methods allow us restrict the scope of the unavoidable @SuppressWarnings
@SuppressWarnings("unchecked")
private static Map<String, IMemoryRendering> getRenderings(CTabItem tabItem) {
return (Map<String, IMemoryRendering>)tabItem.getData(KEY_RENDERINGS);
}
@SuppressWarnings("unchecked")
private static List<IMemoryBlockExtension> getMemoryBlocks(CTabItem tabItem) {
return (List<IMemoryBlockExtension>)tabItem.getData(KEY_MEMORY_BLOCKS);
}
/** /**
* dispose rendering resources associated with the tab item * dispose rendering resources associated with the tab item
* @param item * @param item
@ -485,24 +541,31 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
IMemoryRenderingContainer container = (IMemoryRenderingContainer) item.getData(KEY_CONTAINER); IMemoryRenderingContainer container = (IMemoryRenderingContainer) item.getData(KEY_CONTAINER);
fCurrentContainers.remove( container ); fCurrentContainers.remove( container );
IMemoryRendering rendering = (IMemoryRendering) item.getData(KEY_RENDERING); Map<String, IMemoryRendering> map = getRenderings(item);
Collection<IMemoryRendering> renderings = map.values();
for (IMemoryRendering rendering : renderings) {
// always deactivate rendering before disposing it. // always deactivate rendering before disposing it.
if ( rendering != null ) {
rendering.deactivated(); rendering.deactivated();
rendering.dispose(); rendering.dispose();
} }
IMemoryBlockExtension block = (IMemoryBlockExtension) item.getData(KEY_MEMORY_BLOCK); map.clear();
List<IMemoryBlockExtension> blocks = getMemoryBlocks(item);
for (IMemoryBlockExtension block : blocks) {
try { try {
if (block != null)
block.dispose(); block.dispose();
} catch (DebugException e) { } catch (DebugException e) {
MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Could not dispose memory block", e)); //$NON-NLS-1$ 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) { private CTabItem createTab(CTabFolder tabFolder, int index) {
int swtStyle = SWT.CLOSE; int swtStyle = SWT.CLOSE;
CTabItem tab = new CTabItem(tabFolder, swtStyle, index); CTabItem tab = new CTabItem(tabFolder, swtStyle, index);
tab.setData(KEY_RENDERINGS, new HashMap<String, IMemoryRendering>());
tab.setData(KEY_MEMORY_BLOCKS, new ArrayList<IMemoryBlock>());
return tab; return tab;
} }
@ -544,7 +607,6 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
} }
manager.add(sub); manager.add(sub);
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
} }
@ -602,43 +664,82 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
handleDebugContextChanged(((StructuredSelection) event.getContext()).getFirstElement()); handleDebugContextChanged(((StructuredSelection) event.getContext()).getFirstElement());
} }
public void handleDebugContextChanged(Object context) { 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(final Object context) {
if(defaultRenderingTypeId == null) if(defaultRenderingTypeId == null)
return; return;
if(context instanceof IAdaptable) if(context instanceof IAdaptable)
{ {
IAdaptable adaptable = (IAdaptable) context; 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)); 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); fGotoAddressBarControl.setVisible(true);
// revisit; see bug 307023 // If we've already created a tab folder for this retrieval
// String addressSpaces[][] = getAddressSpaces(retrieval); // object, bring it to the forefront. Otherwise create the
// if(addressSpaces.length > 0) // folder.
// { CTabFolder tabFolder = fContextFolders.get(retrieval);
// fGotoAddressSpaceControl.setVisible(true); if(tabFolder != null) {
// fGotoAddressSpaceControl.setItems(addressSpaces[0]);
// fGotoAddressSpaceControl.setData(KEY_ADDRESS_SPACE_PREFIXES, addressSpaces[1]);
// }
// else
// fGotoAddressSpaceControl.setVisible(false);
CTabFolder tabFolder = getTabFolder(retrieval);
if(tabFolder != null)
{
fStackLayout.topControl = tabFolder; fStackLayout.topControl = tabFolder;
} }
else else {
{ tabFolder = createTabFolder(fRenderingsComposite);
tabFolder = this.createTabFolder(fRenderingsComposite); tabFolder.addSelectionListener(new SelectionListener() {
tabFolder.addSelectionListener(new SelectionListener()
{
public void widgetDefaultSelected(SelectionEvent e) {} public void widgetDefaultSelected(SelectionEvent e) {}
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
updateMemorySpaceControlSelection((CTabItem)e.item);
getSite().getSelectionProvider().setSelection(new StructuredSelection(((CTabItem) e.item).getData(KEY_RENDERING))); 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); tabFolder.setData(KEY_RETRIEVAL, retrieval);
CTabItem item = createTab(tabFolder, 0); CTabItem item = createTab(tabFolder, 0);
populateTabWithRendering(item, retrieval, context); populateTabWithRendering(item, retrieval, context, null);
setTabFolder(retrieval, tabFolder); fContextFolders.put(retrieval, tabFolder);
fStackLayout.topControl = tabFolder;
fStackLayout.topControl = getTabFolder(retrieval);
} }
// update debug context to the new selection // update debug context to the new selection
tabFolder.setData(KEY_CONTEXT, context); tabFolder.setData(KEY_CONTEXT, context);
}
else
{ final CTabFolder activeFolder = tabFolder;
handleUnsupportedSelection(); if (!activeFolder.equals(tabFolder)) {
return;
} }
// revisit; see bug 307023 CTabItem tabItem = activeFolder.getSelection();
//fGotoAddressSpaceControl.pack(true); 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); 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() private String getDefaultRenderingTypeId()
@ -678,14 +831,12 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
store.setValue(PREF_DEFAULT_RENDERING, defaultRenderingTypeId); 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()); IMemoryRenderingType type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId());
try { try {
final IMemoryRendering rendering = type.createRendering(); final IMemoryRendering rendering = type.createRendering();
IMemoryRenderingContainer container = new IMemoryRenderingContainer() IMemoryRenderingContainer container = new IMemoryRenderingContainer() {
{
public void addMemoryRendering(IMemoryRendering rendering) {} public void addMemoryRendering(IMemoryRendering rendering) {}
public IMemoryRendering getActiveRendering() { 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); fCurrentContainers.add(container);
rendering.init(container, block); rendering.init(container, block);
rendering.createControl(tab.getParent()); rendering.createControl(tab.getParent());
tab.setControl(rendering.getControl()); tab.setControl(rendering.getControl());
tab.getParent().setSelection(0); tab.getParent().setSelection(0);
getRenderings(tab).put(memorySpaceId, rendering);
tab.setData(KEY_RENDERING, rendering); tab.setData(KEY_RENDERING, rendering);
tab.setData(KEY_MEMORY_SPACE, memorySpaceId);
tab.setData(KEY_CONTAINER, container); 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))); getSite().getSelectionProvider().setSelection(new StructuredSelection(tab.getData(KEY_RENDERING)));
updateLabel(tab, rendering); updateLabel(tab, rendering);
@ -748,19 +902,60 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
} }
} }
private CTabFolder getTabFolder(Object context) private void updateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, IMemoryRenderingContainer container, Object context, String memorySpaceId) {
{ IMemoryRenderingType type = (IMemoryRenderingType)tab.getData(KEY_RENDERING_TYPE);
return fContextFolders.get(context); if (type == null) {
type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId());
}
try {
Map<String, IMemoryRendering> 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); final CTabFolder folder = fContextFolders.get(retrieval);
}
private void releaseTabFolder(final Object context)
{
final CTabFolder folder = getTabFolder(context);
if(folder != null) if(folder != null)
{ {
Runnable run = new Runnable() { Runnable run = new Runnable() {
@ -768,7 +963,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
for(CTabItem tab : folder.getItems()) { for(CTabItem tab : folder.getItems()) {
disposeTab(tab); disposeTab(tab);
} }
fContextFolders.remove(context); fContextFolders.remove(retrieval);
folder.dispose(); folder.dispose();
if (fStackLayout.topControl.equals(folder)) { 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 expression expression to be evaluated to an addressL
* @param context context for evaluating the expression. This is typically * @param context context for evaluating the expression. This is typically
* a debug element. * 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 * @return a memory block based on the given expression and context
* @throws DebugException if unable to retrieve the specified memory * @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; IMemoryBlockExtension block = null;
if(retrieval instanceof IAdaptable) if(retrieval instanceof IAdaptable) {
{ IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension)((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class);
IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension) if (retrievalExtension != null) {
((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class); if (retrievalExtension instanceof IMemorySpaceAwareMemoryBlockRetrieval) {
if(retrievalExtension != null) block = ((IMemorySpaceAwareMemoryBlockRetrieval)retrievalExtension).getMemoryBlock(expression, context, memorySpaceID);
block = retrievalExtension.getExtendedMemoryBlock(expression, context); //$NON-NLS-1$ }
else {
block = retrievalExtension.getExtendedMemoryBlock(expression, context);
}
}
} }
if ( block == null ) { if ( block == null ) {
throw new DebugException(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Extended Memory Block could not be obtained")); //$NON-NLS-1$ 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 * @return BigInteger address of the expression
* @throws DebugException * @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. // 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(); BigInteger address = newBlock.getBigBaseAddress();
newBlock.dispose(); newBlock.dispose();
return address; return address;
@ -862,8 +1062,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM
* @param runnable * @param runnable
* the runnable to execute * the runnable to execute
*/ */
private void runOnUIThread(final Runnable runnable) private void runOnUIThread(final Runnable runnable) {
{
if (Display.getCurrent() != null) { if (Display.getCurrent() != null) {
runnable.run(); runnable.run();
} }

View file

@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.debug.core,
org.eclipse.swt, org.eclipse.swt,
org.eclipse.jface, org.eclipse.jface,
org.eclipse.ui, 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-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPlugin Bundle-Activator: org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPlugin
Bundle-Vendor: %providerName Bundle-Vendor: %providerName

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.debug.ui.memory.traditional;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.math.BigInteger; import java.math.BigInteger;
import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider;
import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.Command; import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionEvent;
@ -83,7 +84,7 @@ import org.eclipse.ui.progress.UIJob;
*/ */
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering, IMemoryRenderingViewportProvider
{ {
protected Rendering fRendering; protected Rendering fRendering;
protected Action displayEndianBigAction; protected Action displayEndianBigAction;
@ -1264,6 +1265,13 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe
public void resetRendering() throws DebugException { public void resetRendering() throws DebugException {
fRendering.gotoAddress(fRendering.fBaseAddress); 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 class CopyAction extends Action