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:
parent
8a30df00b7
commit
582657cf05
3 changed files with 422 additions and 235 deletions
|
@ -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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue