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:
parent
167b797c27
commit
441f6bc65b
3 changed files with 205 additions and 127 deletions
|
@ -13,9 +13,11 @@
|
||||||
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.ArrayList;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.utils.Addr64;
|
||||||
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;
|
||||||
|
@ -41,29 +43,35 @@ import org.eclipse.debug.core.model.MemoryByte;
|
||||||
*/
|
*/
|
||||||
public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtension
|
public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtension
|
||||||
{
|
{
|
||||||
|
private final ILaunch fLaunch;
|
||||||
|
private final IDebugTarget fDebugTarget;
|
||||||
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 BigInteger fStartAddress;
|
protected BigInteger fBaseAddress;
|
||||||
private BigInteger fEndAddress;
|
protected long fLength;
|
||||||
private long fLength = 0;
|
|
||||||
|
private ArrayList<Object> fConnections = new ArrayList<Object>();
|
||||||
|
private boolean isEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param retrieval - the MemoryBlockRetrieval (session context)
|
* @param retrieval - the MemoryBlockRetrieval (session context)
|
||||||
* @param modelId -
|
* @param modelId -
|
||||||
* @param expression - the displayed expression
|
* @param expression - the displayed expression in the UI
|
||||||
* @param startAddress - the actual memory block start address
|
* @param address - the actual memory block start address
|
||||||
* @param length - the memory block length (could be 0)
|
* @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) {
|
||||||
fRetrieval = retrieval;
|
|
||||||
fModelId = modelId;
|
fLaunch = null; // TODO: fRetrieval.getLaunch();
|
||||||
fExpression = expression;
|
fDebugTarget = null; // TODO: fRetrieval.getDebugTarget();
|
||||||
fStartAddress = startAddress;
|
fRetrieval = retrieval;
|
||||||
fEndAddress = startAddress.add(BigInteger.valueOf(length));
|
fModelId = modelId;
|
||||||
fLength = length;
|
fExpression = expression;
|
||||||
|
fBaseAddress = address;
|
||||||
|
fLength = length;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fRetrieval.getExecutor().execute(new Runnable() {
|
fRetrieval.getExecutor().execute(new Runnable() {
|
||||||
|
@ -71,7 +79,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
fRetrieval.getSession().addServiceEventListener(DsfMemoryBlock.this, null);
|
fRetrieval.getSession().addServiceEventListener(DsfMemoryBlock.this, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
// Session is shut down.
|
// Session is shut down.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,8 +108,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 fDebugTarget;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -115,8 +122,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 fLaunch;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -127,12 +133,7 @@ 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() {
|
||||||
// Warning: doesn't support 64-bit addresses
|
// Not implemented (obsolete)
|
||||||
long address = fStartAddress.longValue();
|
|
||||||
if (fStartAddress.equals(BigInteger.valueOf(address)))
|
|
||||||
return address;
|
|
||||||
|
|
||||||
// FRCH: Should we throw an exception instead?
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,38 +141,31 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* @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
|
// Not implemented (obsolete)
|
||||||
return fLength;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlock#getBytes()
|
* @see org.eclipse.debug.core.model.IMemoryBlock#getBytes()
|
||||||
*/
|
*/
|
||||||
public byte[] getBytes() throws DebugException {
|
public byte[] getBytes() throws DebugException {
|
||||||
MemoryByte[] block = fetchMemoryBlock(fStartAddress, fLength);
|
// Not implemented (obsolete)
|
||||||
int length = block.length;
|
return new byte[0];
|
||||||
byte[] bytes = new byte[length];
|
|
||||||
// Extract bytes from MemoryBytes
|
|
||||||
for (int i : bytes)
|
|
||||||
bytes[i] = block[i].getValue();
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlock#supportsValueModification()
|
* @see org.eclipse.debug.core.model.IMemoryBlock#supportsValueModification()
|
||||||
*/
|
*/
|
||||||
public boolean supportsValueModification() {
|
public boolean supportsValueModification() {
|
||||||
return true;
|
// return fDebugTarget.supportsValueModification(this);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @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 {
|
||||||
if (offset <= Integer.MAX_VALUE)
|
// Not implemented (obsolete)
|
||||||
writeMemoryBlock((int) offset, bytes);
|
|
||||||
|
|
||||||
// FRCH: Should we throw an exception if offset is too large?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -189,14 +183,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 fStartAddress;
|
return fBaseAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (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
|
// Null indicates that memory can be retrieved at addresses lower than the block base address
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +198,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
|
// Null indicates that memory can be retrieved at addresses higher the block base address
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,14 +207,19 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
*/
|
*/
|
||||||
public BigInteger getBigLength() throws DebugException {
|
public BigInteger getBigLength() throws DebugException {
|
||||||
// -1 indicates that memory block is unbounded
|
// -1 indicates that memory block is unbounded
|
||||||
return BigInteger.ONE.negate();
|
return BigInteger.valueOf(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (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 {
|
||||||
// FRCH: return fRetrieval.getDebugTarget().getAddressSize();
|
// // TODO:
|
||||||
|
// try {
|
||||||
|
// return fDebugTarget.getAddressSize();
|
||||||
|
// } catch (CoreException e) {
|
||||||
|
// throw new DebugException(e.getStatus());
|
||||||
|
// }
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +227,7 @@ 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 {
|
||||||
|
// TODO: return fDebugTarget.supportBaseAddressModification(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportsChangeManagement()
|
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#supportsChangeManagement()
|
||||||
*/
|
*/
|
||||||
public boolean supportsChangeManagement() {
|
public boolean supportsChangeManagement() {
|
||||||
|
// Let the UI handle block content modification
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,14 +243,14 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#setBaseAddress(java.math.BigInteger)
|
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#setBaseAddress(java.math.BigInteger)
|
||||||
*/
|
*/
|
||||||
public void setBaseAddress(BigInteger address) throws DebugException {
|
public void setBaseAddress(BigInteger address) throws DebugException {
|
||||||
// TODO Auto-generated method stub
|
fBaseAddress = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (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 offset, long units) throws DebugException {
|
public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
|
||||||
return getBytesFromAddress(fStartAddress.add(offset), units);
|
return getBytesFromAddress(fBaseAddress.add(offset), units);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -257,42 +258,50 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
*/
|
*/
|
||||||
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
|
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
|
||||||
fLength = units;
|
fLength = units;
|
||||||
fEndAddress = fStartAddress.add(BigInteger.valueOf(units));
|
MemoryByte[] block = fetchMemoryBlock(address, units);
|
||||||
return fetchMemoryBlock(address, units);
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (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 {
|
||||||
// Ensure that the offset can be cast into an int
|
writeMemoryBlock(offset.longValue(), bytes);
|
||||||
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)
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#connect(java.lang.Object)
|
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#connect(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
public void connect(Object client) {
|
public void connect(Object client) {
|
||||||
// TODO Auto-generated method stub
|
if (!fConnections.contains(client))
|
||||||
|
fConnections.add(client);
|
||||||
|
if (fConnections.size() == 1)
|
||||||
|
enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#disconnect(java.lang.Object)
|
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#disconnect(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
public void disconnect(Object client) {
|
public void disconnect(Object client) {
|
||||||
// TODO Auto-generated method stub
|
if (fConnections.contains(client))
|
||||||
|
fConnections.remove(client);
|
||||||
|
if (fConnections.size() == 0)
|
||||||
|
disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getConnections()
|
* @see org.eclipse.debug.core.model.IMemoryBlockExtension#getConnections()
|
||||||
*/
|
*/
|
||||||
public Object[] getConnections() {
|
public Object[] getConnections() {
|
||||||
// TODO Auto-generated method stub
|
return fConnections.toArray();
|
||||||
return new Object[0];
|
}
|
||||||
|
|
||||||
|
private void enable() {
|
||||||
|
isEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disable() {
|
||||||
|
isEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -305,7 +314,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
fRetrieval.getSession().removeServiceEventListener(DsfMemoryBlock.this);
|
fRetrieval.getSession().removeServiceEventListener(DsfMemoryBlock.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch(RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
// Session is shut down.
|
// Session is shut down.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,7 +330,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 {
|
||||||
// FRCH: return fRetrieval.getDebugTarget().getAddressableSize();
|
// TODO: return fDebugTarget.getAddressableSize();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,55 +343,50 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* Job), we use a Query that will patiently wait for the underlying
|
* Job), we use a Query that will patiently wait for the underlying
|
||||||
* asynchronous calls to complete before returning.
|
* 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 the IAddress interface
|
||||||
*
|
final Addr64 address = new Addr64(bigAddress);
|
||||||
* 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)
|
|
||||||
*/
|
|
||||||
final int word_size = 1;
|
final int word_size = 1;
|
||||||
final int offset = 0;
|
|
||||||
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[]>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(final DataRequestMonitor<MemoryByte[]> rm) {
|
protected void execute(final DataRequestMonitor<MemoryByte[]> rm) {
|
||||||
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
|
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
|
||||||
if (memoryService != null) {
|
if (memoryService != null) {
|
||||||
// Place holder for the result
|
|
||||||
final MemoryByte[] buffer = new MemoryByte[(int) length];
|
|
||||||
// Go for it
|
// Go for it
|
||||||
memoryService.getMemory(
|
memoryService.getMemory(
|
||||||
fRetrieval.getContext(), address, word_size, buffer, offset, (int) length, mode,
|
fRetrieval.getContext(), address, 0, word_size, (int) length,
|
||||||
new RequestMonitor(fRetrieval.getExecutor(), rm) {
|
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleOK() {
|
protected void handleOK() {
|
||||||
rm.setData(buffer);
|
rm.setData(getData());
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fRetrieval.getExecutor().execute(query);
|
fRetrieval.getExecutor().execute(query);
|
||||||
try {
|
try {
|
||||||
return query.get();
|
return query.get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(MemoryChangedEvent e) {
|
public void eventDispatched(MemoryChangedEvent e) {
|
||||||
handleMemoryChange(e.getAddress());
|
handleMemoryChange(e.getAddress().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
|
@ -396,32 +400,38 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* @param bytes
|
* @param bytes
|
||||||
* @throws DebugException
|
* @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 word_size = 1;
|
||||||
final int mode = 0;
|
|
||||||
|
|
||||||
IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
|
final IMemory memoryService = (IMemory) fRetrieval.getServiceTracker().getService();
|
||||||
if (memoryService != null) {
|
if (memoryService != null) {
|
||||||
memoryService.setMemory(
|
memoryService.getExecutor().execute(new Runnable() {
|
||||||
fRetrieval.getContext(), fStartAddress, word_size, bytes, offset, bytes.length, mode,
|
public void run() {
|
||||||
new RequestMonitor(fRetrieval.getExecutor(), null) {
|
memoryService.setMemory(
|
||||||
@Override
|
fRetrieval.getContext(), address, offset, word_size, bytes.length, bytes,
|
||||||
protected void handleOK() {
|
new RequestMonitor(fRetrieval.getExecutor(), null) {
|
||||||
handleMemoryChange(fStartAddress);
|
@Override
|
||||||
}
|
protected void handleOK() {
|
||||||
});
|
// handleMemoryChange(fBaseAddress);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param address
|
* @param address
|
||||||
* @param length
|
* @param length
|
||||||
*/
|
*/
|
||||||
public void handleMemoryChange(BigInteger address) {
|
public void handleMemoryChange(BigInteger address) {
|
||||||
// Check if the change affects this particular block (0 is universal)
|
// Check if the change affects this particular block (0 is universal)
|
||||||
|
BigInteger fEndAddress = fBaseAddress.add(BigInteger.valueOf(fLength));
|
||||||
if (address.equals(BigInteger.ZERO) ||
|
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
|
// Notify the event listeners
|
||||||
DebugEvent debugEvent = new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT);
|
DebugEvent debugEvent = new DebugEvent(this, DebugEvent.CHANGE, DebugEvent.CONTENT);
|
||||||
|
|
|
@ -181,7 +181,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
* long)
|
* long)
|
||||||
*/
|
*/
|
||||||
public IMemoryBlock getMemoryBlock(final long startAddress, final long length) throws DebugException {
|
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)
|
// Put here for the sake of completeness (not used with IMemoryBlockExtension)
|
||||||
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
|
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
|
||||||
return new DsfMemoryBlock(this, fModelId, expression, BigInteger.valueOf(startAddress), length);
|
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);
|
dmc = (IDMContext<?>)((IAdaptable)context).getAdapter(IDMContext.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: throw an exception
|
||||||
if (dmc == null) {
|
if (dmc == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +250,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
// Resolve the expression
|
// Resolve the expression
|
||||||
blockAddress = resolveMemoryAddress(fContext, expression);
|
blockAddress = resolveMemoryAddress(fContext, expression);
|
||||||
if (blockAddress == null)
|
if (blockAddress == null)
|
||||||
|
// TODO: throw an exception
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,13 +279,13 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
// Use a Query to "synchronize" the inherently asynchronous downstream calls
|
// Use a Query to "synchronize" the inherently asynchronous downstream calls
|
||||||
Query<BigInteger> query = new Query<BigInteger>() {
|
Query<BigInteger> query = new Query<BigInteger>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(final DataRequestMonitor<BigInteger> rm) {
|
protected void execute(final DataRequestMonitor<BigInteger> drm) {
|
||||||
// Lookup for the ExpressionService
|
// Lookup for the ExpressionService
|
||||||
final IExpressions expressionService = (IExpressions) fExpressionServiceTracker.getService();
|
final IExpressions expressionService = (IExpressions) fExpressionServiceTracker.getService();
|
||||||
if (expressionService != null) {
|
if (expressionService != null) {
|
||||||
// Create the expression
|
// Create the expression
|
||||||
final IExpressionDMContext expressionDMC = expressionService.createExpression(idmContext, 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
|
@Override
|
||||||
protected void handleOK() {
|
protected void handleOK() {
|
||||||
// Evaluate the expression - request HEX since it works in every case
|
// 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();
|
FormattedValueDMData data = getData();
|
||||||
if (data.isValid()) {
|
if (data.isValid()) {
|
||||||
String value = data.getFormattedValue().substring(2); // Strip the "0x"
|
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
|
// The happy case
|
||||||
return query.get();
|
return query.get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
// TODO: throw an exception
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
|
// TODO: throw an exception
|
||||||
}
|
}
|
||||||
|
|
||||||
// The error case
|
// The error case
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
* Ericsson Communication - extended the API for IMemoryBlockExtension
|
* Ericsson AB - extended the API for IMemoryBlockExtension
|
||||||
* Ericsson Communication - added support for 64 bit processors
|
* Ericsson AB - added support for 64 bit processors
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.dd.dsf.debug.service;
|
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.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;
|
||||||
|
@ -25,35 +25,99 @@ import org.eclipse.debug.core.model.MemoryByte;
|
||||||
* IDMService interface.
|
* IDMService interface.
|
||||||
*/
|
*/
|
||||||
public interface IMemory extends IDsfService {
|
public interface IMemory extends IDsfService {
|
||||||
|
|
||||||
public class MemoryChangedEvent {
|
|
||||||
BigInteger fAddress;
|
|
||||||
|
|
||||||
public MemoryChangedEvent(BigInteger address) {
|
/**
|
||||||
|
* 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 {
|
||||||
|
IAddress fAddress;
|
||||||
|
|
||||||
|
public MemoryChangedEvent(IAddress address) {
|
||||||
fAddress = address;
|
fAddress = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger getAddress() {
|
public IAddress getAddress() {
|
||||||
return fAddress;
|
return fAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/** Reads memory at the given location */
|
* Reads a memory block from the target.
|
||||||
public void getMemory(IDMContext<?> ctx, BigInteger addr,
|
*
|
||||||
int word_size, MemoryByte[] buf, int offs, int size, int mode, RequestMonitor rm);
|
* An asynchronous memory read request at [address] + [offset] for
|
||||||
|
* [count] memory items, each of size [word_size] bytes, will be
|
||||||
/** Writes the given value to the given memory location. */
|
* issued to the target. The result will be stored in [drm] upon
|
||||||
public void setMemory(IDMContext<?> ctx, BigInteger addr,
|
* completion of the call.
|
||||||
int word_size, byte[] buf, int offs, int size, int mode, RequestMonitor rm);
|
*
|
||||||
|
* 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.
|
* Writes a memory block on the target.
|
||||||
* 'size' is number of bytes to fill.
|
*
|
||||||
* Parameter 0 of sequent 'done' is assigned with Throwable if
|
* An asynchronous memory write request at [address] + [offset] for
|
||||||
* there was an error.
|
* [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,
|
public void setMemory(IDMContext<?> context, IAddress address, long offset,
|
||||||
int word_size, byte[] value, int size, int mode, RequestMonitor rm);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue