1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Update of the Memory Service. Includes JUnit test suite.

This commit is contained in:
Francois Chouinard 2007-10-01 21:06:54 +00:00
parent 167b797c27
commit 441f6bc65b
3 changed files with 205 additions and 127 deletions

View file

@ -13,9 +13,11 @@
package org.eclipse.dd.dsf.debug.model;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.Query;
@ -41,28 +43,34 @@ import org.eclipse.debug.core.model.MemoryByte;
*/
public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtension
{
private final ILaunch fLaunch;
private final IDebugTarget fDebugTarget;
private final DsfMemoryBlockRetrieval fRetrieval;
private final String fModelId;
private final String fExpression;
private final BigInteger fStartAddress;
private BigInteger fEndAddress;
private long fLength = 0;
protected BigInteger fBaseAddress;
protected long fLength;
private ArrayList<Object> fConnections = new ArrayList<Object>();
private boolean isEnabled;
/**
* Constructor.
*
* @param retrieval - the MemoryBlockRetrieval (session context)
* @param modelId -
* @param expression - the displayed expression
* @param startAddress - the actual memory block start address
* @param expression - the displayed expression in the UI
* @param address - the actual memory block start address
* @param length - the memory block length (could be 0)
*/
DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, BigInteger startAddress, long length) {
DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, BigInteger address, long length) {
fLaunch = null; // TODO: fRetrieval.getLaunch();
fDebugTarget = null; // TODO: fRetrieval.getDebugTarget();
fRetrieval = retrieval;
fModelId = modelId;
fExpression = expression;
fStartAddress = startAddress;
fEndAddress = startAddress.add(BigInteger.valueOf(length));
fBaseAddress = address;
fLength = length;
try {
@ -100,8 +108,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
*/
public IDebugTarget getDebugTarget() {
// FRCH: return fRetrieval.getDebugTarget();
return null;
return fDebugTarget;
}
/* (non-Javadoc)
@ -115,8 +122,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
*/
public ILaunch getLaunch() {
// FRCH: return fRetrieval.getDebugTarget().getLaunch();
return null;
return fLaunch;
}
// ////////////////////////////////////////////////////////////////////////
@ -127,12 +133,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlock#getStartAddress()
*/
public long getStartAddress() {
// 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?
// Not implemented (obsolete)
return 0;
}
@ -140,27 +141,23 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlock#getLength()
*/
public long getLength() {
// Warning: could return 0
return fLength;
// Not implemented (obsolete)
return 0;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlock#getBytes()
*/
public byte[] getBytes() throws DebugException {
MemoryByte[] block = fetchMemoryBlock(fStartAddress, fLength);
int length = block.length;
byte[] bytes = new byte[length];
// Extract bytes from MemoryBytes
for (int i : bytes)
bytes[i] = block[i].getValue();
return bytes;
// Not implemented (obsolete)
return new byte[0];
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlock#supportsValueModification()
*/
public boolean supportsValueModification() {
// return fDebugTarget.supportsValueModification(this);
return true;
}
@ -168,10 +165,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlock#setValue(long, byte[])
*/
public void setValue(long offset, byte[] bytes) throws DebugException {
if (offset <= Integer.MAX_VALUE)
writeMemoryBlock((int) offset, bytes);
// FRCH: Should we throw an exception if offset is too large?
// Not implemented (obsolete)
}
// ////////////////////////////////////////////////////////////////////////
@ -189,14 +183,14 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBigBaseAddress()
*/
public BigInteger getBigBaseAddress() throws DebugException {
return fStartAddress;
return fBaseAddress;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockStartAddress()
*/
public BigInteger getMemoryBlockStartAddress() throws DebugException {
// "null" indicates that memory can be retrieved at addresses lower than the block base address
// Null indicates that memory can be retrieved at addresses lower than the block base address
return null;
}
@ -204,7 +198,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getMemoryBlockEndAddress()
*/
public BigInteger getMemoryBlockEndAddress() throws DebugException {
// "null" indicates that memory can be retrieved at addresses higher the block base address
// Null indicates that memory can be retrieved at addresses higher the block base address
return null;
}
@ -213,14 +207,19 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
*/
public BigInteger getBigLength() throws DebugException {
// -1 indicates that memory block is unbounded
return BigInteger.ONE.negate();
return BigInteger.valueOf(-1);
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressSize()
*/
public int getAddressSize() throws DebugException {
// FRCH: return fRetrieval.getDebugTarget().getAddressSize();
// // TODO:
// try {
// return fDebugTarget.getAddressSize();
// } catch (CoreException e) {
// throw new DebugException(e.getStatus());
// }
return 4;
}
@ -228,6 +227,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportBaseAddressModification()
*/
public boolean supportBaseAddressModification() throws DebugException {
// TODO: return fDebugTarget.supportBaseAddressModification(this);
return false;
}
@ -235,6 +235,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportsChangeManagement()
*/
public boolean supportsChangeManagement() {
// Let the UI handle block content modification
return false;
}
@ -242,14 +243,14 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#setBaseAddress(java.math.BigInteger)
*/
public void setBaseAddress(BigInteger address) throws DebugException {
// TODO Auto-generated method stub
fBaseAddress = address;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromOffset(java.math.BigInteger, long)
*/
public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
return getBytesFromAddress(fStartAddress.add(offset), units);
return getBytesFromAddress(fBaseAddress.add(offset), units);
}
/* (non-Javadoc)
@ -257,42 +258,50 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
*/
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
fLength = units;
fEndAddress = fStartAddress.add(BigInteger.valueOf(units));
return fetchMemoryBlock(address, units);
MemoryByte[] block = fetchMemoryBlock(address, units);
return block;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#setValue(java.math.BigInteger, byte[])
*/
public void setValue(BigInteger offset, byte[] bytes) throws DebugException {
// 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?
writeMemoryBlock(offset.longValue(), bytes);
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#connect(java.lang.Object)
*/
public void connect(Object client) {
// TODO Auto-generated method stub
if (!fConnections.contains(client))
fConnections.add(client);
if (fConnections.size() == 1)
enable();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#disconnect(java.lang.Object)
*/
public void disconnect(Object client) {
// TODO Auto-generated method stub
if (fConnections.contains(client))
fConnections.remove(client);
if (fConnections.size() == 0)
disable();
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getConnections()
*/
public Object[] getConnections() {
// TODO Auto-generated method stub
return new Object[0];
return fConnections.toArray();
}
private void enable() {
isEnabled = true;
}
private void disable() {
isEnabled = false;
}
/* (non-Javadoc)
@ -321,7 +330,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getAddressableSize()
*/
public int getAddressableSize() throws DebugException {
// FRCH: return fRetrieval.getDebugTarget().getAddressableSize();
// TODO: return fDebugTarget.getAddressableSize();
return 1;
}
@ -334,20 +343,16 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* Job), we use a Query that will patiently wait for the underlying
* asynchronous calls to complete before returning.
*
* @param address @param length @return MemoryByte[] @throws DebugException
* @param bigAddress
* @param length
* @return MemoryByte[]
* @throws DebugException
*/
private MemoryByte[] fetchMemoryBlock(final BigInteger address, final long length) throws DebugException {
private MemoryByte[] fetchMemoryBlock(BigInteger bigAddress, final long length) throws DebugException {
/* FRCH: Fix the loose ends...
*
* For this first implementation, we make a few simplifying assumptions:
* - word_size = 1 (we want to read individual bytes)
* - offset = 0
* - mode = 0 (will be overridden in getMemory() anyway)
*/
// For the IAddress interface
final Addr64 address = new Addr64(bigAddress);
final int word_size = 1;
final int offset = 0;
final int mode = 0;
// Use a Query to "synchronize" the inherently asynchronous downstream calls
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
@ -355,15 +360,13 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
protected void execute(final DataRequestMonitor<MemoryByte[]> rm) {
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
if (memoryService != null) {
// Place holder for the result
final MemoryByte[] buffer = new MemoryByte[(int) length];
// Go for it
memoryService.getMemory(
fRetrieval.getContext(), address, word_size, buffer, offset, (int) length, mode,
new RequestMonitor(fRetrieval.getExecutor(), rm) {
fRetrieval.getContext(), address, 0, word_size, (int) length,
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(buffer);
rm.setData(getData());
rm.done();
}
});
@ -377,12 +380,13 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
@DsfServiceEventHandler
public void eventDispatched(MemoryChangedEvent e) {
handleMemoryChange(e.getAddress());
handleMemoryChange(e.getAddress().getValue());
}
@DsfServiceEventHandler
@ -396,19 +400,24 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @param bytes
* @throws DebugException
*/
private void writeMemoryBlock(final int offset, final byte[] bytes) throws DebugException {
private void writeMemoryBlock(final long offset, final byte[] bytes) throws DebugException {
// For the IAddress interface
final Addr64 address = new Addr64(fBaseAddress);
final int word_size = 1;
final int mode = 0;
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
final IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
if (memoryService != null) {
memoryService.getExecutor().execute(new Runnable() {
public void run() {
memoryService.setMemory(
fRetrieval.getContext(), fStartAddress, word_size, bytes, offset, bytes.length, mode,
fRetrieval.getContext(), address, offset, word_size, bytes.length, bytes,
new RequestMonitor(fRetrieval.getExecutor(), null) {
@Override
protected void handleOK() {
handleMemoryChange(fStartAddress);
// handleMemoryChange(fBaseAddress);
}
});
}
});
}
@ -420,8 +429,9 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
*/
public void handleMemoryChange(BigInteger address) {
// Check if the change affects this particular block (0 is universal)
BigInteger fEndAddress = fBaseAddress.add(BigInteger.valueOf(fLength));
if (address.equals(BigInteger.ZERO) ||
((fStartAddress.compareTo(address) != 1) && (fEndAddress.compareTo(address) == 1)))
((fBaseAddress.compareTo(address) != 1) && (fEndAddress.compareTo(address) == 1)))
{
// Notify the event listeners
DebugEvent debugEvent = new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT);

View file

@ -181,7 +181,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
* long)
*/
public IMemoryBlock getMemoryBlock(final long startAddress, final long length) throws DebugException {
// The expression to display in the rendering tab
// The expression to display in the rendering tab (in hex by convention)
// 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);
@ -240,6 +240,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
dmc = (IDMContext<?>)((IAdaptable)context).getAdapter(IDMContext.class);
}
// TODO: throw an exception
if (dmc == null) {
return null;
}
@ -249,6 +250,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
// Resolve the expression
blockAddress = resolveMemoryAddress(fContext, expression);
if (blockAddress == null)
// TODO: throw an exception
return null;
}
@ -277,13 +279,13 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
// Use a Query to "synchronize" the inherently asynchronous downstream calls
Query<BigInteger> query = new Query<BigInteger>() {
@Override
protected void execute(final DataRequestMonitor<BigInteger> rm) {
protected void execute(final DataRequestMonitor<BigInteger> drm) {
// 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) {
expressionService.getModelData(expressionDMC, new DataRequestMonitor<IExpressionDMData>(getExecutor(), drm) {
@Override
protected void handleOK() {
// Evaluate the expression - request HEX since it works in every case
@ -298,9 +300,9 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
FormattedValueDMData data = getData();
if (data.isValid()) {
String value = data.getFormattedValue().substring(2); // Strip the "0x"
rm.setData(new BigInteger(value, 16));
drm.setData(new BigInteger(value, 16));
}
rm.done();
drm.done();
}
}
);
@ -315,7 +317,9 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
// The happy case
return query.get();
} catch (InterruptedException e) {
// TODO: throw an exception
} catch (ExecutionException e) {
// TODO: throw an exception
}
// The error case

View file

@ -7,13 +7,13 @@
*
* Contributors:
* Wind River Systems - initial API and implementation
* Ericsson Communication - extended the API for IMemoryBlockExtension
* Ericsson Communication - added support for 64 bit processors
* Ericsson AB - extended the API for IMemoryBlockExtension
* Ericsson AB - added support for 64 bit processors
*******************************************************************************/
package org.eclipse.dd.dsf.debug.service;
import java.math.BigInteger;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.service.IDsfService;
@ -26,34 +26,98 @@ import org.eclipse.debug.core.model.MemoryByte;
*/
public interface IMemory extends IDsfService {
/**
* Event generated every time a byte is modified.
*
* A client wishing to receive such events has to register as a service
* event listener and implement the corresponding dispatchEvent method.
*
* E.g.:
*
* MyMemoryBlock(MIRunControl fRunControl)
* {
* ...
* fRunControl.getSession().addServiceEventListener(MyMemoryBlock.this, null);
* ...
* }
*
* @DsfServiceEventHandler
* public void eventDispatched(MemoryChangedEvent e) {
* IAddress address = e.getAddress();
* // do whatever...
* }
*/
public class MemoryChangedEvent {
BigInteger fAddress;
IAddress fAddress;
public MemoryChangedEvent(BigInteger address) {
public MemoryChangedEvent(IAddress address) {
fAddress = address;
}
public BigInteger getAddress() {
public IAddress getAddress() {
return fAddress;
}
}
/** Reads memory at the given location */
public void getMemory(IDMContext<?> ctx, BigInteger addr,
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);
/**
* Reads a memory block from the target.
*
* An asynchronous memory read request at [address] + [offset] for
* [count] memory items, each of size [word_size] bytes, will be
* issued to the target. The result will be stored in [drm] upon
* completion of the call.
*
* The [drm] result buffer will be of size [word_size] * [count]. The
* successfully read bytes will have their MemoryByte.READABLE flag
* set while the bytes in error (unreachable/bad memory) will have their
* flag byte set to 0. The bytes will respect the target "endianness".
*
* @param context the context of the target memory block
* @param address the memory block address (on the target)
* @param offset the offset from the start address
* @param word_size the size, in bytes, of an addressable item
* @param count the number of data elements to read
* @param drm the asynchronous data request monitor
*/
public void getMemory(IDMContext<?> context, IAddress address, long offset,
int word_size, int count, DataRequestMonitor<MemoryByte[]> drm);
/**
* Fill target memory with given pattern.
* 'size' is number of bytes to fill.
* Parameter 0 of sequent 'done' is assigned with Throwable if
* there was an error.
* Writes a memory block on the target.
*
* An asynchronous memory write request at [address] + [offset] for
* [count] * [word_size] bytes will be issued to the target.
*
* The [buffer] must hold at least [count] * [word_size] bytes.
*
* A MemoryChangedEvent will be generated for the range of addresses.
*
* @param context the context of the target memory block
* @param address the memory block address (on the target)
* @param offset the offset from the start address
* @param word_size the size, in bytes, of an addressable item
* @param count the number of data elements to write
* @param buffer the source buffer
* @param rm the asynchronous data request monitor
*/
public void fillMemory(IDMContext<?> ctx, BigInteger addr,
int word_size, byte[] value, int size, int mode, RequestMonitor rm);
public void setMemory(IDMContext<?> context, IAddress address, long offset,
int word_size, int count, byte[] buffer, RequestMonitor rm);
/**
* Writes [pattern] at memory [address] + [offset], [count] times.
*
* A MemoryChangedEvent will be generated for the range of addresses.
*
* @param context the context of the target memory block
* @param address the memory block address (on the target)
* @param offset the offset from the start address
* @param word_size the size, in bytes, of an addressable item
* @param count the number of data elements to write
* @param pattern the offset in the result buffer
* @param buffer the source buffer
* @param rm the asynchronous data request monitor
*/
public void fillMemory(IDMContext<?> context, IAddress address, long offset,
int word_size, int count, byte[] pattern, RequestMonitor rm);
}