1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 23:15:24 +02:00

[160046] Committed memory service patch from 7/27/07.

This commit is contained in:
Pawel Piech 2007-08-14 23:08:11 +00:00
parent 8a30df00b7
commit 582657cf05
3 changed files with 422 additions and 235 deletions

View file

@ -7,20 +7,26 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Ericsson Communication - upgrade IF from IMemoryBlock to IMemoryBlockExtension * Ericsson Communication - upgrade IF to IMemoryBlockExtension
* Ericsson Communication - added support for 64 bit processors
*******************************************************************************/ *******************************************************************************/
package org.eclipse.dd.dsf.debug.model; package org.eclipse.dd.dsf.debug.model;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.Query; import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.debug.service.IMemory; import org.eclipse.dd.dsf.debug.service.IMemory;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IMemory.MemoryChangedEvent;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
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.ILaunch; import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IMemoryBlockExtension; import org.eclipse.debug.core.model.IMemoryBlockExtension;
@ -28,34 +34,46 @@ import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.MemoryByte; import org.eclipse.debug.core.model.MemoryByte;
/** /**
* This class holds the memory block retrieved from the target as a result of * This class manages the memory block retrieved from the target as a result
* a getBytes() or getBytesFromAddress() call from the platform. * of a getBytesFromAddress() call from the platform.
*
* It performs its read/write functions using the MemoryService.
*/ */
public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtension public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtension
{ {
private final DsfMemoryBlockRetrieval fRetrieval; private final DsfMemoryBlockRetrieval fRetrieval;
private final String fModelId; private final String fModelId;
private final String fExpression; private final String fExpression;
private final long fStartAddress; private final BigInteger fStartAddress;
private final long fLength; private BigInteger fEndAddress;
private final BigInteger fBaseAddress; private long fLength = 0;
/** /**
* Constructor * Constructor.
* *
* @param retrieval * @param retrieval - the MemoryBlockRetrieval (session context)
* @param modelId * @param modelId -
* @param expression * @param expression - the displayed expression
* @param startAddress * @param startAddress - the actual memory block start address
* @param length * @param length - the memory block length (could be 0)
*/ */
DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, long startAddress, long length) { DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, BigInteger startAddress, long length) {
fRetrieval = retrieval; fRetrieval = retrieval;
fModelId = modelId; fModelId = modelId;
fExpression = expression; fExpression = expression;
fStartAddress = startAddress; fStartAddress = startAddress;
fBaseAddress = new BigInteger(Long.toString(startAddress)); fEndAddress = startAddress.add(BigInteger.valueOf(length));
fLength = length; fLength = length;
try {
fRetrieval.getExecutor().execute(new Runnable() {
public void run() {
fRetrieval.getSession().addServiceEventListener(DsfMemoryBlock.this, null);
}
});
} catch(RejectedExecutionException e) {
// Session is shut down.
}
} }
// //////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////
@ -65,7 +83,8 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
*/ */
@Override @SuppressWarnings("unchecked")
@Override
public Object getAdapter(Class adapter) { public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(DsfMemoryBlockRetrieval.class)) { if (adapter.isAssignableFrom(DsfMemoryBlockRetrieval.class)) {
return fRetrieval; return fRetrieval;
@ -81,6 +100,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget() * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
*/ */
public IDebugTarget getDebugTarget() { public IDebugTarget getDebugTarget() {
// FRCH: return fRetrieval.getDebugTarget();
return null; return null;
} }
@ -95,6 +115,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IDebugElement#getLaunch() * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
*/ */
public ILaunch getLaunch() { public ILaunch getLaunch() {
// FRCH: return fRetrieval.getDebugTarget().getLaunch();
return null; return null;
} }
@ -106,13 +127,20 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlock#getStartAddress() * @see org.eclipse.debug.core.model.IMemoryBlock#getStartAddress()
*/ */
public long getStartAddress() { public long getStartAddress() {
return fStartAddress; // Warning: doesn't support 64-bit addresses
long address = fStartAddress.longValue();
if (fStartAddress.equals(BigInteger.valueOf(address)))
return address;
// FRCH: Should we throw an exception instead?
return 0;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlock#getLength() * @see org.eclipse.debug.core.model.IMemoryBlock#getLength()
*/ */
public long getLength() { public long getLength() {
// Warning: could return 0
return fLength; return fLength;
} }
@ -124,7 +152,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
int length = block.length; int length = block.length;
byte[] bytes = new byte[length]; byte[] bytes = new byte[length];
// Extract bytes from MemoryBytes // Extract bytes from MemoryBytes
for (int i = 0; i < length; i++) for (int i : bytes)
bytes[i] = block[i].getValue(); bytes[i] = block[i].getValue();
return bytes; return bytes;
} }
@ -140,7 +168,10 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlock#setValue(long, byte[]) * @see org.eclipse.debug.core.model.IMemoryBlock#setValue(long, byte[])
*/ */
public void setValue(long offset, byte[] bytes) throws DebugException { public void setValue(long offset, byte[] bytes) throws DebugException {
setValue(BigInteger.valueOf(offset), bytes); if (offset <= Integer.MAX_VALUE)
writeMemoryBlock((int) offset, bytes);
// FRCH: Should we throw an exception if offset is too large?
} }
// //////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////
@ -158,13 +189,14 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBigBaseAddress() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBigBaseAddress()
*/ */
public BigInteger getBigBaseAddress() throws DebugException { public BigInteger getBigBaseAddress() throws DebugException {
return fBaseAddress; return fStartAddress;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockStartAddress() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockStartAddress()
*/ */
public BigInteger getMemoryBlockStartAddress() throws DebugException { public BigInteger getMemoryBlockStartAddress() throws DebugException {
// "null" indicates that memory can be retrieved at addresses lower than the block base address
return null; return null;
} }
@ -172,6 +204,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockEndAddress() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockEndAddress()
*/ */
public BigInteger getMemoryBlockEndAddress() throws DebugException { public BigInteger getMemoryBlockEndAddress() throws DebugException {
// "null" indicates that memory can be retrieved at addresses higher the block base address
return null; return null;
} }
@ -179,15 +212,15 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBigLength() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBigLength()
*/ */
public BigInteger getBigLength() throws DebugException { public BigInteger getBigLength() throws DebugException {
return null; // -1 indicates that memory block is unbounded
return BigInteger.ONE.negate();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressSize() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressSize()
*/ */
public int getAddressSize() throws DebugException { public int getAddressSize() throws DebugException {
// TODO: Have the service make a trip to the back-end and // FRCH: return fRetrieval.getDebugTarget().getAddressSize();
// retrieve/store that information for us
return 4; return 4;
} }
@ -195,14 +228,14 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportBaseAddressModification() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportBaseAddressModification()
*/ */
public boolean supportBaseAddressModification() throws DebugException { public boolean supportBaseAddressModification() throws DebugException {
return true; return false;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportsChangeManagement() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportsChangeManagement()
*/ */
public boolean supportsChangeManagement() { public boolean supportsChangeManagement() {
return true; return false;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -215,23 +248,29 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromOffset(java.math.BigInteger, long) * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromOffset(java.math.BigInteger, long)
*/ */
public MemoryByte[] getBytesFromOffset(BigInteger unitOffset, long addressableUnits) throws DebugException { public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
// TODO Auto-generated method stub return getBytesFromAddress(fStartAddress.add(offset), units);
return null;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromAddress(java.math.BigInteger, long) * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromAddress(java.math.BigInteger, long)
*/ */
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException { public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
return fetchMemoryBlock(address.longValue(), units); fLength = units;
fEndAddress = fStartAddress.add(BigInteger.valueOf(units));
return fetchMemoryBlock(address, units);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#setValue(java.math.BigInteger, byte[]) * @see org.eclipse.debug.core.model.IMemoryBlockExtension#setValue(java.math.BigInteger, byte[])
*/ */
public void setValue(BigInteger offset, byte[] bytes) throws DebugException { public void setValue(BigInteger offset, byte[] bytes) throws DebugException {
// TODO Auto-generated method stub // Ensure that the offset can be cast into an int
int offs = offset.intValue();
if (offset.equals(BigInteger.valueOf(offs)))
writeMemoryBlock(offs, bytes);
// FRCH: Should we throw an exception if offset is too large?
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -260,7 +299,15 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#dispose() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#dispose()
*/ */
public void dispose() throws DebugException { public void dispose() throws DebugException {
// TODO Auto-generated method stub try {
fRetrieval.getExecutor().execute(new Runnable() {
public void run() {
fRetrieval.getSession().removeServiceEventListener(DsfMemoryBlock.this);
}
});
} catch(RejectedExecutionException e) {
// Session is shut down.
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -274,8 +321,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressableSize() * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressableSize()
*/ */
public int getAddressableSize() throws DebugException { public int getAddressableSize() throws DebugException {
// TODO: Have the service make a trip to the back-end and // FRCH: return fRetrieval.getDebugTarget().getAddressableSize();
// retrieve/store that information for us
return 1; return 1;
} }
@ -283,25 +329,25 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
// Helper functions // Helper functions
// //////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////
/* The real thing. Since the original call is synchronous (from a platform Job), /*
* we use a Query that will patiently wait for the underlying asynchronous calls * The real thing. Since the original call is synchronous (from a platform
* to complete before returning. * Job), we use a Query that will patiently wait for the underlying
* * asynchronous calls to complete before returning.
* @param address *
* @param length * @param address @param length @return MemoryByte[] @throws DebugException
* @return MemoryBytes[] */
* @throws DebugException private MemoryByte[] fetchMemoryBlock(final BigInteger address, final long length) throws DebugException {
*/
private MemoryByte[] fetchMemoryBlock(final long address, final long length) throws DebugException {
/* For this first implementation, we make a few simplifying assumptions: /* FRCH: Fix the loose ends...
*
* For this first implementation, we make a few simplifying assumptions:
* - word_size = 1 (we want to read individual bytes) * - word_size = 1 (we want to read individual bytes)
* - offset = 0 * - offset = 0
* - mode = hexadecimal (will be overridden in getMemory() anyway) * - mode = 0 (will be overridden in getMemory() anyway)
*/ */
final int word_size = 1; final int word_size = 1;
final int offset = 0; final int offset = 0;
final int mode = 0; // TODO: Add a constant for hexadecimal mode final int mode = 0;
// Use a Query to "synchronize" the inherently asynchronous downstream calls // Use a Query to "synchronize" the inherently asynchronous downstream calls
Query<MemoryByte[]> query = new Query<MemoryByte[]>() { Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
@ -313,7 +359,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
final MemoryByte[] buffer = new MemoryByte[(int) length]; final MemoryByte[] buffer = new MemoryByte[(int) length];
// Go for it // Go for it
memoryService.getMemory( memoryService.getMemory(
fRetrieval.getContext(), new Addr32(address), word_size, buffer, offset, (int) length, mode, fRetrieval.getContext(), address, word_size, buffer, offset, (int) length, mode,
new RequestMonitor(fRetrieval.getExecutor(), rm) { new RequestMonitor(fRetrieval.getExecutor(), rm) {
@Override @Override
protected void handleOK() { protected void handleOK() {
@ -334,4 +380,53 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
return null; return null;
} }
@DsfServiceEventHandler
public void eventDispatched(MemoryChangedEvent e) {
handleMemoryChange(e.getAddress());
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
handleMemoryChange(BigInteger.ZERO);
}
/* Writes an array of bytes to memory.
*
* @param offset
* @param bytes
* @throws DebugException
*/
private void writeMemoryBlock(final int offset, final byte[] bytes) throws DebugException {
final int word_size = 1;
final int mode = 0;
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
if (memoryService != null) {
memoryService.setMemory(
fRetrieval.getContext(), fStartAddress, word_size, bytes, offset, bytes.length, mode,
new RequestMonitor(fRetrieval.getExecutor(), null) {
@Override
protected void handleOK() {
handleMemoryChange(fStartAddress);
}
});
}
}
/**
* @param address
* @param length
*/
public void handleMemoryChange(BigInteger address) {
// Check if the change affects this particular block (0 is universal)
if (address.equals(BigInteger.ZERO) ||
((fStartAddress.compareTo(address) != 1) && (fEndAddress.compareTo(address) == 1)))
{
// Notify the event listeners
DebugEvent debugEvent = new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT);
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { debugEvent });
}
}
} }

View file

@ -7,17 +7,32 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Ericsson Communication - upgrade IF from IMemoryBlockRetrieval to IMemoryBlockRetrievalExtension * Ericsson Communication - upgrade IF to IMemoryBlockRetrievalExtension
* Ericsson Communication - added Expression evaluation
* Ericsson Communication - added support for 64 bit processors
* Ericsson Communication - added support for event handling
*******************************************************************************/ *******************************************************************************/
package org.eclipse.dd.dsf.debug.model; package org.eclipse.dd.dsf.debug.model;
import java.math.BigInteger;
import java.util.concurrent.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfExecutor; import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.DsfDebugPlugin; import org.eclipse.dd.dsf.debug.DsfDebugPlugin;
import org.eclipse.dd.dsf.debug.service.IExpressions;
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
import org.eclipse.dd.dsf.debug.service.IMemory; import org.eclipse.dd.dsf.debug.service.IMemory;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugException;
@ -31,78 +46,102 @@ import org.osgi.util.tracker.ServiceTracker;
/** /**
* Implementation of memory access API of the Eclipse standard debug model. * Implementation of memory access API of the Eclipse standard debug model.
* *
* The IMemoryBlockRetrievalExtension is implemented for the reference * The DsfMemoryBlockRetrieval is not an actual memory block but rather a
* application. This will result in getExtendedMemoryBlock() being called * reference to the memory address space for an execution context (e.g. a
* when a memory block is selected from the memory pane. * process) within a debug session. From this debug 'context', memory blocks
* can then be read/written.
*
* Note: For the reference application, The IMemoryBlockRetrievalExtension
* is implemented. This will result in getExtendedMemoryBlock() being called
* when a memory block is selected from the platform memory pane.
* *
* However, if the 'simpler' IMemoryBlockRetrieval is to be implemented, the * However, if the 'simpler' IMemoryBlockRetrieval is to be implemented, the
* code will still be functional after trivial adjustments. In that case, the * code will still be functional after some trivial adjustments.
* platform will call getMemoryBlock() instead. Note that DsfMemoryBlock will
* have to be 'downgraded' to implement IMemoryBlock (instead of IMemoryBlockExtension)
* *
*/ */
public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBlockRetrievalExtension public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBlockRetrievalExtension
{ {
private final String fModelId; private final String fModelId;
private final DsfSession fSession; private final DsfSession fSession;
private final DsfExecutor fExecutor; private final DsfExecutor fExecutor;
private final IDMContext<?> fContext; private IDMContext<?> fContext;
private final ServiceTracker fServiceTracker; private final ServiceTracker fMemoryServiceTracker;
private final ServiceTracker fExpressionServiceTracker;
/**
* Constructor
*
* @param modelId
* @param dmc
* @throws DebugException
*/
public DsfMemoryBlockRetrieval(String modelId, IDMContext<?> dmc) throws DebugException {
fModelId = modelId;
fContext = dmc;
fSession = DsfSession.getSession(fContext.getSessionId());
if (fSession == null) {
throw new IllegalArgumentException("Session for context " + fContext + " is not active"); //$NON-NLS-1$ //$NON-NLS-2$
}
fExecutor = fSession.getExecutor();
String memoryServiceFilter =
"(&" + //$NON-NLS-1$
"(OBJECTCLASS=" + IMemory.class.getName() + ")" + //$NON-NLS-1$//$NON-NLS-2$
"(" + IDsfService.PROP_SESSION_ID + "=" + dmc.getSessionId() + ")" + //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
")"; //$NON-NLS-1$
BundleContext bundle = DsfDebugPlugin.getBundleContext();
try {
fServiceTracker = new ServiceTracker(bundle, bundle.createFilter(memoryServiceFilter), null);
} catch (InvalidSyntaxException e) {
throw new DebugException(new Status(IStatus.ERROR, DsfDebugPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Error creating service filter.", e)); //$NON-NLS-1$
}
fServiceTracker.open();
}
// ////////////////////////////////////////////////////////////////////////
// Accessors
// ////////////////////////////////////////////////////////////////////////
/** /**
* Constructor
* *
* @return * @param modelId
* @param dmc
* @throws DebugException
*/ */
public String getModelId() { public DsfMemoryBlockRetrieval(String modelId, IDMContext<?> dmc) throws DebugException {
return fModelId;
fModelId = modelId;
fContext = dmc;
fSession = DsfSession.getSession(fContext.getSessionId());
if (fSession == null) {
throw new IllegalArgumentException(
"Session for context " + fContext + " is not active"); //$NON-NLS-1$ //$NON-NLS-2$
}
fExecutor = fSession.getExecutor();
BundleContext bundle = DsfDebugPlugin.getBundleContext();
// Here we chose to use 2 distinct service trackers instead of an
// amalgamated one because it is less error prone (and we are lazy).
// Create a tracker for the MemoryService
String memoryServiceFilter = "(&" + //$NON-NLS-1$
"(OBJECTCLASS=" //$NON-NLS-1$
+ IMemory.class.getName()
+ ")" + //$NON-NLS-1$
"(" + IDsfService.PROP_SESSION_ID //$NON-NLS-1$
+ "=" + dmc.getSessionId() + ")" + //$NON-NLS-1$//$NON-NLS-2$
")"; //$NON-NLS-1$
try {
fMemoryServiceTracker = new ServiceTracker(
bundle, bundle.createFilter(memoryServiceFilter), null);
} catch (InvalidSyntaxException e) {
throw new DebugException(new Status(IStatus.ERROR,
DsfDebugPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR,
"Error creating service filter.", e)); //$NON-NLS-1$
}
fMemoryServiceTracker.open();
// Create a tracker for the ExpressionService
String expressionServiceFilter = "(&" + //$NON-NLS-1$
"(OBJECTCLASS=" //$NON-NLS-1$
+ IExpressions.class.getName()
+ ")" + //$NON-NLS-1$
"(" + IDsfService.PROP_SESSION_ID //$NON-NLS-1$
+ "=" + dmc.getSessionId() + ")" + //$NON-NLS-1$//$NON-NLS-2$
")"; //$NON-NLS-1$
try {
fExpressionServiceTracker = new ServiceTracker(
bundle, bundle.createFilter(expressionServiceFilter), null);
} catch (InvalidSyntaxException e) {
throw new DebugException(new Status(IStatus.ERROR,
DsfDebugPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR,
"Error creating service filter.", e)); //$NON-NLS-1$
}
fExpressionServiceTracker.open();
}
// ////////////////////////////////////////////////////////////////////////
// Accessors
// ////////////////////////////////////////////////////////////////////////
public DsfSession getSession() {
return fSession;
} }
/** /**
* *
* @return * @return
*/ */
public DsfSession getSession() { public DsfExecutor getExecutor() {
return fSession;
}
/**
*
* @return
*/
public DsfExecutor getExecutor() {
return fExecutor; return fExecutor;
} }
@ -110,121 +149,177 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
* *
* @return * @return
*/ */
public IDMContext<?> getContext() { public IDMContext<?> getContext() {
return fContext; return fContext;
} }
/** /**
* *
* @return * @return
*/ */
public ServiceTracker getServiceTracker() { public ServiceTracker getServiceTracker() {
return fServiceTracker; return fMemoryServiceTracker;
} }
// //////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////
// IMemoryBlockRetrieval - obsoleted by IMemoryBlockRetrievalExtension // IMemoryBlockRetrieval - obsoleted by IMemoryBlockRetrievalExtension
// //////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////
/* /*
* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
*/
public boolean supportsStorageRetrieval() {
return true;
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
*/
public IMemoryBlock getMemoryBlock(final long startAddress, final long length) throws DebugException {
// The expression to display in the rendering tab
// Put here for the sake of completeness (not used with IMemoryBlock)
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
return new DsfMemoryBlock(DsfMemoryBlockRetrieval.this, fModelId, expression, startAddress, length);
}
// ////////////////////////////////////////////////////////////////////////
// IMemoryBlockRetrievalExtension
// ////////////////////////////////////////////////////////////////////////
/*
* (non-Javadoc) * (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension#getExtendedMemoryBlock(java.lang.String, java.lang.Object) *
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
*/ */
public IMemoryBlockExtension getExtendedMemoryBlock(String expression, Object context) throws DebugException { public boolean supportsStorageRetrieval() {
return true;
}
boolean validAddress = false; /*
long address = 0; * (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long,
* long)
*/
public IMemoryBlock getMemoryBlock(final long startAddress, final long length) throws DebugException {
// The expression to display in the rendering tab
// Put here for the sake of completeness (not used with IMemoryBlockExtension)
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
return new DsfMemoryBlock(this, fModelId, expression, BigInteger.valueOf(startAddress), length);
}
/* See if the expression is a simple numeric value; if it is, we can // ////////////////////////////////////////////////////////////////////////
* avoid some costly processing (calling the back-end to resolve the // IMemoryBlockRetrievalExtension
* expression and obtain an address) // ////////////////////////////////////////////////////////////////////////
*/
try {
// First, assume a decimal address (not too realistic but bear with us :-)
int base = 10;
int offset = 0;
// Check for "hexadecimality" /*
if (expression.startsWith("0x") || expression.startsWith("0X")) { //$NON-NLS-1$//$NON-NLS-2$ * (non-Javadoc)
base = 16; *
offset = 2; * @see org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension#getExtendedMemoryBlock(java.lang.String,
} * java.lang.Object)
*/
@SuppressWarnings("unchecked")
public IMemoryBlockExtension getExtendedMemoryBlock(String expression, Object context) throws DebugException {
// Now, try to parse the expression. If a NumberFormatException is thrown, // The block start address (supports 64-bit processors)
// then it wasn't a simple numerical expression and we go to plan B BigInteger blockAddress;
address = Long.parseLong(expression.substring(offset), base);
// All right! We saved a trip to the back-end. /*
validAddress = true; * See if the expression is a simple numeric value; if it is, we can
* avoid some costly processing (calling the back-end to resolve the
* expression and obtain an address)
*/
try {
// First, assume a decimal address
int base = 10;
int offset = 0;
} catch (NumberFormatException nfexc) { // Check for "hexadecimality"
// OK, expression is not a simple, absolute numeric value; try to resolve as expression if (expression.startsWith("0x") || expression.startsWith("0X")) { //$NON-NLS-1$//$NON-NLS-2$
} base = 16;
offset = 2;
}
// Check for "octality"
else if (expression.startsWith("0")) { //$NON-NLS-1$
base = 8;
offset = 1;
}
// We have to ask the debugger to resolve the address for us // Now, try to parse the expression. If a NumberFormatException is
if (!validAddress) { // thrown, then it wasn't a simple numerical expression and we go
// [frch] Code removed until we properly hook the ExpressionService // to plan B (attempt an expression evaluation)
// [frch] Code saved in lmcfrch-memory-070625.PATCH blockAddress = new BigInteger(expression.substring(offset), base);
return null;
}
/* At this point, we only know the requested address and we have no } catch (NumberFormatException nfexc) {
* idea of the memory block length. The renderer will provide this // OK, expression is not a simple, absolute numeric value;
* information when it calls getBytesFromAddress() i.e. after the // try to resolve as an expression.
* memory block holder has been instantiated... // In case of failure, simply return 'null'
*
* We could try to out-smart the renderer and do some educated guess
* about the start address it will select and the length it will
* request.
*
* This would 'work' for the standard debug renderers: start address
* on a 16-byte boundary, length of 320 bytes (20 lines of 16 bytes).
* However, this is not such a great idea: a given renderer might ask
* for a block starting at any address adn length it sees fit. Therefore
* we can't make any assumption.
*
* The only safe approach is to just instantiate the IMemoryBlockExtension
* and postpone the actual memory fetch until the renderer explicitly
* asks for it (i.e. calls getBytesFromAddress()).
*
* The down side is that every time we switch renderer, for the same block,
* a trip to the target could result.
*
* However, we have an ace in our sleeve: the memory request cache should
* save us a trip to the back-end.
*/
return new DsfMemoryBlock(DsfMemoryBlockRetrieval.this, fModelId, expression, address, 0); // Drill for the actual DMC
} IDMContext<?> dmc = null;
if (context instanceof IAdaptable) {
dmc = (IDMContext<?>)((IAdaptable)context).getAdapter(IDMContext.class);
}
// //////////////////////////////////////////////////////////////////////// if (dmc == null) {
// Helper functions return null;
// //////////////////////////////////////////////////////////////////////// }
// Update the DMC
fContext = dmc;
// [frch] Code removed until we properly hook the ExpressionService // Resolve the expression
// [frch] Code saved in lmcfrch-memory-070625.PATCH blockAddress = resolveMemoryAddress(fContext, expression);
if (blockAddress == null)
return null;
}
/*
* At this point, we only resolved the requested memory block
* start address and we have no idea of the block's length.
*
* The renderer will provide this information when it calls
* getBytesFromAddress() i.e. after the memory block holder has
* been instantiated.
*
* The down side is that every time we switch renderer, for the
* same memory block, a trip to the target could result. However,
* the memory request cache should save the day.
*/
return new DsfMemoryBlock(this, fModelId, expression, blockAddress, 0);
}
// ////////////////////////////////////////////////////////////////////////
// Helper functions
// ////////////////////////////////////////////////////////////////////////
private BigInteger resolveMemoryAddress(final IDMContext<?> idmContext, final String expression) throws DebugException {
// Use a Query to "synchronize" the inherently asynchronous downstream calls
Query<BigInteger> query = new Query<BigInteger>() {
@Override
protected void execute(final DataRequestMonitor<BigInteger> rm) {
// Lookup for the ExpressionService
final IExpressions expressionService = (IExpressions) fExpressionServiceTracker.getService();
if (expressionService != null) {
// Create the expression
final IExpressionDMContext expressionDMC = expressionService.createExpression(idmContext, expression);
expressionService.getModelData(expressionDMC, new DataRequestMonitor<IExpressionDMData>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Evaluate the expression - request HEX since it works in every case
String formatId = IFormattedValues.HEX_FORMAT;
FormattedValueDMContext valueDmc = expressionService.getFormattedValue(expressionDMC, formatId);
expressionService.getModelData(
valueDmc,
new DataRequestMonitor<FormattedValueDMData>(getExecutor(), null) {
@Override
protected void handleOK() {
// Store the result
FormattedValueDMData data = getData();
if (data.isValid()) {
String value = data.getFormattedValue().substring(2); // Strip the "0x"
rm.setData(new BigInteger(value, 16));
}
rm.done();
}
}
);
}
});
}
}
};
fExecutor.execute(query);
try {
// The happy case
return query.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
// The error case
return null;
}
} }

View file

@ -8,10 +8,12 @@
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Ericsson Communication - extended the API for IMemoryBlockExtension * Ericsson Communication - extended the API for IMemoryBlockExtension
* Ericsson Communication - added support for 64 bit processors
*******************************************************************************/ *******************************************************************************/
package org.eclipse.dd.dsf.debug.service; package org.eclipse.dd.dsf.debug.service;
import org.eclipse.cdt.core.IAddress; import java.math.BigInteger;
import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.dsf.service.IDsfService;
@ -24,13 +26,26 @@ import org.eclipse.debug.core.model.MemoryByte;
*/ */
public interface IMemory extends IDsfService { public interface IMemory extends IDsfService {
/** Writes the given value to the given memory location. */ public class MemoryChangedEvent {
public void setMemory(IDMContext<?> ctx, IAddress addr, BigInteger fAddress;
int word_size, byte[] buf, int offs, int size, int mode, RequestMonitor requestMonitor);
public MemoryChangedEvent(BigInteger address) {
fAddress = address;
}
public BigInteger getAddress() {
return fAddress;
}
}
/** Reads memory at the given location */ /** Reads memory at the given location */
public void getMemory(IDMContext<?> ctx, IAddress addr, public void getMemory(IDMContext<?> ctx, BigInteger addr,
int word_size, byte[] buf, int offs, int size, int mode, RequestMonitor requestMonitor); int word_size, MemoryByte[] buf, int offs, int size, int mode, RequestMonitor rm);
/** Writes the given value to the given memory location. */
public void setMemory(IDMContext<?> ctx, BigInteger addr,
int word_size, byte[] buf, int offs, int size, int mode, RequestMonitor rm);
/** /**
* Fill target memory with given pattern. * Fill target memory with given pattern.
@ -38,25 +53,7 @@ public interface IMemory extends IDsfService {
* Parameter 0 of sequent 'done' is assigned with Throwable if * Parameter 0 of sequent 'done' is assigned with Throwable if
* there was an error. * there was an error.
*/ */
public void fillMemory(IDMContext<?> ctx, IAddress addr, public void fillMemory(IDMContext<?> ctx, BigInteger addr,
int word_size, byte[] value, int size, int mode, RequestMonitor requestMonitor); int word_size, byte[] value, int size, int mode, RequestMonitor rm);
// ////////////////////////////////////////////////////////////////////////
// Replicated the base functions to support IMemoryBlockExtension
// ////////////////////////////////////////////////////////////////////////
/** Writes the given value to the given memory location. */
public void setMemory(IDMContext<?> ctx, IAddress addr,
int word_size, MemoryByte[] buf, int offs, int size, int mode, RequestMonitor requestMonitor);
/** Reads memory at the given location */
public void getMemory(IDMContext<?> ctx, IAddress addr,
int word_size, MemoryByte[] buf, int offs, int size, int mode, RequestMonitor requestMonitor);
public void fillMemory(IDMContext<?> ctx, IAddress addr,
int word_size, MemoryByte[] value, int size, int mode, RequestMonitor requestMonitor);
// /** Reads memory at the given location */
// public void resolveMemoryAddress(IDMContext<?> ctx, String expression, BigInteger[] address, RequestMonitor requestMonitor);
} }