Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java')
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java1332
1 files changed, 667 insertions, 665 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java
index e00d21453f9..52f90903777 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java
@@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
- *
+ *
* Contributors:
* Wind River Systems - initial API and implementation
* Ericsson AB - expanded from initial stub
@@ -76,75 +76,73 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
private static final String READ_MEMORY_BYTES_FEATURE = "data-read-memory-bytes"; //$NON-NLS-1$
//data-read-memory write is deprecated, its description could be ambiguous for e.g. 16 bit addressable systems
private static final String DATA_WRITE_MEMORY_16_NOT_SUPPORTED = "data-write-memory with word-size != 1 not supported"; //$NON-NLS-1$
-
- public class MemoryChangedEvent extends AbstractDMEvent<IMemoryDMContext>
- implements IMemoryChangedEvent
- {
- private IAddress[] fAddresses;
-
- public MemoryChangedEvent(IMemoryDMContext context, IAddress[] addresses) {
- super(context);
- fAddresses = addresses;
- }
-
- @Override
- public IAddress[] getAddresses() {
- return fAddresses;
- }
- }
+
+ public class MemoryChangedEvent extends AbstractDMEvent<IMemoryDMContext> implements IMemoryChangedEvent {
+ private IAddress[] fAddresses;
+
+ public MemoryChangedEvent(IMemoryDMContext context, IAddress[] addresses) {
+ super(context);
+ fAddresses = addresses;
+ }
+
+ @Override
+ public IAddress[] getAddresses() {
+ return fAddresses;
+ }
+ }
// Back-end commands cache
private CommandCache fCommandCache;
private CommandFactory fCommandFactory;
// Map of memory caches
- private Map<IMemoryDMContext, MIMemoryCache> fMemoryCaches;
-
- /** @since 4.2 */
- protected MIMemoryCache getMemoryCache(IMemoryDMContext memoryDMC) {
- MIMemoryCache cache = fMemoryCaches.get(memoryDMC);
- if (cache == null) {
- cache = new MIMemoryCache();
- fMemoryCaches.put(memoryDMC, cache);
- }
- return cache;
- }
-
- // Whether the -data-read-memory-bytes should be used
- // instead of -data-read-memory
- private boolean fDataReadMemoryBytes;
-
+ private Map<IMemoryDMContext, MIMemoryCache> fMemoryCaches;
+
+ /** @since 4.2 */
+ protected MIMemoryCache getMemoryCache(IMemoryDMContext memoryDMC) {
+ MIMemoryCache cache = fMemoryCaches.get(memoryDMC);
+ if (cache == null) {
+ cache = new MIMemoryCache();
+ fMemoryCaches.put(memoryDMC, cache);
+ }
+ return cache;
+ }
+
+ // Whether the -data-read-memory-bytes should be used
+ // instead of -data-read-memory
+ private boolean fDataReadMemoryBytes;
+
/**
- * Constructor
+ * Constructor
*/
public MIMemory(DsfSession session) {
super(session);
- }
+ }
- ///////////////////////////////////////////////////////////////////////////
- // AbstractDsfService overrides
- ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+ // AbstractDsfService overrides
+ ///////////////////////////////////////////////////////////////////////////
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
*/
@Override
- public void initialize(final RequestMonitor requestMonitor) {
- super.initialize(new ImmediateRequestMonitor(requestMonitor) {
- @Override
- protected void handleSuccess() {
- doInitialize(requestMonitor);
- }
- });
- }
-
- private void doInitialize(final RequestMonitor requestMonitor) {
- IGDBControl commandControl = getServicesTracker().getService(IGDBControl.class);
- BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
-
- fDataReadMemoryBytes = commandControl.getFeatures().contains(READ_MEMORY_BYTES_FEATURE);
-
- fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(new ImmediateRequestMonitor(requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+ IGDBControl commandControl = getServicesTracker().getService(IGDBControl.class);
+ BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
+
+ fDataReadMemoryBytes = commandControl.getFeatures().contains(READ_MEMORY_BYTES_FEATURE);
+
+ fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
// This cache stores the result of a command when received; also, this cache
// is manipulated when receiving events. Currently, events are received after
@@ -154,223 +152,231 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
// To solve this, we use a bufferedCommandControl that will delay the command
// result by two scheduling of the executor.
// See bug 280461
- fCommandCache = new CommandCache(getSession(), bufferedCommandControl);
- fCommandCache.setContextAvailable(commandControl.getContext(), true);
+ fCommandCache = new CommandCache(getSession(), bufferedCommandControl);
+ fCommandCache.setContextAvailable(commandControl.getContext(), true);
- register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>());
+ register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>());
- fMemoryCaches = new HashMap<IMemoryDMContext, MIMemoryCache>();
+ fMemoryCaches = new HashMap<IMemoryDMContext, MIMemoryCache>();
- getSession().addServiceEventListener(this, null);
+ getSession().addServiceEventListener(this, null);
- requestMonitor.done();
- }
+ requestMonitor.done();
+ }
- /* (non-Javadoc)
- * @see org.eclipse.cdt.dsf.service.AbstractDsfService#shutdown(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
- */
- @Override
- public void shutdown(final RequestMonitor requestMonitor) {
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.service.AbstractDsfService#shutdown(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
- unregister();
+ unregister();
- getSession().removeServiceEventListener(this);
+ getSession().removeServiceEventListener(this);
- super.shutdown(requestMonitor);
- }
+ super.shutdown(requestMonitor);
+ }
- /* (non-Javadoc)
- * @see org.eclipse.cdt.dsf.service.AbstractDsfService#getBundleContext()
- */
- @Override
- protected BundleContext getBundleContext() {
- return GdbPlugin.getBundleContext();
- }
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.service.AbstractDsfService#getBundleContext()
+ */
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
- ///////////////////////////////////////////////////////////////////////////
- // IMemory
- ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
+ // IMemory
+ ///////////////////////////////////////////////////////////////////////////
- /* (non-Javadoc)
- * @see org.eclipse.cdt.dsf.debug.service.IMemory#getMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
- */
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.service.IMemory#getMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
@Override
- public void getMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
- int wordSize, int wordCount, DataRequestMonitor<MemoryByte[]> drm)
- {
- if (memoryDMC == null) {
- drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
- drm.done();
- return;
- }
-
- if (wordSize < 1) {
- drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
- drm.done();
- return;
- }
-
- if (wordCount < 0) {
- drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
- drm.done();
- return;
- }
-
- getMemoryCache(memoryDMC).getMemory(memoryDMC, address.add(offset), wordSize, wordCount, drm);
+ public void getMemory(IMemoryDMContext memoryDMC, IAddress address, long offset, int wordSize, int wordCount,
+ DataRequestMonitor<MemoryByte[]> drm) {
+ if (memoryDMC == null) {
+ drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
+ drm.done();
+ return;
+ }
+
+ if (wordSize < 1) {
+ drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", //$NON-NLS-1$
+ null));
+ drm.done();
+ return;
+ }
+
+ if (wordCount < 0) {
+ drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Invalid word count (< 0)", null)); //$NON-NLS-1$
+ drm.done();
+ return;
+ }
+
+ getMemoryCache(memoryDMC).getMemory(memoryDMC, address.add(offset), wordSize, wordCount, drm);
}
- /* (non-Javadoc)
- * @see org.eclipse.cdt.dsf.debug.service.IMemory#setMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.cdt.dsf.concurrent.RequestMonitor)
- */
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.service.IMemory#setMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
@Override
- public void setMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
- int wordSize, int wordCount, byte[] buffer, RequestMonitor rm)
- {
- if (memoryDMC == null) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
- rm.done();
- return;
- }
-
- if (wordSize < 1) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- if (wordCount < 0) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- if (buffer.length < wordCount * wordSize) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Buffer too short", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, wordSize, wordCount, buffer, rm);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.cdt.dsf.debug.service.IMemory#fillMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.cdt.dsf.concurrent.RequestMonitor)
- */
+ public void setMemory(IMemoryDMContext memoryDMC, IAddress address, long offset, int wordSize, int wordCount,
+ byte[] buffer, RequestMonitor rm) {
+ if (memoryDMC == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
+ rm.done();
+ return;
+ }
+
+ if (wordSize < 1) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", //$NON-NLS-1$
+ null));
+ rm.done();
+ return;
+ }
+
+ if (wordCount < 0) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Invalid word count (< 0)", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ if (buffer.length < wordCount * wordSize) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Buffer too short", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, wordSize, wordCount, buffer, rm);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.service.IMemory#fillMemory(org.eclipse.cdt.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
@Override
- public void fillMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
- int wordSize, int count, byte[] pattern, RequestMonitor rm)
- {
- if (memoryDMC == null) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
- rm.done();
- return;
- }
-
- if (wordSize < 1) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- if (count < 0) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid repeat count (< 0)", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- if (pattern.length < 1) {
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Empty pattern", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- // Create an aggregate buffer so we can write in 1 shot
- int length = pattern.length;
- byte[] buffer = new byte[count * length];
- for (int i = 0; i < count; i++) {
- System.arraycopy(pattern, 0, buffer, i * length, length);
- }
-
- int word_count = buffer.length / wordSize;
- if (buffer.length % wordSize != 0) {
- word_count ++;
- }
-
- // All is clear: go for it
- getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, wordSize, word_count, buffer, rm);
- }
-
- ///////////////////////////////////////////////////////////////////////
- // Back-end functions
- ///////////////////////////////////////////////////////////////////////
-
- /**
- * @param memoryDMC
- * @param address
- * @param offset
- * @param wordSize
- * @param wordCount in addressable units
- * @param drm
- *
- * @since 1.1
- */
- protected void readMemoryBlock(IDMContext dmc, IAddress address, final long offset,
- final int wordSize, final int wordCount, final DataRequestMonitor<MemoryByte[]> drm)
- {
- if (fDataReadMemoryBytes) {
- fCommandCache.execute(
- fCommandFactory.createMIDataReadMemoryBytes(dmc, address.toString(), offset, wordCount, wordSize),
- new DataRequestMonitor<MIDataReadMemoryBytesInfo>(getExecutor(), drm) {
- @Override
- protected void handleSuccess() {
- // Retrieve the memory block
- drm.setData(getData().getMIMemoryBlock());
- drm.done();
- }
- @Override
- protected void handleFailure() {
- drm.setData(createInvalidBlock(wordSize * wordCount));
- drm.done();
- }
- });
- } else {
- if (wordSize != 1) {
- //The word-size is specified within the resulting command data-read-memory
- //The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
- //octets or system dependent bytes (minimum addressable memory).
- //As this command is deprecated there is no good reason to augment the support for word sizes != 1
- drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
- drm.done();
- return;
- }
-
- /* To simplify the parsing of the MI result, we request the output to
- * be on 1 row of [count] columns, no char interpretation.
- */
- int mode = MIFormat.HEXADECIMAL;
- int nbRows = 1;
- int nbCols = wordCount;
- Character asChar = null;
-
- fCommandCache.execute(
- fCommandFactory.createMIDataReadMemory(dmc, offset, address.toString(), mode, wordSize, nbRows, nbCols, asChar),
- new DataRequestMonitor<MIDataReadMemoryInfo>(getExecutor(), drm) {
- @Override
- protected void handleSuccess() {
- // Retrieve the memory block
- drm.setData(getData().getMIMemoryBlock());
- drm.done();
- }
- @Override
- protected void handleFailure() {
- drm.setData(createInvalidBlock(wordSize * wordCount));
- drm.done();
- }
- }
- );
- }
- }
-
+ public void fillMemory(IMemoryDMContext memoryDMC, IAddress address, long offset, int wordSize, int count,
+ byte[] pattern, RequestMonitor rm) {
+ if (memoryDMC == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
+ rm.done();
+ return;
+ }
+
+ if (wordSize < 1) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", //$NON-NLS-1$
+ null));
+ rm.done();
+ return;
+ }
+
+ if (count < 0) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Invalid repeat count (< 0)", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ if (pattern.length < 1) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Empty pattern", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Create an aggregate buffer so we can write in 1 shot
+ int length = pattern.length;
+ byte[] buffer = new byte[count * length];
+ for (int i = 0; i < count; i++) {
+ System.arraycopy(pattern, 0, buffer, i * length, length);
+ }
+
+ int word_count = buffer.length / wordSize;
+ if (buffer.length % wordSize != 0) {
+ word_count++;
+ }
+
+ // All is clear: go for it
+ getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, wordSize, word_count, buffer, rm);
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Back-end functions
+ ///////////////////////////////////////////////////////////////////////
+
+ /**
+ * @param memoryDMC
+ * @param address
+ * @param offset
+ * @param wordSize
+ * @param wordCount in addressable units
+ * @param drm
+ *
+ * @since 1.1
+ */
+ protected void readMemoryBlock(IDMContext dmc, IAddress address, final long offset, final int wordSize,
+ final int wordCount, final DataRequestMonitor<MemoryByte[]> drm) {
+ if (fDataReadMemoryBytes) {
+ fCommandCache.execute(
+ fCommandFactory.createMIDataReadMemoryBytes(dmc, address.toString(), offset, wordCount, wordSize),
+ new DataRequestMonitor<MIDataReadMemoryBytesInfo>(getExecutor(), drm) {
+ @Override
+ protected void handleSuccess() {
+ // Retrieve the memory block
+ drm.setData(getData().getMIMemoryBlock());
+ drm.done();
+ }
+
+ @Override
+ protected void handleFailure() {
+ drm.setData(createInvalidBlock(wordSize * wordCount));
+ drm.done();
+ }
+ });
+ } else {
+ if (wordSize != 1) {
+ //The word-size is specified within the resulting command data-read-memory
+ //The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
+ //octets or system dependent bytes (minimum addressable memory).
+ //As this command is deprecated there is no good reason to augment the support for word sizes != 1
+ drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
+ DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
+ drm.done();
+ return;
+ }
+
+ /* To simplify the parsing of the MI result, we request the output to
+ * be on 1 row of [count] columns, no char interpretation.
+ */
+ int mode = MIFormat.HEXADECIMAL;
+ int nbRows = 1;
+ int nbCols = wordCount;
+ Character asChar = null;
+
+ fCommandCache
+ .execute(
+ fCommandFactory.createMIDataReadMemory(dmc, offset, address.toString(), mode, wordSize,
+ nbRows, nbCols, asChar),
+ new DataRequestMonitor<MIDataReadMemoryInfo>(getExecutor(), drm) {
+ @Override
+ protected void handleSuccess() {
+ // Retrieve the memory block
+ drm.setData(getData().getMIMemoryBlock());
+ drm.done();
+ }
+
+ @Override
+ protected void handleFailure() {
+ drm.setData(createInvalidBlock(wordSize * wordCount));
+ drm.done();
+ }
+ });
+ }
+ }
+
private MemoryByte[] createInvalidBlock(int size) {
// Bug234289: If memory read fails, return a block marked as invalid
MemoryByte[] block = new MemoryByte[size];
@@ -380,139 +386,140 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
return block;
}
- /**
- * @param memoryDMC
- * @param address
- * @param offset
- * @param wordSize
- * @param wordCount in addressable units
- * @param buffer
- * @param rm
- *
- * @since 1.1
- */
- protected void writeMemoryBlock(final IDMContext dmc, final IAddress address, final long offset,
- final int wordSize, final int wordCount, final byte[] buffer, final RequestMonitor rm)
- {
- if (fDataReadMemoryBytes) {
- // Use -data-write-memory-bytes for performance,
- fCommandCache.execute(
- fCommandFactory.createMIDataWriteMemoryBytes(dmc, address.add(offset).toString(),
- (buffer.length == wordCount*wordSize) ? buffer : Arrays.copyOf(buffer, wordCount*wordSize)),
- new DataRequestMonitor<MIInfo>(getExecutor(), rm)
- );
- } else {
- if (wordSize != 1) {
- //The word-size is specified within the resulting command data-write-memory
- //The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
- //octets or system dependent bytes (minimum addressable memory).
- //As this command is deprecated there is no good reason to augment the support for word sizes != 1
- rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
- rm.done();
- return;
- }
-
- // Each byte is written individually (GDB power...)
- // so we need to keep track of the count
- final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), rm);
- countingRM.setDoneCount(wordCount);
-
- // We will format the individual bytes in decimal
- int format = MIFormat.DECIMAL;
- String baseAddress = address.toString();
-
- // Issue an MI request for each byte to write
- for (int i = 0; i < wordCount; i++) {
- String value = Byte.toString(buffer[i]);
- fCommandCache.execute(
- fCommandFactory.createMIDataWriteMemory(dmc, offset + i, baseAddress, format, wordSize, value),
- new DataRequestMonitor<MIDataWriteMemoryInfo>(getExecutor(), countingRM)
- );
- }
- }
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Event handlers
- //////////////////////////////////////////////////////////////////////////
- @DsfServiceEventHandler
+ /**
+ * @param memoryDMC
+ * @param address
+ * @param offset
+ * @param wordSize
+ * @param wordCount in addressable units
+ * @param buffer
+ * @param rm
+ *
+ * @since 1.1
+ */
+ protected void writeMemoryBlock(final IDMContext dmc, final IAddress address, final long offset, final int wordSize,
+ final int wordCount, final byte[] buffer, final RequestMonitor rm) {
+ if (fDataReadMemoryBytes) {
+ // Use -data-write-memory-bytes for performance,
+ fCommandCache.execute(
+ fCommandFactory.createMIDataWriteMemoryBytes(dmc, address.add(offset).toString(),
+ (buffer.length == wordCount * wordSize) ? buffer
+ : Arrays.copyOf(buffer, wordCount * wordSize)),
+ new DataRequestMonitor<MIInfo>(getExecutor(), rm));
+ } else {
+ if (wordSize != 1) {
+ //The word-size is specified within the resulting command data-write-memory
+ //The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
+ //octets or system dependent bytes (minimum addressable memory).
+ //As this command is deprecated there is no good reason to augment the support for word sizes != 1
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
+ DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
+ rm.done();
+ return;
+ }
+
+ // Each byte is written individually (GDB power...)
+ // so we need to keep track of the count
+ final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), rm);
+ countingRM.setDoneCount(wordCount);
+
+ // We will format the individual bytes in decimal
+ int format = MIFormat.DECIMAL;
+ String baseAddress = address.toString();
+
+ // Issue an MI request for each byte to write
+ for (int i = 0; i < wordCount; i++) {
+ String value = Byte.toString(buffer[i]);
+ fCommandCache.execute(
+ fCommandFactory.createMIDataWriteMemory(dmc, offset + i, baseAddress, format, wordSize, value),
+ new DataRequestMonitor<MIDataWriteMemoryInfo>(getExecutor(), countingRM));
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Event handlers
+ //////////////////////////////////////////////////////////////////////////
+ @DsfServiceEventHandler
public void eventDispatched(IResumedDMEvent e) {
- if (e instanceof IContainerResumedDMEvent) {
- fCommandCache.setContextAvailable(e.getDMContext(), false);
- }
-
- if (e.getReason() != StateChangeReason.STEP) {
- IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(e.getDMContext(), IMemoryDMContext.class);
- // It is the memory context we want to clear, not only the context that resumed. The resumed context
- // is probably a thread but that running thread could have changed any memory within the memory
- // context.
- if (memoryDMC != null) {
- fCommandCache.reset(memoryDMC);
-
- memoryCacheReset(memoryDMC);
- }
- }
+ if (e instanceof IContainerResumedDMEvent) {
+ fCommandCache.setContextAvailable(e.getDMContext(), false);
+ }
+
+ if (e.getReason() != StateChangeReason.STEP) {
+ IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(e.getDMContext(), IMemoryDMContext.class);
+ // It is the memory context we want to clear, not only the context that resumed. The resumed context
+ // is probably a thread but that running thread could have changed any memory within the memory
+ // context.
+ if (memoryDMC != null) {
+ fCommandCache.reset(memoryDMC);
+
+ memoryCacheReset(memoryDMC);
+ }
+ }
}
-
- @DsfServiceEventHandler
+
+ @DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {
- if (e instanceof IContainerSuspendedDMEvent) {
- fCommandCache.setContextAvailable(e.getDMContext(), true);
- }
-
- IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(e.getDMContext(), IMemoryDMContext.class);
- // It is the memory context we want to clear, not only the context that stopped. The stopped context
- // is probably a thread but that thread that ran could have changed any memory within the memory
- // context.
- if (memoryDMC != null) {
- fCommandCache.reset(memoryDMC);
-
- memoryCacheReset(memoryDMC);
- }
+ if (e instanceof IContainerSuspendedDMEvent) {
+ fCommandCache.setContextAvailable(e.getDMContext(), true);
+ }
+
+ IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(e.getDMContext(), IMemoryDMContext.class);
+ // It is the memory context we want to clear, not only the context that stopped. The stopped context
+ // is probably a thread but that thread that ran could have changed any memory within the memory
+ // context.
+ if (memoryDMC != null) {
+ fCommandCache.reset(memoryDMC);
+
+ memoryCacheReset(memoryDMC);
+ }
}
/**
* @deprecated Replaced by the generic {@link #eventDispatched(IExpressionChangedDMEvent)}
*/
- @Deprecated
+ @Deprecated
public void eventDispatched(ExpressionChangedEvent e) {
- }
+ }
- /**
- * @noreference This method is not intended to be referenced by clients.
- * @since 4.2
- */
- @DsfServiceEventHandler
- public void eventDispatched(IExpressionChangedDMEvent e) {
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ * @since 4.2
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(IExpressionChangedDMEvent e) {
- // Get the context and expression service handle
- final IExpressionDMContext context = e.getDMContext();
+ // Get the context and expression service handle
+ final IExpressionDMContext context = e.getDMContext();
IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
// Get the variable information and update the corresponding memory locations
if (expressionService != null) {
expressionService.getExpressionAddressData(context,
- new DataRequestMonitor<IExpressionDMAddress>(getExecutor(), null) {
- @Override
- protected void handleSuccess() {
- // Figure out which memory area was modified
- IExpressionDMAddress expression = getData();
- IAddress expAddress = expression.getAddress();
- if (expAddress != IExpressions.IExpressionDMLocation.INVALID_ADDRESS) {
- final int count = expression.getSize();
- final Addr64 address;
- if (expAddress instanceof Addr64) {
- address = (Addr64) expAddress;
- } else {
- address = new Addr64(expAddress.getValue());
+ new DataRequestMonitor<IExpressionDMAddress>(getExecutor(), null) {
+ @Override
+ protected void handleSuccess() {
+ // Figure out which memory area was modified
+ IExpressionDMAddress expression = getData();
+ IAddress expAddress = expression.getAddress();
+ if (expAddress != IExpressions.IExpressionDMLocation.INVALID_ADDRESS) {
+ final int count = expression.getSize();
+ final Addr64 address;
+ if (expAddress instanceof Addr64) {
+ address = (Addr64) expAddress;
+ } else {
+ address = new Addr64(expAddress.getValue());
+ }
+
+ final IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context,
+ IMemoryDMContext.class);
+ getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0,
+ getAddressableSize(memoryDMC), count, true,
+ new RequestMonitor(getExecutor(), null));
}
-
- final IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
- getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0, getAddressableSize(memoryDMC), count, true,
- new RequestMonitor(getExecutor(), null));
}
- }
- });
+ });
}
}
@@ -523,18 +530,19 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
protected int getAddressableSize(IMemoryDMContext context) {
return 1;
}
-
+
///////////////////////////////////////////////////////////////////////////
// SortedLinkedlist
///////////////////////////////////////////////////////////////////////////
// This class is really the equivalent of a C struct (old habits die hard...)
- // For simplicity, everything is public.
- private static class MemoryBlock {
+ // For simplicity, everything is public.
+ private static class MemoryBlock {
public IAddress fAddress;
public long fLengthInAddressableUnits;
public long fLengthInOctets;
public MemoryByte[] fBlock;
+
public MemoryBlock(IAddress address, long lengthInOctets, long lengthInAddressableUnits, MemoryByte[] block) {
// A memory block is expected to be populated with the contents of a defined range of addresses
// therefore the number of octets shall be divisible by the number of addresses
@@ -546,8 +554,8 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
}
- // Address-ordered data structure to cache the memory blocks.
- // Contiguous blocks are merged if possible.
+ // Address-ordered data structure to cache the memory blocks.
+ // Contiguous blocks are merged if possible.
@SuppressWarnings("serial")
private static class SortedMemoryBlockList extends LinkedList<MemoryBlock> {
@@ -579,7 +587,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
}
- // Put at the end of the list and merge if necessary
+ // Put at the end of the list and merge if necessary
addLast(block);
compact(size() - 1);
return true;
@@ -589,7 +597,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
// Note: Merge is not performed if resulting block size would exceed MAXINT
private void compact(int index) {
- MemoryBlock newBlock = get(index);
+ MemoryBlock newBlock = get(index);
// Case where the block is to be merged with the previous block
if (index > 0) {
@@ -597,12 +605,15 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
IAddress endOfPreviousBlock = prevBlock.fAddress.add(prevBlock.fLengthInAddressableUnits);
if (endOfPreviousBlock.distanceTo(newBlock.fAddress).longValue() == 0) {
long newLengthInOctets = prevBlock.fLengthInOctets + newBlock.fLengthInOctets;
- long newLengthInAddressableUnits = prevBlock.fLengthInAddressableUnits + newBlock.fLengthInAddressableUnits;
+ long newLengthInAddressableUnits = prevBlock.fLengthInAddressableUnits
+ + newBlock.fLengthInAddressableUnits;
if (newLengthInOctets <= Integer.MAX_VALUE) {
- MemoryByte[] block = new MemoryByte[(int) newLengthInOctets] ;
+ MemoryByte[] block = new MemoryByte[(int) newLengthInOctets];
System.arraycopy(prevBlock.fBlock, 0, block, 0, (int) prevBlock.fLengthInOctets);
- System.arraycopy(newBlock.fBlock, 0, block, (int) prevBlock.fLengthInOctets, (int) newBlock.fLengthInOctets);
- newBlock = new MemoryBlock(prevBlock.fAddress, newLengthInOctets, newLengthInAddressableUnits, block);
+ System.arraycopy(newBlock.fBlock, 0, block, (int) prevBlock.fLengthInOctets,
+ (int) newBlock.fLengthInOctets);
+ newBlock = new MemoryBlock(prevBlock.fAddress, newLengthInOctets, newLengthInAddressableUnits,
+ block);
remove(index);
index -= 1;
set(index, newBlock);
@@ -619,9 +630,10 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
long newLength = newBlock.fLengthInOctets + nextBlock.fLengthInOctets;
long newAddressesLength = newBlock.fLengthInAddressableUnits + nextBlock.fLengthInAddressableUnits;
if (newLength <= Integer.MAX_VALUE) {
- MemoryByte[] block = new MemoryByte[(int) newLength] ;
+ MemoryByte[] block = new MemoryByte[(int) newLength];
System.arraycopy(newBlock.fBlock, 0, block, 0, (int) newBlock.fLengthInOctets);
- System.arraycopy(nextBlock.fBlock, 0, block, (int) newBlock.fLengthInOctets, (int) nextBlock.fLengthInOctets);
+ System.arraycopy(nextBlock.fBlock, 0, block, (int) newBlock.fLengthInOctets,
+ (int) nextBlock.fLengthInOctets);
newBlock = new MemoryBlock(newBlock.fAddress, newLength, newAddressesLength, block);
set(index, newBlock);
remove(index + 1);
@@ -641,74 +653,74 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
private SortedMemoryBlockList fMemoryBlockList;
public MIMemoryCache() {
- // Create the memory block cache
- fMemoryBlockList = new SortedMemoryBlockList();
+ // Create the memory block cache
+ fMemoryBlockList = new SortedMemoryBlockList();
}
public void reset() {
- // Clear the memory cache
- fMemoryBlockList.clear();
+ // Clear the memory cache
+ fMemoryBlockList.clear();
}
- /**
- * This function walks the address-sorted memory block list to identify
- * the 'missing' blocks (i.e. the holes) that need to be fetched on the target.
- *
- * The idea is fairly simple but an illustration could perhaps help.
- * Assume the cache holds a number of cached memory blocks with gaps i.e.
- * there is un-cached memory areas between blocks A, B and C:
- *
- * +---------+ +---------+ +---------+
- * + A + + B + + C +
- * +---------+ +---------+ +---------+
- * : : : : : :
- * [a] : : [b] : : [c] : : [d]
- * : : : : : :
- * [e---+--] : [f--+---------+--] : :
- * [g---+---------+------+---------+------+---------+----]
- * : : : : : :
- * : [h] : : [i----+--] : :
- *
- *
- * We have the following cases to consider.The requested block [a-i] either:
- *
- * [1] Fits entirely before A, in one of the gaps, or after C
- * with no overlap and no contiguousness (e.g. [a], [b], [c] and [d])
- * -> Add the requested block to the list of blocks to fetch
- *
- * [2] Starts before an existing block but overlaps part of it, possibly
- * spilling in the gap following the cached block (e.g. [e], [f] and [g])
- * -> Determine the length of the missing part (< count)
- * -> Add a request to fill the gap before the existing block
- * -> Update the requested block for the next iteration:
- * - Start address to point just after the end of the cached block
- * - Count reduced by cached block length (possibly becoming negative, e.g. [e])
- * At this point, the updated requested block starts just beyond the cached block
- * for the next iteration.
- *
- * [3] Starts at or into an existing block and overlaps part of it ([h] and [i])
- * -> Update the requested block for the next iteration:
- * - Start address to point just after the end of the cached block
- * - Count reduced by length to end of cached block (possibly becoming negative, e.g. [h])
- * At this point, the updated requested block starts just beyond the cached block
- * for the next iteration.
- *
- * We iterate over the cached blocks list until there is no entry left or until
- * the remaining requested block count is <= 0, meaning the result list contains
- * only the sub-blocks needed to fill the gap(s), if any.
- *
- * (As is often the case, it takes much more typing to explain it than to just do it :-)
- *
- * What is missing is a parameter that indicates the minimal block size that is worth fetching.
- * This is target-specific and straight in the realm of the coalescing function...
- *
- * @param reqBlockStart The address of the requested block
- * @param count Its length
- * @return A list of the sub-blocks to fetch in order to fill enough gaps in the memory cache
- * to service the request
- */
- private List<MemoryBlock> getListOfMissingBlocks(IAddress reqBlockStart, int wordCount, int wordSize) {
- int octetCount = wordCount * wordSize;
+ /**
+ * This function walks the address-sorted memory block list to identify
+ * the 'missing' blocks (i.e. the holes) that need to be fetched on the target.
+ *
+ * The idea is fairly simple but an illustration could perhaps help.
+ * Assume the cache holds a number of cached memory blocks with gaps i.e.
+ * there is un-cached memory areas between blocks A, B and C:
+ *
+ * +---------+ +---------+ +---------+
+ * + A + + B + + C +
+ * +---------+ +---------+ +---------+
+ * : : : : : :
+ * [a] : : [b] : : [c] : : [d]
+ * : : : : : :
+ * [e---+--] : [f--+---------+--] : :
+ * [g---+---------+------+---------+------+---------+----]
+ * : : : : : :
+ * : [h] : : [i----+--] : :
+ *
+ *
+ * We have the following cases to consider.The requested block [a-i] either:
+ *
+ * [1] Fits entirely before A, in one of the gaps, or after C
+ * with no overlap and no contiguousness (e.g. [a], [b], [c] and [d])
+ * -> Add the requested block to the list of blocks to fetch
+ *
+ * [2] Starts before an existing block but overlaps part of it, possibly
+ * spilling in the gap following the cached block (e.g. [e], [f] and [g])
+ * -> Determine the length of the missing part (< count)
+ * -> Add a request to fill the gap before the existing block
+ * -> Update the requested block for the next iteration:
+ * - Start address to point just after the end of the cached block
+ * - Count reduced by cached block length (possibly becoming negative, e.g. [e])
+ * At this point, the updated requested block starts just beyond the cached block
+ * for the next iteration.
+ *
+ * [3] Starts at or into an existing block and overlaps part of it ([h] and [i])
+ * -> Update the requested block for the next iteration:
+ * - Start address to point just after the end of the cached block
+ * - Count reduced by length to end of cached block (possibly becoming negative, e.g. [h])
+ * At this point, the updated requested block starts just beyond the cached block
+ * for the next iteration.
+ *
+ * We iterate over the cached blocks list until there is no entry left or until
+ * the remaining requested block count is <= 0, meaning the result list contains
+ * only the sub-blocks needed to fill the gap(s), if any.
+ *
+ * (As is often the case, it takes much more typing to explain it than to just do it :-)
+ *
+ * What is missing is a parameter that indicates the minimal block size that is worth fetching.
+ * This is target-specific and straight in the realm of the coalescing function...
+ *
+ * @param reqBlockStart The address of the requested block
+ * @param count Its length
+ * @return A list of the sub-blocks to fetch in order to fill enough gaps in the memory cache
+ * to service the request
+ */
+ private List<MemoryBlock> getListOfMissingBlocks(IAddress reqBlockStart, int wordCount, int wordSize) {
+ int octetCount = wordCount * wordSize;
LinkedList<MemoryBlock> list = new LinkedList<MemoryBlock>();
ListIterator<MemoryBlock> it = fMemoryBlockList.listIterator();
@@ -717,15 +729,17 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
while (it.hasNext() && octetCount > 0) {
MemoryBlock cachedBlock = it.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
- IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
+ IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
// Case where we miss a block before the cached block
if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0) {
- int lengthInOctets = (int) Math.min(reqBlockStart.distanceTo(cachedBlockStart).longValue()*wordSize, octetCount);
+ int lengthInOctets = (int) Math
+ .min(reqBlockStart.distanceTo(cachedBlockStart).longValue() * wordSize, octetCount);
// If both blocks start at the same location, no need to create a new cached block
if (lengthInOctets > 0) {
int lengthInAddressableUnits = lengthInOctets / wordSize;
- MemoryBlock newBlock = new MemoryBlock(reqBlockStart, lengthInOctets, lengthInAddressableUnits, new MemoryByte[0]);
+ MemoryBlock newBlock = new MemoryBlock(reqBlockStart, lengthInOctets, lengthInAddressableUnits,
+ new MemoryByte[0]);
list.add(newBlock);
}
// Adjust request block start and length for the next iteration
@@ -735,11 +749,10 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
// Case where the requested block starts somewhere in the cached block
else if (cachedBlockStart.distanceTo(reqBlockStart).longValue() > 0
- && reqBlockStart.distanceTo(cachedBlockEnd).longValue() >= 0)
- {
+ && reqBlockStart.distanceTo(cachedBlockEnd).longValue() >= 0) {
// Start of the requested block already in cache
// Adjust request block start and length for the next iteration
- octetCount -= reqBlockStart.distanceTo(cachedBlockEnd).longValue()*wordSize;
+ octetCount -= reqBlockStart.distanceTo(cachedBlockEnd).longValue() * wordSize;
reqBlockStart = cachedBlockEnd;
}
}
@@ -750,39 +763,39 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, octetCount, addressesLength, new MemoryByte[0]);
list.add(newBlock);
}
-
+
return list;
}
- /**
- * This function walks the address-sorted memory block list to get the
- * cached memory bytes (possibly from multiple contiguous blocks).
- * This function is called *after* the missing blocks have been read from
- * the back end i.e. the requested memory is all cached.
- *
- * Again, this is fairly simple. As we loop over the address-ordered list,
- * There are really only 2 cases:
- *
- * [1] The requested block fits entirely in the cached block ([a] or [b])
- * [2] The requested block starts in a cached block and ends in the
- * following (contiguous) one ([c]) in which case it is treated
- * as 2 contiguous requests ([c'] and [c"])
- *
- * +--------------+--------------+
- * + A + B +
- * +--------------+--------------+
- * : [a----] : [b-----] :
- * : : :
- * : [c-----+------] :
- * : [c'---]+[c"---] :
+ /**
+ * This function walks the address-sorted memory block list to get the
+ * cached memory bytes (possibly from multiple contiguous blocks).
+ * This function is called *after* the missing blocks have been read from
+ * the back end i.e. the requested memory is all cached.
+ *
+ * Again, this is fairly simple. As we loop over the address-ordered list,
+ * There are really only 2 cases:
*
- * @param reqBlockStart The address of the requested block
- * @param count Its length
- * @return The cached memory content
- */
- private MemoryByte[] getMemoryBlockFromCache(IAddress reqBlockStart, int wordCount, int wordSize) {
- int count = wordCount * wordSize;
-
+ * [1] The requested block fits entirely in the cached block ([a] or [b])
+ * [2] The requested block starts in a cached block and ends in the
+ * following (contiguous) one ([c]) in which case it is treated
+ * as 2 contiguous requests ([c'] and [c"])
+ *
+ * +--------------+--------------+
+ * + A + B +
+ * +--------------+--------------+
+ * : [a----] : [b-----] :
+ * : : :
+ * : [c-----+------] :
+ * : [c'---]+[c"---] :
+ *
+ * @param reqBlockStart The address of the requested block
+ * @param count Its length
+ * @return The cached memory content
+ */
+ private MemoryByte[] getMemoryBlockFromCache(IAddress reqBlockStart, int wordCount, int wordSize) {
+ int count = wordCount * wordSize;
+
IAddress reqBlockEnd = reqBlockStart.add(wordCount);
MemoryByte[] resultBlock = new MemoryByte[count];
ListIterator<MemoryBlock> iter = fMemoryBlockList.listIterator();
@@ -790,41 +803,38 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
- IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
+ IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
- // Case where the cached block overlaps completely the requested memory block
+ // Case where the cached block overlaps completely the requested memory block
if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
- && reqBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
- {
+ && reqBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0) {
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue() * wordSize;
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, count);
}
-
- // Case where the beginning of the cached block is within the requested memory block
+
+ // Case where the beginning of the cached block is within the requested memory block
else if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0
- && cachedBlockStart.distanceTo(reqBlockEnd).longValue() > 0)
- {
+ && cachedBlockStart.distanceTo(reqBlockEnd).longValue() > 0) {
int pos = (int) reqBlockStart.distanceTo(cachedBlockStart).longValue() * wordSize;
int length = (int) Math.min(cachedBlock.fLengthInOctets, count - pos);
System.arraycopy(cachedBlock.fBlock, 0, resultBlock, pos, length);
}
-
- // Case where the end of the cached block is within the requested memory block
+
+ // Case where the end of the cached block is within the requested memory block
else if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
- && reqBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
- {
+ && reqBlockStart.distanceTo(cachedBlockEnd).longValue() > 0) {
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue() * wordSize;
int length = (int) Math.min(cachedBlock.fLengthInOctets - pos, count);
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, length);
}
- }
+ }
return resultBlock;
}
/**
- * This function walks the address-sorted memory block list and updates
- * the content with the actual memory just read from the target.
- *
+ * This function walks the address-sorted memory block list and updates
+ * the content with the actual memory just read from the target.
+ *
* @param modBlockStart
* @param wordCount - Number of addressable units
* @param modBlock
@@ -838,211 +848,203 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
- IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
-
+ IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
+
// For now, we only bother to update bytes already cached.
// Note: In a better implementation (v1.1), we would augment
- // the cache with the missing memory blocks since we went
+ // the cache with the missing memory blocks since we went
// through the pains of reading them in the first place.
// (this is left as an exercise to the reader :-)
- // Case where the modified block is completely included in the cached block
+ // Case where the modified block is completely included in the cached block
if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
- && modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
- {
+ && modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0) {
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue() * wordSize;
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, count);
}
-
+
// Case where the cached block is completely included in the modified block
else if (modBlockStart.distanceTo(cachedBlockStart).longValue() >= 0
- && cachedBlockEnd.distanceTo(modBlockEnd).longValue() >= 0)
- {
+ && cachedBlockEnd.distanceTo(modBlockEnd).longValue() >= 0) {
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue() * wordSize;
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, (int) cachedBlock.fLengthInOctets);
}
- // Case where the beginning of the modified block is within the cached block
+ // Case where the beginning of the modified block is within the cached block
else if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
- && modBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
- {
+ && modBlockStart.distanceTo(cachedBlockEnd).longValue() > 0) {
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue() * wordSize;
int length = (int) modBlockStart.distanceTo(cachedBlockEnd).longValue() * wordSize;
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, length);
}
-
- // Case where the end of the modified block is within the cached block
+
+ // Case where the end of the modified block is within the cached block
else if (cachedBlockStart.distanceTo(modBlockEnd).longValue() > 0
- && modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
- {
+ && modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0) {
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue() * wordSize;
int length = (int) cachedBlockStart.distanceTo(modBlockEnd).longValue() * wordSize;
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, length);
}
- }
+ }
return;
}
- /**
+ /**
* @param memoryDMC
- * @param address the memory block address (on the target)
- * @param wordSize the size, in bytes, of an addressable item
- * @param wordCount the number of addressable units to read
- * @param drm the asynchronous data request monitor
- */
- public void getMemory(IMemoryDMContext memoryDMC, final IAddress address, final int wordSize,
- final int wordCount, final DataRequestMonitor<MemoryByte[]> drm)
- {
- // Determine the number of read requests to issue
- List<MemoryBlock> missingBlocks = getListOfMissingBlocks(address, wordCount, wordSize);
- int numberOfRequests = missingBlocks.size();
-
- // A read request will be issued for each block needed
- // so we need to keep track of the count
- final CountingRequestMonitor countingRM =
- new CountingRequestMonitor(getExecutor(), drm) {
- @Override
- protected void handleSuccess() {
- // We received everything so read the result from the memory cache
- drm.setData(getMemoryBlockFromCache(address, wordCount, wordSize));
- drm.done();
- }
- };
- countingRM.setDoneCount(numberOfRequests);
-
- // Issue the read requests
- for (int i = 0; i < numberOfRequests; i++) {
- MemoryBlock block = missingBlocks.get(i);
- final IAddress startAddress = block.fAddress;
- final int length = (int) block.fLengthInAddressableUnits;
- readMemoryBlock(memoryDMC, startAddress, 0, wordSize, length,
- new DataRequestMonitor<MemoryByte[]>(getSession().getExecutor(), drm) {
- @Override
- protected void handleSuccess() {
- MemoryByte[] block = getData();
- int lenghtInaddressableUnits = block.length / wordSize;
- MemoryBlock memoryBlock = new MemoryBlock(startAddress, block.length, lenghtInaddressableUnits, block);
- fMemoryBlockList.add(memoryBlock);
- countingRM.done();
- }
- });
- }
- }
-
- /**
+ * @param address the memory block address (on the target)
+ * @param wordSize the size, in bytes, of an addressable item
+ * @param wordCount the number of addressable units to read
+ * @param drm the asynchronous data request monitor
+ */
+ public void getMemory(IMemoryDMContext memoryDMC, final IAddress address, final int wordSize,
+ final int wordCount, final DataRequestMonitor<MemoryByte[]> drm) {
+ // Determine the number of read requests to issue
+ List<MemoryBlock> missingBlocks = getListOfMissingBlocks(address, wordCount, wordSize);
+ int numberOfRequests = missingBlocks.size();
+
+ // A read request will be issued for each block needed
+ // so we need to keep track of the count
+ final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), drm) {
+ @Override
+ protected void handleSuccess() {
+ // We received everything so read the result from the memory cache
+ drm.setData(getMemoryBlockFromCache(address, wordCount, wordSize));
+ drm.done();
+ }
+ };
+ countingRM.setDoneCount(numberOfRequests);
+
+ // Issue the read requests
+ for (int i = 0; i < numberOfRequests; i++) {
+ MemoryBlock block = missingBlocks.get(i);
+ final IAddress startAddress = block.fAddress;
+ final int length = (int) block.fLengthInAddressableUnits;
+ readMemoryBlock(memoryDMC, startAddress, 0, wordSize, length,
+ new DataRequestMonitor<MemoryByte[]>(getSession().getExecutor(), drm) {
+ @Override
+ protected void handleSuccess() {
+ MemoryByte[] block = getData();
+ int lenghtInaddressableUnits = block.length / wordSize;
+ MemoryBlock memoryBlock = new MemoryBlock(startAddress, block.length,
+ lenghtInaddressableUnits, block);
+ fMemoryBlockList.add(memoryBlock);
+ countingRM.done();
+ }
+ });
+ }
+ }
+
+ /**
* @param memoryDMC
- * @param address the memory block address (on the target)
- * @param offset the offset from the start address
- * @param wordSize the size, in bytes, of an addressable item
- * @param wordCount the number of addressable units to write
- * @param buffer the source buffer
- * @param rm the asynchronous request monitor
- */
- public void setMemory(final IMemoryDMContext memoryDMC, final IAddress address,
- final long offset, final int wordSize, final int wordCount, final byte[] buffer,
- final RequestMonitor rm)
- {
- writeMemoryBlock(
- memoryDMC, address, offset, wordSize, wordCount, buffer,
- new RequestMonitor(getSession().getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- // Clear the command cache (otherwise we can't guarantee
- // that the subsequent memory read will be correct)
- fCommandCache.reset();
-
- // Re-read the modified memory block to asynchronously update of the memory cache
- readMemoryBlock(memoryDMC, address, offset, wordSize, wordCount,
- new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- updateMemoryCache(address.add(offset), wordCount, getData(), wordSize);
+ * @param address the memory block address (on the target)
+ * @param offset the offset from the start address
+ * @param wordSize the size, in bytes, of an addressable item
+ * @param wordCount the number of addressable units to write
+ * @param buffer the source buffer
+ * @param rm the asynchronous request monitor
+ */
+ public void setMemory(final IMemoryDMContext memoryDMC, final IAddress address, final long offset,
+ final int wordSize, final int wordCount, final byte[] buffer, final RequestMonitor rm) {
+ writeMemoryBlock(memoryDMC, address, offset, wordSize, wordCount, buffer,
+ new RequestMonitor(getSession().getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // Clear the command cache (otherwise we can't guarantee
+ // that the subsequent memory read will be correct)
+ fCommandCache.reset();
+
+ // Re-read the modified memory block to asynchronously update of the memory cache
+ readMemoryBlock(memoryDMC, address, offset, wordSize, wordCount,
+ new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ updateMemoryCache(address.add(offset), wordCount, getData(), wordSize);
+ // Send the MemoryChangedEvent
+ IAddress[] addresses = new IAddress[wordCount];
+ for (int i = 0; i < wordCount; i++) {
+ addresses[i] = address.add(offset + i);
+ }
+ getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses),
+ getProperties());
+ rm.done();
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * @param memoryDMC
+ * @param address
+ * @param offset
+ * @param wordSize
+ * @param wordCount
+ * @param sendMemoryEvent Indicates if a IMemoryChangedEvent should be sent if the memory cache has changed.
+ * @param rm
+ */
+ public void refreshMemory(final IMemoryDMContext memoryDMC, final IAddress address, final long offset,
+ final int wordSize, final int wordCount, final boolean sendMemoryEvent, final RequestMonitor rm) {
+ // Check if we already cache part of this memory area (which means it
+ // is used by a memory service client that will have to be updated)
+ List<MemoryBlock> list = getListOfMissingBlocks(address, wordCount, wordSize);
+ int sizeToRead = 0;
+ for (MemoryBlock block : list) {
+ sizeToRead += block.fLengthInAddressableUnits;
+ }
+
+ // If none of the requested memory is in cache, just get out
+ if (sizeToRead == wordCount) {
+ rm.done();
+ return;
+ }
+
+ // Read the corresponding memory block
+ fCommandCache.reset();
+ readMemoryBlock(memoryDMC, address, offset, wordSize, wordCount,
+ new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ MemoryByte[] oldBlock = getMemoryBlockFromCache(address, wordCount, wordSize);
+ MemoryByte[] newBlock = getData();
+ boolean blocksDiffer = false;
+ for (int i = 0; i < oldBlock.length; i++) {
+ if (oldBlock[i].getValue() != newBlock[i].getValue()) {
+ blocksDiffer = true;
+ break;
+ }
+ }
+ if (blocksDiffer) {
+ updateMemoryCache(address.add(offset), wordCount, newBlock, wordSize);
+ if (sendMemoryEvent) {
// Send the MemoryChangedEvent
- IAddress[] addresses = new IAddress[wordCount];
+ final IAddress[] addresses = new IAddress[wordCount];
for (int i = 0; i < wordCount; i++) {
addresses[i] = address.add(offset + i);
}
- getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());
- rm.done();
- }
- });
- }
- });
- }
-
- /**
- * @param memoryDMC
- * @param address
- * @param offset
- * @param wordSize
- * @param wordCount
- * @param sendMemoryEvent Indicates if a IMemoryChangedEvent should be sent if the memory cache has changed.
- * @param rm
- */
- public void refreshMemory(final IMemoryDMContext memoryDMC, final IAddress address,
- final long offset, final int wordSize, final int wordCount, final boolean sendMemoryEvent,
- final RequestMonitor rm)
- {
- // Check if we already cache part of this memory area (which means it
- // is used by a memory service client that will have to be updated)
- List<MemoryBlock> list = getListOfMissingBlocks(address, wordCount, wordSize);
- int sizeToRead = 0;
- for (MemoryBlock block : list) {
- sizeToRead += block.fLengthInAddressableUnits;
- }
-
- // If none of the requested memory is in cache, just get out
- if (sizeToRead == wordCount) {
- rm.done();
- return;
- }
-
- // Read the corresponding memory block
- fCommandCache.reset();
- readMemoryBlock(memoryDMC, address, offset, wordSize, wordCount,
- new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- MemoryByte[] oldBlock = getMemoryBlockFromCache(address, wordCount, wordSize);
- MemoryByte[] newBlock = getData();
- boolean blocksDiffer = false;
- for (int i = 0; i < oldBlock.length; i++) {
- if (oldBlock[i].getValue() != newBlock[i].getValue()) {
- blocksDiffer = true;
- break;
- }
- }
- if (blocksDiffer) {
- updateMemoryCache(address.add(offset), wordCount, newBlock, wordSize);
- if (sendMemoryEvent) {
- // Send the MemoryChangedEvent
- final IAddress[] addresses = new IAddress[wordCount];
- for (int i = 0; i < wordCount; i++) {
- addresses[i] = address.add(offset + i);
- }
- getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());
- }
- }
- rm.done();
- }
- });
- }
+ getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses),
+ getProperties());
+ }
+ }
+ rm.done();
+ }
+ });
+ }
}
- /**
- * {@inheritDoc}
- * @since 1.1
- */
+ /**
+ * {@inheritDoc}
+ * @since 1.1
+ */
@Override
- public void flushCache(IDMContext context) {
- fCommandCache.reset(context);
-
- IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
-
- if (memoryDMC != null) {
- memoryCacheReset(memoryDMC);
- }
- }
+ public void flushCache(IDMContext context) {
+ fCommandCache.reset(context);
+
+ IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
+
+ if (memoryDMC != null) {
+ memoryCacheReset(memoryDMC);
+ }
+ }
/**
* Reset the cache for the given memory context or any of its associated

Back to the top